返回符杰博客列表

Tiny学习笔记(四)

发布于 12天前

毕业季终于过去了,我又回来啦(貌似tiny的小版本又往上升了升)。好吧,回归正题,上回说到了tinyFilterProcessor这个方法,所有的请求在走完过滤器之后都会集中到这个方法。

public void tinyFilterProcessor(HttpServletRequest request,
                            HttpServletResponse response) throws IOException, ServletException {
                   logger.logMessage(LogLevel.DEBUG, "请求路径:<{}>", servletPath);
                   List<TinyFilter> tinyFilters = tinyFilterManager
                                     .getTinyFiltersWithUrl(servletPath);//获取tiny过滤器列表
                   WebContext wrapperContext = null;
                   try {
                            wrapperContext = getWebContext(context, tinyFilters, request,
                                               response);//获取web上下文
                            // 如果请求已经结束,则不执行进一步的处理。例如,当requestContext已经被重定向了,则立即结束请求的处理。
                            if (isRequestFinished(tinyFilters.size(), wrapperContext)) {
                                     return;
                            }
                            servletPath = getServletPath(wrapperContext.getRequest(),
                                               wrapperContext);// 重新获取路径
                            // 可能之前被修改过
                            if (isRequestPassedThru(servletPath)//对于需要排除的req,直接交回控制权给filter
                                               || !tinyProcessorManager.execute(servletPath,
                                                                 wrapperContext)) {
                                     giveUpControl(wrapperContext);
                                     return;
                            }
                   } catch (Exception e) {
                            if (wrapperContext == null) {
                                     wrapperContext = WebContextUtil.getWebContext(request);
                            }
                            handleException(wrapperContext, e, context.getRequest(),
                                               context.getResponse());
                   } finally {
                            postProcess(wrapperContext, tinyFilters);
                   }
         }

if (isRequestPassedThru(servletPath) || !tinyProcessorManager.execute(servletPath,  wrapperContext))在这一句中重点来看tinyProcessorManager.execute(servletPath, wrapperContext)这个方法,方法不长,主要作用就是找出对应处理器。

for (TinyProcessor tinyProcessor : tinyProcessorList) {
        if (tinyProcessor.isMatch(url)) {
            canExecute = true;
            tinyProcessor.process(url, context);
            break;
        }
}//遍历处理器列表,找出与url相匹配的处理器,执行process操作。

在这里我跟踪了一个很基本的login请求,果然最后跳转到了SpringMvcTinyProcessor中,blob.png

最后的重头戏从SpringMvcTinyProcessor中的reallyProcess方法开始。看了一下,诶,发现,这个和springmvc的源码有点像233333.大概就有以下几个作用,获取请求的参数,重新设置的参数,处理service请求,最后在finally中复原之前的场景。(这一块的了解不是特别透彻,今天先看看流程)。在doservice中,处理流程大概是以下几步,保存现场(保存request等相关信息)。将框架需要的对象放入request中,请求分发服务,恢复现场。最重要的就是doDispatch(请求分发服务)。

