5.2.7 用include方法包含网络资源

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

通过在RequestDispatcher接口中定义的include方法,可以在一个Servlet类中包含另外一个网络资源(包括HTML、JSP、Servlet等)。在Servlet类中可以使用如下的代码获得RequestDispatcher对象:

RequestDispatcher rd =

getServletContext().getRequestDispatcher("/servlet/IncludedServlet");

其中getRequestDispatcher方法的参数值是一个相对于Web根目录的Web资源路径。该Web路径必须以“/”开头,表示Web根目录。

在下面的例子中演示了如何使用include方法包含Web资源。

例子 : 用include方法包含网络资源

1. 实例说明

这个例子由三个Web资源组成,其中有两个Servlet:IncludingServlet和IncludedServlet,一个HTML页:IncludedHtml.html。在IncludingServlet类的service方法中包含另外两个Web资源。IncludingServlet类使用了一个charset请求参数,通过该请求参数,可以指定IncludingServlet类输出信息的字符集编码。并可以观察在用include方法包含的资源中修改字符集编码后产生的效果。

2. 编写IncludedServlet类

IncludedServlet类是被包含的Servlet类,该类的实现代码如下:

package chapter5;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class IncludedServlet extends HttpServlet
{
    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        response.setContentType("text/html; charset=UTF-8");       
        PrintWriter out = response.getWriter();
        out.println("<b>UTF-8编码格式</b><br/>");
        out.println("IncludedServlet URI:" + request.getRequestURI() + "<p/>");
    }
}

3. 配置IncludedServlet类

IncludedServlet类的配置代码如下:

<servlet>
    <servlet-name>IncludedServlet</servlet-name>
    <servlet-class>chapter5.IncludedServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>IncludedServlet</servlet-name>
    <url-pattern>/IncludedServlet</url-pattern>
</servlet-mapping>

4. 编写IncludedHtml.html

IncludedHtml.html是被包含的HTML页面,实现代码如下:

<html>
    <head>
        <title>IncludedHtml</title>
    </head>
    <body>   
        <table border="1">
            <tr>
                <td>
                    书名
                </td>
                <td>
                    出版日期
                </td>
            </tr>
            <tr>
                <td>
                    Java基础
                </td>
                <td>
                    2006年12月
                </td>
            </tr>
        </table>
    </body>
</html>

5. 编写IncludingServlet类

IncludingServlet类包含了IncludedHtml.html和IncludedServlet,该类的实现代码如下:

package chapter5;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class IncludingServlet extends HttpServlet
{
    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        String charset = request.getParameter("charset");//  获得charset请求参数
        //  如果指定了charset参数,则设置Content-Type字段的字符集编码部分
        if(charset != null)       
            response.setContentType("text/html; charset=" + charset);
        else
            response.setContentType("text/html");
        PrintWriter out = response.getWriter();       
        out.println("<b>" + ((charset == null)?"ISO-8859-1":charset) + "编码格式</b><br/>");
        out.println("IncludingServlet URI:" + request.getRequestURI() + "<p/>");
        RequestDispatcher rd = getServletContext().getRequestDispatcher(
                "/IncludedServlet");        
        //  包含IncludedServlet
        rd.include(request, response);               
        rd = getServletContext().getRequestDispatcher(
                "/chapter5/IncludedHtml.html");
        //  包含IncludedHtml.html
        rd.include(request, response);
    }
}

6. 配置IncludingServlet类

IncludingServlet类的配置代码如下:

<servlet>
    <servlet-name>IncludingServlet</servlet-name>
    <servlet-class>chapter5.IncludingServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>IncludingServlet</servlet-name>
    <url-pattern>/IncludingServlet</url-pattern>
</servlet-mapping>

7. 测试默认编码

在浏览器的地址栏中输入如下的URL:

http://localhost:8080/demo/IncludingServlet

浏览器中显示的结果如图5.10所示。

10

图5.10 测试默认编码

8. 测试UTF-8编码

在浏览器地址栏中输入如下的URL:

http://localhost:8080/demo/IncludingServlet?charset=utf-8

浏览器中显示的结果如图5.11所示。

11

图5.11 测试UTF-8编码

9. 程序总结

从图5.10可以看出,所有中文字符都显示成了“?”,这个问题在上面曾经讲过。是由于服务端的编码问题所致,但在IncludedServlet中已经通过setContentType方法设置了编码格式。而且通过http://localhost:8080/demo/IncludedServlet可以正常输出中文。那么为什么IncludedServlet的输出都是“?”呢?答案只有一个,就是在IncludedServlet中的setContentType方法并未起作用。因此,可以得出一个结论:在使用include方法包含Web资源时,在被包含资源中无法修改Content-Type字段的值,既然无法修改Content-Type字段的值,那么HTTP响应消息头的其他字段值应该也无法修改(读者可以自己去做实验)。所以还可以有一个推论,就是在被包含资源中无法修改HTTP响应消息头的字段值(包括调用addHeader、setHeader等方法都不起作用)。

在使用include方法时应注意以下四点:

(1)include方法的参数值必须是Web资源的相对路径,而且这个Web路径是相对于当前Web应用程序根目录的,而且路径前必须加“/”。

(2)在被包含资源中无法改变HTTP响应消息头的字段值。

(3)在被包含资源中并不会改变HTTP请求路径,如在IncludedServlet中输出的URL仍然是/demo/servlet/IncludingServlet(见图3.14和图3.15)。

(4)如果在IncludingServlet中使用的是PrintWriter对象输出的信息,那么在被包含资源(IncludedServlet)中也会使用PrintWriter对象来输出信息,这是因为PrintWriter对象已经在IncludingServlet对象中获得了,而且PrintWriter和ServletOutputStream对象不能同时使用,所以IncludedServlet和IncludingServlet类使用的是同一个PrintWriter对象(读者可以通过hashcode方法来证明这一点),而且在IncludedServlet中不能使用getOutputStream方法来获得ServletOutputStream对象,否则将抛出异常。当然,如果在IncludingServlet类中使用ServletOutputStream对象来输出信息,那么在IncludedServlet类中也不能使用PrintWriter对象来输出信息。