JSP中文乱码问题终极解决方案(上)
摘要:
本文首先介绍了一个JSP的源文件执行过程,即需要经过三个阶段,两次编码,才能完成一次完整的输出。特别需要注意的是,在这个过程中,编码问题贯穿始终。我们知道在JSP/Servlet中,主要有以下四种方式可以设置编码,即 pageEncoding、contentType、request.setCharacterEncoding 和 response.setCharacterEncoding,在本文中,我们就这四种方式进行深入的介绍和总结。
一. JSP的执行过程与编码设定概述
在JSP/Servlet中,主要有以下四种方式可以设置编码,其中前两个只能应用于JSP中,而后两个可以用于 JSP 和 Servlet 中。
- pageEncoding=”UTF-8”;
- contentType=”text/html;charset=UTF-8”;
- request.setCharacterEncoding(“UTF-8”) ;
- response.setCharacterEncoding(“UTF-8”)。
事实上,一个JSP的源文件需要经过三个阶段,两次编码,才能完成一次完整的输出,这三个阶段是:
第一阶段:转译(.jsp -> .java;pageEncoding -> UTF-8)。将jsp编译成Servlet(.java)文件,用到的指令是pageEncoding。在编译过程中,根据pageEncoding=“XXX”的指示,找到编码的规则为“XXX”,然后服务器将JSP文件编译成.java文件时会根据pageEncoding的设定读取jsp,结果是由指定的编码方案翻译成统一的UTF-8编码的JAVA源码(即.java)。
第二阶段:编译(.java -> .class;UTF-8 -> UTF-8)。从Servlet文件(.java)到Java字节码文件(.class),从UTF-8到UTF-8。在这一阶段中,不论JSP编写时候用的是什么编码方案,经过这个阶段的结果全部是UTF-8的encoding的java源码。JAVAC用UTF-8的encoding读取java源码,编译成UTF-8编码的二进制码(即.class),这是JVM对常数字串在二进制码(Java encoding)内表达的规范。这一过程是由JVM的内在规范决定的,不受外界控制。
第三阶段:编译(UTF-8 -> contentType)。从服务器到浏览器,这在一过程中用到的指令是contentType。服务器载入和执行由第二阶段生成出来JAVA二进制码,输出的结果,也就是在客户端可见到的结果,在这次输出过程中,由contentType属性中的charset来指定,将UTF8形式的二进制码以charset的编码形式来输出。如果没有人为设定,则默认的是ISO-8859-1的形式。
特别需要注意的是,pageEncoding 的默认值是 “ISO-8859-1”, contentType 的默认值是 “text/html;ISO-8859-1”。
Ps: 第一、三两个阶段的转码个人感觉联想到Sting转码更容易理解些,例如 :new String(name.getBytes(“ISO-8859-1”), “utf-8”)。
二. pageEncoding=”UTF-8”
pageEncoding=”UTF-8” 的作用是设置JSP编译成Servlet时使用的编码。通常,在JSP内部定义的字符串(直接在JSP中定义,而不是从浏览器提交的数据)出现乱码时,很多都是由于该参数设置错误引起的。例如,你的 JSP文件中含有中文字符,而在JSP中却指定pageEncoding=”iso-8859-1”,就会导致中文字符显示异常。看下面的例子:
<%@ page language="java" pageEncoding="iso-8859-1" import="java.util.*" %><html><head><title>哈哈</title></head><body>中文 <br></body>
</html>
在其编译为Servlet后,其源码(片段)如下所示:
public void _jspService(HttpServletRequest request, HttpServletResponse response)throws java.io.IOException, ServletException {// ...out.write("<html>\r\n");out.write(" <head>\r\n");out.write(" <title>哈哈</title>\r\n");out.write(" </head>\r\n");out.write(" <body>\r\n");out.write(" \t ä¸æ–‡ <br>\r\n");out.write(" </body>\r\n");out.write("</html>\r\n");// ...
访问该页面,页面显示如下:
我们可以看到,由于pageEncoding被指定为”iso-8859-1”,导致其在由服务器将JSP文件编译成.java文件过程中,在使用 “iso-8859-1” 读取jsp并翻译成统一的UTF-8编码的JAVA源码时,所有的中文字符被转成乱码,并使得其呈现给用户的响应也包含乱码。特别地,该属性还有一个功能,就是在JSP中不指定contentType参数,也不使用response.setCharacterEncoding方法时,指定对服务器响应的内容进行编码。
二. contentType=”text/html;charset=UTF-8”
contentType=”text/html;charset=UTF-8” 的作用是将上述第二阶段所生成的UTF8形式的二进制码以charset的编码形式来输出到客户端,如果设置不当的话,会出现乱码。看下面的例子:
<%@ page language="java" contentType="text/html;iso-8859-1" import="java.util.*" pageEncoding="utf-8"%><html><head><title>哇哈哈</title></head><body>哇哈哈 <br></body>
</html>
在其编译为Servlet后,其源码(片段)如下所示:
public void _jspService(HttpServletRequest request, HttpServletResponse response)throws java.io.IOException, ServletException {// ...out.write("<html>\r\n");out.write(" <head>\r\n");out.write(" <title>哇哈哈</title>\r\n");out.write(" </head>\r\n");out.write(" <body>\r\n");out.write(" \t 哇哈哈 <br>\r\n");out.write(" </body>\r\n");out.write("</html>\r\n");// ...
访问该页面,页面显示如下:
三. request.setCharacterEncoding(“UTF-8”)
request.setCharacterEncoding(“UTF-8”)用来指定对浏览器发送来的数据以特定的字符集进行重新编码,常用于对 POST 请求参数进行解码。具体见我的博文 《JSP中文乱码问题终极解决方案(下)》中 “POST 请求的请求参数为中文情形” 一节。
四. response.setCharacterEncoding(“UTF-8”)
response.setCharacterEncoding(“UTF-8”)的作用是:在服务器将响应返回到浏览器前,对响应使用指定字符集进行重新编码。一旦使用了该种方式,即使该响应页面指定了具体的 contentType,也将失效。看下面的例子:
<%@ page language="java" contentType="text/html;iso-8859-1" import="java.util.*" pageEncoding="utf-8"%><html><head><title>哇哈哈</title></head><body>哇哈哈 <br></body>
</html>
在其编译为Servlet后,其源码(片段)如下所示:
public void _jspService(HttpServletRequest request, HttpServletResponse response)throws java.io.IOException, ServletException {// ...out.write("<html>\r\n");out.write(" <head>\r\n");out.write(" <title>哇哈哈</title>\r\n");out.write(" </head>\r\n");out.write(" <body>\r\n");out.write(" \t 哇哈哈 <br>\r\n");out.write(" </body>\r\n");out.write("</html>\r\n");// ...
访问该页面,页面显示如下:
五. 四种编码设定方式之间的相互影响以及作用的优先级
根据上文内容,我们得出以下三点:
在指定JSP编译成Servlet时使用的编码时,优先级为: pageEncoding=”UTF-8” > contentType=”text/html;charset=UTF-8”
在指定服务器对响应内容的编码时,优先级为:response.setCharacterEncoding(“UTF-8”) > contentType=”text/html;charset=UTF-8” > pageEncoding=”UTF-8”
request.setCharacterEncoding(“UTF-8”) 只用来指定对浏览器发送来的请求数据的解码方式。
更多关于 JSP技术的细节见我的其他两篇博客: 《Java Web基础 — Jsp 综述(上)》 和 《Java Web基础 — Jsp 综述(下)》。
更多关于 JSP中文乱码问题的解决方案见我的另一篇博客:《 JSP中文乱码问题终极解决方案(下)》。
引用
关于JSP页面中的pageEncoding和contentType两种属性的区别
JSP里ContentType ,charset和pageEncoding的理解与区别
JSP中文乱码问题终极解决方案(上)相关推荐
- JSP中文乱码问题终极解决方案(转)
JSP中文乱码问题终极解决方案 http://www.cnblogs.com/beijiguangyong/archive/2012/03/31/2437124.html 在介绍方法之前我们首先应该清 ...
- JSP中文乱码问题终极解决方案
在介绍方法之前我们首先应该清楚具体的问题有哪些,笔者在本博客当中论述的JSP中文乱码问题有如下几个方面:页面乱码.参数乱码.表单乱码.源文件乱码.下面来逐一解决其中的乱码问题. 一.JSP页面中文乱码 ...
- vim、gvim在windows下中文乱码的终极解决方案
From: http://www.liuhuadong.com/archives/68/index.html vim.gvim在windows下中文乱码的终极解决方案 在windows下vim的中文字 ...
- Java中文jsp页面被转码了_JSP中文乱码问题终极解决方案
转载自: http://www.cnblogs.com/beijiguangyong/ http://www.cnblogs.com/beijiguangyong/archive/2012/03/31 ...
- Tomcat 中 jsp 中文乱码显示处理解决方案
JSP 中文乱码处理解决方案 初学JSP,尤其是Tomcat环境,经常会因为中文汉字字符集设置问题导致中文乱码,本文就这一问题提出解决方案,解决中文乱码问题,供各位参考,我采用的方案是统一字符集至UT ...
- gvim在windows下中文乱码的终极解决方案
打开vim的配置文件,位置在/etc/vim/vimrc 在其中加入 set encoding=utf-8 set fileencodings=utf-8,gb2312,gbk,gb18030 set ...
- python graphviz中文乱码_graphviz画决策树图中文乱码问题终极解决方案
大家在画决策树的过程中,一定非常希望能画出带有中文特征名称或类别名称的决策树.但我们直接用graphviz画图时,中文却会出现乱码.如下图所示,相信大家都遇见过:在红酒数据集中,将feature_na ...
- JSP中文乱码解决方案了解和TOMCAT中文乱码解决
java 中文乱码终极解决方案 首先,确保你的数据库是支持中文的.把数据库的编码方式设置能支持中文的,如GB2132,utf-8等,而且经过测试后确实能写入中文且正常显示.这样就就保证了数据库确实是支 ...
- jsp mysql中文乱码,jsp中文乱码 jsp mysql 乱码的解决方法
jsp中文乱码 jsp mysql 乱码的解决方法 jsp中文乱码 jsp mysql 乱码要servlet里面支持中文的方法: 在dopost或者doget的第一句加上: request.setCh ...
最新文章
- XeLaTeX插入GB/T 7714-2005规范的参考文献方法
- Spring Bean的生命周期(详细)
- BZOJ 4734 UOJ #269 [清华集训2016]如何优雅地求和 (多项式)
- container_of实例
- 开关问题(POJ-1830)
- Hadoop ecosystem
- 组合查询--表单对象转化为json数组
- JavaScript复习笔记(3)——数据类型(null、undefined、NaN)与深度克隆
- PL\SQL设置中文
- C++ set find 找不到本来存在的元素
- C语言程序入门(零基础入门)
- sendmail 邮件服务器 套件,SENDMAIL邮件服务器的安装与设置
- model.compile
- 三菱服务器绝对位置,绝对位置控制指令
- JavaSwing_4.5: JMenuBar(菜单栏)
- 深入理解JVM(十五)垃圾回收相关概念
- js跳转新页面,指定div加载新页面
- 面向集团客户的云计算运营平台概述——之云计算运营平台方案(一)
- nyoj 分数加减法
- (循环练习)海军礼炮问题