您的位置 首页 > 腾讯云社区

【springmvc】controller的初始化与匹配---平凡的学生族

初始化

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 初始化搜集所有控制器方法的过程分析文章的开头和结尾都总结得很好,但我在此也写下自己的理解(与原文大同小异):

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

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

通过mappingRegistry会获取可能路径前缀匹配的RequestMappingInfoaddMatchingMappings将RequestMappingInfo数组转为Match数组。利用了mappingRegistry。按照匹配程度排序选出最佳匹配的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); } ... ---来自腾讯云社区的---平凡的学生族

关于作者: 瞎采新闻

这里可以显示个人介绍!这里可以显示个人介绍!

热门文章

留言与评论(共有 0 条评论)
   
验证码: