做门户网站有前途吗,扒人家网站做网站,微信二维码生成器,全屏类网站springMVC的请求映射 上一次分析了一下springMVC的大致流程#xff0c;这次细分一下#xff0c;对请求映射进行分析。 先从DispatcherServlet中的getHandler()方法分析 protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {for (Hand…springMVC的请求映射 上一次分析了一下springMVC的大致流程这次细分一下对请求映射进行分析。 先从DispatcherServlet中的getHandler()方法分析 protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {for (HandlerMapping hm : this.handlerMappings) {if (logger.isTraceEnabled()) {logger.trace(Testing handler map [ hm ] in DispatcherServlet with name getServletName() );}HandlerExecutionChain handler hm.getHandler(request);if (handler ! null) {return handler;}}return null;
} 可以看到这是遍历所有的handlerMappings然后第一个返回不是NULL的handler既是那handlerMappings包含了那些实现类呢我们来看看initHandlerMappings这个方法 private void initHandlerMappings(ApplicationContext context) {this.handlerMappings null;//detectAllHandlerMappings 默认是trueif (this.detectAllHandlerMappings) {// 从ApplicationContext 里面获取HandlerMapping的实现类MapString, HandlerMapping matchingBeans BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);//根据Order对HandlerMappings进行排序if (!matchingBeans.isEmpty()) {this.handlerMappings new ArrayListHandlerMapping(matchingBeans.values());// We keep HandlerMappings in sorted order.AnnotationAwareOrderComparator.sort(this.handlerMappings);}}else {try {//获取bean name是handlerMapping的HandlerMapping实现类HandlerMapping hm context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);this.handlerMappings Collections.singletonList(hm);}catch (NoSuchBeanDefinitionException ex) {// Ignore, well add a default HandlerMapping later.}}//若HandlerMappings为空则设置默认的在DispatcherServlet同级目录下的DispatcherServlet.properties里面设置的org.springframework.web.servlet.HandlerAdapterorg.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapterif (this.handlerMappings null) {this.handlerMappings getDefaultStrategies(context, HandlerMapping.class);if (logger.isDebugEnabled()) {logger.debug(No HandlerMappings found in servlet getServletName() : using default);}}
} 所以若我们想使用自定义的HandlerMapping 可在springMVC的xml配置文件中加上一个HandlerMapping的实现类,若是使用的是 这个进行配置的其默认会加载RequestMappingHandlerMapping这个实现类(具体在org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser见)而可以在web.xml中将detectAllHandlerMappings 设置为false然后在springMVC.xml中配置一个name为handlerMapping的实现类。如下 // web.xml
servletservlet-namemyweb/servlet-nameservlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-classinit-paramparam-namecontextConfigLocation/param-nameparam-valueclasspath:mvc.xml/param-value/init-param!-- 不加载所有的HandlerMapping的实现类的bean --init-paramparam-namedetectAllHandlerMappings/param-nameparam-valuefalse/param-value/init-paramload-on-startup1/load-on-startup
/servlet//mvc.xml
bean namehandlerMapping classxxx具体实现类 继续看handlerMapping是怎么根据request获取到HandlerExecutionChain这个包含拦截器、具体处理的controller的,在AbstractHandlerMapping中以下方法 Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {//获取具体的处理类Object handler getHandlerInternal(request);if (handler null) {handler getDefaultHandler();}if (handler null) {return null;}// Bean name or resolved handler?if (handler instanceof String) {String handlerName (String) handler;handler getApplicationContext().getBean(handlerName);}//根据定义的Interceptors过滤出需要执行的拦截器聚合成HandlerExecutionChain这个执行链HandlerExecutionChain executionChain getHandlerExecutionChain(handler, request);//CORS跨域请求if (CorsUtils.isCorsRequest(request)) {CorsConfiguration globalConfig this.corsConfigSource.getCorsConfiguration(request);CorsConfiguration handlerConfig getCorsConfiguration(handler, request);CorsConfiguration config (globalConfig ! null ? globalConfig.combine(handlerConfig) : handlerConfig);executionChain getCorsHandlerExecutionChain(request, executionChain, config);}return executionChain;
} 看getHandlerInternal(request) 这个方法这个方法是个抽象方法所以其实现在它的子类中可以看出这个是一个模板模式其在抽象类中定义出方法的骨架而后某些方法交给子类实现这个方法有两个实现类AbstractHandlerMethodMapping,AbstractUrlHandlerMapping 这两个具体实现类我们先看AbstractHandlerMethodMapping 这个类实现的 /*** Look up a handler method for the given request.*/
Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {//获取请求路径String lookupPath getUrlPathHelper().getLookupPathForRequest(request);if (logger.isDebugEnabled()) {logger.debug(Looking up handler method for path lookupPath);}//开启读锁this.mappingRegistry.acquireReadLock();try {//获取handlerMethodHandlerMethod handlerMethod lookupHandlerMethod(lookupPath, request);if (logger.isDebugEnabled()) {if (handlerMethod ! null) {logger.debug(Returning handler method [ handlerMethod ]);}else {logger.debug(Did not find handler method for [ lookupPath ]);}}return (handlerMethod ! null ? handlerMethod.createWithResolvedBean() : null);}finally {//释放锁this.mappingRegistry.releaseReadLock();}
} 从这里可以看出 其最后处理的是一个HandlerMethod类我们来看看这个类的结构 public class HandlerMethod {private final Object bean;private final BeanFactory beanFactory;private final Class? beanType;private final Method method;private final Method bridgedMethod;private final MethodParameter[] parameters;private final HandlerMethod resolvedFromHandlerMethod;
} 可以看出其是一个聚合的类里面包含了bean,method故而其可以一个方法对应一个请求。 protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {ListMatch matches new ArrayListMatch();//根据请求路径匹配ListT 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);}if (!matches.isEmpty()) {//最长路径匹配原则ComparatorMatch comparator new MatchComparator(getMappingComparator(request));Collections.sort(matches, comparator);if (logger.isTraceEnabled()) {logger.trace(Found matches.size() matching mapping(s) for [ lookupPath ] : matches);}Match bestMatch matches.get(0);if (matches.size() 1) {if (CorsUtils.isPreFlightRequest(request)) {return PREFLIGHT_AMBIGUOUS_MATCH;}Match secondBestMatch matches.get(1);if (comparator.compare(bestMatch, secondBestMatch) 0) {Method m1 bestMatch.handlerMethod.getMethod();Method m2 secondBestMatch.handlerMethod.getMethod();throw new IllegalStateException(Ambiguous handler methods mapped for HTTP path request.getRequestURL() : { m1 , m2 });}}返回handlerMethodhandleMatch(bestMatch.mapping, lookupPath, request);return bestMatch.handlerMethod;}else {return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);}
} AbstractHandlerMethodMapping 这个抽象类实现了InitializingBean接口所以我们可以看看afterPropertiesSet()方法其在实例化进行的初始化操作initHandlerMethods()方法可以看出其在初始化时就初始化了HandlerMethod这个。 protected void initHandlerMethods() {// 获取所有的BeanString[] beanNames (this.detectHandlerMethodsInAncestorContexts ?BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :getApplicationContext().getBeanNamesForType(Object.class));for (String name : beanNames) {//判断这个bean是否包含Controller,和RequestMapping这两个注解if (!name.startsWith(SCOPED_TARGET_NAME_PREFIX) isHandler(getApplicationContext().getType(name))) {//将其注册到MappingRegistrydetectHandlerMethods(name);}}//空方法handlerMethodsInitialized(getHandlerMethods());
} 转载于:https://www.cnblogs.com/myzhong2014/p/5310140.html