环境:Springboot3.0.5
在默认情况下,口响RestController接口返回的息格数据格式是json,如下接口:
@RestController@RequestMapping("/rmf")public class ResponseMessageFormatController { @GetMapping("/index") public Users index() { return new Users(1,式及 "张飒", 66, "男") ; } }
接口返回
接口默认返回了json数据格式
通过Postman,我这里是基于解析没有在Header中添加Accept。当后台在处理该请求时会认为你能接收任意类型的自定数据格式也就是MediaType=*/*,紧接着会获取当前所有的义接应消原理HttpMessageConverter支持的MediaType,然后遍历所有的口响MediaType,找到第一个类型中只要不包含'*'的息格MediaType就直接返回,默认情况下application/json排在第一个,式及所以最终确定返回客户端的基于解析数据格式将会是application/json,最后再遍历所有的自定HttpMessageConverter找出支持applicatioin/json类型的HttpMessageConverter,最终确定了MappingJackson2HttpMessageConverter直接进行客户端的义接应消原理输出。
核心源码:
public abstract class AbstractMessageConverterMethodProcessor { protected <T> void writeWithMessageConverters(...) { List<MediaType> acceptableTypes; try { // 获取请求header中的Accept,如果请求中没有,则返回 */* 接受任意类型 acceptableTypes = getAcceptableMediaTypes(request); } // 获取当前容器中所有的HttpMessageConverter支持的MediaType List<MediaType> producibleTypes = getProducibleMediaTypes(request, valueType, targetType); List<MediaType> compatibleMediaTypes = new ArrayList<>(); // 确定具体输出的应该是那种消息格式, determineCompatibleMediaTypes(acceptableTypes, producibleTypes, compatibleMediaTypes); // 遍历 for (MediaType mediaType : compatibleMediaTypes) { // 判断当前的MediaType的类型[type] 和 子类型 [subtype] 中分别不是 * 和 *+ // 就符合条件,找到第一个直接返回,这就确定了将会给客户端返回的消息格式 if (mediaType.isConcrete()) { selectedMediaType = mediaType; break; } else if (mediaType.isPresentIn(ALL_APPLICATION_MEDIA_TYPES)) { selectedMediaType = MediaType.APPLICATION_OCTET_STREAM; break; } } if (selectedMediaType != null) { selectedMediaType = selectedMediaType.removeQualityValue(); // 遍历所有的HttpMessageConverter,是否有能支持上面确定的selectedMediaType for (HttpMessageConverter<?> converter : this.messageConverters) { GenericHttpMessageConverter genericConverter =(converter instanceof GenericHttpMessageConverter ghmc ? ghmc : 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); // 输出结果 ((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage); } } } }}
以上是关于消息处理的部分源码分析。
如果需要返回xml格式的数据,我们只需引入下面依赖即可。
引入依赖:
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId></dependency>
正确的返回了xml格式
为什么引入上面的依赖后就可以直接通过设置Accept为application/xml就可以返回xml格式呢?
原理:
// 在这导入的JacksonHttpMessageConvertersConfiguration类中进行了配置@Import({ JacksonHttpMessageConvertersConfiguration.class })public class HttpMessageConvertersAutoConfiguration { }@Configuration(proxyBeanMethods = false)class JacksonHttpMessageConvertersConfiguration { @Configuration(proxyBeanMethods = false) // 当前的类路径下有XmlMapper类,该类就在上面引入的包中 @ConditionalOnClass(XmlMapper.class) @ConditionalOnBean(Jackson2ObjectMapperBuilder.class) protected static class MappingJackson2XmlHttpMessageConverterConfiguration { @Bean @ConditionalOnMissingBean public MappingJackson2XmlHttpMessageConverter mappingJackson2XmlHttpMessageConverter(Jackson2ObjectMapperBuilder builder) { return new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()); } } }
当当前的类路径下有XmlMapper就会自动的创建处理XML格式的MappingJackson2XmlHttpMessageConverter
如果客户端要求接收的数据格式是yaml格式,这时候就需要自定义HttpMessageConverter
引入依赖:
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-yaml</artifactId></dependency>
自定义HttpMessageConverter:
@Componentpublic class YamlHttpMessageConverter extends AbstractHttpMessageConverter<Object> { public YamlHttpMessageConverter() { super(new MediaType("application", "yaml")) ; } @Override protected boolean supports(Class<?> clazz) { return true ; } @Override protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { return null ; } @Override protected void writeInternal(Object t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { try (OutputStream os = outputMessage.getBody()) { YAMLFactory factory = new YAMLFactory(); // 该配置作用就是:去掉开头的三个 '---' factory.configure(Feature.WRITE_DOC_START_MARKER, false) ; ObjectMapper mapper = new ObjectMapper(factory) ; os.write(mapper.writeValueAsString(t).getBytes(StandardCharsets.UTF_8)) ; } }}
正确的返回了yaml格式
责任编辑:武晓燕 来源: 实战案例锦集 自定义接口响应(责任编辑:焦点)
人工智能创企『蓦然认知』获1000万美金A轮投资 专注自然语言处理
经典恐怖解谜《恐怖美术馆》Switch实体版内容 3月9日发售
人工智能企业Kasisto融资920万美元 通过机器人KAI解决理财问题