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:nginx服务器类型

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 2018 17:20:51 GMT 与请求头的if modified头呼应,主要跟缓存有关

8 Refresh: 1;url=http://www.sdedu.org 定时刷新

9 Content-Disposition: attachment;filename=ab.zip 跟下载有关,下载文件名字ab.zip

10 Set-Cookie:SS=Q0=5Lb_nQ; path=/search

11 Expires: -1 通知浏览器是否缓存当前资源,如果这个头的值是一个以毫秒为单位的值,就是通知浏览器缓存资源到指定的时间点,如果值是0或-1则是通知浏览器禁止缓存。

12 Cache-Control: no-cache 通知浏览器是否缓存的头,no-cache代表不缓存

max-age=0和no-cache的区别:no-cache强制直接向源服务器请求不经过缓存服务器,而max-age=0需要经过缓存服务器。等于0时,缓存服务器需要将请求转发给源服务器。

13 Connection: close/Keep-Alive 连接状态

14 Date:  Sat, 30 Mar 2024 14:40:10 GMT   Date可以用来判断是否来自缓存

Response的方法,就是针对响应内容进行的,它可以设置状态码、设置响应头,设置响应内容。

二、response常用方法 

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

1、设置状态码

设置状态码有如下API

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

代码实现:

/**
 * 设置状态码
 */
@WebServlet("/ResponseDemo01")
public class ResponseDemo01 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置404
        response.setStatus(404);
        response.getWriter().write("Hello Status");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

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

2、设置响应头

设置影响头的方法,可以影响到页面的效果,有时候需要和上面设置状态码的方法配合使用,它常用的方法:

(1)void setHeader(String name, String value)  用给定名称和值设置响应头。如果已经设置了头,则新值将重写以前的值。

(2)void setIntHeader(String name, int value) 此方法的默认行为是对包装的响应对象调用 addIntHeader(String name, int value)。 

下面简单了解一下setIntHeader方法,这个方法可以用在设置页面刷新频率,设置发送数据的长度等。

代码实现:

/**
 * 设置使用setIntHeader方法
 */
@WebServlet("/ResponseDemo02")
public class ResponseDemo02 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置刷新
        /* response.setIntHeader("Refresh",5);
        response.getWriter().write("<font color='blue' size='10px'>this is setIntHeader method"+"+"+Math.random()*100+"</font>");*/
        //设置发送数据长度,一个英文字符代表1个长度
        response.setIntHeader("Content-Length",8);
        response.getWriter().write("Hello World");

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

实际效果,会每隔5秒刷新一次页面

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

3、设置响应消息

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

(1)ServletOutputStream getOutputStream() 

(2)PrintWriter getWriter()  

上文中的response.getWriter().write("Hello Status"),就使用了PrintWriter。

三、response常用功能

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

请求重定向
1、请求重定向

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

/**
 * 请求重定向
 */
@WebServlet("/ResponseDemo03")
public class ResponseDemo03 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //原理实现
        //设置状态码
        response.setStatus(302);
        //设置消息头
        response.setHeader("Location","http://www.baidu.com");

        //api实现
        //以上代码等效如下代码
        //response.sendRedirect("http://www.baidu.com");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

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

2、控制缓存

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

/**
 * 浏览器缓存的设置
 */
@WebServlet("/ResponseDemo04")
public class ResponseDemo04 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置不使用缓存
        /*public void setDateHeader(String name, long date)
        用给定名称和日期值设置响应头。该日期根据距历元时间的毫秒数指定。如果已经设置了头,则新值将重写以前的值。
        containsHeader 方法可用于测试在设置其值之前头是否存在。*/
        //方式1
        if(response.containsHeader("Expires")){
            response.setDateHeader("Expires",-1);
        }
        //方式2
        response.setHeader("Cache-Control","no-cache");
        //方式3
        response.setHeader("Pragma","no-cache");

        Date date=new Date();
        String time = date.toLocaleString();
        //设置使用缓存
        //response.setDateHeader("Expires",System.currentTimeMillis()+1000*60*60*1);//1 hour
        //response.setHeader("Cache-Control","max-age=60");//60 s

        response.getWriter().write("<font color='blue'>"+time+"</font>");


    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

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

3、页面刷新 

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


/**
 * 定时刷新
 */
@WebServlet("/ResponseDemo05")
public class ResponseDemo05 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //3 秒后 刷新进入百度主页
        response.setHeader("Refresh","3;url=http://www.baidu.com");
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

