1.概述
2.主要过程
3.分析
4.相关类
5.部分源码注释
1.概述
根据MVC的概念,我们知道,请求到服务器后都需要经过控制器.这就需要一种机制把请求准确的调用控制器,
也就是需要明确哪个请求要调用哪个处理器.一般的MVC都有自己处理请求和控制器之间的关系映射的方法.
2.主要工作过程
A.根据hm中的request(url,method,header等)根据urlMap和handlerMethods查找合适的HandlerMethod(处理器)
B.然后找到HandlerMethod之后,生成一个HandlerExecutionChain,遍历拦截器,把处理器需要使用的拦截器放入.
3.概述
Nodejs中一般把这种映射关系叫路由router,大多数仅仅支持url的匹配
在SpringMVC, 使用@RequestMapping注解, 支持url, header, method等参数组合匹配, 这样会达到精确的匹配效果.
例如:@RequestMapping(value = "methods", method = { RequestMethod.GET, RequestMethod.POST }, params = { "id=007", "name" })
SpringMVC在把Controller注入容器的时候,会把使用@RequestMapping注解的信息解析,保存到RequestMappingInfo这个类中,
也就是RequestMappingInfo表示一个@RequestMapping.
在SpringMVC中, 前面已经说过,使用HandlerMethod表示处理器.
另一个问题来了,我们是在处理器方法上使用@RequestMapping注解的,也就是默认了@RequestMapping注解的配置信息和当前的处理器方法是
绑定的,例如:
@RequestMapping(value = "params", params = { "id=007", "name" })
public String paramsMapping(HttpServletRequest req, Model model) {
}
最终的表现形式是:RequestMappingInfo -> HandlerMethod
也就是说, 我们需要这样: 找到RequestMappingInfo,就能找到对应的HandlerMethod.
所以我们需要在RequestMappingInfo和HandlerMethod之间建立一种关系,说白了就是key-value的形式, OK, 没错用map保存就可以了.
在AbstractHandlerMethodMapping中有这两个属性:LinkedHashMap<T, HandlerMethod> handlerMethods和LinkedMultiValueMap<String, T> urlMap
查找最合适的处理器将使用这两个重要的参数.urlMap直接拿当前的路径直接匹配(这一,一个key对应多个value),这是最好的情况,当匹配不到的时候会遍历所有的映射.
RequestMappingHandlerMapping继承了前者,T 为 RequestMappingInfo.
过程解析(使用的是RequestMappingHandlerMapping)
根据request(url,method,header等)和urlMap和handlerMethods查找目标HandlerMethod(处理器)
然后找到处理器之后,生成一个HandlerExecutionChain,遍历所有的拦截器,把处理器需要使用的拦截器放入.
->dispatcherservlet.getHandler
->hm.getHandler
->AbstractHandlerMapping.getHandler
->AbstractHandlerMethodMapping.getHandlerInternal/AbstractHandlerMapping.getDefaultHandler //如果找不到合适的处理器,就返回默认的处理器
->AbstractHandlerMethodMapping.lookupHandlerMethod//匹配合适的处理器(关键部分,使用urlMap和handlerMethods查找)
->AbstractHandlerMapping.getHandlerExecutionChain(handler, request)//遍历注册的拦截器,根据lookupPath和拦截器路径匹配,合适的就加进去(注意一些内置的拦截器)
4.相关类
RequestMappingInfo @RequestMapping注解配置参数的封装
PatternsRequestCondition patternsCondition;//value = {"path"}:路径正则匹配,路径配置可以使用{id}这样的restful风格
RequestMethodsRequestCondition methodsCondition;//例如method = {RequestMethod.GET}
ParamsRequestCondition paramsCondition;//例如params = {"name=weber"}
HeadersRequestCondition headersCondition;//例如headers={"content-type=text/*"}
ConsumesRequestCondition consumesCondition;//例如consumes = {"text/plain", "application/json"}消费者,其实就是请求需要的类型,例如发送json数据到服务器
ProducesRequestCondition producesCondition;//例如produces = {"text/plain", "application/json"}生产者,相应的类型,例如返回json数据给客户端
RequestConditionHolder customConditionHolder;//
HandlerMethod 表示一个类函数的封装类,包括函数的Method和所属的类,和函数的参数等.例如Controller中的每一个处理器可以用它表示,请看hm中和ha具体使用
Object bean;//控制器
BeanFactory beanFactory;//XMLApplicationContext
Method method;//处理器
bridgedMethod;//桥接处理器
MethodParameter[] parameters;//处理器参数
Match AbstractHandlerMethodMapping内部类,保存匹配的映射和处理器
T mapping
HandlerMethod handlerMethod
部分源码
AbstractHandlerMapping
/**
* Abstract base class for {@link org.springframework.web.servlet.HandlerMapping}
* implementations. Supports ordering, a default handler, handler interceptors,
* including handler interceptors mapped by path patterns.
*
* <p>Note: This base class does <i>not</i> support exposure of the
* {@link #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE}. Support for this attribute
* is up to concrete subclasses, typically based on request URL mappings.
*
* @author Juergen Hoeller
* @author Rossen Stoyanchev
* @since 07.04.2003
* @see #getHandlerInternal
* @see #setDefaultHandler
* @see #setAlwaysUseFullPath
* @see #setUrlDecode
* @see org.springframework.util.AntPathMatcher
* @see #setInterceptors
* @see org.springframework.web.servlet.HandlerInterceptor
*/
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
implements HandlerMapping, Ordered {//注意这个order,说明hm也是按照order顺序优先级匹配的
//实现了order接口,在dispacherServlet中初始化的时候,我们会看到,会对它们进行排序
private int order = Integer.MAX_VALUE; // default: same as non-Ordered
private Object defaultHandler;//默认处理器
private UrlPathHelper urlPathHelper = new UrlPathHelper();//URL匹配工具
private PathMatcher pathMatcher = new AntPathMatcher();//路径匹配器
private final List<Object> interceptors = new ArrayList<Object>();
private final List<HandlerInterceptor> adaptedInterceptors = new ArrayList<HandlerInterceptor>();
private final List<MappedInterceptor> mappedInterceptors = new ArrayList<MappedInterceptor>();//当前hm配置的所有拦截器,用来和处理器封装处理器链
/**
* Specify the order value for this HandlerMapping bean.
* <p>Default value is {@code Integer.MAX_VALUE}, meaning that it's non-ordered.
* @see org.springframework.core.Ordered#getOrder()
*/
public final void setOrder(int order) {
this.order = order;
}
@Override
public final int getOrder() {
return this.order;
}
/**
* Set the default handler for this handler mapping.
* This handler will be returned if no specific mapping was found.
* <p>Default is {@code null}, indicating no default handler.
*/
public void setDefaultHandler(Object defaultHandler) {
this.defaultHandler = defaultHandler;
}
/**
* Return the default handler for this handler mapping,
* or {@code null} if none.
*/
public Object getDefaultHandler() {
return this.defaultHandler;
}
/**
* Set if URL lookup should always use the full path within the current servlet
* context. Else, the path within the current servlet mapping is used if applicable
* (that is, in the case of a ".../*" servlet mapping in web.xml).
* <p>Default is "false".
* @see org.springframework.web.util.UrlPathHelper#setAlwaysUseFullPath
*/
public void setAlwaysUseFullPath(boolean alwaysUseFullPath) {
this.urlPathHelper.setAlwaysUseFullPath(alwaysUseFullPath);
}
/**
* Set if context path and request URI should be URL-decoded. Both are returned
* <i>undecoded</i> by the Servlet API, in contrast to the servlet pat