Servlet 中文乱码问题解析及详细解决方法
使用 servlet 向客户端浏览器回送中文时,经常出现中文乱码的问题,这里给大家完完全全地搞明白:
一、基本常识
中文系统默认是 GBK 编码(GBK是对GB2312的补充,包含它)
需要处理编码问题的地方:
- 浏览器发送请求(Request)时,所用的编码格式;
- Web 服务器响应(Response)回送的数据,所用的编码格式;
- 浏览器解析响应回送的数据,所用的编码格式;
- 又分为两种情况:
- 请求发生乱码往往是 servlet 程序获取请求信息时,获取的信息乱码,问题产生在服务端;
- 而客户端浏览器出现,往往是2、3两处的编码格式不一造成的;
查看平台默认字符编码方法:java.nio.charset.Charset.defaultCharset();
HttpServletResponse 类中的 getOutputStream() 获取的字节节流,用于向浏览器输出二进制数据(图片、视频等任何形式数据);而 getWriter() 获取的是字符输出流,用于输出文本数据,二者不能同时使用;
getBytes() 方法通过平台默认字符集进行编码,可传传递参数指定字符集(如 getBytes("UTF-8"))
二、了解编码的过程
以我们要解决的问题角度出发:编码是将文字按照一种规范转变成另一种形式的过程;而解码,是编码的逆过程;这中间的依据也就是那个规范,就是字符集(编码表,如 UTF-8、GBK)。
编码时,程序从字符集中寻找字符在此字符集里的一个"编号"(往往是一种更利于计算机使用字符);这些编号组成的数据,无论传递到什么平台,最后接收数据的平台使用,同一字符集进行解码,就能获取到原本的数据,过程:用接收到的编码数据,从字符集中寻找对应表示的字符进行还原,最终数据的完美传递。
三、解决乱码问题
Request 乱码
从浏览器发起的访问方式有三种:
- 在地址栏直接输入URL访问:浏览器默认将请求参数按 UTF-8 进行编码,
- 点击超链接访问:浏览器将参数按照当前页面的显示编码进行编码
- 提交表单访问:同上
网上常用的设置表单的方法:request.setCharacterEncoding("UTF-8")只对 POST 请求方式有效,所以解决请求乱码要针对两个情况:
GET 方式
get请求乱码解决办法一:修改服务器端对URI参数的默认编码
get请求乱码办法一:修改服务器端对URI参数的默认编码
在tomcat的server.xml中,设置元素的属性URIEncoding=”UTF-8”即可。(默认没有设置此属性)
扩展:
1.设置元素的属性useBodyEncodingForURI=“true”,意思是请求体和uri使用相同的编码格式。
通过设置这两个属性,既可以解决get方式的乱码,又可以解决post方式的乱码。
2.通过修改server.xml指定服务器对get和post统一按照utf-8解码,要求tomcat管理下的所有web应用都要使用utf-8编码,即所有的jsp、html页面都必须使用utf-8编码。
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"
URIEncoding="UTF-8" useBodyEncodingForURI="true"/>
get请求乱码办法二:逆向操作
参数从浏览器到服务器,经过客户端编码,服务器端解码,最终成为乱码。那我们将乱码进行相反的编解码,即可得到正常的参数值。此时注意上文提到的编码规律总结,只有源头对了,才能成功解决问题。
String name = request.getParameter("name");//得到乱码的数据
name = new String(name.getBytes("GBK"),"utf-8");
//将得到的数据进行GBK方式解码,然后把得到的字节再通过UTF-8编码,得到正常的name值
get请求乱码方法三:手动编码解码
在JSP页面中先把中文编码后再提交,服务器获取后再按照同样的方式解码
//场景:从网页下载,文件名为中文
...
String filePath = "D:\\javacode\\javaweb_Servlet2\\response\\src\\main\\webapp\\哈哈11.xml";
// 通过一些方法,从路径中提取出 文件名:
//通过获取最后一个 / 的脚标 + 1 确定文件名的第一个字符索引,而后从此索引开始截取字符串,就是文件名
String fileName = filePath.substring(filePath.lastIndexOf("\\") + 1);
//URLEncoder.encode() 方法设置以指定字符集对文件名进行编码
resp.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(fileName,"utf-8"));
...
POST 方式
post方式提交的参数存在于请求体中,浏览器将参数按照当前页面的显示编码进行编码页面的编码方式一般情况下已经被设置成了UTF-8,只需要修改服务端解码方式(与浏览器页面编码方式一致) ```java
request.setCharacterEncoding(“UTF-8”);
Response 乱码
实际遇到更多的乱码情况是浏览器接收响应数据的乱码,我们需要了解发生乱码的流程:

首先 getBytes() 以 UTF-8 字符集对字符串进行编码,并写入响应对象,响应数据回送至浏览器,浏览器默认使用平台默认编码(中文系统)进行解码,用 GB 码表解码 UTF-8 的编码的数据,结果就是出现乱码。
所以我们要做的使:响应所回送数据所用字符集 和 浏览器用来解析回送数据所用字符集相同
设置浏览器的解码格式:
response.setHeader("content-type","text/html;charset=UTF-8");
//或
response.setContentType("text/html;charset=utf-8");
大白话说就是用 content-type 响应头,告诉浏览器我回送过来的数据时 text/html 类型,要用 UTF-8 字符集解码;
设置好浏览器用于解析响应回送数据的字符集后,现在要设置响应回送的数据字符集,分为两种情况,也就是最开始提到的,处理字节和字符流数据是有差异的:
- 使用 response.getWriter() 流写出的的数据乱码解决方式:
//设置将发送到客户端的响应 的字符编码,只能用于设置 getWritet()的字符编码
response.setCharactEncoding("UTF-8");
//同时设置浏览器的解码方式
response.setHeader("content-type","text/html;charset=UTF-8");
需要在调用 getWriter() 方法前 和 响应提交前使用
- 使用 response.getOutputStream() 流写出的数据乱码解决方式:
//服务端对字符进行编码的时候,指定编码方式
response.getOutputStream().write("汉字".getBytes("UTF-8"));
//同时设置浏览器的解码方式
response.setHeader("content-type","text/html;charset=UTF-8");
字符响应流只用用来输出字符,而字节响应流可以用来输出任何东西
四、扩展:
- 查看当前响应头所设置的字符编码(没有获取到字符集类型说明是默认的):response.getContentType()
- 可使用 response.writer().print() 传递 HTML 标签代码间接设置网页的编码格式,如:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//直接向网页输出 HTML 标签代码
response.getWriter().println("<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>");
}
- 为了避免可能的失误,直接将设置编码相关代码放在最前面(无论是后端还是前端)
参考:response与request中文乱码问题及解决方式 Servlet 中文乱码问题及解决方案剖析
Servlet 中文乱码问题解析及详细解决方法的更多相关文章
- php -- 解决php连接sqlserver2005中文乱码问题(附详细解决方法)
@_@~~ --php5.2 --phpstudy --apache --sqlserver2005 @_@~~问题描述 问题一:php连接sqlsever2005,输入中文,然后查询sqlserve ...
- Code:Blocks 中文乱码问题原因分析和解决方法
下面说说修改的地方. 1.修改源文件保存编码在:settings->Editor->gernal settings 看到右边的Encoding group Box了吗?如下图所示: Use ...
- JSP中文乱码问题的由来以及解决方法
首先明确一点,在计算机中,只有二进制的数据! 一.java_web乱码问题的由来 1.字符集 1.1 ASCII字符集 在早期的计算机系统中,使用的字符非常少,这些字符包括26个英文字母.数字符号和一 ...
- Python BeautifulSoup中文乱码问题的2种解决方法
解决方法一: 使用python的BeautifulSoup来抓取网页然后输出网页标题,但是输出的总是乱码,找了好久找到解决办法,下面分享给大家首先是代码 from bs4 import Beautif ...
- XFTP连接主机文件名显示中文乱码且不能下载的解决方法
Xftp连接主机文件名显示中文乱码且不能下载的本地解决方法 原因:Xftp编码格式问题 解决方法:把Xftp的编码格式增加UTF-8 具体步骤:打开Xftp,文件-属性,在打开的属性界面中打开&quo ...
- Tomcat中文乱码问题的原理和解决方法
1) 更改 D:\Tomcat\conf\server.xml,指定浏览器的编码格式为“简体中文”: 方法是找到 server.xml 中的 <Connector port="8080 ...
- 对于使用了SSH造成的中文乱码问题,4大解决方法
修改struts2.xml struts2.xml 中添加 <constant name="struts.i18n.encoding" value="UTF-8&q ...
- jsp和servlet中文乱码
jsp和servlet之间出现中文乱码的集中原因和解决方法详解:http://blog.csdn.net/longyuhome/article/details/7856270
- 中文乱码在java中URLEncoder.encode方法要调用两次解决
中文乱码在java中URLEncoder.encode方法要调用两次解决 一.场景: 1.我在客户端要通过get方式调用服务器端的url,将中文参数做utf-8编码,需要在js中两次的进行编码,服务器 ...
随机推荐
- 基于微信小程序的租房小程序
乐直租全国租房小程序前端 房源分钟上传,可快捷联系房东的小程序. 该小程序操作简单,布局清新,欢迎 start ~ 传送门:Github 扫码体验: pages: 首页 index 选择发布页 bef ...
- Python模块三
collections模块 在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.defaultdict. ...
- WINDOWS上JDK安装与环境变量设置
一.JDK安装 jdk版本:jdk1.8.0_144 下载链接:https://pan.baidu.com/s/1eS2bFhg 密码:e3q1 下载JDK后点击安装,可以根据需要修改JDK的安装目录 ...
- lesson01
题目: Action3: 统计全班的成绩 班里有5名同学,现在需要你用numpy来统计下这些人在语文.英语.数学中的平均成绩.最小成绩.最大成绩.方差.标准差.然后把这些人的总成绩排序,得出名次进行 ...
- node 微信授权 获取openid
node获取微信授权拿到openid 需要了解的网站 1.微信授权. 先说一下流程(一张图代替所有): 流程步骤: 1.用户同意,获取code. 2.通过code获取网页授权access_toke ...
- linux入门系列18--Web服务之Apache服务2
接上一篇文章,在了解Apache基本配置以及SELinux相关知识后,继续演示Apache提供的虚拟主机功能以及访问控制方式. 如果还没看上一篇的建议先查看后再来,上篇文章"linux入门系 ...
- 欢乐C++ —— 2. 深复制与浅复制
1. 简述 通俗点讲,深复制与浅复制一般对指针而言, 深复制复制指针所指向的内容, 浅复制复制指针的值. 2. 举例 栗子: 当我们有现在有指针A指向一块数据,和指针B. 深复制- ...
- VIM不正常退出产生的swp文件
VIM不正常退出产生的swp文件 当你非正常关闭vim编辑器时(比如直接关闭终端或者电脑断电),会生成一个.swp文件,这个文件是一个临时交换文件,用来备份缓冲区中的内容. 第一次产生的交换文件名为“ ...
- sweep line-The Skyline Problem
2020-01-10 17:51:05 问题描述: 问题求解: 本题是经典的sweep line问题. 对于sweep line问题我们需要考虑的只有两点: 1. 延水平方向 / 时间方向 :时间队列 ...
- 使用SparkSQL编写wordCount的词频统计
# 使用SparkSQL编写wordCount的词频统计 ## word.txt```hello hello scala sparkjava sql html java hellojack jack ...