5.1.7 输出消息正文

优质
小牛编辑
131浏览
2023-12-01

例子 : 输出消息正文

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对象。它们虽然都可以输出文本信息,但对中文编码的处理方式却不同。