Tomcat8.x Servlet内部跳转机制 req.getRequestDispatcher("...").forward(req, resp);
来源:互联网 发布:java字符串的方法 编辑:程序博客网 时间:2024/05/18 16:16
// 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.ApplicationDispatcherclass 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.StandardContextif (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); } // <servlet-mapping>// <servlet-name>HelloServlet</servlet-name>// <url-pattern>/hello/*</url-pattern>//</servlet-mapping> // 转发地址:/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的资源}}
0 0
- Tomcat8.x Servlet内部跳转机制 req.getRequestDispatcher("...").forward(req, resp);
- 关于request.getRequestDispatcher("######").forward(req, resp)
- Tomcat8.x Servlet应用 req.getParameter("username")的内部机制
- Tomcat8.x Servlet应用 req.getCookies() 的内部机制
- response.sendRedirect("")和request.getRequestDispatcher("").forward(req,resp);
- req.getRequestDispatcher和resp.sendRedirect的区别
- 理解req和resp Servlet学习
- req
- zmq req重试机制
- request.getRequestDispatcher(Request req,Response res) 和sendRedirect()
- #216. REQ
- require.js源码分析之req({})内部处理
- Servlet实现通过getRequestDispatcher().forward页面转发
- servlet的转发(request.getRequestDispatcher().forward())
- ZeroMQ 之 Rep/Req
- express req object
- OpenSSL命令---req
- HttpServletRequest req 的用法
- 数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇
- 淘淘商城---8.10
- 数据库连接池---(一)
- jQuery基础学习
- 用C#代码生成一个简单的PDF文件(转)
- Tomcat8.x Servlet内部跳转机制 req.getRequestDispatcher("...").forward(req, resp);
- matlab显示中文乱码的解决办法
- BZOJ-2243: [SDOI2011]染色-树链剖分
- colored manual page
- 位域
- Tomcat8.x 在上下文的web.xml配置跳转到jsp文件<jsp-file>
- mysql笔记五——数据库连接池(原理、构建)和java动态代理的使用
- Java内存模型
- 第五天(5道)