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&param2=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
原创粉丝点击