SpringMVC源码系列文章
前文中我们介绍了SpringMVC容器的启动,包括前端控制器DispatcherServlet对象的创建,过滤器添加到Tomcat容器的过滤器集合中,将所有拦截器、跨域配置、消息转换器等配置统一添加到各自集合中,解析@RequestMapping注解生成请求路径和Controller方法的映射map。本章来研究下**请求的执行过程
**。
说到请求过程,那么得先说下入口在哪里?入口肯定是统一分发请求给处理程序的**DispatcherServlet
**,DispatcherServlet归根结底也是Servlet。Tomcat通过请求Mapping映射和Servelt对应关系找到Servelt,调用Servelt之前会执行过滤器链,所有过滤器放行才会走到Servelt真正的执行逻辑。
// 接受User对象并返回
@PostMapping("/test")
@ResponseBody
public User test(@RequestBody User user) {
user.setName("李四");
System.out.println(user);
return user;
}
DispatcherServelt重写的doPost方法
**就是入口了本文就不讲过滤器的调用了,因为从DispatcherServelt开始,过滤器链已经执行完成,之前文章Tomcat源码解析(八):一个请求的执行流程(附Tomcat整体总结)有介绍过。
DispatcherServlet的类图如下:
从doPost到doDispatch方法
doPost
**方法是由DispatcherServelt的父类**FrameworkServlet
**实现的**processRequest(request, response)
**doService(request, response)
**// FrameworkServlet类方法
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
...
try {
doService(request, response);
}
catch (ServletException | IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
...
}
}
doDispatch(request, response)
**// DispatcherServlet类方法
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
// ... 设置一堆Attribute属性
try {
doDispatch(request, response);
}
finally {
...
}
}
核心方法**
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);
// 如果是上传请求,这个参数置为true,最后会去清理资源
multipartRequestParsed = (processedRequest != request);
// 获取HandlerExcutionChain (内部包括Handler)
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
// 请求url找不到404就会走到这里
noHandlerFound(processedRequest, response);
return;
}
// 获取适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// get请求缓存相关,以后有机会单独将
String method = request.getMethod();
boolean isGet = HttpMethod.GET.matches(method);
if (isGet || HttpMethod.HEAD.matches(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 调用拦截器的前置方法preHandle
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 执行handler方法
// 需要跳转页面这里才会返回ModelAndView对象,否则@ResponseBody返回对象这里返回null
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
applyDefaultViewName(processedRequest, mv);
// 调用拦截器的后置方法postHandle
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
//从4.3开始,我们也在处理处理程序方法抛出的错误,
//使它们可用于@ExceptionHandler方法和其他场景。
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 处理结果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
// 调用拦截器请求处理完成后的回调triggerAfterCompletion
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
// 调用拦截器请求处理完成后的回调triggerAfterCompletion
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// 异步处理的回调
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// 如果是上传请求,清理相关资源
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
遍历所有的HandlerMapping,只要getHandler方法能获取到**HandlerExecutionChain
**立即返回。
// DispatcherServlet类方法
@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;
}
如下这三个HandlerMapping是web容器启动时候加载的,上篇文章SpringMVC源码解析(一):web容器启动流程有具体介绍。三个轮流调用getHandler方法,而HandlerMapping也有顺序的,**RequestMappingHanderMapping
**排序为0优先级最高,而它也是处理**@RequestMapping
**注解的映射关系的映射器。
调用**抽象类
**的方法,那么上面看到的三个HandlerMapping应该都会调用此方法,而这里肯定有一些核心的不同的方法实现在不同的HandlerMapping具体实现类中,典型的**模板方法
**设计模式。
// AbstractHandlerMapping类方法
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 获取Handler
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// handler为bean的名称
// 这种Controller应该是实现Controler、HttpRequestHandler接口的方式
// 以前的老实现方式,暂不研究
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
...
// 获取执行链(包括Handler和拦截器)
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
// ...打印日志
// 添加跨域设置(本身也是拦截器)到拦截器链中第一个位置
if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
CorsConfiguration config = getCorsConfiguration(handler, request);
if (getCorsConfigurationSource() != null) {
CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);
config = (globalConfig != null ? globalConfig.combine(config) : config);
}
if (config != null) {
config.validateAllowCredentials();
}
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
// RequestMappingInfoHandlerMapping类方法
@Override
@Nullable
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
try {
// 核心方法调用父类的getHandlerInternal方法
return super.getHandlerInternal(request);
}
finally {
ProducesRequestCondition.clearMediaTypesAttribute(request);
}
}
查找路径
**HandlerMethod
**// AbstractHandlerMethodMapping类方法
@Override
@Nullable
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// 通过request获取查找路径
String lookupPath = initLookupPath(request);
this.mappingRegistry.acquireReadLock();
try {
// 通过查找路径获取HandlerMethod
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
uri
**,如图/springmvc/test,/springmvc为**项目路径
**,/test为我们需要的**查找路径
** 这个方法的核心内容就是从之前讲的SpringMVC源码解析(一):web容器启动流程注册的**两个map
**获取数据。
// AbstractHandlerMethodMapping类方法
@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<Match> matches = new ArrayList<>();
// 通过查找路径获取RequestMappingInfo
List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
if (directPathMatches != null) {
// 通过RequestMappingInfo获取HandlerMethod
addMatchingMappings(directPathMatches, matches, request);
}
...
if (!matches.isEmpty()) {
Match bestMatch = matches.get(0);
if (matches.size() > 1) {
//...匹配多个,抛错异常
}
request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod());
handleMatch(bestMatch.mapping, lookupPath, request);
// 获取HandlerMethod并返回
return bestMatch.getHandlerMethod();
}
else {
return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);
}
}
我们自定义的拦截器统一用**MappedInterceptor
**这个拦截器包装了一层,为了统一调用**matcher
**方法,匹配此拦截器请求是否拦截本次请求,如果是则会添加到拦截器链中。
// AbstractHandlerMapping类方法
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
// 创建HandlerExecutionChain对象
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
// 遍历所有的拦截器,这拦截器是web容器启动时候解析加载的的
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
// 我们自定义的拦截器统一用MappedInterceptor这个拦截器包装了一层
// 为了统一的匹配方法,下面调用maches
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
// matcher匹配当前请求路径是否符合拦截器的拦截请求
if (mappedInterceptor.matches(request)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
// 执行器链对象,主要就是两个属性handler:Handler对象,interceptorList:拦截器集合
public class HandlerExecutionChain {
private final Object handler;
private final List<HandlerInterceptor> interceptorList = new ArrayList<>();
// 构造方法
public HandlerExecutionChain(Object handler) {
this(handler, (HandlerInterceptor[]) null);
}
...
}
看下HandlerAdapter接口
public interface HandlerAdapter {
/**
* 因为有多个HandlerMapping和HandlerAdapter
* 对于HandlerAdapter是否支持对应的HandlerMapping,通过此方法判断
*/
boolean supports(Object handler);
/**
* 具体调用Hangder的方法
*/
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
因为不同的**Hander
**(@RequestMapping、实现Controller接口、实现HttpRequestHandler接口)对应的**HandlerAdapter
**(适配器)不一样,通过HandlerAdapter的**supports
**方法判断当前HandlerAdapter**是否支持此次请求的Hander
**。
// DispatcherServlet类方法
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
RequestMappingHandlerAdapter
**重写的supportsInternal返回true,表示其**支持
// AbstractHandlerMethodAdapter类方法
@Override
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
// RequestMappingHandlerAdapter类方法
@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
由上面HandlerAdapter接口可以猜到,**RequestMappingHandlerAdapter
**适配器就是我们需要的,之后会通过handle方法去**执行Hangder方法
**即调用**Controller#Method
**。
AbstractHandlerMethodAdapter类的handle方法即重写HandlerAdapter的handle方法,所有的HandlerAdapter执行Hangdler都会进入此方法,而具体的方法实现又要调用HandlerAdapter的实现类,如下,实现类就在**RequestMappingHandlerAdapter
**类的**handleInternal
**方法。
// AbstractHandlerMethodAdapter类方法
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
解析请求
**,**执行真正逻辑
**,**解析响应
**// ServletInvocableHandlerMethod类方法
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 执行Handler并获取返回值
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);
if (returnValue == null) {
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
disableContentCachingIfNecessary(webRequest);
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}
mavContainer.setRequestHandled(false);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
try {
// 处理响应,返回对象转换响应信息,如对象转化为json
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
// 异常向上抛
throw ex;
}
}
// InvocableHandlerMethod类方法,实现HandlerMethod接口
@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 获取请求参数
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
// 执行真正逻辑
return doInvoke(args);
}
拿到具体Controller的**Method
**方法参数,遍历所有参数寻找支持每个参数类型的**参数解析器
**,解析参数并返回。
// InvocableHandlerMethod类方法,实现HandlerMethod接口
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 从HandlerMethod中获取参数信息
// 之前项目启动就加载了Handler,里面包含了具体要执行的Controller的Method
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}
// 遍历所有的参数
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
// 寻找支持当前参数类型的参数解析器
if (!this.resolvers.supportsParameter(parameter)) {
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
try {
// 根据上一步获取的参数解析器解析参数并返回具体参数
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
}
catch (Exception ex) {
throw ex;
}
}
return args;
}
遍历所有的**参数解析器
**,调用参数解析器的**supportsParameter
**方法,返回true,表示此解析器可以解析当前参数类型,而且将方法的参数与解析器放入缓存**argumentResolverCache
**,以后同一个接口调用第二次,参数解析器直接从缓存中获取就可以,不再需要遍历调用supportsParameter方法去筛选获取。
// HandlerMethodArgumentResolverComposite类方法
@Override
public boolean supportsParameter(MethodParameter parameter) {
return getArgumentResolver(parameter) != null;
}
@Nullable
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
if (result == null) {
for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
if (resolver.supportsParameter(parameter)) {
result = resolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
HandlerMethodArgumentResolver argumentResolvers
**中一共有27个 @RequestParam
**、**@PathVariable
**等等@RequestBody
**注解参数解析器@RequestBody
**即可// RequestResponseBodyMethodProcessor类方法
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestBody.class);
}
// HandlerMethodArgumentResolverComposite类方法
@Override
@Nullable
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
// 获取参数解析器,此时上面已经筛查出来,放到argumentResolverCache缓存中
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
if (resolver == null) {
throw new IllegalArgumentException("Unsupported parameter type [" +
parameter.getParameterType().getName() + "]. supportsParameter should be called first.");
}
// 解析方法
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}
RequestResponseBodyMethodProcessor
**的**resolveArgument
**方法 消息转换器
**获取请求参数@Validated
**注解的校验,以后单独将// RequestResponseBodyMethodProcessor类方法
@Override
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
parameter = parameter.nestedIfOptional();
// 获取参数对象
Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
String name = Conventions.getVariableNameForParameter(parameter);
if (binderFactory != null) {
WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
if (arg != null) {
// @Validated注解的校验
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
}
}
if (mavContainer != null) {
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
}
}
return adaptArgumentIfNecessary(arg, parameter);
}
@RequstBody
**的**required
**属性是否为**true
** Required request body is missing
**// RequestResponseBodyMethodProcessor类方法
@Override
protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter,
Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
Assert.state(servletRequest != null, "No HttpServletRequest");
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);
// 进一步调用方法,通过消息转换器获取请求参数
Object arg = readWithMessageConverters(inputMessage, parameter, paramType);
// 如果请求为空,检查@RequstBody是否为请求必须参数
if (arg == null && checkRequired(parameter)) {
throw new HttpMessageNotReadableException("Required request body is missing: " +
parameter.getExecutable().toGenericString(), inputMessage);
}
return arg;
}
// @requestBody注解required属性是否为true
protected boolean checkRequired(MethodParameter parameter) {
RequestBody requestBody = parameter.getParameterAnnotation(RequestBody.class);
return (requestBody != null && requestBody.required() && !parameter.isOptional());
}
消息转换器接口
MediaType类
**:表示互联网中多媒体数据类型的格式;例如:text/html,text/plain,application/json…**canRead方法
**:检查能否将请求信息转换为mediaType表示的数据类型,这个mediaType是前端页面请求时设定的contentType格式**read方法
**:如果canRead方法返回值为true,则调用read方法将请求信息转换为T类型对象**canWrite方法
**:检查clazz对象是否能转换为mediaType类型,此时的mediaType表示后端想要响应给前端的数据格式**write方法
**:如果canWrite返回值为true,则将T类型的对象写到响应流中,同时指定mediaType类型**回到上面的readWithMessageConverters方法
ContentType
**媒体内容类型,肯定是**application/json
**,默认**application/octet-stream
**消息转换器
**,调用**canRead
**方法筛选可以将**请求信息
**转为指定的媒体类型**contentType
**的转换器扩展点RequestBodyAdvice
**,可以对**请求
**做一些修改,如加密拦截请求等等// AbstractMessageConverterMethodArgumentResolver类方法
@Nullable
protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
MediaType contentType;
boolean noContentType = false;
try {
// 获取请求头ContentType
contentType = inputMessage.getHeaders().getContentType();
}
catch (InvalidMediaTypeException ex) {
throw new HttpMediaTypeNotSupportedException(ex.getMessage());
}
if (contentType == null) {
noContentType = true;
// 默认媒体类型 "application/octet-stream"
contentType = MediaType.APPLICATION_OCTET_STREAM;
}
// 获取Controller的Class对象
Class<?> contextClass = parameter.getContainingClass();
// 获取方法参数的Class对象
Class<T> targetClass = (targetType instanceof Class ? (Class<T>) targetType : null);
if (targetClass == null) {
ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
targetClass = (Class<T>) resolvableType.resolve();
}
HttpMethod httpMethod = (inputMessage instanceof HttpRequest ? ((HttpRequest) inputMessage).getMethod() : null);
Object body = NO_VALUE;
EmptyBodyCheckingHttpInputMessage message = null;
try {
message = new EmptyBodyCheckingHttpInputMessage(inputMessage);
// 遍历所有的消息转换器
for (HttpMessageConverter<?> converter : this.messageConverters) {
Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass();
GenericHttpMessageConverter<?> genericConverter =
(converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null);
// 调用canRead方法,筛选每个消息过滤器是否能将请求信息转为指定的媒体类型contentType
if (genericConverter != null ? genericConverter.canRead(targetType, contextClass, contentType) :
(targetClass != null && converter.canRead(targetClass, contentType))) {
if (message.hasBody()) {
// 获取请求增强器并调用beforeBodyRead方法
HttpInputMessage msgToUse =
getAdvice().beforeBodyRead(message, parameter, targetType, converterType);
// 消息转换器真正将请求信息转为参数对象的方法
body = (genericConverter != null ? genericConverter.read(targetType, contextClass, msgToUse) :
((HttpMessageConverter<T>) converter).read(targetClass, msgToUse));
// 获取请求增强器并调用afterBodyRead方法
body = getAdvice().afterBodyRead(body, msgToUse, parameter, targetType, converterType);
}
else {
body = getAdvice().handleEmptyBody(null, message, parameter, targetType, converterType);
}
break;
}
}
}
catch (IOException ex) {
throw new HttpMessageNotReadableException("I/O error while reading input message", ex, inputMessage);
}
...
return body;
}
MappingJackson2HttpMessageConverter
**genericConverter.canRead**
筛选
**方法
// AbstractJackson2HttpMessageConverter类方法
@Override
public boolean canRead(Type type, @Nullable Class<?> contextClass, @Nullable MediaType mediaType) {
// 判断是否支持传入的mediaType
if (!canRead(mediaType)) {
return false;
}
JavaType javaType = getJavaType(type, contextClass);
ObjectMapper objectMapper = selectObjectMapper(javaType.getRawClass(), mediaType);
if (objectMapper == null) {
return false;
}
AtomicReference<Throwable> causeRef = new AtomicReference<>();
// 判断类能否反序列化,并将错误记录到causeRef中,下面会打印
if (objectMapper.canDeserialize(javaType, causeRef)) {
return true;
}
// 打印causeRef,不能反序列化的错误
logWarningIfNecessary(javaType, causeRef.get());
return false;
}
genericConverter.read**
json反序列化为对象
**方法
// AbstractJackson2HttpMessageConverter类方法
@Override
public Object read(Type type, @Nullable Class<?> contextClass, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
JavaType javaType = getJavaType(type, contextClass);
return readJavaType(javaType, inputMessage);
}
上篇文章SpringMVC源码解析(一):web容器启动流程介绍过,类上有**@ControllerAdvice
**注解且实现**RequestBodyAdvice接口
**的即为RequestBodyAdvice增强器,主要就是在请求信息转换为参数对象的**前后
**做一些**扩展
**处理。
RequestBodyAdvice请求增强器
public interface RequestBodyAdvice {
// 是否支持,自定义判断条件,如包含某个自定义注解等等
// 该方法返回true时,才会进去下面的beforeBodyRead方法
boolean supports(MethodParameter methodParameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType);
// 请求体解析前处理,一般在此方法中对body数据进行修改
HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException;
// 请求体解析后处理,一般直接返回原实例
Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType);
// 当body为empty时操作(body什么都不传才算,即使{}也不算空)
@Nullable
Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType);
}
回到上面的getAdvice().beforeBodyRead方法
beforeBodyRead
**方法`对请求信息做处理// RequestResponseBodyAdviceChain类方法
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage request, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
// 获取所有请求增强器
for (RequestBodyAdvice advice : getMatchingAdvice(parameter, RequestBodyAdvice.class)) {
if (advice.supports(parameter, targetType, converterType)) {
request = advice.beforeBodyRead(request, parameter, targetType, converterType);
}
}
return request;
}
getAdvice().afterBodyRead方法
参数对象
**做一些**扩展处理
**了afterBodyRead
**处理// RequestResponseBodyAdviceChain类方法
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
for (RequestBodyAdvice advice : getMatchingAdvice(parameter, RequestBodyAdvice.class)) {
if (advice.supports(parameter, targetType, converterType)) {
body = advice.afterBodyRead(body, inputMessage, parameter, targetType, converterType);
}
}
return body;
}
getAdvice().handleEmptyBody方法
// RequestResponseBodyAdviceChain类方法
@Override
@Nullable
public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
for (RequestBodyAdvice advice : getMatchingAdvice(parameter, RequestBodyAdvice.class)) {
if (advice.supports(parameter, targetType, converterType)) {
body = advice.handleEmptyBody(body, inputMessage, parameter, targetType, converterType);
}
}
return body;
}
method.invoke(obj,args)
**标准反射调用方法// InvocableHandlerMethod类方法
@Nullable
protected Object doInvoke(Object... args) throws Exception {
Method method = getBridgedMethod();
try {
if (KotlinDetector.isSuspendingFunction(method)) {
return CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args);
}
// 反射调用方法
return method.invoke(getBean(), args);
}
catch (IllegalArgumentException ex) {
...
}
}
handleReturnValue
**处理方法// HandlerMethodReturnValueHandlerComposite类方法
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 获取方法返回值处理器
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
// 处理方法
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
supportsReturnType
**方法筛选// HandlerMethodReturnValueHandlerComposite类方法
@Nullable
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
boolean isAsyncValue = isAsyncReturnValue(value, returnType);
// 遍历所有的返回值处理器
for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
// 排除异步处理器,不用管
if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
continue;
}
// 通过调用处理器的supportsReturnType方法筛选
if (handler.supportsReturnType(returnType)) {
return handler;
}
}
return null;
}
查看**
RequestResponseBodyMethodProcessor
**的筛选方法**handleReturnValue
**
方法
**或**类上
**包含注解**@ResponseBody
**即可@Override
public boolean supportsReturnType(MethodParameter returnType) {
return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
returnType.hasMethodAnnotation(ResponseBody.class));
}
// RequestResponseBodyMethodProcessor类方法
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// 即使返回值为空,也要尝试。ResponseBodyAdvice可能会参与其中。
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
这里用的消息转换器与获取请求参数里的转换器一样,都是**MappingJackson2HttpMessageConverter
**。之前转化器是需要将请求信息body里的json字符串转换(**反序列化
**)为对象;这里的转换器是将对象转换(**序列化
**)对json字符串。
genericConverter.canWrite**
筛选
**方法
// AbstractGenericHttpMessageConverter类方法
@Override
public boolean canWrite(@Nullable Type type, Class<?> clazz, @Nullable MediaType mediaType) {
return canWrite(clazz, mediaType);
}
// AbstractJackson2HttpMessageConverter类方法
@Override
public boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType) {
// 判断是否支持传入的mediaType
if (!canWrite(mediaType)) {
return false;
}
if (mediaType != null && mediaType.getCharset() != null) {
Charset charset = mediaType.getCharset();
if (!ENCODINGS.containsKey(charset.name())) {
return false;
}
}
ObjectMapper objectMapper = selectObjectMapper(clazz, mediaType);
if (objectMapper == null) {
return false;
}
AtomicReference<Throwable> causeRef = new AtomicReference<>();
// 判断对象是否能序列化为json字符串,并将错误记录到causeRef中,下面会打印
if (objectMapper.canSerialize(clazz, causeRef)) {
return true;
}
// 打印causeRef,不能序列化的错误
logWarningIfNecessary(clazz, causeRef.get());
return false;
}
genericConverter.write**
对象序列化为json
**方法
// AbstractGenericHttpMessageConverter类方法
@Override
public final void write(final T t, @Nullable final Type type, @Nullable MediaType contentType,
HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
// 设置默认请求头
final HttpHeaders headers = outputMessage.getHeaders();
addDefaultHeaders(headers, t, contentType);
if (outputMessage instanceof StreamingHttpOutputMessage) {
StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;
streamingOutputMessage.setBody(outputStream -> writeInternal(t, type, new HttpOutputMessage() {
@Override
public OutputStream getBody() {
return outputStream;
}
@Override
public HttpHeaders getHeaders() {
return headers;
}
}));
}
else {
// jackson序列化方法
writeInternal(t, type, outputMessage);
outputMessage.getBody().flush();
}
}
输出流
**中 上篇文章SpringMVC源码解析(一):web容器启动流程介绍过,类上有**@ControllerAdvice
**注解且实现**ResponseBodyAdvice接口
**的即为ResponseBodyAdvice增强器,主要就是在返回对象转换响应信息**前
**做一些**扩展
**处理。
ResponseBodyAdvice响应增强器
public interface ResponseBodyAdvice<T> {
// 是否支持,自定义判断条件
// 该方法返回true时,才会进去下面的 beforeBodyWrite方法
boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);
// 响应写入之前调用
@Nullable
T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response);
}
回到上面的getAdvice().beforeBodyWrite方法
supports
**方法筛选支持的增强,然后调用增强方法**beforeBodyWrite
**body即为方法返回值
**,还没有序列化,我们可以对**返回值
**做**扩展处理
**了// RequestResponseBodyAdviceChain类方法
@Override
@Nullable
public Object beforeBodyWrite(@Nullable Object body, MethodParameter returnType, MediaType contentType,
Class<? extends HttpMessageConverter<?>> converterType,
ServerHttpRequest request, ServerHttpResponse response) {
return processBody(body, returnType, contentType, converterType, request, response);
}
@Nullable
private <T> Object processBody(@Nullable Object body, MethodParameter returnType, MediaType contentType,
Class<? extends HttpMessageConverter<?>> converterType,
ServerHttpRequest request, ServerHttpResponse response) {
// 遍历所有的响应增强器,调用supports方法,筛选支持的增强器
for (ResponseBodyAdvice<?> advice : getMatchingAdvice(returnType, ResponseBodyAdvice.class)) {
if (advice.supports(returnType, converterType)) {
body = ((ResponseBodyAdvice<T>) advice).beforeBodyWrite((T) body, returnType,
contentType, converterType, request, response);
}
}
return body;
}
执行器链HandlerExecutionChain
**里面就包含了拦截器集合,如下// 执行器链对象,主要就是两个属性handler:Handler对象,interceptorList:拦截器集合
public class HandlerExecutionChain {
private final Object handler;
private final List<HandlerInterceptor> interceptorList = new ArrayList<>();
// 构造方法
public HandlerExecutionChain(Object handler) {
this(handler, (HandlerInterceptor[]) null);
}
...
}
拦截器接口
public interface HandlerInterceptor {
/**
* 执行处理程序之前的拦截点
*/
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
/**
* 成功执行处理程序后的拦截点
*/
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
/**
* 请求处理完成后的回调,即渲染视图后
*/
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
前
**后
**最后
**必执行preHandle
**方法afterCompletion
**,并且**Handler都不再执行
**,直接返回// HandlerExecutionChain类方法
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
for (int i = 0; i < this.interceptorList.size(); i++) {
// 遍历所有的拦截器,调用preHandle方法
HandlerInterceptor interceptor = this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
// 拦截器集合索引下标记录
this.interceptorIndex = i;
}
return true;
}
倒序
**遍历执行**postHandle
**方法// HandlerExecutionChain类方法
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
throws Exception {
for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
interceptor.postHandle(request, response, this.handler, mv);
}
}
倒序
**调用**afterCompletion
**方法void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
try {
interceptor.afterCompletion(request, response, this.handler, ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
一般来说拦截器preHandle的方法会返回true(表示放行),那么对于拦截器三个方法执行顺序即为:123 321 321
之前文章SpringMVC源码解析(一):web容器启动流程有介绍,筛选异常处理器即**类上@ControllerAdvice
**,**方法上@ExceptionHandler
**。
@ControllerAdvice
public class ExceptionController {
@ExceptionHandler(value = {Exception.class})
@ResponseBody
public ResponseEntity<String> exceptionHandler(Exception e) {
return ResponseEntity.status(500).body("系统异常");
}
}
// DispatcherServlet类方法
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
boolean errorView = false;
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
// 执行异常处理器
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
...
// 执行拦截器的最终处理
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
resolveException
**方法,返回结果不为null,即跳出循环直接返回@Nullable
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
@Nullable Object handler, Exception ex) throws Exception {
...
// 遍历异常处理器
ModelAndView exMv = null;
if (this.handlerExceptionResolvers != null) {
for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
exMv = resolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
}
// 最后抛出异常
throw ex;
}
JavaWeb是每一个业务逻辑就需要构建一个**Servelt
**,Tomcat解析请求也是通过请求路径映射找到对于的Servelt程序。而SpringMVC只构建**一个
**Servelt,那就是**DispatcherServlet
**,这里Servelt接收所有的请求,然后再根据请求路径分发出去找到对于的Controller方法。
uri
**获取@RequestMapping注解映射的路径@Controller#Method @RequestMapping
**对应关系添加到**map
**集合中 定义Handler的方式有很多,早期有实现Controller、HttpRequestHandler接口,现在常用的@Controller方式,不同的Handler方式生成请求和Handler的映射的方法就不同,这时候抽象出来**HandlerMapping
**(根据request请求匹配/映射上能够处理当前request的Handler),上面说的获取执行器链获取Handler就是专门处理@Controller的HandlerMapping,这样就出现了不同实现的HandlerMapping。
不同Handler调用具体实现逻辑的方法也不同,@Controller方式直接调用记录的类的Method即可,而其他实现接口的方式这是调用此接口实现类的重写handleRequest方法,这时候抽象出来**HandlerAdapter
**,不同HandlerAdapter处理不同Handler。
@RequestBody
**、**@RequestParam
**、**@PathVariable
**注解SpringMVC都内置的**参数解析器
**jackson
**和**fastjson
**转换器json字符串反序列化为java对象
**请求增强器RequestponseBodyAdvice
**,可以对**转换前
**的body和转换后的对象做扩展处理@ResponseBody
**的,使用消息转换器将**java对象序列化为json字符串
**(以后会传给前端)响应增强器ResponseBodyAdvice
**,可以对方法返回值做扩展处理再序列化前后
**及**最后
**无论是否抛异常都会执行的**三个位置
**,都可以做扩展处理