目录
- 一、核心方法
- 1.setStatus
- 2.setHeader(Stringname,Stringvalue)
- 3.addHeader(Stringname,Stringvalue)
- 4.setContentType(Stringtype)
- 二、响应一个网页
- 三、返回一个文件
- 四、返回json数据
一、核心方法
1.setStatus
设置响应状态码 如果没有调用这个方法,默认返回200状态码(前提:正常执行,没有异常) 如果出现异常,返回500
前端代码:
<body> <h3>设置响应头</h3> <input type=\"text\" id=\"status\"> <br> <button onclick=\"setStatus()\">提交</button> </body> <script> function setStatus(){ //js中发送请求:(1)ajax(2)直接修改url let status = document.querySelector(\"#status\"); //后端会设置文本框输入的值为响应状态码:严格来做需要验证(省略) 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 { //获取请求发送的queryString数据:status=xxx String status = req.getParameter(\"status\"); resp.setStatus((Integer.parseInt(status))); resp.getWriter().write(\"设置响应状态码成功\"); } }
前端显示:
提交后fiddler抓包:
2.setHeader(String name,String value)
设置响应头
响应头name键已有,会覆盖原有的键值对
前端代码:
<h3>设置响应头</h3> <a href=\"response\" rel=\"external nofollow\" >设置</a>
后端代码:
//设置响应头的键值对,键可以是标准的http响应头的键,也可以是自定义的 //响应状态码是301,302,307,响应头有Location字段,才是重定向 resp.setHeader(\"Location\",\"http://www.baidu.com\"); resp.setHeader(\"username\",\"张三\");
fiddler抓包结果:
3.addHeader(String name,String value)
设置响应头
响应头name键已有,不会影响,添加一个新的
这两个了解即可
4.setContentType(String type)
设置响应头Content-Type的值,等同于setHeader(“Content-Type”,String type) 因为Content-Type是标识body的数据格式,所以还需要设置body的内容
1.响应一个网页
//响应html:设置响应的Content-Type resp.setContentType(\"text/html; charset=utf-8\");
可以返回静态和动态网页
两种方式展示:
前端代码:
<body> <h3>返回响应正文为简单的html</h3> <a href=\"html?type=1\" rel=\"external nofollow\" >查看</a> <h3>返回响应正文为复杂的html(动态变化的)</h3> <input type=\"text\" id=\"username\" placeholder=\"输入姓名\"> <br> <button onclick=\"toWelcome()\">跳转</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>获取网页成功</h3>\"); }else if(\"2\".equals(type)){//返回复杂的动态html //html?type=2&username=xxx String username = req.getParameter(\"username\"); pw.println(\"<p>\"); pw.println(\"欢迎你,\"+username); pw.println(\"</p>\"); } } }
简单:
前端显示:
点击“查看”:
动态:
前端显式:
点击“跳转”:
关于动态网页:在Java的代码中,写很多html的代码
耦合性太强(两个完全不同的编程语言,放在一起来开发)、维护性、扩展性很差
解决方式:
- 模板技术
- 这种方式还存在一些问题,进一步发展就有了ajax技术的产生
二、响应一个网页
返回已有的一个网页
(1)重定向:
特点:url地址栏会变,发起两次请求
原理:
第一次返回301/302/307响应状态码,及响应头Location:网页的地址
第二次:浏览器自动的跳转到Location设置的地址
还是比较常用的:比如登录成功(其实也可以在js代码中跳转)后,跳转到某个首页
(2)转发:
特点:url地址栏不变,只有一次请求
原理:当次请求Servlet时,由Servlet获取到转发路径的html,把这个路径的内容设置到响应正文
前端代码:
<h3>重定向到hello.html</h3> <a href=\"goto?type=1\" rel=\"external nofollow\" >跳转</a> <h3>转发到hello.html</h3> <a href=\"goto?type=2\" rel=\"external nofollow\" >跳转</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)){//转发 req.getRequestDispatcher(\"hello.html\") .forward(req,resp); } } }
三、返回一个文件
设置一下Content-Type,然后把文件的二进制数据放在响应正文就可以
前端代码:
<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\"> //获取响应对象的字节输出流 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); } }
问题:图片、音乐、视频是静态文件,直接放在web应用webapp下,就可以直接访问,那还需要Servlet来返回么?是否多此一举?
如果文件总的大小非常大,放在web应用的webapp下就不合适了:打包就比较费劲,使用Servlet去读取本地其他地方的文件,来返回,就比较适合
四、返回json数据
常用于ajax请求,返回一些数据,用于动态的填充网页
前端代码:
<body> <h3>获取ajax响应数据,动态生成网页内容</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是一个字符串 //转换为json对象 let array = JSON.parse(resp); for(json of array){//遍历 //每一个json对象,创建一个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(); //设置回调函数 xhr.onreadystatechange = function(){ //4:客户端接收到响应后回调 if(xhr.readyState == 4){ // 回调函数可能需要使用响应的内容,作为传入参数 args.callback(xhr.status,xhr.responseText); } } xhr.open(args.method,args.url); // 如果args中,Content-Type属性有内容,就设置Content-Type请求头 if(args.contentType){//js中,除了判断boolean值,还可以判断字符串,对象等,有值就为true xhr.setRequestHeader(\"Content-Type\",args.contentType); } //如果args中,设置了body请求正文,调用send(body) if(args.body){ xhr.send(args.body); }else{//如果没有设置,调用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对象,转换为一个json字符串,list和数组会转换为[],一个对象{成员变量名:值} String json = mapper.writeValueAsString(messages); //[{\"from\":\"汪汪\",\"to\":\"喵喵\",\"info\":\"我喜欢你\"},{\"from\":\"喵喵\",\"to\":\"汪汪\",\"info\":\"我喜欢你\"}] System.out.println(\"转换的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; } } }
点击“试试”:
具体过程:
对应可以使用的数据格式:
做猪小侠源码的代理,提供一站式服务
如果你不懂得搭建网站或者服务器,小程序,源码之类的怎么办? 第一通过本站学习各种互联网的技术 第二就是联系客服,我帮帮你搭建(当然要收取部分的费用) 第三成为我们的代理,我们提供整套的服务。