Spring 源码解析十:申请参数注解解析器与响应值注解处理器
在 Spring 源码解析六:处理器映射与处理器适配解决 中,有一些申请参数默认的注解解析器与响应值默认的注解处理器还未解析
申请参数默认的注解解析器次要是:
- RequestParamMethodArgumentResolver
- RequestParamMapMethodArgumentResolver
- PathVariableMethodArgumentResolver
- PathVariableMapMethodArgumentResolver
- MatrixVariableMethodArgumentResolver
- MatrixVariableMapMethodArgumentResolver
- ServletModelAttributeMethodProcessor
- RequestResponseBodyMethodProcessor
- RequestPartMethodArgumentResolver
- RequestHeaderMethodArgumentResolver
- RequestHeaderMapMethodArgumentResolver
- ServletCookieValueMethodArgumentResolver
- ExpressionValueMethodArgumentResolver
- SessionAttributeMethodArgumentResolver
- RequestAttributeMethodArgumentResolver
- ServletRequestMethodArgumentResolver
- ServletResponseMethodArgumentResolver
- HttpEntityMethodProcessor
- RedirectAttributesMethodArgumentResolver
- ModelMethodProcessor
- MapMethodProcessor
- ErrorsMethodArgumentResolver
- SessionStatusMethodArgumentResolver
- UriComponentsBuilderMethodArgumentResolver
- PrincipalMethodArgumentResolver
响应值默认的注解处理器次要是:
- ModelAndViewMethodReturnValueHandler
- ModelMethodProcessor
- ViewMethodReturnValueHandler
- ResponseBodyEmitterReturnValueHandler
- StreamingResponseBodyReturnValueHandler
- HttpEntityMethodProcessor
- HttpHeadersReturnValueHandler
- CallableMethodReturnValueHandler
- DeferredResultMethodReturnValueHandler
- AsyncTaskMethodReturnValueHandler
- ServletModelAttributeMethodProcessor
- RequestResponseBodyMethodProcessor
- ViewNameMethodReturnValueHandler
- MapMethodProcessor
- ModelAndViewResolverMethodReturnValueHandler
上面咱们选一些典型的来解析
1. RequestParamMethodArgumentResolver
RequestParamMethodArgumentResolver
的次要性能是解析 @RequestParam
public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver implements UriComponentsContributor {}
先来看看 AbstractNamedValueMethodArgumentResolver
public abstract class AbstractNamedValueMethodArgumentResolver implements HandlerMethodArgumentResolver { // 解析参数 @Override public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { // 获取名称值信息 NamedValueInfo namedValueInfo = getNamedValueInfo(parameter); // 如果名字里有表达式,解析表达式 Object resolvedName = resolveEmbeddedValuesAndExpressions(namedValueInfo.name); // 解析名称对应的值,由子类实现 Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest); // 如果没有值 if (arg == null) { // 有defaultValue的话,解析defaultValue的表达式,并应用默认值 if (namedValueInfo.defaultValue != null) { arg = resolveEmbeddedValuesAndExpressions(namedValueInfo.defaultValue); } // ... 代码省略 } // ... 代码省略 if (binderFactory != null) { WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name); try { // 转换值String类型到指标类型 arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter); } catch (ConversionNotSupportedException ex) { // ... 代码省略 } // ... 代码省略 } // 后置解决,由子类实现 handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest); return arg; }}
再来看看 RequestParamMethodArgumentResolver
public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver implements UriComponentsContributor { // 解析名字 @Override protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception { // 获取原生的HttpServletRequest HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class); // ... 代码省略 Object arg = null; MultipartRequest multipartRequest = request.getNativeRequest(MultipartRequest.class); // 文件上传解决 if (multipartRequest != null) { List<MultipartFile> files = multipartRequest.getFiles(name); if (!files.isEmpty()) { arg = (files.size() == 1 ? files.get(0) : files); } } // 获取参数值 if (arg == null) { String[] paramValues = request.getParameterValues(name); if (paramValues != null) { arg = (paramValues.length == 1 ? paramValues[0] : paramValues); } } return arg; }}
2. RequestParamMapMethodArgumentResolver
RequestParamMapMethodArgumentResolver
的次要性能是解析 @RequestParam
,但不指定参数名字,返回整个参数 Map
public class RequestParamMapMethodArgumentResolver implements HandlerMethodArgumentResolver { // 解析参数 @Override public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { // MultiValueMap if (MultiValueMap.class.isAssignableFrom(parameter.getParameterType())) { Class<?> valueType = resolvableType.as(MultiValueMap.class).getGeneric(1).resolve(); // 文件上传 if (valueType == MultipartFile.class) { // ... 代码省略 } // 单片文件上传 else if (valueType == Part.class) { // ... 代码省略 } // 一般字符 else { Map<String, String[]> parameterMap = webRequest.getParameterMap(); MultiValueMap<String, String> result = new LinkedMultiValueMap<>(parameterMap.size()); parameterMap.forEach((key, values) -> { for (String value : values) { result.add(key, value); } }); return result; } } // 一般Map else { Class<?> valueType = resolvableType.asMap().getGeneric(1).resolve(); // 文件上传 if (valueType == MultipartFile.class) { // ... 代码省略 } // 单片文件上传 else if (valueType == Part.class) { // ... 代码省略 } // 一般字符 else { Map<String, String[]> parameterMap = webRequest.getParameterMap(); Map<String, String> result = CollectionUtils.newLinkedHashMap(parameterMap.size()); parameterMap.forEach((key, values) -> { if (values.length > 0) { result.put(key, values[0]); } }); return result; } } }}
3. PathVariableMethodArgumentResolver
PathVariableMethodArgumentResolver
的次要性能是解析 @PathVariable
public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver implements UriComponentsContributor { // 解析名字 @Override protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception { // 获取解析好的Map Map<String, String> uriTemplateVars = (Map<String, String>) request.getAttribute( HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST); // 从Map中取 return (uriTemplateVars != null ? uriTemplateVars.get(name) : null); }}
4. RequestResponseBodyMethodProcessor
RequestResponseBodyMethodProcessor
的次要性能是解决 @RequestBody
和 @ResponseBody
先来看看继承关系
- AbstractMessageConverterMethodArgumentResolver - AbstractMessageConverterMethodProcessor - RequestResponseBodyMethodProcessor
4.1. AbstractMessageConverterMethodArgumentResolver
AbstractMessageConverterMethodArgumentResolver
的次要性能是能够应用音讯转换器把输出转换成须要的对象
public abstract class AbstractMessageConverterMethodArgumentResolver implements HandlerMethodArgumentResolver { // 应用音讯转换器把申请体读取为对象 protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException { // ... 代码省略 // 获取转换到指标对象的类 Class<T> targetClass = (targetType instanceof Class ? (Class<T>) targetType : null); if (targetClass == null) { ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter); targetClass = (Class<T>) resolvableType.resolve(); } // ... 代码省略 Object body = NO_VALUE; EmptyBodyCheckingHttpInputMessage message; try { // 初始化一个输出流读取器 message = new EmptyBodyCheckingHttpInputMessage(inputMessage); // 遍历转换器 for (HttpMessageConverter<?> converter : this.messageConverters) { // 转换类型 Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass(); // 是否是GenericHttpMessageConverter GenericHttpMessageConverter<?> genericConverter = (converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null); // 读取申请体,解决 if (genericConverter != null ? genericConverter.canRead(targetType, contextClass, contentType) : (targetClass != null && converter.canRead(targetClass, contentType))) { if (message.hasBody()) { // 读取前解决 HttpInputMessage msgToUse = getAdvice().beforeBodyRead(message, parameter, targetType, converterType); // 读取申请体 body = (genericConverter != null ? genericConverter.read(targetType, contextClass, msgToUse) : ((HttpMessageConverter<T>) converter).read(targetClass, msgToUse)); // 读取后处理 body = getAdvice().afterBodyRead(body, msgToUse, parameter, targetType, converterType); } else { // 空申请体 body = getAdvice().handleEmptyBody(null, message, parameter, targetType, converterType); } break; } } } catch (IOException ex) { // ... 代码省略 } // ... 代码省略 return body; }}
4.2. AbstractMessageConverterMethodProcessor
AbstractMessageConverterMethodProcessor
的次要性能是能够应用音讯转换器把响应对象转换成输入
public abstract class AbstractMessageConverterMethodProcessor extends AbstractMessageConverterMethodArgumentResolver implements HandlerMethodReturnValueHandler { // 转换对象为输入 protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType, ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { // 响应体 Object body; // 值类型 Class<?> valueType; // 指标类型 Type targetType; // 字符 if (value instanceof CharSequence) { body = value.toString(); valueType = String.class; targetType = String.class; } // 非字符 else { body = value; valueType = getReturnValueType(body, returnType); targetType = GenericTypeResolver.resolveType(getGenericType(returnType), returnType.getContainingClass()); } // 如果是输入为资源类型,二进制流或文件 if (isResourceType(value, returnType)) { outputMessage.getHeaders().set(HttpHeaders.ACCEPT_RANGES, "bytes"); if (value != null && inputMessage.getHeaders().getFirst(HttpHeaders.RANGE) != null && outputMessage.getServletResponse().getStatus() == 200) { Resource resource = (Resource) value; try { List<HttpRange> httpRanges = inputMessage.getHeaders().getRange(); outputMessage.getServletResponse().setStatus(HttpStatus.PARTIAL_CONTENT.value()); body = HttpRange.toResourceRegions(httpRanges, resource); valueType = body.getClass(); targetType = RESOURCE_REGION_LIST_TYPE; } catch (IllegalArgumentException ex) { // ... 代码省略 } } } MediaType selectedMediaType = null; // 输入内容类型content-type MediaType contentType = outputMessage.getHeaders().getContentType(); // 有内容类型 boolean isContentTypePreset = contentType != null && contentType.isConcrete(); if (isContentTypePreset) { selectedMediaType = contentType; } else { // ... 代码省略,如果没有内容类型,就从内容判断 } // 遍历音讯转换器 for (HttpMessageConverter<?> converter : this.messageConverters) { // 是否是GenericHttpMessageConverter GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null); if (genericConverter != null ? ((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) : converter.canWrite(valueType, selectedMediaType)) { // 输入前置解决 body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType, (Class<? extends HttpMessageConverter<?>>) converter.getClass(), inputMessage, outputMessage); if (body != null) { // 增加Content-Disposition头 addContentDispositionHeader(inputMessage, outputMessage); // 把body转换并输入到outputMessage if (genericConverter != null) { genericConverter.write(body, targetType, selectedMediaType, outputMessage); } else { ((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage); } } return; } } // ... 代码省略 }}
4.3. RequestResponseBodyMethodProcessor
RequestResponseBodyMethodProcessor
的次要性能是输出与输入都能够应用音讯转换器转换
public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor { // 解析参数 @Override public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { // 应用音讯转换器把申请体读取为对象 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); // ... 代码省略 } // ... 代码省略 } // 适配一下Optional return adaptArgumentIfNecessary(arg, parameter); } // 应用音讯转换器把申请体读取为对象 @Override protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter, Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException { // 获取原始的申请对象 HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class); ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest); // 应用父类的办法转换 Object arg = readWithMessageConverters(inputMessage, parameter, paramType); // ... 代码省略 return arg; }}
public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor { // 解决响应值 @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { ServletServerHttpRequest inputMessage = createInputMessage(webRequest); ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); // 应用父类的办法转换对象为输入 writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage); }}
5. HttpEntityMethodProcessor
HttpEntityMethodProcessor
的次要性能是解决 HttpEntity
public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodProcessor { // 解析名字 @Override public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws IOException, HttpMediaTypeNotSupportedException { // 创立ServletServerHttpRequest ServletServerHttpRequest inputMessage = createInputMessage(webRequest); // 获取数据类型 Type paramType = getHttpEntityType(parameter); // 应用音讯转换器把申请体读取为对象 Object body = readWithMessageConverters(webRequest, parameter, paramType); // 如果RequestEntity类型,封装为RequestEntity,不然就是一般的HttpEntity if (RequestEntity.class == parameter.getParameterType()) { return new RequestEntity<>(body, inputMessage.getHeaders(), inputMessage.getMethod(), inputMessage.getURI()); } else { return new HttpEntity<>(body, inputMessage.getHeaders()); } }}
public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodProcessor { // 解决响应值 @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { // ... 代码省略 // 创立输入输出音讯对象 ServletServerHttpRequest inputMessage = createInputMessage(webRequest); ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); HttpEntity<?> responseEntity = (HttpEntity<?>) returnValue; // 获取输入音讯头 HttpHeaders outputHeaders = outputMessage.getHeaders(); HttpHeaders entityHeaders = responseEntity.getHeaders(); // ... 代码省略,把entityHeaders载入outputHeaders if (responseEntity instanceof ResponseEntity) { // ... 代码省略,如果是 get/head 办法,并且是200状态码,间接输出 } // 应用父类的办法转换对象为输入 writeWithMessageConverters(responseEntity.getBody(), returnType, inputMessage, outputMessage); // ... 代码省略 }}
6. ModelAndViewMethodReturnValueHandler
ModelAndViewMethodReturnValueHandler
的次要性能是输入 ModelAndView
public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturnValueHandler { // 解决响应值 @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { // 没有响应值,间接返回 if (returnValue == null) { mavContainer.setRequestHandled(true); return; } ModelAndView mav = (ModelAndView) returnValue; // 是viewName if (mav.isReference()) { String viewName = mav.getViewName(); mavContainer.setViewName(viewName); if (viewName != null && isRedirectViewName(viewName)) { mavContainer.setRedirectModelScenario(true); } } // 是view对象 else { View view = mav.getView(); mavContainer.setView(view); if (view instanceof SmartView && ((SmartView) view).isRedirectView()) { mavContainer.setRedirectModelScenario(true); } } mavContainer.setStatus(mav.getStatus()); mavContainer.addAllAttributes(mav.getModel()); }}
7. StreamingResponseBodyReturnValueHandler
StreamingResponseBodyReturnValueHandler
的次要性能是输入 StreamingResponseBody
public class ResponseBodyEmitterReturnValueHandler implements HandlerMethodReturnValueHandler { // 解决响应值 @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { // 没有响应值,间接返回 if (returnValue == null) { mavContainer.setRequestHandled(true); return; } // 获取原始输入 HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class); ServerHttpResponse outputMessage = new ServletServerHttpResponse(response); // 如果是ResponseEntity,并且有响应体,间接输入 if (returnValue instanceof ResponseEntity) { ResponseEntity<?> responseEntity = (ResponseEntity<?>) returnValue; response.setStatus(responseEntity.getStatusCodeValue()); outputMessage.getHeaders().putAll(responseEntity.getHeaders()); returnValue = responseEntity.getBody(); if (returnValue == null) { mavContainer.setRequestHandled(true); outputMessage.flush(); return; } } StreamingResponseBody streamingBody = (StreamingResponseBody) returnValue; Callable<Void> callable = new StreamingResponseBodyTask(outputMessage.getBody(), streamingBody); // 异步输入 WebAsyncUtils.getAsyncManager(webRequest).startCallableProcessing(callable, mavContainer); }}
8. ViewNameMethodReturnValueHandler
ViewNameMethodReturnValueHandler
的次要性能是输入视图名字
public class ViewNameMethodReturnValueHandler implements HandlerMethodReturnValueHandler { // 解决响应值 @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { if (returnValue instanceof CharSequence) { String viewName = returnValue.toString(); mavContainer.setViewName(viewName); if (isRedirectViewName(viewName)) { mavContainer.setRedirectModelScenario(true); } } else if (returnValue != null) { // should not happen throw new UnsupportedOperationException("Unexpected return type: " + returnType.getParameterType().getName() + " in method: " + returnType.getMethod()); } }}
后续
更多博客,查看 https://github.com/senntyou/blogs
作者:深予之 (@senntyou)
版权申明:自在转载-非商用-非衍生-放弃署名(创意共享 3.0 许可证)