关于后端:Spring-源码解析十请求参数注解解析器与响应值注解处理器

60次阅读

共计 16936 个字符,预计需要花费 43 分钟才能阅读完成。

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 许可证)

正文完
 0