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 {//设置404response.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 方法可用于测试在设置其值之前头是否存在。*///方式1if(response.containsHeader("Expires")){response.setDateHeader("Expires",-1);}//方式2response.setHeader("Cache-Control","no-cache");//方式3response.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 sresponse.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");

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ruby 之交租阶段信息生成

题目 我看了一下&#xff0c;这个题目应该不是什么机密&#xff0c;所以先放上来了。大概意思是根据合同信息生成交租阶段信息。 解答 要求是要使用 Ruby 生成交租阶段信息&#xff0c;由于时间比较仓促&#xff0c;变量名那些就用得随意了些。要点主要有下面这些&#xff1a…

Redission--布隆过滤器解决缓存穿透问题

布隆过滤器在缓存穿透问题中的使用 布隆过滤器的核心是一个位数组 布隆过滤器的误判 使用Redission的布隆过滤器步骤 添加 Redission 依赖&#xff1a;首先需要将 Redission 添加到你的 Java 项目中&#xff0c;你可以通过 Maven 来添加 Redission 的依赖。 创建 Redissio…

机器学习全攻略:概念、流程、分类与行业应用案例集锦

目录 1.引言 2.从零开始认识机器学习&#xff1a;基本概念与重要术语 3.五步走&#xff1a;掌握机器学习项目执行的完整流程 3.1.问题定义与数据收集 3.2.数据预处理与特征工程 3.3.模型选择与训练 3.4.模型评估与优化 3.5.模型部署与监控 4.深入了解各类机器学习方法…

LeetCode-146. LRU 缓存【设计 哈希表 链表 双向链表】

LeetCode-146. LRU 缓存【设计 哈希表 链表 双向链表】 题目描述&#xff1a;解题思路一&#xff1a;双向链表&#xff0c;函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。一张图&#xff1a;知识点__slots__ 解题思路二&#xff1a;0解题思路三&#xff1a;0 题目描述&am…

使用 Flume 将 CSV 数据导入 Kafka:实现实时数据流

使用 Flume 将 CSV 数据导入 Kafka&#xff1a;实现实时数据流 文介绍了如何使用 Apache Flume 将 CSV 格式的数据从本地文件系统导入到 Apache Kafka 中&#xff0c;以实现实时数据流处理。通过 Flume 的配置和操作步骤&#xff0c;我们可以轻松地将数据从 CSV 文件中读取并发…

医院云HIS系统源码,二级医院、专科医院his系统源码,经扩展后能够应用于医联体/医共体

基于云计算技术的B/S架构的HIS系统&#xff0c;为医疗机构提供标准化的、信息化的、可共享的医疗信息管理系统&#xff0c;实现医患事务管理和临床诊疗管理等标准医疗管理信息系统的功能。 系统利用云计算平台的技术优势&#xff0c;建立统一的云HIS、云病历、云LIS&#xff0…

设计模式12--组合模式

定义 案例一 案例二 优缺点

【ESP32S3 Sense接入语音识别+MiniMax模型+TTS模块语音播报】

【ESP32S3 Sense接入语音识别MiniMax模型TTS模块语音播报】 1. 前言2. 功能模块概述2.1 语音接入2.2 大模型接入2.3 TTS模块接入 3. 先决条件3.1 环境配置3.2 所需零件3.3 硬件连接步骤 4. 核心代码4.1 源码分享4.2 代码解析 5. 上传验证5.1 对话测试5.2 报错 6. 总结 1. 前言 …

【 书生·浦语大模型实战营】学习笔记(一):全链路开源体系介绍

&#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方向综述、论文等成体系的学习资料&#xff0c;配有全面而有深度的专栏内容&#xff0c;包括不限于 前沿论文解读、…

我的2024java实习投递历程

每天投递一个简历吧&#xff0c;我tm投投投投投投投 3/21 周四 招商银行 招银网络科技 杭州 java实习生 4月2号笔试 笔试经验&#xff1a;45分钟 30道选择题 题目回忆版&#xff1a; 1.8进制 1-777 多少个数各位乘积为0 2.有关系R&#xff08;ABCDE&#xff09;&…

【EasyExcel】多sheet、追加列

业务-EasyExcel多sheet、追加列 背景 最近接到一个导出Excel的业务&#xff0c;需求就是多sheet&#xff0c;每个sheet导出不同结构&#xff0c;第一个sheet里面能够根据最后一列动态的追加列&#xff0c;追加多少得看运营人员传了多少需求列。原本使用的 pig4cloud 架子&…

备战蓝桥杯Day36 - 动态规划 - 三角形最小路径和问题

一、什么是动态规划 通过拆分问题&#xff0c;定义问题状态和状态之间的关系&#xff0c;使得问题能够以递推的方式解决。 哪些问题可以使用动态规划&#xff1f; 1、具有最优子结构&#xff1a;问题的最优解所包含的子结构的解也是最优的 2、具有无后效性&#xff1a;未来…

若依框架时间比较的坑(DATE_FORMAT)

背景 - 想做生日的比较 若依自带的比较 <if test"params.beginTime ! null and params.beginTime ! "><!-- 开始时间检索 -->AND date_format(u.create_time,%y%m%d) > date_format(#{params.beginTime},%y%m%d)</if><if test"params…

Linux中的shell脚本之流程控制循环遍历

3 条件判断 4 流程控制语句 1&#xff09;if 语句 案例&#xff0c;用户输入用户名和密码&#xff0c;判断用户名是否是admin,密码是否是123,如果正确&#xff0c;则显示登录成功 首先我创建了shell文件&#xff0c;touch getpawer 其中getpawer 是我自己命的名 #!/bin/bas…

C#实现只保存2天的日志文件

文章目录 业务需求代码运行效果 欢迎讨论&#xff01; 业务需求 在生产环境中&#xff0c;控制台窗口不便展示出来。 为了在生产环境中&#xff0c;完整记录控制台应用的输出&#xff0c;选择将其输出到文件中。 但是&#xff0c;存储所有输出的话会占用很多空间&#xff0c;…

03 Python进阶:MySQL - mysql-connector

mysql-connector安装 要在 Python 中使用 MySQL 数据库&#xff0c;你需要安装 MySQL 官方提供的 MySQL Connector/Python。下面是安装 MySQL Connector/Python 的步骤&#xff1a; 首先&#xff0c;确保你已经安装了 Python&#xff0c;如果没有安装&#xff0c;可以在 Python…

AR/VR技术对制造业劳动力危机的影响

借助 AR/VR 的力量缩小现代制造业的技能差距 数字化转型仍然是企业的首要任务&#xff0c;其许多方面都需要人工干预。然而&#xff0c;推动此类举措所需的技术工人日益短缺。这就造成了我们所说的“制造业劳动力危机”。 制造业应当如何&#xff1a; 制造业用工危机正在影响…

JAVAEE之Cookie/Session

1.Cookie HTTP 协议自身是属于 "无状态" 协议. "无状态" 的含义指的是: 默认情况下 HTTP 协议的客户端和服务器之间的这次通信, 和下次通信之间没有直接的联系. 但是实际开发中, 我们很多时候是需要知道请求之间的关联关系的. 例如登陆网站成功后, 第二…

Qt使用opencv,进行视频录制,功能打开、关闭摄像头,开始、结束录制视频,暂停、继续录制,并保存视频文件

1.效果图 2 代码实现 2.1 .h文件 #ifndef VIDEORECORDWIDGET_H #define VIDEORECORDWIDGET_H#include <QWidget>#include<QFileDialog>#include <QImage> #include <QLabel> #include <QTimer> #include <opencv2/opencv.hpp>using name…

面试题:JVM 调优

一、JVM 参数设置 1. tomcat 的设置 vm 参数 修改 TOMCAT_HOME/bin/catalina.sh 文件&#xff0c;如下图 JAVA_OPTS"-Xms512m -Xmx1024m" 2. springboot 项目 jar 文件启动 通常在linux系统下直接加参数启动springboot项目 nohup java -Xms512m -Xmx1024m -jar…