首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【springmvc】controller的初始化与匹配

【springmvc】controller的初始化与匹配

作者头像
平凡的学生族
发布2020-03-26 11:14:38
1.1K0
发布2020-03-26 11:14:38
举报
文章被收录于专栏:后端技术后端技术

初始化

DispatcherServlet的初始化流程 讲述DispatcherServlet从Servlet::init一路调用至DispatcherServlet::initStrategies的过程。

protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
}

initHandlerMappings会初始化一些HandlerMapping,在处理请求时,DispatcherServlet会调用getHandler:

// DispatcherServlet.java

@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        // 遍历 HandlerMapping 数组
        for (HandlerMapping mapping : this.handlerMappings) {
            // 获得请求对应的 HandlerExecutionChain 对象
            HandlerExecutionChain handler = mapping.getHandler(request);
            // 获得到,则返回
            if (handler != null) {
                return handler;
            }
        }
    }
    return null;
}

当能获取到HandlerExecutionChain时就返回。@RequestMapping一般对应由RequestMappingHandlerMapping处理。

RequestMappingHandlerMapping初始化

我们已经知道,@Controller和@RequestMapping是由RequestMappingHandlerMapping处理的,那么它们是如何被收集的呢? RequestMappingHandlerMapping 初始化搜集所有控制器方法的过程分析文章的开头和结尾都总结得很好,但我在此也写下自己的理解(与原文大同小异):

  1. 注入Bean。WebMvcConfigurationSupport配置类会将RequestMappingHandlerMapping作为
  2. 调用回调。RequestMappingHandlerMapping实现了InitializingBean,在Bean 创建时会回调afterPropertiesSet。并调用至initHandlerMethods
  3. initHandlerMethods完成三件事:
    1. 获取所有Bean(getCandidateBeanNames)
    2. 筛选符合的Bean。判断其是否为@Controller或@RequestMapping(isHandler)
    3. 对符合的Bean,包装其@RequestMapping方法为RequestMappingInfo并注册。(AbstractHandlerMethodMapping::detectHandlerMethods)

运行时

DispatcherServlet::getHandler会一路运行至AbstractHandlerMethodMapping::lookupHandlerMethod,在这里:

  1. 通过mappingRegistry会获取可能路径前缀匹配的RequestMappingInfo
  2. addMatchingMappings将RequestMappingInfo数组转为Match数组。利用了mappingRegistry。
  3. 按照匹配程度排序选出最佳匹配的RequestMappingInfo,并返回其对应的HandlerMethod

Math包含了

private class Match {

        private final T mapping;

        private final HandlerMethod handlerMethod;

从下文的if (matches.isEmpty()),结合自己调试可知: 当路径能完美匹配时,比如以下代码匹配/hello/t

@RestController
@RequestMapping("/hello")
public class HelloController {
    @GetMapping("/t")
    public String hello() {
        return "this is hello";
    }
}

则会执行if (directPathMatches != null) {...},如果@GetMapping("/t")换成@GetMapping("/t*"),则没有完美路径匹配,会执行if (matches.isEmpty()) {...}

@Nullable
    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
        List<Match> matches = new ArrayList<>();
        List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
        if (directPathMatches != null) {
            addMatchingMappings(directPathMatches, matches, request);
        }
        if (matches.isEmpty()) {
            // No choice but to go through all mappings...
            addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
        }
               ...
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 初始化
  • RequestMappingHandlerMapping初始化
  • 运行时
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档