初始化原理
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;
}
消息转换器HttpMessageConverter原理
于 2024-01-20 23:09:46 首次发布