HTTP协议及浏览器编码行为 联系客服

发布时间 : 星期五 文章HTTP协议及浏览器编码行为更新完毕开始阅读0e34aa3531126edb6f1a1046

文件中pageEncoding和web.xml中的jsp-config设置仍然有效,但仅起到一个复查的作用。如果任意一处有不一致的编码声明,都将导致JSP编译时出错。例如,可以如下声明pageEncoding。

对于HTTP响应字符编码,仍然使用contentType参数,当然语法有所不同,以便符合XML规范。

如果contentType参数不存在,那么默认的字符编码将为UTF-8,而不再是ISO-8859-1。 4.一些不推荐的方法

对所有JSP统一使用UTF-8编码是最好的策略。如果非要在JSP中使用和语言相关的编码格式,那么,对于国际化的应用程序来说将是一场噩梦,因为这将导致同一个网页有多个对应的JSP文件,每个文件对应一种语言。如果要支持10种语言,那就有网页数乘以10的JSP文件,其中任意一个网页需要变更,都要改变10个JSP文件,这几乎是无法管理的。 另一种不推荐的情形是对一个JSP使用不同的文件编码和响应编码。比如,下面的声明表示JSP文件本身的编码是GB2312,而生成的HTML内容则使用UTF-8。

<%@ page language=\

pageEncoding=\

这种做法虽然存在理论上的可能性,但实际操作中却很容易把两种编码混淆,从而产生错误。调试这类编码错误是非常复杂的,因为有太多的配置可能对其产生影响。 5.小结

最好以UTF-8编码保存JSP文档。

在JSP中使用pageEncoding参数声明文件字符编码,使用contentType参数声明响应字符编码。

如果应用程序服务器支持JSP 2.0规范,也可以在web.xml中使用jsp-config标记统一声明JSP文件编码。

6.2.3 Servlet的编码设置

对于一个国际化的应用程序而言,仅设置HTML和JSP编码是远远不够的,除了考虑服务器端输出内容的字符编码外,还要考虑如何正确解析来自全球范围内不同地域和语言的用户输入。本节将讨论如何设置编码以确保一个网页上的表单能够接收不同语言的输入,并且在服务器端这些不同语言的字符能够被正确地解析。 1.使用UTF-8编码提交数据

要使应用程序能够接收国际化的输入,首先要确保浏览器使用UTF-8编码向Web服务器提交数据。UTF-8作为通用编码,可以为全球不同的语言进行统一的编码和解码,这样可以大大简化服务器端为了适应多语言所需的编程。

当用户在浏览器单击提交表单时,浏览器会使用当前网页的字符编码提交表单上输入的内容,因此,只要对所有的网页都采用UTF-8编码,就可以保证浏览器总是使用UTF-8编码提交数据。

对网页编码的设置已经在“6.2.1 HTML的编码设置”和“6.2.2 JSP的编码设置”中详细讨论过了,可以根据网页输出的具体方式在相应的章节找到编码的设置方法,这里就不重复了。 2.设置字符编码以正确解析HTTP请求

当数据提交到服务器端后,一般在Servlet中进行字符编码的解析,然后获取用户输入,进行逻辑运算和业务处理。为了正确地解码用户输入,程序在读取HTTP请求之前,必须调用ServletRequest.setCharacterEncoding()方法来设置合适的字符编码,以便将HTTP请求中包含的字节流解码为字符流。

protected final void doPost(HttpServletRequest req, HttpServletResponse

resp)

throws ServletException, IOException { req.setCharacterEncoding(\String input = req.getParameter(\

}

如上例所示,在Servlet的doPost()方法中,首先调用setCharacterEncoding(),以便将UTF-8设置为字符编码,然后读取名为order的输入参数。这里setCharacterEncoding()设置的编码必须和浏览器提交数据所使用的字符编码一致,上例中即为UTF-8,否则,就会导致读入的字符串为乱码。

关于setCharacterEncoding()方法,一个需要强调的要点是:必须在读取HTTP请求之前设置编码,否则是无效的。这里说的“读取HTTP请求”不仅包括使用getParameter(), getParameterMap(),getParameterNames()和getParameterValues()之类的方法,还包括getReader() 方法,比如下面就是一个错误的例子。

protected final void doPost(HttpServletRequest req, HttpServletResponse

resp)

throws ServletException, IOException { Reader reader = req.getReader();

req.setCharacterEncoding(\错误!必须在 getReader() 之前调

用!

String input = req.getParameter(\有可能读入乱码

}

对于一般的程序,要确保在第一时间调用setCharacterEncoding()可能极为简单,但是,如果使用了比较复杂的Web层框架,情形就会不同。因为程序的控制权往往并不直接进入应用程序代码,而是通过框架转发调用再进入应用程序,此时如果在框架内部首先读取了HTTP请求,那么在应用程序中调用setCharacterEncoding()就为时已晚。

因此,根据所使用的Web框架的不同,调用setCharacterEncoding()的时机和位置都有可能不同,需要根据具体情况而定。上面的示例仅对最普通的Servlet而言,并不适用于所有的Web框架。后面的章节会对一些主流的Web框架进行与国际化相关的具体分析。 3.设置Servlet的响应字符编码

在大多数情况下,Java应用程序通过JSP生成HTML文档,作为响应发回浏览器,相关的设置已经在6.2.2中的“2.设置JSP响应字符编码”中介绍过了。然而,也存在个别特殊情况,程序会选择由Servlet直接生成响应,此时就需要在Servlet中设置响应的字符编码。在ServletAPI中,有三个方法可以用于设置响应字符编码,它们都在ServletResponse接口中定义,分别是setCharacterEncoding(), setContentType()和setLocale()。

一般推荐用setContentType()或者setCharacterEncoding()设置编码。它们的用法大致如下:

protected final void doPost(HttpServletRequest req, HttpServletResponse

resp)

throws ServletException, IOException { resp.setCharacterEncoding(\

resp.setContentType(\

PrintWriter writer = resp.getWriter();

writer.println(\

}

两个方法都会在HTTP响应头中加入ContentType声明,通知浏览器响应内容的字符编码。 仅当旧版本的Servlet规范不支持setContentType()和setCharacterEncoding()时,才会使用setLocale()。调用setLocale()会导致采用和语言相关的默认编码,但仍通过ContentType响应头通知客户端。

这里同样需要注意,设置响应编码必须在输出响应之前执行,否则将起不到预期的效果。下面是一个错误例子。

protected final void doPost(HttpServletRequest req, HttpServletResponse

resp)

throws ServletException, IOException { PrintWriter writer = resp.getWriter();

writer.println(\

resp.setCharacterEncoding(\// 错误,必须在 getWriter() 之前设

置 }

4.小结

将UTF-8设置为网页编码,以UTF-8提交数据。

调用ServletRequest.setCharacterEncoding()设置编码解析HTTP请求。

如果不通过JSP,而是通过Servlet直接生成响应,那么调用ServletResponse接口中定义的setCharacterEncoding()或者setContentType()来设置响应字符编码。

6.2.4 主流Web框架的编码设置

在实际项目开发中,往往不会直接使用Servlet/JSP,更多的是在一些Web框架的基础上搭建应用程序,这些Web框架在带来完善的设计模式的同时,也对Serlet/JSP编程接口进行包装和扩展,这在一定程度上造成了不小的学习曲线。习惯在Servlet/JSP模式下工作的开发人员有时也会产生困扰:如何在这些框架下写出支持国际化的代码呢?面对更丰富的编程接口和类继承,应该从何处入手,通过什么方法来设置恰当的字符编码呢?本节将尝试回答这些问题。

1.Struts框架下的编码设置