// Servlet内部跳转的源代码片段 req.getRequestDispatcher("...").forward(req, resp);
// req.getRequestDispatcher("/hello?parmam1=value1¶m2=value2").forward(req, resp);
// Servlet内部跳转的源代码片段 req.getRequestDispatcher("...").forward(req, resp);
// req.getRequestDispatcher("/hello?parmam1=value1¶m2=value2").forward(req, resp);
// 取得转发器 ----------------------- 1
// req.getRequestDispatcher("/hello?parmam1=value1¶m2=value2") ==== org.apache.catalina.core.ApplicationDispatcher
class org.apache.catalina.connector.RequestFacade{
public RequestDispatcher getRequestDispatcher(String path) {
return request.getRequestDispatcher(path);//!!!
}
}
class org.apache.catalina.connector.Request{
public RequestDispatcher getRequestDispatcher(String path) {
Context context = getContext(); // org.apache.catalina.core.StandardContext
if (path == null) {
return null;
} else if (path.startsWith("/")) {
// !!! org.apache.catalina.core.ApplicationContextFacade.getRequestDispatcher("/a/hello-servlet")
return (context.getServletContext().getRequestDispatcher(path));
}
}
}
class org.apache.catalina.core.ApplicationContextFacade{
public RequestDispatcher getRequestDispatcher(final String path) {
// context == org.apache.catalina.core.ApplicationContext
return context.getRequestDispatcher(path);
}
}
class org.apache.catalina.core.ApplicationContext{
public RequestDispatcher getRequestDispatcher(String path) {
// path == "/hello?parmam1=value1¶m2=value2"
// path = "/a/b/c/file.jsp"
// path = "/a/b/c/HelloServlet"
// Get query string
String queryString = null;
String normalizedPath = path;
int pos = normalizedPath.indexOf('?');
if (pos >= 0) {
queryString = normalizedPath.substring(pos + 1); // 有带参数 "parmam1=value1¶m2=value2"
normalizedPath = normalizedPath.substring(0, pos); // 标准的地址 "/hello"
}
pos = normalizedPath.length();
// Use the thread local URI and mapping data
DispatchData dd = dispatchData.get();
if (dd == null) { // 每个线程有各自的副本!!!
dd = new DispatchData();
dispatchData.set(dd);
}
MessageBytes uriMB = dd.uriMB;
uriMB.recycle();
// Use the thread local mapping data
MappingData mappingData = dd.mappingData;
// Map the URI
CharChunk uriCC = uriMB.getCharChunk();
try {
// org.apache.catalina.core.StandardContext
// 如:/example
uriCC.append(context.getPath(), 0, context.getPath().length());
/*
* Ignore any trailing path params (separated by ';') for mapping
* purposes
*/
int semicolon = normalizedPath.indexOf(';');
if (pos >= 0 && semicolon > pos) {
semicolon = -1;
}
uriCC.append(normalizedPath, 0, semicolon > 0 ? semicolon : pos);
// uriMB === "/example/a/b/c/file.jsp"
// uriMB === "/example/a/b/c/file.jsp"
// uriMB === "/example/a/b/c/HellorvSelet"
// uriMB === "/test/hello"
service.getMapper().map(context, uriMB, mappingData);//!!!! 匹配路由
if (mappingData.wrapper == null) { // 找到包装器
return (null);
}
/*
* Append any trailing path params (separated by ';') that were
* ignored for mapping purposes, so that they're reflected in the
* RequestDispatcher's requestURI
*/
if (semicolon > 0) {
uriCC.append(normalizedPath, semicolon, pos - semicolon);
}
} catch (Exception e) {
// Should never happen
log(sm.getString("applicationContext.mapping.error"), e);
return (null);
}
//
// HelloServlet
// /hello/*
//
// 转发地址:/hello?parmam1=value1¶m2=value2
// org.apache.catalina.core.StandardWrapper
Wrapper wrapper = mappingData.wrapper; // 匹配的StandardWrapper
String wrapperPath = mappingData.wrapperPath.toString(); // 如:"/hello"
String pathInfo = mappingData.pathInfo.toString();// null
Mapping mapping = (new ApplicationMapping(mappingData)).getMapping(); // 创建映射对象,来保存匹配到的信息
mappingData.recycle(); // 回收掉原来映射器的信息
String encodedUri = URLEncoder.DEFAULT.encode(uriCC.toString()); // 如: "/test/hello"
// Construct a RequestDispatcher to process this request
// org.apache.catalina.core.ApplicationDispatcher
return new ApplicationDispatcher(wrapper, encodedUri, wrapperPath, pathInfo,
queryString, mapping, null);
}
}
// 调用转发器的forward方法 ----------------------- 2
// ApplicationDispatcher.forward(req, resp);
class org.apache.catalina.core.ApplicationDispatcher{
// 构造函数
public ApplicationDispatcher(Wrapper wrapper, String requestURI, String servletPath,
String pathInfo, String queryString, Mapping mapping, String name) {
super();
// Save all of our configuration parameters
this.wrapper = wrapper; // org.apache.catalina.core.StandardWrapper
this.context = (Context) wrapper.getParent();
this.requestURI = requestURI;
this.servletPath = servletPath;
this.pathInfo = pathInfo;
this.queryString = queryString;
this.mapping = mapping;
this.name = name;
}
// 内部跳转
public void forward(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
doForward(request,response);//!!!! 跳转
}
private void doForward(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
// 清除数据,回收空间
// 不回收编码转换器
// org.apache.catalina.connector.ResponseFacade
response.resetBuffer();
State state = new State(request, response, false); // 创建state对象
wrapResponse(state);//!!! 包裹org.apache.catalina.connector.ResponseFacade对象
// 包裹 request == org.apache.catalina.connector.RequestFacade
ApplicationHttpRequest wrequest =
(ApplicationHttpRequest) wrapRequest(state);
String contextPath = context.getPath(); // 如: “/test”
HttpServletRequest hrequest = state.hrequest;
// hrequest == org.apache.catalina.connector.RequestFacade
// wrequest == org.apache.catalina.connector.ApplicationHttpRequest
if (hrequest.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI) == null) {
// 把原请求对象RequestFacade的信息,放入新的请求对象ApplicationHttpRequest
wrequest.setAttribute(RequestDispatcher.FORWARD_REQUEST_URI,
hrequest.getRequestURI());
wrequest.setAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH,
hrequest.getContextPath());
wrequest.setAttribute(RequestDispatcher.FORWARD_SERVLET_PATH,
hrequest.getServletPath());
wrequest.setAttribute(RequestDispatcher.FORWARD_PATH_INFO,
hrequest.getPathInfo());
wrequest.setAttribute(RequestDispatcher.FORWARD_QUERY_STRING,
hrequest.getQueryString());
Mapping mapping;
if (hrequest instanceof org.apache.catalina.servlet4preview.http.HttpServletRequest) {
mapping = ((org.apache.catalina.servlet4preview.http.HttpServletRequest)
hrequest).getMapping(); // 取得路由匹配信息
} else {
mapping = (new ApplicationMapping(null)).getMapping();
}
wrequest.setAttribute(
org.apache.catalina.servlet4preview.RequestDispatcher.FORWARD_MAPPING,
mapping);
}
// 设置新的请求对象ApplicationHttpRequest的信息
wrequest.setContextPath(contextPath);
wrequest.setRequestURI(requestURI);
wrequest.setServletPath(servletPath);
wrequest.setPathInfo(pathInfo);
if (queryString != null) {
wrequest.setQueryString(queryString);
wrequest.setQueryParams(queryString);
}
wrequest.setMapping(mapping);
// request == org.apache.catalina.connector.RequestFacade
// response == org.apache.catalina.connector.ResponseFacade
processRequest(request,response,state); // 处理请求
((ResponseFacade) response).finish(); // 结束请求
PrintWriter writer = response.getWriter(); // 关闭输出对象
writer.close();
}
// 处理请求
private void processRequest(ServletRequest request,
ServletResponse response,
State state)
throws IOException, ServletException {
// request == org.apache.catalina.connector.RequestFacade
// response == org.apache.catalina.connector.ResponseFacade
// context === org.apache.catalina.core.StandardContext
if (context.getFireRequestListenersOnForwards() &&
!context.fireRequestInitEvent(request)) { // 如果有配置监听器,就出发跳转监听器
doInvoke = false;
}
// state.outerRequest == org.apache.catalina.connector.RequestFacade
// response == org.apache.catalina.connector.ResponseFacade
invoke(state.outerRequest, response, state);
}
// 调用
private void invoke(ServletRequest request, ServletResponse response,
State state) throws IOException, ServletException {
// request == org.apache.catalina.connector.RequestFacade
// response == org.apache.catalina.connector.ResponseFacade
// wrapper == org.apache.catalina.core.StandardWrapper 是Servlet的包装器
// !!!!! 加载Servlet类,创建Servlet对象,反射Servlet对象内部的注解,如:@Resource声明的资源,并进行依赖注入到Servlet对象中!!!
// !!!!! 调用Servlet对象的init方法
servlet = wrapper.allocate();
// Get the FilterChain Here 创建过滤器链条
ApplicationFilterChain filterChain =
ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
if ((servlet != null) && (filterChain != null)) {
filterChain.doFilter(request, response); // 执行过滤链条
}
filterChain.release(); // 回收过滤器链条的资源
wrapper.deallocate(servlet); // 回收Servlet的资源
}
}