四、response乱码处理

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

/**
 * 响应字节流和字符流的乱码处理
 */
@WebServlet("/ResponseDemo06")
public class ResponseDemo06 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1 字节流
        System.out.println(response.getCharacterEncoding());
        //ISO-8859-1 tomcat默认的字符编码,针对字符流,对字节流无影响
        //response.getOutputStream().write("china".getBytes());
        //getByte()默认使用平台的字符编码,即GBK,而浏览器默认使用GBK解码,因此没有乱码
        //response.getOutputStream().write("中国".getBytes());
        /**
         * 一般浏览器都会设置utf-8解码,这里需指定服务器编码方式为utf-8,设置浏览器解码也是utf-8
         */
        //通知浏览器使用utf-8来解码
        response.setHeader("Content-Type","text/html;charset=utf-8");
        response.getOutputStream().write("中国".getBytes("utf-8"));

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

        //也可以用如下api
        //response.setContentType("text/html;charset=utf-8");
        //response.getWriter().write("我是英文");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
1、字节流发送数据

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

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

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

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

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

2、字符流发送数据

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

 这是因为字符流本质上还是会转化为字节流,当服务器不指定字符编码时,会默认使用tomcat的字符编码,即ISO-8859-1,而浏览器不指定解码时默认使用GBK,因此会产生乱码,另外ISO-8859-1是单字节编码无法表示中文。

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

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

//也可以用如下api
response.setContentType("text/html;charset=utf-8");

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/504744.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

红黑树介绍及插入操作的实现

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

node.js的错误处理

当我打开一个不存在的文件时&#xff0c;错误如下&#xff1a; 在读取文件里面写入console.log&#xff08;err&#xff09;&#xff0c;在控制台中可以看到我的错误代码类型&#xff1a;文件不存在的错误代码 ENOENT。见更多错误代码---打开node.js官方API文档Error 错误 | N…

高炉项目中DeviceNET到Ethernet的转换奥秘

在工业自动化的世界中&#xff0c;高炉项目中的数据通信至关重要。其中DeviceNET和Ethernet作为两种主流的网络协议&#xff0c;扮演着不可或缺的角色。它们之间的转换不仅仅是技术上的桥梁&#xff0c;更是实现信息高效传递的关键。今天&#xff0c;我们就来揭开从DeviceNET到…

每日面经分享(pytest入门)

1. pytest具有什么功能 a. 自动发现和执行测试用例&#xff1a;pytest可以自动发现项目中的测试文件和测试函数&#xff0c;无需手动编写测试套件或测试运行器。 b. 丰富的断言函数&#xff1a;pytest提供了丰富的断言函数&#xff0c;方便地验证测试结果是否符合预期。断言函…

【STM32 HAL库SPI/QSPI协议学习,基于外部Flash读取】

1、SPI协议 简介 SPI 协议是由摩托罗拉公司提出的通讯协议 (Serial Peripheral Interface)&#xff0c;即串行外围设备接口&#xff0c;是一种高速全双工的通信总线。它被广泛地使用在 ADC、LCD 等设备与 MCU 间&#xff0c;要求通讯速率较高的场合。 通信方式&#xff1a;同…

基于SpringBoot+Vue交通管理在线服务系统的开发(源码+部署说明+演示视频+源码介绍+lw)

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…

Docker搭建LNMP环境实战(10):大结局!脚本化一次性安装测试、生产环境

实现使用 Docker 在一台服务器上搭建支持 80、443 端口访问的测试、生产双站点系统。 1、生产环境&测试环境的规划和部署 1.1、说明 图1 系统部署示意图 1&#xff09;项目 此处以一个演示项目的形式来进行环境的规划和部署。此项目名称默认定义为&#xff1a;“demo”&a…

网安学习笔记-day11,FTP服务器

FTP服务器 FTP介绍 FTP(File Transfer Protocol)文件传输协议 端口号&#xff1a;TCP 20/21 工作方式&#xff1a; 主动模式被动模式 服务器部署 准备阶段 配置IP windowsXP 192.168.1.21&#xff08;也可DHCP自动获取&#xff09; Windows2003 192.168.1.1 安装万维网…

[SWPUCTF 2021 新生赛]crypto5(小明文攻击)

题目&#xff1a; 直接暴力破解&#xff1a; from Cryptodome.Util.number import * import gmpy2 flag 251667516535309413648396638468065433877208653392633709079856557751521873194647157371165991714772070474300653458826262598807568390941796270326238953302426553…

