消息转换器HttpMessageConverter原理

初始化原理
1. 使用默认值,从DispatchServlet.properties加载的默认的RequestMappingHandlerAdapter,构造方法提供了四个简单类型的值
2. 使用的@EnableMVC,但是自己又实现了WebMvcConfigurer接口设置消息转换器,此时只有自己的
3. 使用的@EnableMVC,自己没有设置消息转换器,会默认提供好多,根据导入的包来加入
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
    // 创建RequestMappingHandlerAdapter对象的时候,会默认给4个消息转换器
    RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();{
        public RequestMappingHandlerAdapter() {
        		this.messageConverters = new ArrayList<>(4);
        		this.messageConverters.add(new ByteArrayHttpMessageConverter());
        		this.messageConverters.add(new StringHttpMessageConverter());
        		if (!shouldIgnoreXml) {
        			this.messageConverters.add(new SourceHttpMessageConverter<>());
        		}
        		this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
        	}
    }
    // 设置消息转换器,会覆盖状态对象的时候给的默认值
    adapter.setMessageConverters(getMessageConverters());{
        if (this.messageConverters == null) {
            this.messageConverters = new ArrayList<>();
            // 调用实现了WebMvcConfigurer接口,存入自己设置的转换器
            configureMessageConverters(this.messageConverters);
            // 如果自己设置了,那么就不会有默认的了
            if (this.messageConverters.isEmpty()) {
                // 如果没有自己设置,给默认的消息转换器
                addDefaultHttpMessageConverters(this.messageConverters);{
                    // 前几个就是构造方法中的默认值
                    messageConverters.add(new ByteArrayHttpMessageConverter());
                    messageConverters.add(new StringHttpMessageConverter());
                    messageConverters.add(new ResourceHttpMessageConverter());
                    messageConverters.add(new ResourceRegionHttpMessageConverter());
                    if (!shouldIgnoreXml) {
                        messageConverters.add(new SourceHttpMessageConverter<>());
                    }
                    // @EnableMVC默认又给了几个
                    messageConverters.add(new AllEncompassingFormHttpMessageConverter());
                    if (romePresent) {
                        messageConverters.add(new AtomFeedHttpMessageConverter());
                        messageConverters.add(new RssChannelHttpMessageConverter());
                    }
                    // 根据引入jar包的不同,来添加对应的转换器
                    if (!shouldIgnoreXml) {
                        if (jackson2XmlPresent) {
                            Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
                            messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
                        }
                        if (jaxb2Present) { messageConverters.add(new Jaxb2RootElementHttpMessageConverter());}
                    }

                    if (kotlinSerializationJsonPresent) {
                        messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
                    }
                    if (jackson2Present) {
                        Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
                        messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
                    }
                    if (gsonPresent) {messageConverters.add(new GsonHttpMessageConverter());}
                    if (jsonbPresent) {messageConverters.add(new JsonbHttpMessageConverter());}
                    if (jackson2SmilePresent) {
                    	Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.smile();
                    	messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build()));
                    }
                    if (jackson2CborPresent) {
                    	Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.cbor();
                    	messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build()));
                    }
                }
            }
            // 调用实现了WebMvcConfigurer接口,扩展自己设置的转换器
            extendMessageConverters(this.messageConverters);
        }
        return this.messageConverters;
    }
    adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
    adapter.setCustomArgumentResolvers(getArgumentResolvers());
    adapter.setCustomReturnValueHandlers(getReturnValueHandlers());

    if (jackson2Present) {
        adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
        adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
    }

    AsyncSupportConfigurer configurer = getAsyncSupportConfigurer();
    if (configurer.getTaskExecutor() != null) {
        adapter.setTaskExecutor(configurer.getTaskExecutor());
    }
    if (configurer.getTimeout() != null) {
        adapter.setAsyncRequestTimeout(configurer.getTimeout());
    }
    adapter.setCallableInterceptors(configurer.getCallableInterceptors());
    adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());
    return adapter;
}
2.1 读取原理
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);{
// 获取到请求参数对象,使用消息转换器读取消息
Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());{
    Object arg = readWithMessageConverters(inputMessage, parameter, paramType);{
        boolean noContentType = false;
        MediaType contentType = inputMessage.getHeaders().getContentType();
        // 给默认的内容类型
        if (contentType == null) {
            noContentType = true;
            contentType = MediaType.APPLICATION_OCTET_STREAM;
        }
        // 获取到参数对象所属的类
        Class<?> contextClass = parameter.getContainingClass();
        // 获取参数的类型,如果给定的参数类型不是Class,返回null
        Class<T> targetClass = (targetType instanceof Class ? (Class<T>) targetType : null);
        // 如果参数类型不是Class
        if (targetClass == null) {
            // 根据给的参数找到对应类的Class来
            ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
            targetClass = (Class<T>) resolvableType.resolve();
        }
        // 判断输入消息的类型是不是HttpRequest,标注了@RequestBody的情况是ServletServerHttpRequest,符合条件
        // 获取到请求类型 POST转HttpMethod对象
        HttpMethod httpMethod = (inputMessage instanceof HttpRequest ? ((HttpRequest) inputMessage).getMethod() : null);
        // 读取的值默认为空对象
        Object body = NO_VALUE;
        try {
            // 根据传递过来的inputMessage消息提创建一个EmptyBodyCheckingHttpInputMessage,内部会自己处理请求体
            //比如自己设置了inputMessage
            EmptyBodyCheckingHttpInputMessage message = new EmptyBodyCheckingHttpInputMessage(inputMessage);{
                this.headers = inputMessage.getHeaders();
                // 获取body
                InputStream inputStream = inputMessage.getBody();
                // 默认就是为false,除非传递的inputMessage参数重写了markSupported为true
                if (inputStream.markSupported()) {
                    inputStream.mark(1);
                    this.body = (inputStream.read() != -1 ? inputStream : null);
                    inputStream.reset();
                }
                else {
                    // 创建一个新的输入流
                    PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream);
                    // 将请求体的输入村进入
                    int b = pushbackInputStream.read();
                    if (b == -1) {
                        this.body = null;
                    }
                    else {
                        this.body = pushbackInputStream;
                        pushbackInputStream.unread(b);
                    }
                }
            }
            // 遍历所有的消息类型转换器对消息进行类型转换
            // 这里的消息转换器有三种情况,详见消息转换器HttpMessageConverter原理
            for (HttpMessageConverter<?> converter : this.messageConverters) {
                // 获取消息转换器的类型
                Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass();
                // 判断消息转换器是否是GenericHttpMessageConverter,如果不是,返回null,是的话就强转为GenericHttpMessageConverter类型
                GenericHttpMessageConverter<?> genericConverter = (converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null);
                // 判断当前消息转换器是否可以读取请求数据
                if (genericConverter != null ?
                        // 如果消息类型为GenericHttpMessageConverter,那么直接判断它是否可以读取
                        genericConverter.canRead(targetType, contextClass, contentType){
                            // 判断消息转换器是否支持媒体类型
                            if (!canRead(mediaType)) {
                                return false;
                            }
                            // 将参数类型包装成JavaType类型
                            JavaType javaType = getJavaType(type, contextClass);
                            // 获取到合适的ObjectMapper,这个ObjectMapper就是有来序列化的
                            ObjectMapper objectMapper = selectObjectMapper(javaType.getRawClass(), mediaType);{
                                // objectMapperRegistrations默认为空,除非自己设置的
                                if (targetMediaType == null || CollectionUtils.isEmpty(this.objectMapperRegistrations)) {
                                    return this.defaultObjectMapper;
                                }
                                // 如果注册表不为空
                                // 遍历ObjectMapperRegistration注册表,根据媒体类型来获取对应的ObjectMapper
                                for (Map.Entry<Class<?>, Map<MediaType, ObjectMapper>> typeEntry : getObjectMapperRegistrations().entrySet()) {
                                    if (typeEntry.getKey().isAssignableFrom(targetType)) {
                                        for (Map.Entry<MediaType, ObjectMapper> objectMapperEntry : typeEntry.getValue().entrySet()) {
                                            if (objectMapperEntry.getKey().includes(targetMediaType)) {
                                                return objectMapperEntry.getValue();
                                            }
                                        }
                                        return null;
                                    }
                                }
                                // 都没找到,返回默认的
                                return this.defaultObjectMapper;
                            }
                            // 如果没有找到objectMapper,就没有办法序列化
                            if (objectMapper == null) {
                                return false;
                            }
                            // 判断objectMapper是否可以序列化javaType类型
                            AtomicReference<Throwable> causeRef = new AtomicReference<>();
                            if (objectMapper.canDeserialize(javaType, causeRef)) {
                                return true;
                            }
                            return false;
                        } :
                        // 否则还要判断参数类型不能为空,再判断它是否可以读取
                        (targetClass != null && converter.canRead(targetClass, contentType))) {
                    // 实现了RequestResponseBodyAdvice的执行链,在创建当前参数解析器的时候就已经将
                    // 在RequestMappingHandlerAdapter初始化的时候,给参数解析器设置的
                    // this.requestResponseBodyAdvice就是在RequestMappingHandlerAdapter初始化的时候,执行initControllerAdviceCache();方法
                    // 从@ControllerAdvice中,实现了requestResponseBodyAdvice的类缓存下来了
                    // resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
                    RequestResponseBodyAdviceChain advice = this.advice;
                    // 上面已经将请求体的数据存在EmptyBodyCheckingHttpInputMessage massage中了
                    if (message.hasBody()) {
                        // 找到真实要用的HttpInputMessage消息体
                        // 因为HttpInputMessage可以通过ControllerAdviceBean中实现RequestBodyAdvice来处理,返回新的HttpInputMessage
                        HttpInputMessage msgToUse = advice.beforeBodyRead(message, parameter, targetType, converterType);{
                            // 找到匹配的可用的RequestBodyAdvice,因为可能在@ControllerAdvice中设置条件,可能不满足当前Bean的方法
                            for (RequestBodyAdvice advice : getMatchingAdvice(parameter, RequestBodyAdvice.class)) {
                                // 判断当前RequestBodyAdvice的supports是否返回的true
                                if (advice.supports(parameter, targetType, converterType)) {
                                    // 调用接口的beforeBodyRead,在这之前还没开始读取,所以可以改请求体内部的数据
                                    request = advice.beforeBodyRead(request, parameter, targetType, converterType);{
                                        // 我自定义的RequestBodyAdvice,获取body,改变数据,然后又存进去,可达到加密解密的
                                        InputStream body = inputMessage.getBody();
                                        Object object = JSON.parseObject(IoUtil.read(body, Charset.defaultCharset()), targetType);
                                        if (object instanceof A) {
                                            ((A) object).setId(-1)
                                        }
                                        // 将数据返回出去
                                        return new MappingJacksonInputMessage(new ByteArrayInputStream(JSON.toJSONString(object).getBytes(StandardCharsets.UTF_8)), inputMessage.getHeaders());
                                    }
                                }
                            }
                            return request;
                        }
                        // 调用转换器的read方法
                        body = (genericConverter != null ? genericConverter.read(targetType, contextClass, msgToUse) :
                                ((HttpMessageConverter<T>) converter).read(targetClass, msgToUse));{
                                    // 将Bean和参数类型封装成JavaType
                                    // 再使用ObjectMapper读取body
                                    JavaType javaType = getJavaType(type, contextClass);
                                    return readJavaType(javaType, inputMessage);
                                }
                        // 上面调用过RequestBodyAdvice的beforeRead方法,现在调用RequestBodyAdvice的advice.afterBodyRead
                        // 就是一些读取前后的切面
                        body = advice.afterBodyRead(body, msgToUse, parameter, targetType, converterType);
                    }
                    else {
                        // 如果没有请求体
                        // 上面调用过RequestBodyAdvice的beforeRead,afterRead方法,在这里调用RequestBodyAdvice的advice.handleEmptyBody
                        // 处理请求体为空的数据
                        body = advice.handleEmptyBody(null, message, parameter, targetType, converterType);
                    }
                    break;
                }
            }
        }
        catch (IOException ex) {
            throw new HttpMessageNotReadableException("I/O error while reading input message", ex, inputMessage);
        }
        // 如果body为初始值NO_VALUE,表示没有消息处理器或者没有合适的消息处理器来处理当前参数
        if (body == NO_VALUE) {
            // 没有请求方法POST,或者请求方法不支持,或者没有请求体,这个时候没有内容是正常的,直接返回null
            if (httpMethod == null || !SUPPORTED_METHODS.contains(httpMethod) || (noContentType && !message.hasBody())) {
                return null;
            }
            // 否则还没解析出参数表示无法处理当前这个请求参数
            throw new HttpMediaTypeNotSupportedException(contentType,getSupportedMediaTypes(targetClass != null ? targetClass : Object.class));

        }
        // 返回处理后的请求体
        return body;
    }
    // 没有读取到参数,但是参数又是必须要的,设置了required=true
    if (arg == null && checkRequired(parameter)) {
        // 参数不可读的异常
        throw new HttpMessageNotReadableException("Required request body is missing: " + parameter.getExecutable().toGenericString(), inputMessage);
    }
    // 返回解析之后的参数
    return arg;
}

