目录
先来了解默认的适配规则
1. 多端内容适配
1. 默认规则
1.SpringBoot 多端内容适配。
a.基于请求头内容协商:(默认开启)
ⅰ. 客户端向服务端发送请求,携带HTTP标准的Accept请求头。
1. Accept: application/json、text/xml、text/yaml
2.服务端根据客户端请求头期望的数据类型进行动态返回
b.基于请求参数内容协商:(默认关闭)
i.发送请求 GET /projects/spring-boot?format=json
ii.匹配到 @GetMapping("/projects/spring-boot")
iii.根据参数协商,优先返回 json 类型数据【需要开启参数匹配设置】
ⅳ.发送请求 GET /projects/spring-boot?format=xml,优先返回 xml 类型数据
2. 效果演示
默认返回json数据
@RestController
public class PersonController {
@GetMapping("/person")
public Person person() {
Person person = new Person();
person.setId(1l);
person.setUserName("pjp");
person.setAge(21);
person.setEmail("175@qq.com");
return person;
}
}
请求同一个接口,可以返回json和xml不同格式数据
- 引入支持写出xml内容依赖
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
- 标注注解
@JacksonXmlRootElement // 可以写出为xml文档
@Data
public class Person {
private Long id;
private String userName;
private String email;
private Integer age;
}
此时引入jackson-dataformat-xml依赖 没有标注@JacksonXmlRootElement 依然返回的是xml格式的数据
- 开启基于请求参数的内容协商
# 开启基于请求参数的内容协商功能。 默认参数名:format。 默认此功能不开启
spring.mvc.contentnegotiation.favor-parameter=true
没有标注@JacksonXmlRootElement 依然生效
# 开启基于请求参数的内容协商功能。 默认参数名:format。 默认此功能不开启
spring.mvc.contentnegotiation.favor-parameter=true
# 指定内容协商时使用的参数名。默认是 format
spring.mvc.contentnegotiation.parameter-name=type
3.增加yaml返回支持
导入依赖
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
把对象写出成YAML
ObjectMapper类(com.fasterxml.jackson.databind.ObjectMapper)是Jackson的主要类,它可以帮助我们快速的进行各个类型和Json类型的相互转换。
public static void main(String[] args) throws JsonProcessingException {
Person person = new Person();
person.setId(1l);
person.setUserName("pjp");
person.setAge(21);
person.setEmail("175@qq.com");
ObjectMapper mapper = new ObjectMapper();
//将对象转换为Json字符串
String s = mapper.writeValueAsString(person);
System.out.println(s);
}
输出:
{"id":1,"userName":"pjp","email":"175@qq.com","age":21}
public static void main(String[] args) throws JsonProcessingException {
Person person = new Person();
person.setId(1l);
person.setUserName("pjp");
person.setAge(21);
person.setEmail("175@qq.com");
//去掉输出前的 ---
// YAMLFactory yamlFactory = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
YAMLFactory yamlFactory = new YAMLFactory();
ObjectMapper mapper = new ObjectMapper(yamlFactory);
//将对象转换为YAML字符串
String s = mapper.writeValueAsString(person);
System.out.println(s);
}
输出:
---
id: 1
userName: "pjp"
email: "175@qq.com"
age: 21
编写配置
# 新增一种媒体类型
#spring.mvc.contentnegotiation.media-types.yaml=text/yaml
#或者
spring.mvc.contentnegotiation.media-types.yaml=application/yaml
增加HttpMessageConverter组件,专门负责把对象写出为yaml格式
package com.pjp.config;
import com.pjp.component.MyYAMLMessageConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
//自己写一个配置 一个能把对象转为yaml的messageConverter
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// WebMvcConfigurer.super.extendMessageConverters(converters);
converters.add(new MyYAMLMessageConverter());
}
}
package com.pjp.component;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
public class MyYAMLMessageConverter extends AbstractHttpMessageConverter<Object> {
private ObjectMapper objectMapper = null;
public MyYAMLMessageConverter() {
//new MediaType媒体类型
//告诉SpringBoot这个MessageConverter支持哪种媒体类型
super(new MediaType("application", "yaml", Charset.forName("UTF-8")));
YAMLFactory factory = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
this.objectMapper = new ObjectMapper(factory);
}
@Override
protected boolean supports(Class<?> clazz) {
//在这里判断类型
//当前 只要是对象类型,不是基本类型直接返回true
String clazzName = clazz.getName();
if (clazzName.equals(java.lang.Integer.class) ||
clazzName.equals(java.lang.Byte.class) ||
clazzName.equals(java.lang.Long.class) ||
clazzName.equals(java.lang.Double.class) ||
clazzName.equals(java.lang.Float.class) ||
clazzName.equals(java.lang.Character.class) ||
clazzName.equals(java.lang.Short.class) ||
clazzName.equals(java.lang.Boolean.class)) {
return false;
}
return true;
}
@Override//@RequestBody
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return null;
}
@Override//@ResponseBody 把对象写出去
protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
//通过OutputStream将自定义数据写出去
// OutputStream body = outputMessage.getBody();
// try {
// this.objectMapper.writeValue(body,o);
// }finally {
// body.close();
// }
//新语法try-with 自动关闭流
try (OutputStream body = outputMessage.getBody()) {
this.objectMapper.writeValue(body, o);
}
}
}