• Servlet Response常用方法


    接下来记录一下Servlet Response相关的信息,在service方法中使用的是HttpServletResponse,它继承自ServletResponse,扩展了Http协议相关的内容,下面简单记录一下它的基本用法。

    response组成内容

    以下是一个常见response响应的内容,它包括状态行、响应头、一个空行和实体内容,其中"HTTP/1.1 200 OK"就是状态行,包括协议、状态代号和状态描述信息,下面有若干响应头,空行和实体内容这里没展示。

    HTTP请求中的常用响应头如下:
    1 Location: http://www.it315.org/index.jsp 配合302实现请求重定向
    2 Server:apache tomcat 服务器类型
    3 Content-Encoding: gzip 服务器发送数据的压缩格式
    4 Content-Length: 80 发送数据的长度
    5 Content-Language: zh-cn 发送数据的语言环境
    6 Content-Type: text/html; charset=GB2312 可接受数据格式和语言
    7 Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT 与请求头的if modified头呼应,主要跟缓存有关
    8 Refresh: 1;url=http://www.it315.org 定时刷新
    9 Content-Disposition: attachment;filename=aaa.zip 跟下载有关,下载文件名字aaa.zip
    10 Transfer-Encoding: chunked 分块编码
    11 Set-Cookie:SS=Q0=5Lb_nQ; path=/search
    12 ETag: W/"83794-1208174400000" Etag一般和MD5配合使用,验证文件完整性
    13 Expires: -1 通知浏览器是否缓存当前资源,如果这个头的值是一个以毫秒为单位的值,就是通知浏览器缓存资源到指定的时间点,如果值是0或-1则是通知浏览器禁止缓存。
    14 Cache-Control: no-cache 通知浏览器是否缓存的头,no-cache代表不缓存
    15 Pragma: no-cache 通知浏览器是否缓存的头,no-cache代表不缓存
    16 Connection: close/Keep-Alive 连接状态
    17 Date: Tue, 11 Jul 2000 18:23:51 GMT  Date可以用来判断是否来自缓存
     
    Response的方法,就是针对响应内容进行的,它可以设置状态码、设置响应头,设置响应内容。

    response常用方法

    response提供了常用的api,有如下三类,通过它可以实现response的诸多功能。

    设置状态码

    设置状态码有如下API

    (1)response.setStatus(int status) 设置状态码

    (2)response.setStatus(int status,String description),java8中已经被弃用了,被标记为过时deprecated

    下面设置状态码为404,测试。

     1 package com.boe.response;
     2 
     3 import javax.servlet.ServletException;
     4 import javax.servlet.annotation.WebServlet;
     5 import javax.servlet.http.HttpServlet;
     6 import javax.servlet.http.HttpServletRequest;
     7 import javax.servlet.http.HttpServletResponse;
     8 import java.io.IOException;
     9 
    10 /**
    11  * 设置状态码
    12  */
    13 @WebServlet("/ResponseDemo05")
    14 public class ResponseDemo05 extends HttpServlet {
    15     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    16         //设置404
    17         response.setStatus(404);
    18         response.getWriter().write("Hello status");
    19     }
    20 
    21     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    22         doPost(request, response);
    23     }
    24 }

    访问页面后发现尽管能正常访问到资源,但是状态码被设置成了404。

    状态码404

    设置响应头

    设置影响头的方法,可以影响到页面的效果,有时候需要和上面设置状态码的方法配合使用,它常用的方法如下,前三个是set,后三个是add。

    (1)void setHeader(String name, String value)  用给定名称和值设置响应头。如果已经设置了头,则新值将重写以前的值。containsHeader 方法可用于测试在设置其值之前头是否存在
    (2)void setDateHeader(String name, long date) 给给定名称和日期值设置响应头,该日期根据距历元时间的毫秒数指定。如果已经设置了头,则新值将重写以前的值
    (3)void setIntHeader(String name, int value) 此方法的默认行为是对包装的响应对象调用 addIntHeader(String name, int value)。 
    (4)void addHeader(String name, String value) 用给定名称和值添加响应头,此方法允许响应头有多个值
    (5)void addDateHeader(String name, long date) 用给定名称和日期值添加响应头,该日期根据距历元时间的毫秒数指定,此方法允许响应头有多个值
    (6)void addIntHeader(String name, int value) 用给定名称和整数值添加响应头。此方法允许响应头有多个值
    关于API的使用,后面说功能时使用,以上常用的api就是setHeader,setDateHeader,后面response功能上面会使用这两种方法,下面简单了解一下setIntHeader方法,这个方法可以用在设置页面刷新频率,设置发送数据的长度等。
     1 package com.boe.response;
     2 
     3 import javax.servlet.ServletException;
     4 import javax.servlet.annotation.WebServlet;
     5 import javax.servlet.http.HttpServlet;
     6 import javax.servlet.http.HttpServletRequest;
     7 import javax.servlet.http.HttpServletResponse;
     8 import java.io.IOException;
     9 
    10 /**
    11  * 设置使用setIntHeader方法
    12  */
    13 @WebServlet("/ResponseDemo06")
    14 public class ResponseDemo06 extends HttpServlet {
    15     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    16         //设置刷新
    17         /* response.setIntHeader("Refresh",2);
    18         response.getWriter().write("<font color='blue' size='10px'>this is setIntHeader method"+"+"+Math.random()*100+"</font>");*/
    19         //设置发送数据长度,一个英文字符代表1个长度
    20         response.setIntHeader("Content-Length",10);
    21         response.getWriter().write("I come from china");
    22 
    23     }
    24 
    25     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    26         doPost(request, response);
    27     }
    28 }

    实际效果,会每隔2秒刷新一次页面,这里没有截取gif,使用两张贴图记录一下。

    另外setIntHeader里如果设置Content-length,还可以控制输出到页面的数据长度,发现输出到页面的实际长度被截取了。

    设置响应消息

    有两种方法可以设置响应消息,如下。

    (1)ServletOutputStream getOutputStream() 
    (2)PrintWriter getWriter()  
    上文中的response.getWriter().write("Hello status"),就使用了PrintWriter。

    response常用功能

    response常用功能有请求重定向、控制缓存、页面刷新等。

    请求重定向

    请求重定向的原理就是设置状态码为302,并且在响应头里设置location的路径,就可以实现重定向,也可以直接使用现成api来实现。

     1 package com.boe.response;
     2 
     3 import javax.servlet.ServletException;
     4 import javax.servlet.annotation.WebServlet;
     5 import javax.servlet.http.HttpServlet;
     6 import javax.servlet.http.HttpServletRequest;
     7 import javax.servlet.http.HttpServletResponse;
     8 import java.io.IOException;
     9 
    10 /**
    11  * 请求重定向
    12  */
    13 @WebServlet("/ResponseDemo02")
    14 public class ResponseDemo02 extends HttpServlet {
    15     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    16         //原理实现
    17         //设置状态码
    18         response.setStatus(302);
    19         //设置消息头
    20         response.setHeader("Location","http://www.baidu.com");
    21 
    22         //api实现
    23         //以上代码等效如下代码
    24         //response.sendRedirect("http://www.baidu.com");
    25     }
    26 
    27     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    28         doPost(request, response);
    29     }
    30 }

    访问ResponseDemo02后页面跳转到百度,重定向的地址是会改变的。

    控制缓存

    控制缓存有三个api可以使用,可以通过设置影响头的Cache-Control、Pragma和Expires来控制,参考前面对响应头的介绍和如下代码。

     1 package com.boe.response;
     2 
     3 import javax.servlet.ServletException;
     4 import javax.servlet.annotation.WebServlet;
     5 import javax.servlet.http.HttpServlet;
     6 import javax.servlet.http.HttpServletRequest;
     7 import javax.servlet.http.HttpServletResponse;
     8 import java.io.IOException;
     9 import java.util.Date;
    10 
    11 /**
    12  * 浏览器缓存的设置
    13  */
    14 @WebServlet("/ResponseDemo04")
    15 public class ResponseDemo04 extends HttpServlet {
    16     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    17         //设置不使用缓存
    18         /*public void setDateHeader(String name, long date)
    19         用给定名称和日期值设置响应头。该日期根据距历元时间的毫秒数指定。如果已经设置了头,则新值将重写以前的值。
    20         containsHeader 方法可用于测试在设置其值之前头是否存在。*/
    21         //方式1
    22         if(response.containsHeader("Expires")){
    23             response.setDateHeader("Expires",-1);
    24         }
    25         //方式2
    26         response.setHeader("Cache-Control","no-cache");
    27         //方式3
    28         response.setHeader("Pragma","no-cache");
    29 
    30         Date date=new Date();
    31         String time = date.toLocaleString();
    32         //设置使用缓存
    33         //response.setDateHeader("Expires",System.currentTimeMillis()+1000*60*60*1);//1 hour
    34         //response.setHeader("Cache-Control","max-age=60");//60 s
    35 
    36         response.getWriter().write("<font color='blue'>"+time+"</font>");
    37 
    38 
    39     }
    40 
    41     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    42         doPost(request, response);
    43     }
    44 }

    当不使用缓存时,每次刷新一下页面,就会打印新的时间,这里就不展示了。当设置完使用缓存,在缓存的寿命范围内,时间都不会变的,目前在IE和火狐浏览器测试可以,chrome没有效果。

    页面刷新 

    页面刷新可以设置响应头的Refresh,里面一个时间参数单位为秒,一个刷新后页面的url地址,注意使用url,这个可以用在注册后隔几秒跳转到主页这种场景。以下代码就是实现访问ResponseDemo03请求后,等待3秒会刷新进入百度主页的功能。

     1 package com.boe.response;
     2 
     3 import javax.servlet.ServletException;
     4 import javax.servlet.annotation.WebServlet;
     5 import javax.servlet.http.HttpServlet;
     6 import javax.servlet.http.HttpServletRequest;
     7 import javax.servlet.http.HttpServletResponse;
     8 import java.io.IOException;
     9 
    10 /**
    11  * 定时刷新
    12  */
    13 @WebServlet("/ResponseDemo03")
    14 public class ResponseDemo03 extends HttpServlet {
    15     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    16         //3 秒
    17         response.setHeader("Refresh","3;url=http://www.baidu.com");
    18     }
    19     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    20         doPost(request, response);
    21     }
    22 }

    response乱码处理

    涉及到响应,势必可能会有服务器和浏览器编解码不一致的问题,并会产生乱码,接下来使用字节流和字符流发送数据,查看乱码情况,使用如下基准代码进行调试,根据测试条件做调整即可。

     1 package com.boe.response;
     2 
     3 import javax.servlet.ServletException;
     4 import javax.servlet.annotation.WebServlet;
     5 import javax.servlet.http.HttpServlet;
     6 import javax.servlet.http.HttpServletRequest;
     7 import javax.servlet.http.HttpServletResponse;
     8 import java.io.IOException;
     9 
    10 /**
    11  * 响应字节流和字符流的乱码处理
    12  */
    13 @WebServlet("/ResponseDemo01")
    14 public class ResponseDemo01 extends HttpServlet {
    15     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    16         //1 字节流
    17         System.out.println(response.getCharacterEncoding());
    18         //ISO-8859-1 tomcat默认的字符编码,针对字符流,对字节流无影响
    19         //response.getOutputStream().write("china".getBytes());
    20         //getByte()默认使用平台的字符编码,即GBK,而浏览器默认使用GBK解码,因此没有乱码
    21         //response.getOutputStream().write("中国".getBytes());
    22         /**
    23          * 一般浏览器都会设置utf-8解码,这里需指定服务器编码方式为utf-8,设置浏览器解码也是utf-8
    24          */
    25         //通知浏览器使用utf-8来解码
    26         /*response.setHeader("Content-Type","text/html;charset=utf-8");
    27         response.getOutputStream().write("中国".getBytes("utf-8"));*/
    28 
    29         //2 字符流
    30         //默认使用iso-8859-1将字符流转变成字节流,底层由Tomcat服务器来完成,会使用Tomcat默认的字符集
    31         //通知服务端发送数据时字符集utf-8
    32         //response.setCharacterEncoding("utf-8");
    33         //如果告诉浏览器使用何种字符集,则这句可以不用写,服务会在发送数据自动采用浏览器设置的字符集
    34         //通知浏览器指定utf-8读取
    35         //response.setHeader("Content-Type","text/html;charset=utf-8");
    36 
    37         //也可以用如下api
    38         //response.setContentType("text/html;charset=utf-8");
    39         //response.getWriter().write("我是英文");
    40     }
    41 
    42     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    43         doPost(request, response);
    44     }
    45 }

    字节流发送数据

    使用字节流发送数据使用ServletOutputStream的write方法,使用发现在不设置任何编码格式的情况下,浏览器能正常显示中文,并没有乱码产生,通过查看响应头发现也没有指定Content-Type。

    这是因为用getByte方法得到字节数组时,使用的是平台默认的字符集,即GBK,而当不指定浏览器解码字符集时也是使用平台默认的字符集GBK,两者一致因此没有产生乱码。

    一般浏览器会使用utf-8来解码,因此需要使用如下代码指定浏览器的解码字符集,以及服务器的编码字符集均为utf-8。

    1 response.setHeader("Content-Type","text/html;charset=utf-8");
    2 response.getOutputStream().write("中国".getBytes("utf-8"))

    修改后发现响应头里有指定Content-Type。

    字符流发送数据

    使用字符流发送数据使用PrintWriter的write方法,在不设置字符集的情况下,发现'我是英文'四个字显示四个问号,产生了乱码问题。

    这是因为字符流本质上还是会转化为字节流,当服务器不指定字符编码时,会默认使用tomcat的字符编码,即iso-8859-1,而浏览器不指定解码时默认使用GBK,因此会产生乱码,另外iso-8859-1是单字节编码无法表示中文,'我是英文'最后返回给浏览器3f 3f 3f 3f,显示四个问号。

    想要解决乱码问题也是通过统一编码方式,服务端使用setCharacterEncoding的方法指定,浏览器字符集有两种方法指定,两种都可以,本质上就是设置响应头里的Content-Type。

    1 //默认使用iso-8859-1将字符流转变成字节流,底层由Tomcat服务器来完成,会使用Tomcat默认的字符集
    2 //通知服务端发送数据时字符集utf-8
    3 //response.setCharacterEncoding("utf-8");
    4 //如果告诉浏览器使用何种字符集,则这句可以不用写,服务会在发送数据自动采用浏览器设置的字符集
    5 //通知浏览器指定utf-8读取
    6 //response.setHeader("Content-Type","text/html;charset=utf-8");
    7  
    8 //也可以用如下api
    9 //response.setContentType("text/html;charset=utf-8");

    修改后浏览器能正常显示中文。

     
    参考博文:
    (2)https://www.jianshu.com/p/da01a20a515e 分块编码Transfer-Encoding
    (5)https://www.jianshu.com/p/53fbd4d91a31 utf-8,gbk2312,iso-8859-1字符集
     
  • 相关阅读:
    海量数据处理
    mysql数据导出
    手机归属地
    如何正确合理的建立MYSQL数据库索引
    Java 复杂excel报表导出
    NullpointerException真的一定要被预防?
    代码传递信息方式的探究
    ThreadLoacl的反思
    Codis分布式锁
    spring mvc:事务引起的try/catch失效
  • 原文地址:https://www.cnblogs.com/youngchaolin/p/11533181.html
Copyright © 2020-2023  润新知