网上介绍HandlerMapping和HandlerAdapter的文章很多,今天我用自己的理解和语言来介绍下HandlerMapping和HandlerAdapter

一. HandlerMapping和HandlerAdapter的作用和背景:

SpringMVC的M、V、C就不说了,HandlerMapping就是用来存放用户Request(具体可以理解为一个请求URL)和处理具体请求的Handler中的method关系的地方,例如:将/query?id=XXX的请求交给XXXService.queryById(int id)这个方法来处理。

真正调用一个方法,首先必须找到方法定义,然后传入实参。HandlerMapping是用来映射URL和method的关系的话,HandlerAdapter是用来负责传递方法的实参。

二. HandlerMapping和HandlerAdapter的构成:

在Spring源码中,HandlerMapping含有HandlerExcutionChain对象,HandlerExcutionChain是由Handler和拦截器组成。有兴趣可以看下源代码,这里我仍然用自己的理解和语言来描述。

HandlerExcutionChain你可以理解为一个对象,它是由Object(实际上就是Controller)、URL Pattern(URL的封装)和Method组成(具体对应的就是HandlerExcutionChain中的handler、interceptors),或者你可以这么理解HandlerMapping就是List<MyHandlerMapping(handler,method,url)>,URL请求交给Controller的method()来处理。

其中handler就是SpringMVC中所有的Controller(例如:加上@Controller的类),可以循环context中所有BeanName对应的Bean,判断Bean对象是否有@Controller标签来实现。method就是Controller中具体执行请求的方法,通过循环Bean中的所有method,判断是否有@RequestMapping的value和请求的url是否匹配。url就是把Controller和method的@RequestMapping拼起来。

HandlerAdapter是用来存放调用Controller的method时传入的形参类型,在SpringMVC中参数都是在请求URL上带入的。我们可以把HandlerAdapter理解为一个Map<HandlerMapping,paramMapping<position index,param type>>,其中HandlerMapping是用来保存请求的URL和Controller的method之间的关系,paramMapping用来保存该HandlerMapping.method的形参类型(paramMapping的key是position index,value是param type)

// HandlerMapping源码
public interface HandlerMapping {
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";
String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes"; HandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception;
} // HandlerExcutionChain源码
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
private final Object handler;
private HandlerInterceptor[] interceptors;
private List<HandlerInterceptor> interceptorList;
private int interceptorIndex;
public HandlerExecutionChain(Object handler) {
this(handler, (HandlerInterceptor[])null);
} public HandlerExecutionChain(Object handler, HandlerInterceptor... interceptors) {
this.interceptorIndex = -1;
if (handler instanceof HandlerExecutionChain) {
HandlerExecutionChain originalChain = (HandlerExecutionChain)handler;
this.handler = originalChain.getHandler();
this.interceptorList = new ArrayList();
CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
} else {
this.handler = handler;
this.interceptors = interceptors;
} } public Object getHandler() {
return this.handler;
} public void addInterceptor(HandlerInterceptor interceptor) {
this.initInterceptorList().add(interceptor);
} public void addInterceptors(HandlerInterceptor... interceptors) {
if (!ObjectUtils.isEmpty(interceptors)) {
CollectionUtils.mergeArrayIntoCollection(interceptors, this.initInterceptorList());
} } private List<HandlerInterceptor> initInterceptorList() {
if (this.interceptorList == null) {
this.interceptorList = new ArrayList();
if (this.interceptors != null) {
CollectionUtils.mergeArrayIntoCollection(this.interceptors, this.interceptorList);
}
} this.interceptors = null;
return this.interceptorList;
} public HandlerInterceptor[] getInterceptors() {
if (this.interceptors == null && this.interceptorList != null) {
this.interceptors = (HandlerInterceptor[])this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
} return this.interceptors;
} boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
} return true;
} void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = interceptors.length - 1; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
} } void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = this.interceptorIndex; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i]; try {
interceptor.afterCompletion(request, response, this.handler, ex);
} catch (Throwable var8) {
logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
}
}
} } void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = interceptors.length - 1; i >= 0; --i) {
if (interceptors[i] instanceof AsyncHandlerInterceptor) {
try {
AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor)interceptors[i];
asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);
} catch (Throwable var6) {
logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", var6);
}
}
}
} } public String toString() {
Object handler = this.getHandler();
if (handler == null) {
return "HandlerExecutionChain with no handler";
} else {
StringBuilder sb = new StringBuilder();
sb.append("HandlerExecutionChain with handler [").append(handler).append("]");
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
sb.append(" and ").append(interceptors.length).append(" interceptor");
if (interceptors.length > 1) {
sb.append("s");
}
} return sb.toString();
}
}
}

按照自己理解写的intiHandlerMapping()方法:

