Java?Servlet響應httpServletResponse過程詳解
一、核心方法
1.setStatus
設置響應狀態(tài)碼 如果沒有調(diào)用這個方法,默認返回200狀態(tài)碼(前提:正常執(zhí)行,沒有異常) 如果出現(xiàn)異常,返回500
前端代碼:
<body> <h3>設置響應頭</h3> <input type="text" id="status"> <br> <button onclick="setStatus()">提交</button> </body> <script> function setStatus(){ //js中發(fā)送請求:(1)ajax(2)直接修改url let status = document.querySelector("#status"); //后端會設置文本框輸入的值為響應狀態(tài)碼:嚴格來做需要驗證(省略) window.location.href = "response?status="+status.value; } </script>
后端代碼:
@WebServlet("/response") public class ResponseStudyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //獲取請求發(fā)送的queryString數(shù)據(jù):status=xxx String status = req.getParameter("status"); resp.setStatus((Integer.parseInt(status))); resp.getWriter().write("設置響應狀態(tài)碼成功"); } }
前端顯示:
提交后fiddler抓包:
2.setHeader(String name,String value)
設置響應頭
響應頭name鍵已有,會覆蓋原有的鍵值對
前端代碼:
<h3>設置響應頭</h3> <a href="response" rel="external nofollow" >設置</a>
后端代碼:
//設置響應頭的鍵值對,鍵可以是標準的http響應頭的鍵,也可以是自定義的 //響應狀態(tài)碼是301,302,307,響應頭有Location字段,才是重定向 resp.setHeader("Location","http://www.baidu.com"); resp.setHeader("username","張三");
fiddler抓包結(jié)果:
3.addHeader(String name,String value)
設置響應頭
響應頭name鍵已有,不會影響,添加一個新的
這兩個了解即可
4.setContentType(String type)
設置響應頭Content-Type的值,等同于setHeader(“Content-Type”,String type) 因為Content-Type是標識body的數(shù)據(jù)格式,所以還需要設置body的內(nèi)容
1.響應一個網(wǎng)頁
//響應html:設置響應的Content-Type resp.setContentType("text/html; charset=utf-8");
可以返回靜態(tài)和動態(tài)網(wǎng)頁
兩種方式展示:
前端代碼:
<body> <h3>返回響應正文為簡單的html</h3> <a href="html?type=1" rel="external nofollow" >查看</a> <h3>返回響應正文為復雜的html(動態(tài)變化的)</h3> <input type="text" id="username" placeholder="輸入姓名"> <br> <button onclick="toWelcome()">跳轉(zhuǎn)</button> </body> <script> function toWelcome(){ let username = document.querySelector("#username"); window.location.href = "html?type=2&username="+username.value; } </script>
后端代碼:
@WebServlet("/html") public class HTMLTypeServlet extends HttpServlet { //html?type=... @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //響應html:設置響應的Content-Type resp.setContentType("text/html; charset=utf-8"); PrintWriter pw = resp.getWriter(); //獲取queryString中,type的值 String type = req.getParameter("type"); if("1".equals(type)){//返回簡單的html pw.println("<h3>獲取網(wǎng)頁成功</h3>"); }else if("2".equals(type)){//返回復雜的動態(tài)html //html?type=2&username=xxx String username = req.getParameter("username"); pw.println("<p>"); pw.println("歡迎你,"+username); pw.println("</p>"); } } }
簡單:
前端顯示:
點擊“查看”:
動態(tài):
前端顯式:
點擊“跳轉(zhuǎn)”:
關(guān)于動態(tài)網(wǎng)頁:在Java的代碼中,寫很多html的代碼
耦合性太強(兩個完全不同的編程語言,放在一起來開發(fā))、維護性、擴展性很差
解決方式:
- 模板技術(shù)
- 這種方式還存在一些問題,進一步發(fā)展就有了ajax技術(shù)的產(chǎn)生
二、響應一個網(wǎng)頁
返回已有的一個網(wǎng)頁
(1)重定向:
特點:url地址欄會變,發(fā)起兩次請求
原理:
第一次返回301/302/307響應狀態(tài)碼,及響應頭Location:網(wǎng)頁的地址
第二次:瀏覽器自動的跳轉(zhuǎn)到Location設置的地址
還是比較常用的:比如登錄成功(其實也可以在js代碼中跳轉(zhuǎn))后,跳轉(zhuǎn)到某個首頁
(2)轉(zhuǎn)發(fā):
特點:url地址欄不變,只有一次請求
原理:當次請求Servlet時,由Servlet獲取到轉(zhuǎn)發(fā)路徑的html,把這個路徑的內(nèi)容設置到響應正文
前端代碼:
<h3>重定向到hello.html</h3> <a href="goto?type=1" rel="external nofollow" >跳轉(zhuǎn)</a> <h3>轉(zhuǎn)發(fā)到hello.html</h3> <a href="goto?type=2" rel="external nofollow" >跳轉(zhuǎn)</a>
后端代碼:
@WebServlet("/goto") public class GoToServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //goto?type=xxx String type = req.getParameter("type"); if("1".equals(type)){//重定向 // resp.setStatus(301); // resp.setHeader("Location","hello.html"); //以上代碼可以簡化為sendRedirect resp.sendRedirect("hello.html"); }else if("2".equals(type)){//轉(zhuǎn)發(fā) req.getRequestDispatcher("hello.html") .forward(req,resp); } } }
三、返回一個文件
設置一下Content-Type,然后把文件的二進制數(shù)據(jù)放在響應正文就可以
前端代碼:
<h3>獲取一個圖片(渲染展示)</h3> <img src="file?type=photo&show=1"> <h3>獲取一個音樂(渲染展示)</h3> <audio src="file?type=music&show=1" controls></audio> <h3>獲取一個圖片(下載)</h3> <a href="file?type=photo&show=0" rel="external nofollow" >下載</a> <h3>獲取一個音樂(下載)</h3> <audio src="file?type=music&show=0" controls></audio>
后端代碼:
@WebServlet("/file") public class FileServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //<img src="file?type=photo&show=1"> //獲取響應對象的字節(jié)輸出流 OutputStream os = resp.getOutputStream(); //返回的文件類型:1.圖片 2.音樂 String type = req.getParameter("type"); //返回時的操作:1.渲染 2.下載 String show = req.getParameter("show"); File file = null; byte[] data = null; //<img src="file?type=photo&show=1"> if("photo".equals(type)){//返回圖片 if("1".equals(show)){ resp.setContentType("image/jpeg");//jpg格式 }else{ //這樣只是沒有設置下載的文件名,有興趣可以自行擴展完成 resp.setContentType("application/octet-stream"); } file =new File("D:\\java\\servlet-study\\src\\main\\resources\\cui.jpg"); //<audio src="file?type=music&show=1" controls></audio> }else if("music".equals(type)){//返回音樂 if("1".equals(show)){ resp.setContentType("audio/mp3");//mp3格式 }else{ resp.setContentType("application/octet-stream"); } file = new File("D:\\java\\servlet-study\\src\\main\\resources\\這世界有那么多人.mp3"); }//其他格式可以自行擴展完成 //返回一個文件類型:Content-Length,body data = Files.readAllBytes(file.toPath()); resp.setContentLength(data.length);//setHeader("Content-Length",xxx) os.write(data); } }
問題:圖片、音樂、視頻是靜態(tài)文件,直接放在web應用webapp下,就可以直接訪問,那還需要Servlet來返回么?是否多此一舉?
如果文件總的大小非常大,放在web應用的webapp下就不合適了:打包就比較費勁,使用Servlet去讀取本地其他地方的文件,來返回,就比較適合
四、返回json數(shù)據(jù)
常用于ajax請求,返回一些數(shù)據(jù),用于動態(tài)的填充網(wǎng)頁
前端代碼:
<body> <h3>獲取ajax響應數(shù)據(jù),動態(tài)生成網(wǎng)頁內(nèi)容</h3> <button onclick="gen()">試試</button> <div id="content"></div> </body> <script> function gen(){ let content = document.querySelector("#content"); ajax({ url: "ajax-response", method: "get", callback: function(status,resp){ console.log(resp);//resp是一個字符串 //轉(zhuǎn)換為json對象 let array = JSON.parse(resp); for(json of array){//遍歷 //每一個json對象,創(chuàng)建一個dom來保存信息 let p = document.createElement("p"); p.innerHTML = json.from+" 對 "+json.to+" 說:"+json.info; content.appendChild(p); } } }); } function ajax(args){//var ajax = function(){} let xhr = new XMLHttpRequest(); //設置回調(diào)函數(shù) xhr.onreadystatechange = function(){ //4:客戶端接收到響應后回調(diào) if(xhr.readyState == 4){ // 回調(diào)函數(shù)可能需要使用響應的內(nèi)容,作為傳入?yún)?shù) args.callback(xhr.status,xhr.responseText); } } xhr.open(args.method,args.url); // 如果args中,Content-Type屬性有內(nèi)容,就設置Content-Type請求頭 if(args.contentType){//js中,除了判斷boolean值,還可以判斷字符串,對象等,有值就為true xhr.setRequestHeader("Content-Type",args.contentType); } //如果args中,設置了body請求正文,調(diào)用send(body) if(args.body){ xhr.send(args.body); }else{//如果沒有設置,調(diào)用send() xhr.send(); } } </script>
后端代碼:
@WebServlet("/ajax-response") public class AjaxJsonServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { List<Message> messages = new ArrayList<>(); Message m1 = new Message("汪汪","喵喵","我喜歡你"); Message m2 = new Message("喵喵","汪汪","我喜歡你"); messages.add(m1); messages.add(m2); ObjectMapper mapper = new ObjectMapper(); //把Java對象,轉(zhuǎn)換為一個json字符串,list和數(shù)組會轉(zhuǎn)換為[],一個對象{成員變量名:值} String json = mapper.writeValueAsString(messages); //[{"from":"汪汪","to":"喵喵","info":"我喜歡你"},{"from":"喵喵","to":"汪汪","info":"我喜歡你"}] System.out.println("轉(zhuǎn)換的json字符串"+json); //設置json可以不設置Content-Length,tomcat會設置 resp.setContentType("application/json; charset=utf-8"); resp.getWriter().println(json); } static class Message{ private String from;//誰 private String to;//對誰 private String info;//說了什么 public Message(String from, String to, String info) { this.from = from; this.to = to; this.info = info; } public String getFrom() { return from; } public void setFrom(String from) { this.from = from; } public String getTo() { return to; } public void setTo(String to) { this.to = to; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } } }
點擊“試試”:
具體過程:
對應可以使用的數(shù)據(jù)格式:
到此這篇關(guān)于Java 后端Servlet響應httpServletResponse詳解的文章就介紹到這了,更多相關(guān)Servlet 響應httpServletResponse內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于.java編譯成.class?與?.class反編譯成.java問題
這篇文章主要介紹了關(guān)于.java編譯成.class?與?.class反編譯成.java問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09Spring?Boot中的JdbcClient與JdbcTemplate使用對比分析
這篇文章主要介紹了Spring Boot中的JdbcClient與JdbcTemplate使用對比分析,一起看看Spring Boot 中 JdbcClient 和 JdbcTemplate 之間的差異2024-01-01Swagger實現(xiàn)動態(tài)條件注入與全局攔截功能詳細流程
這篇文章主要介紹了Swagger實現(xiàn)動態(tài)條件注入與全局攔截功能詳細流程,Swagger 可以提供 API 操作的測試文檔,本文記錄 Swagger 使用過程中遇到的小問題2023-01-01詳解Spring學習總結(jié)——Spring實現(xiàn)AOP的多種方式
這篇文章主要介紹了詳解Spring學習總結(jié)——Spring實現(xiàn)AOP的多種方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01在Spring Boot中使用Spring-data-jpa實現(xiàn)分頁查詢
如何使用jpa進行多條件查詢以及查詢列表分頁呢?下面我將介紹兩種多條件查詢方式。具體實例代碼大家參考下本文吧2017-07-07