请求具体过程

一、HandlerMapping

Interface to be implemented by objects that define a mapping between requests and handler objects.

  1. HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

HandlerExecutionChain(包含一个处理器 handler 如HandlerMethod 对象、多个 HandlerInterceptor 拦截器对象)

  • RequestMappingHandlerMapping 的映射关系由 MappingRegistry 维护,通过多个map联结,即可找到请求对应的处理器
  • RequestMappingHandlerMapping 的映射关系初始化入口是 afterProperties 方法,因为其实现了接口 InitializingBean

SpringMVC的请求处理过程中的路径匹配过程(AbstractHandlerMethodMapping#lookupHandlerMethod)

  1. protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
  2. List<Match> matches = new ArrayList<Match>();
  3. List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
  4. if (directPathMatches != null) {
  5. addMatchingMappings(directPathMatches, matches, request);
  6. }
  7. if (matches.isEmpty()) {
  8. // 如正则匹配、RESTFUL路径/list/{cityId}等,这里可以改进,No choice but to go through all mappings...
  9. addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
  10. }
  11.  
  12. if (!matches.isEmpty()) {
  13. Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
  14. Collections.sort(matches, comparator);
  15. if (logger.isTraceEnabled()) {
  16. logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
  17. lookupPath + "] : " + matches);
  18. }
  19. Match bestMatch = matches.get(0);
  20. if (matches.size() > 1) {
  21. if (CorsUtils.isPreFlightRequest(request)) {
  22. return PREFLIGHT_AMBIGUOUS_MATCH;
  23. }
  24. Match secondBestMatch = matches.get(1);
  25. if (comparator.compare(bestMatch, secondBestMatch) == 0) {
  26. Method m1 = bestMatch.handlerMethod.getMethod();
  27. Method m2 = secondBestMatch.handlerMethod.getMethod();
  28. throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
  29. request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
  30. }
  31. }
  32. handleMatch(bestMatch.mapping, lookupPath, request);
  33. return bestMatch.handlerMethod;
  34. }
  35. else {
  36. return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
  37. }
  38. }

RequestMappingHandlerMapping根据,细化匹配条件,整体的查找过程如下:

1.1 从urlMap中直接等值匹配查找匹配条件RequestMappingInfo

1.2 如果等值查找到匹配条件,将其添加到match条件中

1.3 如果没有找到匹配条件,使用所有的handlerMethod的RequestMappingInfo进行匹配

1.4 对匹配到的Match进行排序,取出最高优先级的Match,并核对是否是唯一的最高优先级

二、获取HandlerExecutionChain(AbstractHandlerMapping#getHandler)

  1. @Override
  2. public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
         //模板方法
  3. Object handler = getHandlerInternal(request);
  4. if (handler == null) {
  5. handler = getDefaultHandler();
  6. }
  7. if (handler == null) {
  8. return null;
  9. }
  10. // Bean name or resolved handler?
  11. if (handler instanceof String) {
  12. String handlerName = (String) handler;
  13. handler = getApplicationContext().getBean(handlerName);
  14. }
  15.      //把Handler和HandlerInterceptor包裹成HandlerExecutionChain
  16. HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
  17. if (CorsUtils.isCorsRequest(request)) {
  18. CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
  19. CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
  20. CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
  21. executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
  22. }
  23. return executionChain;
  24. }

3.getHandlerExecutionChain调用

  1. protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
         //为啥这里要做判断,因为DispatchServlet里面的doDispatch调用getHandler返回的是HandlerExecutionChain
  2. HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
  3. (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
  4.  
  5. String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
  6. for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
  7. if (interceptor instanceof MappedInterceptor) {
  8. MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
  9. if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
  10. chain.addInterceptor(mappedInterceptor.getInterceptor());
  11. }
  12. }
  13. else {
  14. chain.addInterceptor(interceptor);
  15. }
  16. }
  17. return chain;
  18. }

三、选择使用HandlerMapping

如何选择合适的HandlerMapping

  1. protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  2. for (HandlerMapping hm : this.handlerMappings) {
  3. if (logger.isTraceEnabled()) {
  4. logger.trace(
  5. "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
  6. }
           //如何选择不同的HandlerMapping
  7. HandlerExecutionChain handler = hm.getHandler(request);
  8. if (handler != null) {
  9. return handler;
  10. }
  11. }
  12. return null;
  13. }