private void initHandlerMappings(ApplicationContext context) {
//首先从容器中取到所有的实例
String[] beanNames = context.getBeanDefinitionNames();
try {
for (String beanName : beanNames) {
Object controller = context.getBean(beanName);
Class<?> clazz = controller.getClass();
//但是不是所有的牛奶都叫特仑苏,只有带有@Controller的才处理
if (!clazz.isAnnotationPresent(Controller.class)) {
continue;
} String baseUrl = ""; if (clazz.isAnnotationPresent(RequestMapping.class)) {
RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class);
baseUrl = requestMapping.value();
} //扫描所有的public方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (!method.isAnnotationPresent(RequestMapping.class)) {
continue;
}
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
String regex = ("/" + baseUrl + requestMapping.value().replaceAll("\\*", ".*")).replaceAll("/+", "/");
Pattern pattern = Pattern.compile(regex);
this.handlerMappings.add(new HandlerMapping(pattern, controller, method));
System.out.println("Mapping: " + regex + " , " + method);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

SpringMVC-HandlerMapping和HandlerAdapter的更多相关文章

  1. SpringMVC源码总结(一)HandlerMapping和HandlerAdapter入门

    SpringMVC在使用过程中,大多是使用注解,对它的实现接口之类的关系理解变得模糊, 通过对XML配置的理解,可以理清各个类的关系,譬如控制器类要实现Controller接口. 接触SpringMV ...

  2. Spring MVC源码分析(三):SpringMVC的HandlerMapping和HandlerAdapter的体系结构设计与实现

    概述在我的上一篇文章:Spring源码分析(三):DispatcherServlet的设计与实现中提到,DispatcherServlet在接收到客户端请求时,会遍历DispatcherServlet ...

  3. springMVC3学习(三)--handlerMapping和handlerAdapter

    基本结构和 springMVC3学习(一)--框架搭建 差不多,这里不再用Annotation注解的方式 以下只说明需要修改的部分: 1.在Spring配置文件中配置HandlerMapping.Ha ...

  4. HandlerMapping和HandlerAdapter配置须知

    ---------------------siwuxie095                                 HandlerMapping 和 HandlerAdapter 配置须知 ...

  5. 从源码的角度彻底搞懂 HandlerMapping 和 HandlerAdapter

    彻底搞懂 HandlerMapping和HandlerAdapter 知识点的回顾: 当Tomcat接收到请求后会回调Servlet的service方法,一开始入门Servlet时,我们会让自己的Se ...

  6. Spring mvc之源码 handlerMapping和handlerAdapter分析

    Spring mvc之源码 handlerMapping和handlerAdapter分析 本篇并不是具体分析Spring mvc,所以好多细节都是一笔带过,主要是带大家梳理一下整个Spring mv ...

  7. Spring MVC中的HandlerMapping与HandlerAdapter

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  8. [Java] SpringMVC工作原理之二:HandlerMapping和HandlerAdapter

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

  9. SpringMVC工作原理 : HandlerMapping和HandlerAdapter

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

  10. Spring MVC 梳理 - handlerMapping和handlerAdapter分析

    参考图片 综上所述我们来猜测一下spring mvc 中根据URL找到处理器Controller中相应方法的流程 ①:获取Request的URL ②:从UrlLookup这个map中找到相应的requ ...

随机推荐

  1. Scrapy源代码分析-经常使用的爬虫类-CrawlSpider(三)

    CrawlSpider classscrapy.contrib.spiders.CrawlSpider 爬取一般站点经常使用的spider.其定义了一些规则(rule)来提供跟进link的方便的机制. ...

  2. 利用GDAL实现影像的几何校正

    一.概述 遥感影像和地理坐标进行关联的方式一般有好几种,一种是直接给出了仿射变换系数,即6个參数,左上角地理坐标,纵横方向上的分辨率,以及旋转系数.在这样的情况下,求出某一像素点的地理坐标非常easy ...

  3. Windows 平台下 Go 语言的安装和环境变量设置

    1. Go 语言 SDK 安装包下载和安装 最新稳定版 1.5.3 安装包 go1.5.3.windows-amd64.msi下载地址 https://golang.org/dl/,大小约 69 MB ...

  4. 国外物联网平台初探(二) ——微软Azure IoT

    平台定位 连接设备.其它 M2M 资产和人员,以便在业务和操作中更好地利用数据. 连接 IoT 设备 将所有设备连接到云,从这些设备接收大规模数据,以及管理这些设备的授权和限制. 在将设备连接到云和处 ...

  5. 杂项: EasyUI | jQuery EasyUI

    ylbtech-杂项-JS: EasyUI | jQuery EasyUI jQuery EasyUI是一组基于jQuery的UI插件集合体,而jQuery EasyUI的目标就是帮助web开发者更轻 ...

  6. Spring配置之OpenSessionInViewFilter

    转自:https://www.cnblogs.com/blogonfly/articles/3991782.html 参考: OpenSessionInViewFilter作用及配置:http://w ...

  7. IO流读取文件内容时,出现空格的问题(未找到原因)

    import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOExceptio ...

  8. WPF黑色背景下常用控件样式

    平时工作用 自己整理的 代码等找到合适的上传空间在进行同步

  9. Datatable筛选数据

    DataRow[] drArr = dt.Select("C1=’abc’");//查询 还可以这样操作: DataRow[] drArr = dt.Select("C1 ...

  10. JavaScriptResult