SpringMVC那些事-请求映射匹配-处理器匹配

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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值