spring下HttpMessageConverter核心代码详解
来源:互联网 发布:达示数据 编辑:程序博客网 时间:2024/05/17 06:56
使用spring的小伙伴肯定对下面的配置特别了解:
<mvc:annotation-driven> <mvc:message-converters register-defaults="false"> <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" /> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes" value="text/plain;charset=UTF-8" /> </bean> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/plain;charset=UTF-8</value> <value>application/json;charset=UTF-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
再看下下面的controller代码:
@GetMapping(value = "/get-person", produces = MediaType.APPLICATION_JSON_VALUE) public @ResponseBody Person getPerson() throws IOException { Person per = new Person("Bill","Gates"); return per; }
responsebody注解的作用是告诉spring框架使用HttpMessageConverter来将getPerson方法返回的Person对象使用mvc:message-converters注解里面配置的消息转换器将返回值经过相应的转换后传递给前端。这里面就离不开AbstractMessageConverterMethodProcessor这个抽象类,下面我们来看下该类相关代码:
protected <T> void writeWithMessageConverters(T value, MethodParameter returnType,ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {Object outputValue;Class<?> valueType;Type declaredType;if (value instanceof CharSequence) {outputValue = value.toString();valueType = String.class;declaredType = String.class;}else {outputValue = value;valueType = getReturnValueType(outputValue, returnType);declaredType = getGenericType(returnType);}HttpServletRequest request = inputMessage.getServletRequest();
//获取前端传递的多媒体类型List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(request);
//获取该方法支持返回的的多媒体类型,对于getPerson方法来说只有application/json一种类型List<MediaType> producibleMediaTypes = getProducibleMediaTypes(request, valueType, declaredType);if (outputValue != null && producibleMediaTypes.isEmpty()) {throw new IllegalArgumentException("No converter found for return value of type: " + valueType);}Set<MediaType> compatibleMediaTypes = new LinkedHashSet<MediaType>();for (MediaType requestedType : requestedMediaTypes) {for (MediaType producibleType : producibleMediaTypes) {if (requestedType.isCompatibleWith(producibleType)) {compatibleMediaTypes.add(getMostSpecificMediaType(requestedType, producibleType));}}}if (compatibleMediaTypes.isEmpty()) {if (outputValue != null) {throw new HttpMediaTypeNotAcceptableException(producibleMediaTypes);}return;}List<MediaType> mediaTypes = new ArrayList<MediaType>(compatibleMediaTypes);MediaType.sortBySpecificityAndQuality(mediaTypes);MediaType selectedMediaType = null;for (MediaType mediaType : mediaTypes) {if (mediaType.isConcrete()) {selectedMediaType = mediaType;break;}else if (mediaType.equals(MediaType.ALL) || mediaType.equals(MEDIA_TYPE_APPLICATION)) {selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;break;}}if (selectedMediaType != null) {
//去除权衡因子:比如对application/json;q=0.8来说,调用removeQualityValue后返回application/jsonselectedMediaType = selectedMediaType.removeQualityValue();
/*接下来的代码的作用就是从mvc:message-converters配置的消息转换器中选择一个可以处理返回值为
Person类且支持返回类型为application/json的转换器,如果找不到则抛出
‘HttpMediaTypeNotAcceptableException’异常,找到则调用相应转换器的write方法将Person对象
按照json格式处理后写入返回消息的body中*/for (HttpMessageConverter<?> messageConverter : this.messageConverters) {if (messageConverter instanceof GenericHttpMessageConverter) {if (((GenericHttpMessageConverter) messageConverter).canWrite(declaredType, valueType, selectedMediaType)) {outputValue = (T) getAdvice().beforeBodyWrite(outputValue, returnType, selectedMediaType,(Class<? extends HttpMessageConverter<?>>) messageConverter.getClass(),inputMessage, outputMessage);if (outputValue != null) {addContentDispositionHeader(inputMessage, outputMessage);((GenericHttpMessageConverter) messageConverter).write(outputValue, declaredType, selectedMediaType, outputMessage);if (logger.isDebugEnabled()) {logger.debug("Written [" + outputValue + "] as \"" + selectedMediaType +"\" using [" + messageConverter + "]");}}return;}}else if (messageConverter.canWrite(valueType, selectedMediaType)) {outputValue = (T) getAdvice().beforeBodyWrite(outputValue, returnType, selectedMediaType,(Class<? extends HttpMessageConverter<?>>) messageConverter.getClass(),inputMessage, outputMessage);if (outputValue != null) {addContentDispositionHeader(inputMessage, outputMessage);((HttpMessageConverter) messageConverter).write(outputValue, selectedMediaType, outputMessage);if (logger.isDebugEnabled()) {logger.debug("Written [" + outputValue + "] as \"" + selectedMediaType +"\" using [" + messageConverter + "]");}}return;}}}if (outputValue != null) {throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);}}
0 0
- spring下HttpMessageConverter核心代码详解
- spring HttpMessageConverter
- HttpMessageConverter详解
- Spring MVC框架下有关HTTP请求信息转换器HttpMessageConverter
- spring mvc HttpMessageConverter使用
- Spring HttpMessageConverter 之 Jackson
- Spring HttpMessageConverter 之 Jackson
- spring httpMessageConverter 和 @ResponseBody
- Spring 核心部门详解
- HttpMessageConverter
- HttpMessageConverter
- HttpMessageConverter
- HttpMessageConverter
- HttpMessageConverter
- HttpMessageConverter
- httpMessageConverter
- iOS 核心动画 代码详解
- spring核心容器 spring container 详解
- Nginx基础及其配制说明
- 学习go语言引发的一系列问题。
- 算法 第4版
- 关于service.setPackage和bindService一直返回false
- mysql主从复制配置
- spring下HttpMessageConverter核心代码详解
- MySQL优化原理
- Over:窗口函数(滑动聚合)
- c++学习笔记
- Redis常用命令整理
- 进程监控
- 创建分区表和查看分区表的Metadata
- ubuntu linux zip和unzip类命令详解
- 如何过滤目录下特定的文件(FileFilter)