5.1.7 输出消息正文
例子 : 输出消息正文
1. 实例说明
在本例中,通过action请求参数来执行四个不同的代码段,以演示使用PrintWriter和ServletOutputStream输出中文信息时的区别。
2. 编写OutText类
public class OutText extends HttpServlet
{
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String action = request.getParameter("action");
if (action != null)
{
// 第1种情况
if (action.equals("1"))
{
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.write("使用PrintWriter输出信息");
}
// 第2种情况
else if (action.equals("2"))
{
ServletOutputStream sos = response.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(sos);
osw.write("使用ServletOutputStream输出信息(未设置客户端和服务端编码)");
osw.flush(); // 或调用sos.close();
}
// 第3种情况
else if (action.equals("3"))
{
ServletOutputStream sos = response.getOutputStream();
sos.write("使用ServletOutputStream输出信息(未设置客户端)".getBytes("UTF-8"));
sos.close(); // 或调用sos.flush();
}
// 第4种情况
else if (action.equals("4"))
{
response.setContentType("text/html;charset=UTF-8");
ServletOutputStream sos = response.getOutputStream();
sos.write("使用ServletOutputStream输出信息".getBytes("UTF-8"));
sos.close(); // 或调用sos.flush();
}
}
}
}
3. 配置OutText类
OutText类配置代码如下:
<servlet>
<servlet-name>OutText</servlet-name>
<servlet-class>chapter5.OutText</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>OutText</servlet-name>
<url-pattern>/OutText</url-pattern>
</servlet-mapping>
4. 测试程序
在浏览器地址栏中输入如下四个URL,并将浏览器的编码设置改为自动选择状态,看看会显示什么信息?
http://localhost:8080/demo/OutText?action=1
http://localhost:8080/demo/OutText?action=2
http://localhost:8080/demo/OutText?action=3
http://localhost:8080/demo/OutText?action=4
5. 程序总结
在本例的代码中第1种情况和第4种情况都会正常显示中文,而当浏览器设为非GB2312编码格式时(如UTF-8),则第2种和第3种情况会显示乱码(但不会是“?”),只要将浏览器的编码格式设置正确(第2种情况设为GB2312,第3种情况设为UTF-8)就可正确显示中文了。在第4种情况, ServletOutputStream并不根据setContentType方法所设置的charset=UTF-8进行编码,因此,需要使用getBytes方法将中文字符串转换为UTF-8格式。然而这时必须让客户端浏览器也按着UTF-8格式来解析字符才确保正常显示中文信息。因此,setContentType方法就只剩下一个功能了,就是设置了客户端编码。所以在使用ServletOutputStream输出中文信息时,必须使用setContentType或addHeader方法来设置HTTP响应消息头的Content-Type字段才能保证正常显示中文信息。
从上面的例子可以总结出使用PrintWriter或ServletOutputStream的四点注意事项:
(1)PrintWriter和ServletOutputStream是互斥的,也就是说不能同时使用PrintWriter和ServletOutputStream向客户端输出信息。如果同时调用getWriter方法和getOutputStream方法,Servlet引擎会抛出java.lang.IllegalStateException异常。
(2)在使用PrintWriter输出中文时,会根据setCharacterEncoding方法或setContentType方法所设置的字符集编码对中文字符进行编码。而ServletOutputStream并不会考虑这个设置。要想使用ServletOutputStream向客户端输出指定编码格式的信息,需要使用String的getBytes方法来转换编码格式。
(3)如果未设置服务端编码,PrintWriter默认使用了ISO-8859-1编码格式,而ServletOutputStream使用了操作系统的默认编码格式,也就是GB2312。因此,如果在未设置服务端编码的情况下,PrintWriter输出的中文字符都被替换成了“?”,而使用ServletOutputStream是不会输出“?”的(当然,如果非要让ServletOutputStream输出“?”也是可以的,只要使用getBytes方法将字符串转换成ISO-8859-1或其他不支持中文信息的编码格式即可,但我想恐怕没人要这么做吧!)。
(4)在使用PrintWriter对象输出信息时,并不需要调用flush或close方法关闭PrintWriter对象。而在使用ServletOutputStream对象输出信息时,最后必须使用close方法关闭ServletOutputStream对象或使用flush方法刷新缓冲区,才能将信息输出到客户端。
在Servlet中可以通过PrintWriter和ServletOutputStream向客户端输出信息。其中PrintWriter在前面已经使用过很多次了,它的主要功能是向客户端输出基于文本的信息。PrintWriter对象可以通过HttpServletResponse接口的getWriter方法获得。而ServletOutputStream一般用于向客户端输出基于字节流的信息。通过HttpServletResponse接口的getOutputStream方法可以获得ServletOutputStream对象。它们虽然都可以输出文本信息,但对中文编码的处理方式却不同。