2.2 转换器的写原理
try {
    // 调用返回值处理器接口对响应结果进行处理
    this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);{
        // 获取返回值处理器
        HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);{
            // 是否是异步的返回结果
            boolean isAsyncValue = isAsyncReturnValue(value, returnType);{
                // 遍历所有的返回值处理器
                for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
                    // 如果是AsyncHandlerMethodReturnValueHandler这个类型并且isAsyncReturnValue返回true,就符合条件
                    // 表示可以处理这个异步结果的handler
                    if (handler instanceof AsyncHandlerMethodReturnValueHandler && ((AsyncHandlerMethodReturnValueHandler) handler).isAsyncReturnValue(value, returnType)) {
                        return true;
                    }
                }
                return false;
            }
            // 遍历所有的返回值处理器
            for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
                // 有两种情况,异步AsyncHandlerMethodReturnValueHandler处理isAsyncValue异步的结果
                // 普通HandlerMethodReturnValueHandler处理普通结果
                // 这样做就是避免没必要的判断,例如普通HandlerMethodReturnValueHandler去执行supportsReturnType为异步结果的逻辑,肯定是不符合条件的
                // AsyncHandlerMethodReturnValueHandler去执行普通返回结果的supportsReturnType,没有不要
                if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
                    continue;
                }
                // 执行当前Handler是否可以处理这个返回值
                if (handler.supportsReturnType(returnType){
                                return ModelAndView.class.isAssignableFrom(returnType.getParameterType());
                                // 类中或者方法中是否有@ResponseBody注解
                                return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) || returnType.hasMethodAnnotation(ResponseBody.class));
                            }) {
                    return handler;
                }
            }
            return null;
        }
        // 到了这里如果没有找到合适的Handler,表示当前返回值无法进行处理,直接报错
        if (handler == null) {
            throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
        }
        // 找到了Handler,使用handler处理返回值 这个只讲处理@ResponseBody的处理器RequestResponseBodyMethodProcessor
        handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);{
            // 请求处理完成
            mavContainer.setRequestHandled(true);
            // 创建InputMessage,可以获取Body为InputStream
            ServletServerHttpRequest inputMessage = createInputMessage(webRequest);{
                HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
                return new ServletServerHttpRequest(servletRequest);
            }
            // 创建输出的对象,也是可以获取Body为OutputStream
            ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);{
                HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
                return new ServletServerHttpResponse(response);
            }
            // 使用消息转换器,写入OutputStream(ServletServerHttpRequest)
            writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);{
                 // 实现了RequestResponseBodyAdvice的执行链,在创建当前参数解析器的时候就已经将
                // 在RequestMappingHandlerAdapter初始化的时候,给参数解析器设置的
                // this.requestResponseBodyAdvice就是在RequestMappingHandlerAdapter初始化的时候,执行initControllerAdviceCache();方法
                // 从@ControllerAdvice中,实现了requestResponseBodyAdvice的类缓存下来了
                // resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
                RequestResponseBodyAdviceChain advice = this.advice;
                // 找到对应的媒体类型,使用消息转换器写消息
                // 遍历所有的消息转换器
                for (HttpMessageConverter<?> converter : this.messageConverters) {
                    // 判断转换器是否是GenericHttpMessageConverter这种类型
                    GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null);
                    // 判断这个GenericHttpMessageConverter是否可以写入这条消息
                    if (genericConverter != null ?
                            ((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType){
                                                                            // 判断当前媒体类型是否支持
                                                                            if (!canWrite(mediaType)) {
                                                                                return false;
                                                                            }
                                                                            // 找到对应的ObjectMapper进行序列化
                                                                            ObjectMapper objectMapper = selectObjectMapper(clazz, mediaType);
                                                                            if (objectMapper == null) {
                                                                                return false;
                                                                            }
                                                                            // 判断ObjectMapper是否可以对当前类型进行序列化
                                                                            AtomicReference<Throwable> causeRef = new AtomicReference<>();
                                                                            if (objectMapper.canSerialize(clazz, causeRef)) {
                                                                                return true;
                                                                            }
                                                                            return false;
                            } :
                            converter.canWrite(valueType, selectedMediaType)) {

                        // 调用过ResponseBodyAdvice的beforeBodyWrite方法
                        // 在写入响应体之前最后对响应值做处理
                        body = advice.beforeBodyWrite(body, returnType, selectedMediaType,(Class<? extends HttpMessageConverter<?>>) converter.getClass(),inputMessage, outputMessage);{
                            return processBody(body, returnType, contentType, converterType, request, response);{
                                // 找到符合条件的ResponseBodyAdvice类
                                for (ResponseBodyAdvice<?> advice : getMatchingAdvice(returnType, ResponseBodyAdvice.class)) {
                                    // 判断ResponseBodyAdvice是否支持处理当前这个返回值
                                    if (advice.supports(returnType, converterType)) {
                                        // 如果可以处理,就将处理后的结果进行返回
                                        // 我们可以在这个对结果进行统一格式化处理
                                        body = ((ResponseBodyAdvice<T>) advice).beforeBodyWrite((T) body, returnType,contentType, converterType, request, response);
                                    }
                                }
                            }
                        }
                        if (body != null) {
                            Object theBody = body;
                            // 添加响应头要暴露的信息
                            addContentDispositionHeader(inputMessage, outputMessage);
                            // 真正写入OutputStream,根据不同类型调用不同类型的write方法
                            if (genericConverter != null) {
                                genericConverter.write(body, targetType, selectedMediaType, outputMessage);{
                                    // 添加响应头
                                    final HttpHeaders headers = outputMessage.getHeaders();
                                    addDefaultHeaders(headers, t, contentType);
                                    // 判断响应的结果是不是就是OutputStream信息,如果是,直接返回数据流信息
                                    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{
                                        // 不是响应Stream信息,写入消息
                                        writeInternal(t, type, outputMessage);{
                                            // 获取媒体类型,json编码,响应对象类型
                                            MediaType contentType = outputMessage.getHeaders().getContentType();
                                            JsonEncoding encoding = getJsonEncoding(contentType);
                                            Class<?> clazz = (object instanceof MappingJacksonValue ?((MappingJacksonValue) object).getValue().getClass() : object.getClass());
                                            // 获取ObjectMapper,写入数据
                                            ObjectMapper objectMapper = selectObjectMapper(clazz, contentType);
                                            ObjectWriter objectWriter = (serializationView != null ?
                                            objectMapper.writerWithView(serializationView) : objectMapper.writer());
                                            objectWriter.writeValue(generator, value);
                                            writeSuffix(generator, object);
                                            generator.flush();
                                        }
                                        // 刷新OutputStream
                                        outputMessage.getBody().flush();
                                    }
                                }
                            }
                            else {
                                ((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);
                            }
                        }
                        return;
                    }
                }
            }
        }
    }
}
catch (Exception ex) {
    throw ex;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值