一、Spring MVC
SpringMVC 核心为: DispatcherServlet >> 前端控制器
请求进入程序中,会进入DispatcherServlet类 , doService >> doDispatch,源代码如下:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//判断请求流中,是否含有文件
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 通过遍历List<HandlerMapping> handlerMappings,寻找当前请求对应的处理程序
//返回的是 当前请求对应的处理器和拦截器链对应的封装对象
/**
* 遍历(List)handlerMappings,handlerMapping调用getHandler(request) -> getHandlerInternal(request) -> lookupHandlerMethod(lookupPath, request)
* 查询handlerMapping下是否存在与当前请求匹配的映射方法处理器,查找到之后,将处理器方法封装进HandlerExecutionChain处理器执行链对象返回
* @RequestMapping标注 路径注册进map MappingRegistry,从注册映射对象查询出最符合的处理器方法(handlerMethod)对象;
*/
mappedHandler = getHandler(processedRequest);
//如果查询不到该请求对应的handler,当前请求流程终止,直接返回对应的处理;
if (mappedHandler == null) {
//对于当前请求进行日志输出,并对本次请求做出处理,
noHandlerFound(processedRequest, response);
return;
}
// 查找(遍历)当前支持当前处理器handler的适配器,
//这里是RequestMappingHandlerAdapter,调用@RequestMapping标注的方法
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
//获取本次请求类型
String method = request.getMethod();
//判断是否为GET类型的请求
boolean isGet = "GET".equals(method);
//Spring MVC缓存机制
if (isGet || "HEAD".equals(method)) {
//查询是否存在于缓存中,如果在的话,直接返回;
//这里类似于http请求与之前的没有改变时,则直接返回上次结果
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
//拦截器
//顺序执行拦截器的preHandle方法(前置方法),如果任何一个拦截器返回false,执行返回,不执行目标方法。
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 通过处理适配器调用处理器,即,调用编写的实际业务请求方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
//结果返回视图处理 如果没有设置视图,则应用默认的视图名
applyDefaultViewName(processedRequest, mv);
//执行拦截器后置方法(倒序)
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 根据ModelAndView对象解析视图
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
//出现异常的话,倒序执行afterCompletion方法。
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
//出现异常的话,倒序执行afterCompletion方法。
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
查找handlerMapping的过程
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
//查询当前请求对应的处理器执行链
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);
/*如果当前handlerMapping中未找到,获取默认的处理器*/
if (handler == null) {
handler = getDefaultHandler();
}
/*如果仍然为空,那么返回null*/
if (handler == null) {
return null;
}
// Bean name or resolved handler?
// 如果返回的是bean的名字,那么根据名字从容器中获取对应的处理器对象
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
//组装处理器执行链对象
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}
if (hasCorsConfigurationSource(handler)) {
CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
config = (config != null ? config.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
/*返回处理器执行链对象*/
return executionChain;
}
// Handler method lookup
/**
* Look up a handler method for the given request.
*/
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
/*获取当前请求的URI*/
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
/*将URI存放到请求中*/
request.setAttribute(LOOKUP_PATH, lookupPath);
/*开启同步锁*/
this.mappingRegistry.acquireReadLock();
try {
/*根据URL查找最佳的请求映射方法处理器*/
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
/*关闭锁*/
finally {
this.mappingRegistry.releaseReadLock();
}
}
/**
*
*
* Look up the best-matching handler method for the current request.
* If multiple matches are found, the best match is selected.
* @param lookupPath mapping lookup path within the current servlet mapping
* @param request the current request
* @return the best-matching handler method, or {@code null} if no match
* @see #handleMatch(Object, String, HttpServletRequest)
* @see #handleNoMatch(Set, String, HttpServletRequest)
*/
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
// 根据lookupPath获取对应的RequestMappingInfo列表
List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
if (directPathMatches != null) {
//对匹配到的列表做一次筛选
// 根据上面获取到的RequestMappingInfo遍历来匹配HandlerMethod。
//这个匹配涉及到多个条件:如请求方法、路径、参数等一系列信息,
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// No choice but to go through all mappings...
addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
}
/*最后筛选,选出一个最适合的handlerMethod*/
if (!matches.isEmpty()) {
Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
matches.sort(comparator);
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
if (logger.isTraceEnabled()) {
logger.trace(matches.size() + " matching mappings: " + matches);
}
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();
String uri = request.getRequestURI();
throw new IllegalStateException(
"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
}
}
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
handleMatch(bestMatch.mapping, lookupPath, request);
return bestMatch.handlerMethod;
}
else {
/* 未匹配上 */
return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
}
}
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
//获取程序中注册的拦截器列表
//正序
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
// 反向遍历拦截器
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
//倒序执行拦截器的后置处理方法
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
//倒序执行
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
一次请求执行过程如下
请求进入doService方法,再调用dispatch方法,
- 首先检查request中是否含有文件流
- 获取handler
-
- 遍历handlerMapping(7种)的方式获取到支持此请求的HandlerMethod
- 将HandlerMethod和容器中注册的拦截器封装成一个HandlerExecutionChain执行链
- 返回dispatch方法中
- 获取能够处理此请求对应的handler的handlerAdapted适配器
- 判断是否为GET或HEAD类型的请求...(MVC实现的请求缓存)
- 顺序执行拦截器链中的前置请求
- 使用处理器适配器执行处理器
-
- 参数的处理 --> 将参数解析器绑定在HandlerMethod对象上(invokeHandlerMethod方法)>> HandlerMethodArgumentResolver
- 根据参数解析器设置方法参数值
- 通过反射,调用处理器方法
- 逆序执行拦截器链的后置方法
- 视图处理
- 如果出现以上步骤异常,将会逆序执行拦截器链中的异常处理方法
请求映射扫描注册过程
请求返回值处理
参数解析器和类型转换器
- 参数解析器在获取的适配器对象属性上绑定,提供 supportsParameter 方法判断当前解析器是否可以处理参数和resolveArgument的处理实现
- 自定义类型转换器 Converter ,实现接口,注册web容器 --- 只对Key/Value形式的参数有效
- 请求体body中,是通过HttpMessageConverter (消息转换器)转换成其他对象