private void doDispatch(HttpServletRequest request,
                            HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        int interceptorIndex = -1;
        boolean multipartRequestParsed = false;
        try {
            ModelAndView mv;
            boolean errorView = false;
            try {
                processedRequest = checkMultipart(request);//判断该请求是否是文件上传的请求,如果是需要先经过multipartResolver的处理。
                multipartRequestParsed = processedRequest != request;
                // Determine handler for the current request.
                mappedHandler = getHandler(processedRequest);//通过请求找到对应的映射处理器,例如我这里跟踪的login则对应的handler就是LoginAction
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }
                // 找到对应的适配器,后面就是由适配器来执行handler的方法
                HandlerAdapter ha = getHandlerAdapter(mappedHandler
                        .getHandler());
                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);//判断是否是get请求  
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request,
                            mappedHandler.getHandler());
                    String requestUri = urlPathHelper.getRequestUri(request);
                    logger.logMessage(LogLevel.DEBUG,
                            "Last-Modified value for [" + requestUri + "] is: "
                                    + lastModified);
                    if (new ServletWebRequest(request, response)
                            .checkNotModified(lastModified) && isGet) {
                        return;//如果缓存没过期直接返回
                    }
                }
                // 获取所有位于controller之前的拦截器
                HandlerInterceptor[] interceptors = mappedHandler
                        .getInterceptors();
                if (interceptors != null) {
                    for (int i = 0; i < interceptors.length; i++) {//顺序执行每一个拦截器
                        HandlerInterceptor interceptor = interceptors[i];
                        if (!interceptor.preHandle(processedRequest, response,
                                mappedHandler.getHandler())) {
                            triggerAfterCompletion(mappedHandler,
                                    interceptorIndex, processedRequest,
                                    response, null);
                            return;//如果被拦截直接返回
                        }
                        interceptorIndex = i;
                    }
                }
                // Actually invoke the handler.
                mv = ha.handle(processedRequest, response,
                        mappedHandler.getHandler());//调用真实的controller方法,比如我这里是loginAction中的方法
                // Do we need view name translation?
                if (mv != null && !mv.hasView()) {
                    mv.setViewName(getDefaultViewName(request));
                }
                // Apply postHandle methods of registered interceptors.
                if (interceptors != null) {
                    for (int i = interceptors.length - 1; i >= 0; i--) {//反序调用拦截器的后置方法
                        HandlerInterceptor interceptor = interceptors[i];
                        interceptor.postHandle(processedRequest, response,
                                mappedHandler.getHandler(), mv);
                    }
                }
            } catch (ModelAndViewDefiningException ex) {
                logger.logMessage(LogLevel.DEBUG,
                        "ModelAndViewDefiningException encountered", ex);
                mv = ex.getModelAndView();
            } catch (Exception ex) {
                Object handler = (mappedHandler != null ? mappedHandler
                        .getHandler() : null);
                mv = processHandlerException(processedRequest, response,
                        handler, ex);
                errorView = (mv != null);
            }
            // Did the handler return a view to render?
            if (mv != null && !mv.wasCleared()) {
                render(mv, processedRequest, response);//完成对页面的渲染
                if (errorView) {
                    WebUtils.clearErrorRequestAttributes(request);
                }
            } else {
                logger.logMessage(
                        LogLevel.DEBUG,
                        "Null ModelAndView returned to SpringMvcTinyProcessor assuming HandlerAdapter completed request handling");
            }
            // Trigger after-completion for successful outcome.
            triggerAfterCompletion(mappedHandler, interceptorIndex,
                    processedRequest, response, null);
        } catch (Exception ex) {
            // Trigger after-completion for thrown exception.
            triggerAfterCompletion(mappedHandler, interceptorIndex,
                    processedRequest, response, ex);
            throw ex;
        } catch (Error err) {
            ServletException ex = new NestedServletException(
                    "Handler processing failed", err);
            // Trigger after-completion for thrown exception.
            triggerAfterCompletion(mappedHandler, interceptorIndex,
                    processedRequest, response, ex);
            throw ex;
        } finally {
            // Clean up any resources used by a multipart request.
            if (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
            }
        }
}

当页面也渲染完毕后,需要经过GZIPFilter这个过滤器,了解一下GZIP算法(gzip是http协议中使用的一种加密算法,客户端向web服务器端发出了请求后,通常情况下服务器端会将页面文件和其他资源,返回到客户端,客户端加载后渲染呈现,这种情况文件一般都比较大,如果开启Gzip ,那么服务器端响应后,会将页面,JS,CSS等文本文件或者其他文件通过高压缩算法将其压缩,然后传输到客户端,由客户端的浏览器负责解压缩与呈现。通常能节省40%以上的流量(一般都有60%左右),一些PHP,JSP文件也能够进行压缩。),至此,请求到这里基本结束了,页面文件也渲染出来了。


 
相关信息
     标签
       附件
      文件 标题 创建者

      评分 0次评分

      日程