Java开发学习笔记之八:servlet之间的协作

2016-08-16

  servlet与servlet,servlet与JSP(其本质也是servlet)之间需要合作。主要因为以下几个原因:
1.当Web程序比较复杂时,使用一个servlet来完成所有的功能显然是不合理的。
2.Web构件之间分工不同。比如servlet比较适合对于请求和响应的控制,而JSP更适合在程序中充当界面。
3.不同的Web应用之间常常需要相互调用,这种相互调用仅仅通过HTML超链接的形式是不够的。

  servlet和其他Web构件(如servlet,JSP,HTML)的合作主要有三类,分别是servlet链接(chaining)、包含响应内容(include)、转递请求(forward)。
  较新的Web应用服务器不支持servlet链接,取而代之的是过滤器(filter)链接机制。下面分别说明后两种机制:包含响应内容和转递请求。
一、包含响应内容
  顾名思义,包含响应内容这种合作机制的原理,就是在一个servlet内容把另一个servlet的响应内容包含进来。具体是这样的:当Servlet需要嵌入另一个Web资源时,首先它建立一个请求分派对象(RequestDispatcher),然后使用RequestDispatcher对象的include方法在响应中包括其他Web资源,最后将原servlet及被包含进来的Web构件的内容合成为原Servlet的响应输出一并发送给客户端。需要注意的是被包含的Web构件(sevlet或JSP)不能改变从原Servlet传递进来的ServletResponse对象的状态编码或头信息,否则将触发异常。参考如下几段代码:
1.
public class includeServlet extends HttpServlet{
  public void doGet(HttpServletRequest req,HttpServletResponse resp)
  {
    RequestDispatcher dispatcher = req.getRequestDispatcher("/servletBeIncluded");
    if (dispatcher != null)
      dispatcher.include(req,resp);
      ...
  }
  ...
}

2.
public class includeServlet extends HttpServlet{
  public void doGet(HttpServletRequest req,HttpServletResponse resp)
  {
    RequestDispatcher dispatcher = getServetConfig().getServletContext().getRequestDispatcher("/servletBeIncluded");
    if (dispatcher != null)
      dispatcher.include(req,resp);
      ...
  }
  ...
}

3.
public class includeServlet extends HttpServlet{
  public void doGet(HttpServletRequest req,HttpServletResponse resp)
  {
    RequestDispatcher dispatcher = getServetConfig().getServletContext().getContext("/webApp2").getRequestDispatcher("/servletBeIncluded");
    if (dispatcher != null)
      dispatcher.include(req,resp);
      ...
  }
  ...
}
以上三段代码分别说明了三种取得RequestDispatcher的方式,其中,第一段代码是由当前的ServletRequest对象直接获得当前Web应用下的另一个要被包含到当前servlet中的servlet的dispatcher,即这一行代码:req.getRequestDispatcher("/servletBeIncluded");第二段代码是由当Web应用的Context对象获得dispatcher;第三段代码是由另一个Web应用的Context对象获得另一个Web应用的servlet的dispatcher。这三段代码说明了以下几点:
1.由当前ServletRequest对象的getRequestDispatcher()方法只能获得当前Web应用的Web构件的dispatcher,达到了在同一个Web应用,不同的Web构件之间的协作。
2.可以由ServletContext获得当前或其它Web应用的Web构件的dispatcher,这样就可以在不同的Web应用之间进行协作。

二、向其它Web资源转递请求
  这种协作机制和上述include机制类似,也是需要先获得待协作Web资源(servlet或jsp)的ResquestDispatcher。与include机制不同的是,前者是包含,而后者是转递,也就是说直接将响应转向到另一个Web构件中去,由另一个Web构件去处理。也就是说当转递执行之后,ServletRequest对象的URL名称路径会变为目标Web构件的URL。参考如下代码:
public class includeServlet extends HttpServlet{
  public void doGet(HttpServletRequest req,HttpServletResponse resp)
  {
    RequestDispatcher dispatcher = req.getRequestDispatcher("/servletWillBeForward");
    if (dispatcher != null)
      dispatcher.forward(req,resp);
      ...
  }
  ...
}

  还有一种转递请求的形式:HttpServletRespnse.sendRedirect(String location)。这种方法与forward不同的地方是:sendRedirect是向客户端发送一个HTTP的URL重定向响应,让客户浏览器将当前Web请求发磅到另一个URL。因此,sendRedirect方法的参数的相对路径不是相对于当前Web应用的当前路径,而是相对于Web应用服务器的根路径;或者可以直接在参数中指明绝对路径,如:
resp.setRedirect("http://xiya.com.cn/xyoa/")。