SpingMVC模块常用几种handlerMapping的初始化过程
2017-10-25 15:45
597 查看
以xml文件为例,内容如下
这里,主要关心的是HandlerMapping接口实现类的初始化问题,所以主要关注以下两个标签即可。
针对mvc的命名空间,spring-webmvc工程中spring.handlers内容如下http://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
1、RequestMappingHandlerMapping类的引入与初始化
RequestMappingHandlerMapping类引入
annotation-driven标签,用来支持基于注解的映射,它的实现类是AnnotationDrivenBeanDefinitionParser,这个类又向容器中注册了RequestMappingHandlerMapping,它就是一个HandlerMapping接口实现类。 RequestMappingHandlerMapping是默认的第一个HandlerMapping,因为它实现了order接口,同时赋值为0。
RequestMappingHandlerMapping类初始化
这里主要是说url和handler之间映射关系的初始化,对应AbstractHandlerMethodMapping类的urlMap属性。RequestMappingHandlerMapping类实现了InitializingBean接口,所以初始化时会调用RequestMappingHandlerMapping类的afterPropertiesSet方法,url和handler之间映射关系的初始化就是这里,是通过扫描特定包内类的注解实现的。例如,扫描到com.winksi.roinchina.controller包下的RoinChinaController类时,发现getToken方法有注解@RequestMapping,所以就会向urlMap内,添加一条记录,key为/getToken。
2、SimpleUrlHandlerMapping类的引入与初始化
SimpleUrlHandlerMapping类的引入
default-servlet-handler标签的解析,会引入DefaultServletHandlerBeanDefinitionParser解析类。在DefaultServletHandlerBeanDefinitionParser类的parse方法内,会引入SimpleUrlHandlerMapping类。
SimpleUrlHandlerMapping类的初始化
SimpleUrlHandlerMapping实现了ApplicationContextAware接口(定义setApplicationContext方法),所以初始化SimpleUrlHandlerMapping时,会调用SimpleUrlHandlerMapping类的setApplicationContext方法。因为SimpleUrlHandlerMapping没有实现setApplicationContext方法,所以实际调用的是ApplicationObjectSupport类的setApplicationContext方法。具体调用顺序,可以参考下图。
需要注意SimpleUrlHandlerMapping类的urlMap属性的赋值,这个属性的复制是在DefaultServletHandlerBeanDefinitionParser类注册SimpleUrlHandlerMapping类时实现的。具体代码如下
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 默认的注解映射的支持 --> <context:component-scan base-package="**.**.controller"/> <mvc:annotation-driven> <mvc:message-converters> <ref bean="fastJsonHttpMessageConverter" /> </mvc:message-converters> </mvc:annotation-driven> <mvc:default-servlet-handler /> <!-- 处理JSON数据转换的 --> <bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"> <!-- 为了处理返回的JSON数据的编码,默认是ISO-88859-1的,这里把它设置为utf-8,解决有乱码的情况 --> <property name="supportedMediaTypes"> <list> <value>application/json;charset=utf-8</value> </list> </property> </bean> </beans>
这里,主要关心的是HandlerMapping接口实现类的初始化问题,所以主要关注以下两个标签即可。
<mvc:annotation-driven> <mvc:default-servlet-handler/>
针对mvc的命名空间,spring-webmvc工程中spring.handlers内容如下http://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
public class MvcNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser()); registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser()); registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser()); registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser()); registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser()); } }
1、RequestMappingHandlerMapping类的引入与初始化
RequestMappingHandlerMapping类引入
<mvc:annotation-driven>
annotation-driven标签,用来支持基于注解的映射,它的实现类是AnnotationDrivenBeanDefinitionParser,这个类又向容器中注册了RequestMappingHandlerMapping,它就是一个HandlerMapping接口实现类。 RequestMappingHandlerMapping是默认的第一个HandlerMapping,因为它实现了order接口,同时赋值为0。
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { 。。。。。。 public BeanDefinition parse(Element element, ParserContext parserContext) { 。。。。。。 RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class); handlerMappingDef.setSource(source); handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); //RequestMappingHandlerMapping是handler中默认的第一个,因为实现了order接口 handlerMappingDef.getPropertyValues().add("order", 0); handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager); 。。。。。。 // Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off" MvcNamespaceUtils.registerDefaultComponents(parserContext, source); parserContext.popAndRegisterContainingComponent(); return null; } 。。。。。。 }
RequestMappingHandlerMapping类初始化
这里主要是说url和handler之间映射关系的初始化,对应AbstractHandlerMethodMapping类的urlMap属性。RequestMappingHandlerMapping类实现了InitializingBean接口,所以初始化时会调用RequestMappingHandlerMapping类的afterPropertiesSet方法,url和handler之间映射关系的初始化就是这里,是通过扫描特定包内类的注解实现的。例如,扫描到com.winksi.roinchina.controller包下的RoinChinaController类时,发现getToken方法有注解@RequestMapping,所以就会向urlMap内,添加一条记录,key为/getToken。
/** * Interface to be implemented by beans that need to react once all their * properties have been set by a BeanFactory: for example, to perform custom * initialization, or merely to check that all mandatory properties have been set. * * <p>An alternative to implementing InitializingBean is specifying a custom * init-method, for example in an XML bean definition. * For a list of all bean lifecycle methods, see the BeanFactory javadocs. * * @author Rod Johnson * @see BeanNameAware * @see BeanFactoryAware * @see BeanFactory * @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName * @see org.springframework.context.ApplicationContextAware */ public interface InitializingBean { /** * Invoked by a BeanFactory after it has set all bean properties supplied * (and satisfied BeanFactoryAware and ApplicationContextAware). * <p>This method allows the bean instance to perform initialization only * possible when all bean properties have been set and to throw an * exception in the event of misconfiguration. * @throws Exception in the event of misconfiguration (such * as failure to set an essential property) or if initialization fails. */ void afterPropertiesSet() throws Exception; }
package com.winksi.roinchina.controller; @Controller public class RoinChinaController { private static final Logger log = LoggerFactory.getLogger(RoinChinaController.class); public RoinChinaController(){ log.info("RoinChinaController init"); } /** * 查询归属地v1.0接口 * * @param input * @return */ @RequestMapping(value = "/getToken", method = RequestMethod.POST) @ResponseBody public JSONObject getToken(@RequestBody JSONObject input) { JSONObject json = new JSONObject(); json.put("akey", "avalue"); return json; } }
2、SimpleUrlHandlerMapping类的引入与初始化
SimpleUrlHandlerMapping类的引入
<mvc:default-servlet-handler/>
default-servlet-handler标签的解析,会引入DefaultServletHandlerBeanDefinitionParser解析类。在DefaultServletHandlerBeanDefinitionParser类的parse方法内,会引入SimpleUrlHandlerMapping类。
class DefaultServletHandlerBeanDefinitionParser implements BeanDefinitionParser { public BeanDefinition parse(Element element, ParserContext parserContext) { Object source = parserContext.extractSource(element); String defaultServletName = element.getAttribute("default-servlet-name"); RootBeanDefinition defaultServletHandlerDef = new RootBeanDefinition(DefaultServletHttpRequestHandler.class); defaultServletHandlerDef.setSource(source); defaultServletHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); if (StringUtils.hasText(defaultServletName)) { defaultServletHandlerDef.getPropertyValues().add("defaultServletName", defaultServletName); } String defaultServletHandlerName = parserContext.getReaderContext().generateBeanName(defaultServletHandlerDef); parserContext.getRegistry().registerBeanDefinition(defaultServletHandlerName, defaultServletHandlerDef); parserContext.registerComponent(new BeanComponentDefinition(defaultServletHandlerDef, defaultServletHandlerName)); Map<String, String> urlMap = new ManagedMap<String, String>(); urlMap.put("/**", defaultServletHandlerName); RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class); handlerMappingDef.setSource(source); handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); handlerMappingDef.getPropertyValues().add("urlMap", urlMap); String handlerMappingBeanName = parserContext.getReaderContext().generateBeanName(handlerMappingDef); parserContext.getRegistry().registerBeanDefinition(handlerMappingBeanName, handlerMappingDef); parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, handlerMappingBeanName)); /** * 里面有RootBeanDefinition beanNameMappingDef = new RootBeanDefinition(BeanNameUrlHandlerMapping.class);类的定义 */ // Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off" MvcNamespaceUtils.registerDefaultComponents(parserContext, source); return null; } }
SimpleUrlHandlerMapping类的初始化
SimpleUrlHandlerMapping实现了ApplicationContextAware接口(定义setApplicationContext方法),所以初始化SimpleUrlHandlerMapping时,会调用SimpleUrlHandlerMapping类的setApplicationContext方法。因为SimpleUrlHandlerMapping没有实现setApplicationContext方法,所以实际调用的是ApplicationObjectSupport类的setApplicationContext方法。具体调用顺序,可以参考下图。
需要注意SimpleUrlHandlerMapping类的urlMap属性的赋值,这个属性的复制是在DefaultServletHandlerBeanDefinitionParser类注册SimpleUrlHandlerMapping类时实现的。具体代码如下
Map<String, String> urlMap = new ManagedMap<String, String>(); urlMap.put("/**", defaultServletHandlerName); RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class); handlerMappingDef.setSource(source); handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); handlerMappingDef.getPropertyValues().add("urlMap", urlMap);
相关文章推荐
- Python模块常用的几种安装方式
- 认识和选用常用的几种 GPRS 模块(转)
- 常用的几种交互表存储过程的实现方法
- Python模块常用的几种安装方式
- Python模块常用的几种安装方式
- 软件设计过程中常用的几种图(一)
- http模块初始化过程
- 常用的几种交互表存储过程的实现方法
- 常用的几种交互表存储过程的实现方法
- 认识和选用常用的几种 GPRS 模块
- 软件设计过程中常用的几种图(二)
- 常用的几种交互表存储过程的实现方法
- Python模块常用的几种安装方式
- Python模块常用的几种安装方式
- 软件设计过程中常用的几种图(一)
- 详解VUE中常用的几种import(模块、文件)引入方式
- MFC dll的初始化过程及关于模块状态的错误
- ARCGIS常用几种本地数据AE初始化
- 常用的几种交互表存储过程的实现方法
- 常用的几种交互表存储过程的实现方法