Mybatis-Plus分页查询时碰到`total`有值但`records`为空

个人原因&#xff1a;Mybatis-Plus分页插件设置了maxLimit单页条数 // 分页插件配置 PaginationInnerInterceptor paginationInnerInterceptor new PaginationInnerInterceptor(DbType.MYSQL); paginationInnerInterceptor.setMaxLimit(200L); // 单页分页条数限制(默认无限…

Mysql重点思考(上)--mysql的索引优化

mysql的索引优化 expalin关键字的用法explain索引优化示例 type列用法执行查询的顺序类型概述 索引概念索引的定义索引的分类主键&唯一区别 唯一索引的创建和查询创建一个唯一索引查询一个唯一索引 场景题合集唯一索引的场景题主键索引的场景题&#xff08;B树&#xff09;…

Python下载bing每日壁纸并实现win11 壁纸自动切换

前言: 爬虫哪家强,当然是python 我是属于啥语言都用,都懂点,不精通,实际工作中能能够顶上就可以。去年写的抓取bing每日的壁纸&#xff0c;保存到本地&#xff0c;并上传到阿里云oss&#xff0c;如果只是本地壁纸切换&#xff0c;存下来就行&#xff0c;一直想做个壁纸站点&…

第四篇:3.3 无效流量(Invalid traffic) - IAB/MRC及《增强现实广告效果测量指南1.0》

翻译计划 第一篇概述—IAB与MRC及《增强现实广告效果测量指南》之目录、适用范围及术语第二篇广告效果测量定义和其他矩阵之- 3.1 广告印象&#xff08;AD Impression&#xff09;第三篇广告效果测量定义和其他矩阵之- 3.2 可见性 &#xff08;Viewability&#xff09;第四篇广…

火力发电必备:DeviceNET转Modbus TCP神技

在当今工业自动化领域&#xff0c;设备间的信息交流至关重要&#xff0c;其中Modbus协议由于其简单、开放和易于实施的特性&#xff0c;已经成为了事实上的行业标准。然而&#xff0c;随着技术的发展&#xff0c;对实时性、可靠性和数据传输速度的要求越来越高&#xff0c;尤其…

【C++航海王:追寻罗杰的编程之路】priority_queue(优先队列) | 容器适配器你知道哪些?

目录 1 -> priority_queue的介绍和使用 1.1 -> priority_queue的介绍 1.2 -> priority_queue的使用 1.3 -> priority_queue的模拟实现 2 -> 容器适配器 2.1 -> 什么是适配器 2.2 -> STL标准库中stack和queue的底层结构 2.3 -> deque的介绍 2.…

Error: Cannot find module ‘@rollup/rollup-win32-x64-msvc‘

1.背景 新项目需要使用vite搭建一个v3项目,之前也弄过,但项目创建后却一直无法跑起来,大聪明的我一直没有注意到这个问题 2.解决步骤 方案1:删除node_modules和package-lock.json文件重新npm install下包,部分码农通过这个步骤可解决 方案2:node版本或者npm版本不对,或者没…

android WMS服务

android WMS服务 WMS的定义 窗口的分类 WMS的启动 WindowManager Activity、Window、DecorView、ViewRootImpl 之间的关系 WindowToken WMS的定义 WMS是WindowManagerService的简称&#xff0c;它是android系统的核心服务之一&#xff0c;它在android的显示功能中扮演着…

作业9:编程练习

1.喝汽水问题 int Func(int money) {int total money;int empty money;while (empty > 1){total total empty / 2;empty empty / 2 empty % 2;}return total; } 2.打印菱形 将菱形看作三部分打印&#xff1a;上三角&#xff0c;中间&#xff0c;下三角 分别列出每一行…

http模块 设置资源类型(mime类型)

虽然浏览器自带websocket功能它会根据响应回来的内容自动去判断资源类型&#xff0c;但是我们加上了mime类型判断代码会更加规范些 一、mime类型概念&#xff1a; 媒体类型是一种标准&#xff0c;它用来表示文档。文件、字节流的性质和格式。HTTP服务可以设置响应头Content-T…

安装VS2022社区版

Visual Studio 2022 平台的使用 1.Visual Studio 的下载地址&#xff1a; https://visualstudio.microsoft.com/zh-hans/downloads/ 2.安装步骤简要记录 耐心等待安装完成 参考链接&#xff1a;Visual Studio 2022安装教程(非常详细)&#xff0c;从零基础入门到精通&…