dispatcherServlet初始化完成之后,调用service方法,它是MVC处理url的入口,实际执行父类HttpServlet下的service方法
映射的匹配
HttpServlet->service():
// 获取请求类型
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
// 不同的请求类型执行的过程不一样,这里仅以get方法为例
doGet(req, resp);
}
FrameworkServlet->doGet():
processRequest(request, response);
DispatcherServlet->doService():
// 前面有一系列将初始化过程中的变量赋到request的attributes属性以及绑定线程变量的过程
doDispatch(request, response);
DispatcherServlet->doDispatch():
// 确定处理执行链
mappedHandler = getHandler(processedRequest);
DispatcherServlet->getHandler():
// 这里的handlerMappings就是上篇中的四个,以下主要讲述RequestMappingHandlerMapping
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
AbstractHandlerMapping->getHandler():
Object handler = getHandlerInternal(request);
AbstractHandlerMethodMapping->getHandlerInternal():
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
AbstractHandlerMethodMapping->lookupHandlerMethod():
List<Match> matches = new ArrayList<>();
// 这里的lookupPath就是请求的url,从urlLookup中获取key完全匹配的
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
// 如果不为空的话,判断其它的信息是否符合,将符合的添加到matches变量中
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// 如果为空的话,从mappingLookup中查找所有信息是否有符合的
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
if (!matches.isEmpty()) {
// 如果匹配多个的话,会根据相关的算法找到最合适的那个,然后返回它的处理方法
// requestMappingInfo的排序参见它的compareTo方法
......
}
else {
// 如果没有匹配的话,会直接根据名字找一次
// 如果找到的话,会对比其他信息,只要有不符合的就会抛出异常
// 如果没有找到,直接返回null
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
DispatcherServlet->getHandler()方法中,按照RequestMappingHandlerMapping、BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping、WelcomePageHandlerMapping的顺序尝试获取执行链,找到直接返回,为空则进入下一个HandlerMapping的尝试,SimpleUrlHandlerMapping的匹配路径是/**,因此最极端情况是返回它的执行链
路径匹配规则
- /a/b 匹配/a/b
- /a/** 匹配/a或者/a/ + 任意字符
- /a/{id} 匹配/a/ + 任意字符(/除外)
- /a/* 匹配/a/ + 任意字符(/除外)
- /a/? 匹配/a/ + 任意一个字符(/除外)
@RequestMapping属性值
- value/path 指定url
- method 指定请求的method类型,如GET,POST,PUT,DELETE等
- params 指定request中必须包含的参数值
- headers 指定header中必须包含的参数值
- consumes 指定header中的提交内容类型
Content-Type,如application/json, text/html等 - produces 指定返回的内容类型
Accept,如application/json,text/html等
只有当请求与@RequestMapping属性值完全符合的时候,才会添加到matches变量中,最终返回它所对应的处理方法