servlet中RequestDispatcher源码解析及使用

半腔热情 提交于 2020-02-08 04:46:22

servlet中RequestDispatcher源码解析及使用

一、简介

RequestDispatcher可以让客户端请求在服务端server中的各个servlet间转发处理。这里结合源码对RequestDispatcher进行介绍。

二、RequestDispatcher

RequestDispatcher接收客户端请求,并将它们发送到server中的其它资源(如servlet、html文件、JSP文件)。RequestDispatcher当作对指定路径或名称的服务资源的包装。

2.1 RequestDispatcher获取

RequestDispatcher是通过HttpServletRequest.getRequestDispatcher方法获取的,参数为指定的资源路径,如果路径是相对路径,则相对目录是当前servlet的。HttpServletRequest.getRequestDispatcher方法定义源码如下:

public RequestDispatcher getRequestDispatcher(String path);

2.2 源码

RequestDispatcher的核心方法是forward和include,这里把RequestDispatcher中定义的常量也列出来,源码如下:

package javax.servlet;
import java.io.IOException;
public interface RequestDispatcher {
    //forward方式下,来源URI名称(值在目标request中attribute中获取)
    static final String FORWARD_REQUEST_URI = "javax.servlet.forward.request_uri";

    //forward方式下,来源context路径名称(值在目标request中attribute中获取)
    static final String FORWARD_CONTEXT_PATH = "javax.servlet.forward.context_path";

    //forward方式下,来源路径信息名称(值在目标request中attribute中获取)
    static final String FORWARD_PATH_INFO = "javax.servlet.forward.path_info";

    //forward方式下,来源servlet的servlet路径名称(值在目标request中attribute中获取)
    static final String FORWARD_SERVLET_PATH = "javax.servlet.forward.servlet_path";

    //forward方式下,来源请求查询串名称(值在目标request中attribute中获取)
    static final String FORWARD_QUERY_STRING = "javax.servlet.forward.query_string";

    //include方式下,目标请求的URI名称(值在目标request中attribute中获取)
    static final String INCLUDE_REQUEST_URI = "javax.servlet.include.request_uri";

    //include方式下,目标context路径名称(值在目标request中attribute中获取)
    static final String INCLUDE_CONTEXT_PATH = "javax.servlet.include.context_path";

    //include方式下,目标路径信息名称(值在目标request中attribute中获取)
    static final String INCLUDE_PATH_INFO = "javax.servlet.include.path_info";

    //include方式下,目标servlet路径名称(值在目标request中attribute中获取)
    static final String INCLUDE_SERVLET_PATH = "javax.servlet.include.servlet_path";

    //include方式下,目标查询串名称(值在目标request中attribute中获取)
    static final String INCLUDE_QUERY_STRING = "javax.servlet.include.query_string";

    //error方式下,传递的异常对象名称(值在目标request中attribute中获取)
    public static final String ERROR_EXCEPTION = "javax.servlet.error.exception";

    //error方式下,传递的异常类型名称(值在目标request中attribute中获取)
    public static final String ERROR_EXCEPTION_TYPE = "javax.servlet.error.exception_type";

    //error方式下,传递的异常信息名称(值在目标request中attribute中获取)
    public static final String ERROR_MESSAGE = "javax.servlet.error.message";

    //error方式下,导致传递异常的请求URI名称(值在目标request中attribute中获取)
    public static final String ERROR_REQUEST_URI = "javax.servlet.error.request_uri";

    //error方式下,传递的发生错误的servlet名称(值在目标request中attribute中获取)
    public static final String ERROR_SERVLET_NAME = "javax.servlet.error.servlet_name";

    //error方式下,传递的响应code名称(值在目标request中attribute中获取)
    public static final String ERROR_STATUS_CODE = "javax.servlet.error.status_code";

    //在内部(浏览器地址不会改变)将请求从一个serlvet转发到另一个资源(servlet、jsp、html)处理
    public void forward(ServletRequest request, ServletResponse response)
        throws ServletException, IOException;

    //在响应请求中添加指定资源(servlet、jsp、html)
    public void include(ServletRequest request, ServletResponse response)
        throws ServletException, IOException;
}

2.3 转发方法

如前源码所示,转发的方法主要有forward和include,为了全面,这里也将HttpServletResponse.sendRedirect方法一并介绍。

2.3.1 forward

forward用于将客户端请求转发给其它server资源(servlet、jsp、html)处理,响应由指定server资源产生,浏览器地址不会改变。流程示意如下:

1请求
2转发
3响应
browser
oneServlet
twoServlet
2.3.2 include

include是在处理客户端请求时,同时添加其它server资源(servlet、jsp、html)的响应,浏览器地址不会改变。流程示意如下:

1请求
2转发
3响应
4响应
browser
oneServlet
twoServlet
2.3.3 sendRedirect

sendRedirect是位于HttpServletResponse中的方法,是直接将用户请求重置,由浏览器再次发起请求,浏览器地址会改变。流程示意图如下:

1请求
2响应
3再次主动
4再次响应
browser
oneServlet
twoServlet

三、示例

请求1的OneServlet.java定义如下:

package requestDispatcher;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

@WebServlet(name="oneServlet", urlPatterns = "/oneServlet")
public class OneServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("this is oneServlet. ");

        String type = Objects.toString(req.getParameter("type"), "redirect");
        RequestDispatcher requestDispatcher = req.getRequestDispatcher(req.getContextPath()+"/twoServlet");
        if("forward".equals(type)){
            //走RequestDispatcher的forward内部转发
            requestDispatcher.forward(req, resp);
        }else if("include".equals(type)){
            //走RequestDispatcher的include内部转发
            requestDispatcher.include(req, resp);
        }else {
            //走HttpServletResponse的sendRedirect转发
            resp.sendRedirect(req.getContextPath()+"/twoServlet");
        }
    }
}

请求2的TwoServlet.java定义如下:

package requestDispatcher;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name="twoServlet", urlPatterns = "/twoServlet")
public class TwoServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取来源servlet的servlet路径
        Object originServletPath = req.getAttribute(RequestDispatcher.FORWARD_PATH_INFO);
        System.out.println("originServletPath:"+originServletPath);
        resp.getWriter().write("this is towServlet.");
    }
}

操作结果:

请求:http://localhost:8080/oneServlet?type=forward
响应:this is towServlet.

请求:http://localhost:8080/oneServlet?type=include
响应:this is oneServlet. this is towServlet.

请求:http://localhost:8080/oneServlet?type=redirect
响应:his is towServlet.
同时:浏览器地址变为 http://localhost:8080/twoServlet
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!