玖叶教程网

前端编程开发入门

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;

}

关联的Dispatcher类型源,DispatcherType源码如下:

package javax.servlet;

public enum DispatcherType {

//通过RequestDispatcher.forward方法请求

FORWARD,

//通过RequestDispatcher.include方法请求

INCLUDE,

//正常请求

REQUEST,

//异步请求

ASYNC,

//错误响应

ERROR

}

2.3 转发方法

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

2.3.1 forward

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

graph LR

browser --1请求--> oneServlet

oneServlet --2转发--> twoServlet

twoServlet --3响应--> browser

2.3.2 include

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

graph LR

browser --1请求--> oneServlet

oneServlet --2转发--> twoServlet

twoServlet --3响应--> oneServlet

oneServlet --4响应--> browser

2.3.3 sendRedirect

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

graph LR

browser --1请求--> oneServlet

oneServlet --2响应--> browser

browser --3再次主动--> twoServlet

twoServlet --4再次响应--> browser

三、示例

请求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

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言