Java Servlet响应httpServletResponse过程详解

目录
  • 一、核心方法
    • 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;
        }
    }
}

点击“试试”:

具体过程:

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

到此这篇关于Java 后端Servlet响应httpServletResponse详解的文章就介绍到这了,更多相关Servlet 响应httpServletResponse内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • HttpServletResponse乱码问题_动力节点Java学院整理

    一个完整的http响应包括响应行,若干响应头和响应数据主体三部分构成.如果我们能用响应对象来进行这三部分的处理,就能向客户发送特定的响应数据包. 先从HttpServletResponse对象的方法中可以看到有如下方法(部分): 这只是一部分,但是我们却可以看出,通过响应对象的方法,我们就能设置响应客户端数据的一些信息.比如setStatus(int sc)方法,我们从HttpServletResponse的API中的字段定义可找到已经设置好的响应码(部分): 我们通过setHeader或者ad

  • Java HttpServletResponse响应实现过程详解

    用户在客户端输入网址(虚拟路径)时,开始发送一个HTTP请求(请求行.请求头.请求体)至服务器.服务器内的Tomcat引擎会解析请求的地址,去找XML文件,然后根据虚拟路径找Servlet的真实路径,真实的Servlet会将请求的信息封装成request(请求)对象,然后再创建一个response(响应)对象,(此时的response内是空的)同时创建servlet对象,并调用service方法(或doGet和doPost方法). 这样就是把两个对象传给了服务器内的某个servlet的servi

  • Java中HttpServletResponse响应中文出现乱码问题

    以字符串的形式输出. 1.response.getWriter().write("您好中国hello"); 如果这样输出的话.则浏览器结果为: 2.加上代码 response.setCharacterEncoding("UTF-8"); response.getWriter().write("您好中国hello"); 则浏览器结果为: 这是因为浏览器解析问题. 加上代码: response.setHeader("Content-type

  • java HttpServletRequest和HttpServletResponse详解

    java  HttpServletRequest和HttpServletResponse详解 最近由于CAS相关的JAR包的重新封装,所以想尽量做到0配置,而这个过程中大量使 用HttpServletRequest,现在整理如下,以便以后查阅.(表格为从别的地方复制的,排版渣了点,酬和看吧.) 请求与响应相关的类和接口非常多,下表是主要的与请求和接口相关的类以及接口. 主要的与请求和接口相关的类及接口 方    法 说    明 ServletInputStream Servlet的输入流 Se

  • Java Servlet响应httpServletResponse过程详解

    目录 一.核心方法 1.setStatus 2.setHeader(Stringname,Stringvalue) 3.addHeader(Stringname,Stringvalue) 4.setContentType(Stringtype) 二.响应一个网页 三.返回一个文件 四.返回json数据 一.核心方法 1.setStatus 设置响应状态码 如果没有调用这个方法,默认返回200状态码(前提:正常执行,没有异常) 如果出现异常,返回500 前端代码: <body> <h3&g

  • 基于java servlet过滤器和监听器(详解)

    1 过滤器 1.过滤器是什么? servlet规范当中定义的一种特殊的组件,用于拦截容器的调用. 注:容器收到请求之后,如果有过滤器,会先调用过滤器,然后在调用servlet. 2.如何写一个过滤器? 1.写一个java类,实现Filter接口; 2.在接口方法中实现拦截方法; 3.配置过滤器(web.xml); 3.配置初始化参数 1.配置初始化参数.(init-param) 2.通过filterconfig提供的getinitparamenter方法读取初始化的值. 4.优先级: 当有多个过

  • java转换时区时间过程详解

    这篇文章主要介绍了java转换时区时间过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一丶时区 由于世界各国家与地区经度不同,地方时也有所不同,因此会划分为不同的时区. 地球是自西向东自转,东边比西边先看到太阳,东边的时间也比西边的早.东边时刻与西边时刻的差值不仅要以时计,而且还要以分和秒来计算,这给人们带来不便. 为了克服时间上的混乱,1884年在华盛顿召开的一次国际经度会议(又称国际子午线会议)上,规定将全球划分为24个时区(东.西

  • Java搭建RabbitMq消息中间件过程详解

    这篇文章主要介绍了Java搭建RabbitMq消息中间件过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言 当系统中出现"生产"和"消费"的速度或稳定性等因素不一致的时候,就需要消息队列. 名词 exchange: 交换机 routingkey: 路由key queue:队列 控制台端口:15672 exchange和queue是需要绑定在一起的,然后消息发送到exchange再由exchange通过ro

  • 基于Java代码操作Redis过程详解

    Jedis简介 实际开发中,我们需要用Redis的连接工具连接Redis然后操作Redis, 对于主流语言,Redis都提供了对应的客户端: 提供了很多客户端 官方推荐的是Jedis 托管地址:https://github.com/xetorthio/jedis 要使用redis首先得下载pom依赖 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId&g

  • JAVA如何调用wsdl过程详解

    前提:① 已经提供了一个wsdl接口② 该接口能正常调用 总体分为两种方式: 1.使用cxf的wsdl2java工具生成本地类(使用方式就是本地类的使用). 2.调用远程的web service方法:创建client来远程调用接口. 因为第二种方式,需要熟悉wsdl,没深入了解不太好操作,主要说下第一种方式. 使用cxf的wsdl2java工具生成本地类主要步骤如下: 1.安装JDK环境(jdk版本是1.6的话,后续会报错jdk6最高只支持ws2.1规范版本) 2.下载apache-cxf发布包

  • Spring Boot使用Servlet及Filter过程详解

    在Spring Boot中使用Servlet,根据Servlet注册方式的不同,有两种使用方式.若使用的是Servlet3.0+版本,则两种方式均可使用:若使用的是Servlet2.5版本,则只能使用配置类方式 一.Servlet3.0+版本方式 (1)创建工程07-servlet (2)导入依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apa

  • 基于java实现websocket协议过程详解

    最近了解了下websocket和socket这个东西,说不得不来说下为何要使用 WebSocket ,和为何不用http. 为何需要WebSocket ? HTTP 协议是一种无状态的.无连接的.单向的应用层协议.它采用了请求/响应模型.通信请求只能由客户端发起,服务端对请求做出应答处理. 这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息. 这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦.大多数 Web 应用程序将通过频繁的异步JavaScr

  • java虚拟机原理:类加载过程详解

    目录 一.Java 类加载过程 1.字节码编译 2.加载 3.连接 4.初始化 总结 一.Java 类加载过程 1.字节码编译 编写好 Java 源码 Student.java , 使用 javac 将上述 Java 源码编译成 Class 字节码文件 Student.class , 2.加载 加载 : 通过 " 类加载子系统 " 将该字节码文件 , 加载到 Java 虚拟机内存中 的 方法区 , 然后开始执行 " 连接 " 操作 , 类加载时机 : Java 程序

随机推荐