springMVC(五): 通过 HandlerMapping 获取 HandlerExecutionChain的更多相关文章

  1. java:JavaScript2:(setTimeout定时器,history.go()前进/后退,navigator.userAgent判断浏览器,location.href,五种方法获取标签属性,setAttribute,innerHTML,三种方法获取form表单信息,JS表单验证,DOM对象,form表单操作)

    1.open,setTimeout,setInterval,clearInterval,clearTimeout <!DOCTYPE> <html> <head> ...

  2. SpringMVC请求参数的获取方式

    一.GET请求参数获取 1. 通过HttpServletRequest获取参数 2. 直接方法参数获取 3. RequestParam注解方式获取请求参数 4. Bean方式获取参数 5. Model ...

  3. SpringMVC工作原理 : HandlerMapping和HandlerAdapter

    一.HandlerMapping 作用是根据当前请求的找到对应的 Handler,并将 Handler(执行程序)与一堆 HandlerInterceptor(拦截器)封装到 HandlerExecu ...

  4. SpringMVC(关于HandlerMapping执行流程原理分析)

    请求过来先碰见中央调度器(前端调度器) //Determine handler for the current request; 对当前请求决定交给哪个handler, 当前请求地址过来 处理器执行链 ...

  5. springmvc(五) 数据回显与自定义异常处理器

    这章讲解一下springmvc的数据回显和自定义异常处理器的使用,两个都很简单 --WH 一.数据回显技术 Springmvc默认支持对pojo类型的数据回显,默认不支持简单类型的数据回显 1.1.什 ...

  6. SpringMVC请求使用@PathVariable获取文件名称并且文件名中存在.导致路径被截取的问题

    在SpringMVC中,当使用@pathVariable通过Get请求获取路径名称时,如果路径名称上存在小数点,则获取不到小数点后面的内容,会被Spring截取. 比如我获取某一文件,路径是local ...

  7. SpringMVC传递参数和获取参数以及返回数据

    1.传递form表单,参数接收到对象,name和对象属性对应上即可:   2.springmvc不能直接通过form表单传递多个对象的list集合,要么采用ajax传递,要么采用封装了list属性的b ...

  8. 项目随笔之springmvc中freemark如何获取项目路径

    转载:http://blog.csdn.net/whatlookingfor/article/details/51538995 在SpringMVC框架中使用Freemarker试图时,要获取根路径的 ...

  9. 在springMVC的controller中获取request,response对象的一个方法

    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttr ...

随机推荐

  1. 带你Python入门,踏进人工智能领域

    1.Python能做什么? 不知大家 没有看<中国好声音>呢?有位选择就是利用AI改编了一首周杰伦的歌<止战之殇>. Python适合做人工智能AI吗? 很明确的告诉你,可以! ...

  2. JSON.stringify转化报错

    两种方式会导致该错误:1.json格式数据存在循环调用.   举个例子: var obj = { title: '标题'}obj.content = obj;JSON.stringify(obj); ...

  3. 环境的配置; host 配置地址

    1.环境的配置: C:\Windows\System32\drivers\etc 2.如果没有下载host 切记复制etc的文件,在c盘桌面打开,更改后替换 3.可下载host 和fiddle 4.多 ...

  4. iOS 开发网络篇—监测网络状态

    iOS开发网络篇—监测网络状态 一.说明 在网络应用中,需要对用户设备的网络状态进行实时监控,有两个目的: (1)让用户了解自己的网络状态,防止一些误会(比如怪应用无能) (2)根据用户的网络状态进行 ...

  5. 怎么让Windows2012和Windows2008多用户同时远程---经过测试有效

    链接地址:https://jingyan.baidu.com/article/cd4c2979f19765756e6e60ec.html 怎么让Windows2012和Windows2008多用户同时 ...

  6. vs启动出错(chenlu-1):参数“basePath”不能是相对路径

    参数“basePath”不能是相对路径 原因: 1.调试路径下没有exe文件.没有生成exe文件. 2.项目属性->配置属性->调试->命令中的参数被设置为相对路径.

  7. C# WinForm窗体控件Panel修改边框颜色以及边框宽度方法

    C# WinForm窗体控件Panel修改边框颜色以及边框宽度方法 1.新建组件这里可以自定义一个Panel控件起名为PanelEx 2.增加一个BoderColor属性和BoderSize属性 pr ...

  8. [转]50个极好的bootstrap 后台框架主题下载

    50个极好的bootstrap 后台框架主题下载 http://sudasuta.com/bootstrap-admin-templates.html 越来越多的设计师和前端工程师开始用bootstr ...

  9. maven 中的mirror详解

    一.前言 今天同事遇到个问题,本来公司是有maven私服的,但同事觉得上面有些东西下载不到,于是在自己本地的maven配置中加了: <mirrors> <mirror> < ...

  10. JavaSE 可变参数的方法重载

    /** * 可变参数的方法重载 */ class A { public void test(int a, int b) { System.out.println(a+", "+b) ...