SpringMVC 第三章 - DispatcherServlet的逻辑处理

    xiaoxiao2021-04-15  313

    这部分应该是SpringMVC的核心,也是我们在平常使用的时候经常会被问到的一个问题,在大学刚接触SpringMVC的时候,经常会看到下面这样的流转图

    简单的说一下,就是每一个请求过来的时候,都是由DispatcherServlet进行转发,那么它的第一步就是用过映射处理器(BeanNameUrlHandlerMapping)找到对应的实体类(Controller类),然后再拿这个实体类和每个Adapter进行适配。那么最最重要的,需要理解的,也是就是上一章节说到两个模块:映射处理器和适配器。 由于 DispatcherServlet 继承 FrameworkServlet, Servlet的默认实现doGet,doPost的实现都指向了DispatcherServlet的**doService**方法,在进行doService方法之前,使用了ThreadLocal保存了当前线程的属性

    最重要的两个方法:

    由handlerMapping获取到对应的handler

    找到合适的handlerAdapter,然后调用handler方法

    /** * 根据request信息寻找对应的Handler * private List<HandlerMapping> handlerMappings 是初始化的时候设置 -- initHandlerMappings(context) */ protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { for (HandlerMapping hm : this.handlerMappings) { // 封装处理 HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } return null; } /** * 根据URL找到匹配的Controller并且返回,如果当前没有找到对应的Controller处理器,那么程序会尝试查找配置中的默认处理器 * 当然,当查找的controller为String类型的时,那就意味着返回的是配置的bean名称,需要根据bean名称查找对应的Bean,最后还要 * 通过getHandlerExecutionChain()方法对返回的Handler进行封装,以保证满足返回类型的匹配 */ public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 根据request获取对应的handler Object handler = getHandlerInternal(request); if (handler == null) { // 如果没有对应的request的handler则使用默认的handler handler = getDefaultHandler(); } if (handler == null) { return null; } if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } // 加入拦截器到执行链 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }

    根据Request查找对应的Handler(1) 截取用于匹配的url有效路径(2) 根据路径寻找Handler

    protected Object getHandlerInternal(HttpServletRequest request) throws Exception { // 截取用于匹配规则的URL有效路径 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); // 根据路径寻找Handler Object handler = lookupHandler(lookupPath, request); if (handler == null) { Object rawHandler = null; if ("/".equals(lookupPath)) { // 如果请求的路径仅仅是"/" 那么使用RootHandler处理 rawHandler = getRootHandler(); } if (rawHandler == null) { // 如果无法找到handler则使用默认handler rawHandler = getDefaultHandler(); } if (rawHandler != null) { if (rawHandler instanceof String) { // 根据beanName获取对应的Bean String handlerName = (String) rawHandler; rawHandler = getApplicationContext().getBean(handlerName); } // 模板方法 validateHandler(rawHandler, request); handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null); } } return handler; }

    将Handler封装成HandlerExecutionChain类型,并且加入两个拦截器,这是一个很优秀的设计模式,后面会专门说到

    protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern, String pathWithinMapping, Map<String, String> uriTemplateVariables) { HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler); // 加入拦截器 chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping)); // 加入拦截器 if (!CollectionUtils.isEmpty(uriTemplateVariables)) { chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables)); } return chain; } HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); 这段代码其实就是将配置的拦截器加入到拦截链中 ---- 相关资源:新年快乐! python实现绚烂的烟花绽放效果

    最新回复(0)