1.handler是什么
     2. handler是如何获取的(不关注分析过程可以跳过直接看总结
     3.handle简单总结

1.handler是什么

了解过SpingMVC流程的同学一定听说过handler,百度翻译过来是处理者,很多博客中称之为处理器.那就按照大部分人的说法称呼它为控制器.说到控制器,会不会联想到我们平常写业务代码中的各种controller,也是控制器,是不是一种东西啊,这里可以大胆猜测一下就是一种东西嘛.好,现在通过源码进行验证猜测!

如果直接从源码中按照类文件类型直接搜索Handler是找不到的,根据springMVC的工作流程开始捋(有很多帖子说过这里不在重述),最早出现handler是在这个地方:
AbstractHandlerMapping.java中getHandler()

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {// 获取handler,如果获取为空则使用默认handler,如果默认的也没有则返回nullObject handler = getHandlerInternal(request);// 省略部分代码....}

测试案例发送实际请求:

@RequestMapping("/test")
@RestController
public class Test {@GetMapping("/add")public String add(String a,Personal personal,@RequestParam(name = "genderType") int gender){int i=0;return a;}}

对应请求来看一下debugg
Object handler = getHandlerInternal(request);
中handler具体是什么内容,截图如下

     从中可以看到handler实际上一个HandlerMethod类型对象,里面的属性有请求所在的类信息、请求方法、请求参数等内容。所以从这里可以认为handler相当于是平常业务代码中每个请求对应的的controller类以及方法信息.上面debug截图对应起来更容易理解!

2.handler是如何获取的

项目启动过程中会有包扫描,与本贴相关的扫描内容是将类上标注@RequestMapping的类信息以及方法上带有@RequestMapping的方法信息扫描到容器中(注意符合restful风格的@GetMapping、@PostMapping等标注的方法信息也会扫描进去,下文会有介绍).每个带有以上注解的方法扫描到容器中都会有一个RequestMappingInfo(请求映射信息,实际上就是注解中各项属性和属性值的数据组装信息)。

具体请求过程实际上是从Map<RequestMappingInfo, MappingRegistration<RequestMappingInfo>>中根据请求对应的RequestMappingInfo获取对应的MappingRegistration,其中含有handler(实际上是HandlerMethod)。

先说项目启动,扫描@RequestMapping处理核心处理
RequestMappingHandlerMapping.java中getMappingForMethod()

protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {// 根据方法上标注@RequestMapping注解获取RequestMappingInfoRequestMappingInfo info = createRequestMappingInfo(method);if (info != null) {// 根据方法所在类上标注@RequestMapping注解获取RequestMappingInfoRequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);if (typeInfo != null) {// 将按照类获取的RequestMappingInfo 与方法获取的RequestMappingInfo 进行组装生成新方法级别上的RequestMappingInfoinfo = typeInfo.combine(info);}// 省略部分代码....}return info;}

根据类信息或是方法信息创建RequestMapping的处理:
RequestMappingHandlerMapping.java中createRequestMappingInfo()

private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
// 获取类或是方法上带有@RequestMapping注解的RequestMapping注解信息(@GetMaping、@PostMapping等都是按照@RequestMapping进行解析,此类注解只不过是指定method为对应的GTE或POST请求方式的@RequestMapping)RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);// 获取类或是方法上自定义请求条件,此处都返回nullRequestCondition<?> condition = (element instanceof Class ?getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);}

具体组装RequestMappingInfo 逻辑:
RequestMappingHandlerMapping.java中createRequestMappingInfo()的重载方法

protected RequestMappingInfo createRequestMappingInfo(RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) {// 此处是读取@RequestMapping注解中各种属性值.比如说请求路径信息path、请求头信息headers、请求方式信息method等信息。RequestMappingInfo.Builder builder = RequestMappingInfo.paths(resolveEmbeddedValuesInPatterns(requestMapping.path())).methods(requestMapping.method()).params(requestMapping.params()).headers(requestMapping.headers()).consumes(requestMapping.consumes()).produces(requestMapping.produces()).mappingName(requestMapping.name());if (customCondition != null) {builder.customCondition(customCondition);}return builder.options(this.config).build();}

至此项目启动,能扫描到的类中所有带有@RequestMapping注解的方法都有一个RequestMappingInfo创建加载完成。
    发送请求获取HandlerMethod 逻辑
AbstractHandlerMethodMapping.java中getHandlerInternal

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {// 获取请求路径,此处不做展开介绍String lookupPath = initLookupPath(request);// 省略部分代码try {// 根据请求路径以及请求信息获取HandlerMethodHandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);}// 省略部分代码}

获取的具体逻辑在
AbstractHandlerMethodMapping.java中lookupHandlerMethod

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {List<Match> matches = new ArrayList<>();List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);if (directPathMatches != null) {addMatchingMappings(directPathMatches, matches, request);}if (matches.isEmpty()) {addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);}if (!matches.isEmpty()) {Match bestMatch = matches.get(0);// 省略部分代码bestMatch.getHandlerMethod());handleMatch(bestMatch.mapping, lookupPath, request);return bestMatch.getHandlerMethod();}// 省略部分代码}

梳理一下上面的逻辑:HandlerMethod由bestMatch.getHandlerMethod()获取,bestMatch由matches.get(0)获取,matches是由addMatchingMappings(directPathMatches, matches, request);进行封装处理而来.下面就继续看addMatchingMappings方法.
AbstractHandlerMethodMapping.java中addMatchingMappings()

private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {for (T mapping : mappings) {T match = getMatchingMapping(mapping, request);if (match != null) {matches.add(new Match(match, this.mappingRegistry.getRegistrations().get(mapping)));}}}

从上面可以发现matches中由Match组装而来,查看Match实现发现HandlerMethod是由getHandlerMethod()而来(见Match实现).到这终于搞清楚HandlerMethod的最终出处.

private class Match {private final T mapping;private final MappingRegistration<T> registration;public Match(T mapping, MappingRegistration<T> registration) {this.mapping = mapping;this.registration = registration;}public HandlerMethod getHandlerMethod() {return this.registration.getHandlerMethod();}// 省略部分代码.....}

那问题来了,映射注册器中MappingRegistration中如何进行组装的HandlerMethod.不要着急请继续往下看.
    分析发现项目启动过程中,容器会将所有’‘认为’'是handler的bean(实际就是带有@Controller或是@RequestMapping的类,至于为什么下面有讲)中的方法对象method与映射对象信息RequestMapping进行做注册匹配.
     RequestMappingHandlerMapping.java中isHandler

protected boolean isHandler(Class<?> beanType) {//定义了哪种beanType符合Handler.即类中有@Controller或是@RequestMapping注解return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));}

注册匹配具体处理:
将handler与对应的requestMapping做对应匹配放到注册器中.

public void register(T mapping, Object handler, Method method) {// 省略部分代码....// 按照handler与method对象进行组装HandlerMethod.(两个参数对应测试案例中的类的beanName:test,以及请求方法对象:public java.lang.String com.it.txm.demo.methodReslove.Test.add(java.lang.String,com.it.txm.demo.methodReslove.Personal,int));创建过程就是简单的构造函数创建,不深入分析.HandlerMethod handlerMethod = createHandlerMethod(handler, method);// 省略部分代码....// 将requestMappingInfo和包含handlerMethod的信息组装到映射MappingRegistrythis.registry.put(mapping,new MappingRegistration<>(mapping, handlerMethod, directPaths, name, corsConfig != null));}

至此handlerMethod的来龙去脉已经梳理完毕!

3.handler简单总结

handler相当于是平常业务代码中每个请求对应的的controller类以及方法信息.文章第一部分的debug截图对应起来更容易理解!

handler来源分析:
          1.项目启动过程中将所带有@RequestMapping注解的方法对应创建一个requestMappingInfo对象(存储注解中各属性信息);
         2.项目启动过程中,容器会将所有的认为是handler的bean中的每个方法进行匹配处理,期间会创建handlerMethod,将映射信息RequestMappingInfo与MappingRegistration(其中包含handlerMethod)进行组装map处理,前者为key,后者为value.
         3.发送请求,解析请求信息,从Map<RequestMappingInfo, MappingRegistration<RequestMappingInfo>>中根据RequestMappingInfo获取MappingRegistration信息,在从中获取HandlerMethod.

通俗易懂聊springMVC中的handler是什么相关推荐

  1. springmvc中的设计模式---适配器模式_晏无心_新浪博客

    springmvc的基本流程在之前的文章里都大致分析完了,接下来总结下springmvc中运用了哪些设计模式. 一.设计模式 什么是设计模式,通俗来讲,就是是一套被反复使用.多数人知晓的.经过分类的. ...

  2. JavaEE开发之SpringMVC中的自定义拦截器及异常处理

    上篇博客我们聊了<JavaEE开发之SpringMVC中的路由配置及参数传递详解>,本篇博客我们就聊一下自定义拦截器的实现.以及使用ModelAndView对象将Controller的值加 ...

  3. SpringMVC中的拦截器

    SpringMVC中的拦截器 拦截器的作用 Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理. 用户可以自己定义一些拦截器来实现 ...

  4. SpringMVC 中的异常处理

    SpringMVC 中的异常处理 异常处理的思路 系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发.测试通过手段减 ...

  5. springMVC中Dispatcher中的/和/*的区别

    1. 首先 / 这个是表示默认的路径,及表示:当没有找到可以匹配的URL就用这个URL去匹配. 2. 在springmvc中可以配置多个DispatcherServlet,比如: 配置多个Dispat ...

  6. 框架:SpringMVC中Interceptor拦截器的两种实现

    Spring中使用Interceptor拦截器 SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证, ...

  7. SpringMVC中使用Interceptor拦截器

    2019独角兽企业重金招聘Python工程师标准>>> SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理. ...

  8. 一篇文章教你弄懂 SpringMvc中的HandlerInterceptor

    文章列表 一.HandlerInterceptor简介 一.HandlerInterceptor应用实例 写在前面: 我是「境里婆娑」.我还是从前那个少年,没有一丝丝改变,时间只不过是考验,种在心中信 ...

  9. java中的model_Java程序员必看之springmvc中的Model对象在重定向中的数据

    原标题:Java程序员必看之springmvc中的Model对象在重定向中的数据 在springmvc框架中,一个handler方法中的参数可以内置接收Model类型的对象,主要用于存储数据之用,主要 ...

最新文章

  1. java订单实现的_java订单系统的开发
  2. ucache来广营(望京)机房
  3. “一切都是消息”--iMSF(即时消息服务框架)之【请求-响应】模式(点对点)...
  4. 嵌套母版页中的控件访问
  5. JDK版本Java SE、Java EE、Java ME的区别
  6. C++ vector 使用详解
  7. xml.query() 实例演示
  8. app运行租用服务器,app租用服务器
  9. python 映射网络驱动器_用Delphi实现网络驱动器的映射和断开
  10. Lockdir 文件夹加密 破解
  11. 毕业生见习期考核鉴定表(单位考核意见)
  12. 查看英伟达NVIDIA显卡型号
  13. linux head
  14. Jmeter把响应数据结果保存到本地文件
  15. 怎么更改當前的USERENV(#39;LANG#39;)返回值 oracle
  16. LaTeX入门学习(2)(安装)
  17. 毁掉一个孩子只要十步(80%的家长都在做)
  18. 哈代-温伯格平衡定律(The Hardy-Weinberg Equilibrium)
  19. 2015计算机考试成绩查询网址,2015年下半年软考成绩查询入口!
  20. html带复选框的表格,Html 表格行 ID 复选框

热门文章

  1. Git 工作中怎么用?
  2. 2021年中式烹调师(中级)考试题及中式烹调师(中级)找解析
  3. p16panda合并concat
  4. 盘点美国最出人意料的20种高薪职业
  5. Java练习:单选题
  6. ctfshow---命令执行
  7. 江西省南昌市谷歌高清卫星地图下载(百度网盘离线包下载)
  8. css旋转不围绕圆心,css3:元素总是围绕中心旋转[关闭](css3: element always rotates around center [closed])...
  9. 制药实验室信息管理系统(LIMS)
  10. MySql高级(教学版)