《JSP实用教程(第2版)/耿祥义》错误之处理汉字乱码
原书部分摘录
JSP内置对象
3.1.2处理汉字信息
避免出现汉字乱码问题有两种解决方法:
1)使用page指定Context Type属性的值时
<%@ page contentType="text/html;Charset=GB2312" %>
即将其中出现的Charset中的首字母大写。
2)<%@ page contentType="text/html;charset=GB2312" %>
即将其中出现的charset中的首字母小写。然后内置对象request将获取的信息重新编码,即用ISO-8859-1编码,并存放到字节数组中;再将数组转化成字符串对象。
String str=request.getParameter("boy");
byte b[]=str.getBytes("ISO-8859-1");
str=new String(b);
第一种方法应该是个错误
以下摘自JSP2.2规范
页编译指令中contentType部分
contentType
Defines the MIME type and the character encoding for the response of the JSP page, and is also used in determining the character encoding of the JSP page.
Values are either of the form “TYPE” or “TYPE;charset=CHARSET”with an optional white space after the “;”. “TYPE” is a MIME type, see the IANA registry at http://www.iana.org/assignments/media-types/index.html for useful values. “CHARSET”, if present, must be the IANA name for a character encoding.
The default value for “TYPE” is “text/html” for JSP pages in standard syntax, or “text/xml” for JSP documents in XML syntax. If “CHARSET” is not specified, the response character encoding is determined as described in Section JSP.4.2, “Response Character Encoding”.
The corresponding JSP configuration element is default content- type (see Section JSP.3.3.9, “Declaring Default Content Type”). See Chapter JSP.4, “Internationalization Issues” for complete details on character encodings.
翻译:
contentType
定义了MIME类型和响应字符编码的JSP页,它也用来决定JSP页的解码字符集。
它的值要么是“TYPE”,要么是“TYPE;charset=CHARSET”在;后可带一个可选的空白,“TYPE”是一个可选的MIME类型,可以到IANA看到注册的可用的值http://www.iana.org/assignments/media-types/index.html。“CHARSET”,如果出现了,必须是字符编码中IANA的名字。
对于JSP页面的标准语法,默认的“TYPE”是“text/html”,对于JSP文档中的XML语法,默认的是“text/xml”。如果“CHARSET”没有指定,则响应字符解编码取决于4.2节的描述“响应字符编码”
相应的JSP配置元素即默认的content-type(看3.3.9节 “声明默认的Content Type”)。看第4章 “国际化问题” 有字符编码的完整细节。
4.2节的描述“响应字符编码”摘取部分
The initial response character encoding is set to the CHARSET value of the contentType attribute of the page directive. If the page doesn’t provide this attribute or the attribute doesn’t have a CHARSET value, the initial response character encoding is determined as follows:
? For documents in XML syntax, it is UTF-8.
? For JSP pages in standard syntax, it is the character encoding specified by the BOM, by the pageEncoding attribute of the page directive, or by a JSP configuration element page-encoding whose URL pattern matches the page. Only the character encoding specified for the requested page is used; the encodings of files included via the include directive are not taken into consideration. If there’s no such specification, no initial response character encoding is passed
to ServletResponse.setContentType() - the ServletResponse object’s default, ISO-8859-1, is used.
翻译:
初始的字符编码是通过页编译指令中的contentType属性中的CHARSET值决定的,如果JSP页没有提供这个属性,或者这个属性没有设置CHARSET值,那么初始响应字符编码取决于以下规则:
对于文档中的XML语法,按UTF-8格式编码。
对于JSP语法,它的字符编码取决于BOM,或者页编译指令中的pageEncoding属性,或通过一个JSP配置元素页面编码的URL模式匹配的页面。唯一指定的字符编码所请求的页面使用;通过include指令编码的文件包括不考虑。如果没有这些指定,不通过ServletResponse.setContentType()初始化字符编码ServletResponse对象的默认使用ISO-8859-1。
分析一下,charset把首字母改成大写的做法显然不符合规范,但是这种做法服务器能解析说明服务器具有容错性。tomcat旧版本忽略“Charset=GB2312”参数,用BOM解析的是GB2312编码,在tomcat1.7中,服务器直接忽略“Charset=GB2312”,采用ISO-8859-1编码。
根据测试,如果按第一方法,旧版本部分显示正常,新的tomcat会出现乱码,所以说完全依赖于tomcat的容错性的方法根本不靠谱!!
顺便说一下:第二种方法的byte转String方法已过时,在后续版本中使用会有风险
建议使用
str=new String(b,UTF-8);