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.mzph.cn/news/784721.shtml

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

相关文章

Redis超好用可视化工具--RedisInsight工具安装

RedisInsight 保姆级安装 RedisInsight 是Redis官方出品的可视化redis管理工具&#xff0c;具有很强大的功能。接下来&#xff0c;让我们一起去完成这款炫酷工具的安装 1. RedisInsight 下载 RedisInsight 官方下载地址&#xff0c;https://redis.io/docs/connect/insight/ …

springboot在线学习做题答题统计系统-可视化分析系统

系统阐述的是使用可视化的学习系统的设计与实现&#xff0c;对于java、B/S结构、MySql进行了较为深入的学习与应用。主要针对系统的设计&#xff0c;描述&#xff0c;实现和分析与测试方面来表明开发的过程。开发中使用了 springboot框架和MySql数据库技术搭建系统的整体架构。…

CleanMyMac X2024专业免费的国产Mac笔记本清理软件

非常高兴有机会向大家介绍CleanMyMac X 2024这款专业的Mac清理软件。它以其强大的清理能力、系统优化效果、出色的用户体验以及高度的安全性&#xff0c;在Mac清理软件市场中独树一帜。 CleanMyMac X2024全新版下载如下: https://wm.makeding.com/iclk/?zoneid49983 一、主要…

挖一挖:PostgreSQL Java里的double类型存储到varchar精度丢失问题

前言 大概故事是这样的&#xff0c;PostgreSQL数据库&#xff0c;表结构&#xff1a; create table t1(a varchar);然后使用标准的Java jdbc去插入数据&#xff0c;其基本代码如下&#xff1a; import java.sql.*; public class PgDoubleTest {public static void main(Stri…

C语言TCP服务器模型 : select + 多线程与双循环单线程阻塞服务器的比较

观察到的实验现象: 启动三个客户端: 使用双循环阻塞服务器:只能accept后等待收发,同时只能与一个客户端建立连接,必须等已连接的客户端多次收发 明确断开后才能与下个客户端连接 使用IO多路复用select:可以同时接收所有的连接请求,并且连接状态一直是存活的,直到客户端关闭连…

53 v-bind 和 v-model 的实现和区别

前言 这个主要的来源是 偶尔的情况下 出现的问题 就比如是 el-select 中选择组件之后, 视图不回显, 然后 model 不更新等等 这个 其实就是 vue 中 视图 -> 模型 的数据同步, 我们通常意义上的处理一般是通过 模型 -> 数据 的数据同步, 比如 我们代码里面更新了 model.…

C#/.NET/.NET Core优秀项目和框架2024年3月简报

前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架&#xff08;每周至少会推荐两个优秀的项目和框架当然节假日除外&#xff09;&#xff0c;公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等&#xff08;打不开或者打开GitHub很慢的同学…

变更控制、变更类型

目录 1、变更控制 2、变更类型 1、变更控制 在软件开发过程中会有许多变更&#xff0c;如代码、配置、SQL、基线、构建版本、发布版本等变更。对于变更都要有一个控制机制&#xff0c;以保证所以变更都是可控的、可跟踪的、可重现的。对变更进行控制的机构称为变更控制委员会…

爬虫(Web Crawler)介绍与应用

## 摘要 本文将介绍什么是爬虫&#xff08;Web Crawler&#xff09;以及其在信息抓取、数据分析等领域的应用。我们将深入探讨爬虫的工作原理、设计特点以及开发过程中需要考虑的关键问题。 ## 一、什么是爬虫 爬虫是一种自动化程序或脚本&#xff0c;用于从互联网上抓取信息…

[HackMyVM]靶场Pipy

难度:easy kali:192.168.56.104 靶机:192.168.56.141 端口扫描 ┌──(root㉿kali2)-[~/Desktop] └─# nmap 192.168.56.141 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-31 20:10 CST Nmap scan report for 192.168.56.141 Host is up (0.00…

Vitepress部署到GitHub Pages,工作流

效果&#xff1a; 第一步&#xff1a; 部署 VitePress 站点 | VitePress 执行 npm run docs:build&#xff0c;npm run docs:preview&#xff0c;生成dist文件 第二步&#xff1a; 手动创建.gitignore文件&#xff1a; node_modules .DS_Store dist-ssr cache .cache .temp *…

Python100个库分享第5个—fuzzywuzzy

目录 专栏导读库介绍安装fuzz模块用法1&#xff1a;简单匹配&#xff08;Ratio&#xff09;fuzz模块用法2&#xff1a;推荐使用—非完全匹配&#xff08;Partial Ratio&#xff09;fuzz模块用法3&#xff1a;Token Sort Ratio&#xff09;process模块extract提取多条数据extrac…

55 npm run serve 和 npm run build 的分包策略

前言 这里我们来看一下 vue 这边 打包的时候的一些 拆分包的一些策略 我们经常会使用到 npm run build 进行服务的打包 然后 打包出来的情况, 可能如下, 可以看到 chunk-vendors 是进行了包的拆分, 我们这里就是 来看一下 这里 npm run build 的时候的, 一个分包的策略 测试…

Verilog基础【一】

文章目录 1.1 第一个verilog设计1.2 Verilog 简介1.3 Verilog环境搭建1.4 Verilog 设计方法设计方法设计流程 2.1 Verilog 基础语法格式注释标识符与关键字 2.2 Verilog 数值表示数值种类整数数值表示方法实数表示方法十进制&#xff1a;科学计数法&#xff1a; 字符串表示方法…

ubuntu23.10配置RUST开发环境

系统版本: gcc版本 下载rustup安装脚本: curl --proto https --tlsv1.2 https://sh.rustup.rs -sSf | sh下载完成后会自动执行 选择默认安装选项 添加cargo安装目录到环境变量 vim ~/.bashrc 默认已添加 使用环境变量立即生效 source ~/.bashrc 执行rust开发环境,在终端输入…

使用Pilotfish扩展Sui执行能力

Pilotfish第一个多机智能合约执行引擎&#xff0c;使Sui网络的验证节点可以利用多台机器&#xff0c;并在负载增加时自动扩展以执行更多的交易。这一目标实现不会影响可靠性或功能完整性。 Pilotfish可以从内部执行机器的故障中恢复&#xff0c;并支持Sui的全面动态操作。其流…

表白墙项目(JAVA实现)

1、在html里 class使用. id使用# 2、记得引入响应依赖&#xff08;举例lombok&#xff09; 3、messageController package com.example.demo.demos.web; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; i…

Springboot集成knife4j (swagger)

1、添加依赖 在pom.xml 文件中添加 knife4j-spring-boot-starter 的依赖 <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>3.0.3</version> </depe…

【千帆杯】K12教育常规赛 北京场线下交流会心得

千帆杯K12教育常规赛 北京场线下交流会心得 ​ 周日有幸参加了 百度智能云千帆AppBuilder北京场线下交流会 ( 活动链接 )&#xff0c;去线下组队创作了 K12教育 相关的智能体。参赛过程中认识了不少大佬与朋友&#xff0c;抱大佬队友的腿&#xff0c;他的 猜成语 应用获得了线…

【OS探秘】【虚拟化】【软件开发】VirtualBox 虚拟化软件卸载和重装

往期OS系列博文&#xff1a; 【OS探秘】【虚拟化】【软件开发】在Windows 11上安装mac OS虚拟机 【OS探秘】【虚拟化】【软件开发】在Windows 11上安装Kali Linux虚拟机 一、事出有因 近日&#xff0c;笔者的Oracle VM VirtualBox突然抽风了&#xff0c;虚拟机无法启动&…