消息转换器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; }