JSP页面编码
Page character encoding指的是JSP文件和Tag文件本身的编码格式。
- 如果web.xml中<jsp-config>元素中配置了<page-encoding>,页面上page指令的pageEncoding属性必须和web.xml中<jsp-config>元素中的<page-encoding>元素指定的page-encoding一致,否则会导致转换错误。也就是说<page-encoding>配置和pageEncoding属性其实是等价的。
- 如果page指令没有pageEncoding属性和<page-encoding>配置,但有contentType属性,则最终采用contentType属性中的charset。如果contentType也没有charset ,则默认采用ISO-8859-1。
- 如果有pageEncoding或<page-encoding>,它们的优先权比contentType属性的charset高。
- 有一种例外情况,就是在文件中发现了byte order mark(BOM),此时BOM就相当于<page-encoding>。如果BOM映射的字符编码与pageEncoding或contentType中的charset不同,一样会导致转换错误。
总结:在判定pageEncoding时,BOM优先权最高,其次是pageEncoding和<page-encoding>,然后是page指令的contentType,最后是ISO-8859-1。
响应编码
响应的编码根本上是由ServletResponse对象的characterEncoding属性决定的。
page指令的contentType属性就是用来设定ServletResponse的charsetEncoding的。如果contentType的CHARSET没有指定,则分两种情况:
- 如果是使用的XML语法的文档,则默认是UTF-8;
- 使用JSP语法的文件,则取决于BOM,pageEncoding或<page-encoding>。
响应的编码只由请求的页面决定,通过include指令包含的页面不算。
总结:在判定响应的编码时,page指令的contentType中的charset优先权最高,其次是BOM,然后是pageEncoding和<page-encoding>,最后是ISO-8859-1。
另外,响应的编码受三个方法的影响,setCharacterEncoding, setContentType和setLocale。setLocale的优先级最低。
contentType属性的TYPE值如果不指定,则默认是text/html。
总结:如果只设置page指令的contentType,容易保证了页面编码和响应编码的统一。
page指令的contentType与<meta>元素的Content-Type的区别
在响应结果中,page指令的contentType影响的是HTTP响应头Content-Type。而<meta>元素中的Content-Type则只是一段文本内容,只有当HTTP响应头中没有Content-Type时浏览器才会检测这段文本。也就意味着在浏览器中HTTP响应头Content-Type的优先级比<meta>元素的Content-Type属性优先级高。
GET/POST请求编码
前面只讲了页面编码和响应编码,那么请求数据的编码又是由什么决定的?
不同的浏览器对URL可能使用不同的字符编码,中文版的浏览器一般会使用GBK。为了保持统一,很多网站的做法是把URL里面的中文和特殊字符用JavaScript的URL encode。
经过测试,在现在的浏览器中,GET和POST请求数据的编码只受HTML<meta>元素的Content-Type影响。
GET/POST请求数据的读取:
- 读取通过POST传给Servlet的数据,需要给ServletRequest设置正确的characterEncoding才能读取。
- 读取通过GET传给Servlet的数据,只有当tomcat配置文件server.xml中Connection元素的URIEncoding和数据的编码相同时才能正确读取;否则需要转码。
为什么GET和POST不同的解释:任何请求都需要先经过服务器处理,先由服务器读取URL才知道该传给什么Servlet。POST和GET的URL,都受服务器配置URIEncoding的影响,但是POST在通过URL读取成功之后,它的数据不在URL中,所以设置ServletRequest的characterEncoding才能正确读取。
XML视图格式的JSP
采用XML语法格式的JSP页面,其页面字符编码和相应字符编码永远都是UTF-8。