目录
  • 一、核心方法
    • 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 = "https://www.freexyz.cn/dev/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("设置响应状态码成功");
            }
        }

        前端显示:

        Java Servlet响应httpServletResponse过程详解

        提交后fiddler抓包:

        Java Servlet响应httpServletResponse过程详解

        2.setHeader(String name,String value)

        设置响应头

        响应头name键已有,会覆盖原有的键值对

        前端代码:

        <h3>设置响应头</h3>
        <a href="https://www.freexyz.cn/dev/response" rel="external nofollow" >设置</a>
        

        后端代码:

        //设置响应头的键值对,键可以是标准的http响应头的键,也可以是自定义的
        //响应状态码是301,302,307,响应头有Location字段,才是重定向
        resp.setHeader("Location","http://www.baidu.com");
        resp.setHeader("username","张三");

        fiddler抓包结果:

        Java Servlet响应httpServletResponse过程详解

        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="https://www.freexyz.cn/dev/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 = "https://www.freexyz.cn/dev/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 Servlet响应httpServletResponse过程详解

        点击“查看”:

        Java Servlet响应httpServletResponse过程详解

        动态:

        前端显式:

        Java Servlet响应httpServletResponse过程详解

        点击“跳转”:

        Java Servlet响应httpServletResponse过程详解

        关于动态网页:在Java的代码中,写很多html的代码

        耦合性太强(两个完全不同的编程语言,放在一起来开发)、维护性、扩展性很差

        解决方式:

        • 模板技术
        • 这种方式还存在一些问题,进一步发展就有了ajax技术的产生

        二、响应一个网页

        返回已有的一个网页

        (1)重定向:

        特点:url地址栏会变,发起两次请求

        原理:

        第一次返回301/302/307响应状态码,及响应头Location:网页的地址

        第二次:浏览器自动的跳转到Location设置的地址

        还是比较常用的:比如登录成功(其实也可以在js代码中跳转)后,跳转到某个首页

        (2)转发:

        特点:url地址栏不变,只有一次请求

        原理:当次请求Servlet时,由Servlet获取到转发路径的html,把这个路径的内容设置到响应正文

        前端代码:

        <h3>重定向到hello.html</h3>
        <a href="https://www.freexyz.cn/dev/goto?type=1" rel="external nofollow" >跳转</a>
        <h3>转发到hello.html</h3>
        <a href="https://www.freexyz.cn/dev/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="https://www.freexyz.cn/dev/file?type=photo&show=1">
        <h3>获取一个音乐(渲染展示)</h3>
        <audio src="https://www.freexyz.cn/dev/file?type=music&show=1" controls></audio>
        
        <h3>获取一个图片(下载)</h3>
        <a href="https://www.freexyz.cn/dev/file?type=photo&show=0" rel="external nofollow" >下载</a>
        <h3>获取一个音乐(下载)</h3>
        <audio src="https://www.freexyz.cn/dev/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="https://www.freexyz.cn/dev/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="https://www.freexyz.cn/dev/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="https://www.freexyz.cn/dev/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;
                }
            }
        }

        点击“试试”:

        Java Servlet响应httpServletResponse过程详解

        Java Servlet响应httpServletResponse过程详解

        具体过程:

        Java Servlet响应httpServletResponse过程详解

        对应可以使用的数据格式:

        Java Servlet响应httpServletResponse过程详解

        声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。