SpringBoot - 内容协商机制
1.内容协商机制
根据客户端接收能力不同,SpringBoot 返回不同媒体类型的数据
比如: 客户端 Http 请求 Accept: application/xml 则返回 xml 数据,客户端 Http 请求 Accept: application/json 则返回 json 数据
SpringBoot 默认支持返回Json数据,默认不支持返回xml数据,所以需要导入jackson-dataformat-xml 让SpringBoot支持返回xml数据
<!-- 引入支持返回 xml 数据格式 --> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
如果客户端请求头的 Accept为application/xml 则返回 xml 数据,客户端 Http 请求 Accept为application/json 则返回 json 数据
@RestController public class HmcController { @RequestMapping("param") public ReUser param(){ return new ReUser("Levi 张三",18); } }
2.基于请求参数的内容协商
为什么会出现基于请求参数的内容协商,因为游览器无法更改请求头中的Accept参数,所以我们可以通过设置请求参数
来获取我们想要服务器返回的参数类型
spring:
mvc:
contentnegotiation:
favor-parameter: true #开启请求参数内容协商模式
获取Json格式数据:http://localhost:8082/param?format=json
获取Xml格式数据:http://localhost:8082/param?format=xml
3.自定义内容协商的写与读
自定义协商器
public class XTypeHttpMessageConverter implements HttpMessageConverter<ReUser> { //是否可写 @Override public boolean canRead(Class<?> clazz, MediaType mediaType) { return clazz.isAssignableFrom(ReUser.class); } //是否可读 @Override public boolean canWrite(Class<?> clazz, MediaType mediaType) { return clazz.isAssignableFrom(ReUser.class); } //支持的类型 @Override public List<MediaType> getSupportedMediaTypes() { return MediaType.parseMediaTypes("application/x-type"); } //读 处理 @Override public ReUser read(Class<? extends ReUser> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { //获取请求的请求体 String requestBody = StreamUtils.copyToString(inputMessage.getBody(), Charset.forName("UTF-8")); //解析格式 xxx-xxx-xxx String[] split = requestBody.split("-"); //生成对象 返回 ReUser reUser = new ReUser(); reUser.setrId(split[0]); reUser.setrName(split[1]); reUser.setrAage(split[2]); return reUser; } //写 处理 @Override public void write(ReUser reUser, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { //自定义格式 xxx-xxx-xxx String result=reUser.getrId()+"-"+reUser.getrName()+"-"+reUser.getrAage(); //写出去 StreamUtils.copy(result.getBytes(StandardCharsets.UTF_8),outputMessage.getBody()); } }
配置自定义协商器
@Configuration public class ContentNegotiationConfig implements WebMvcConfigurer { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { //支持的类型 Map<String, MediaType> mediaTypeMap=new HashMap<>(); mediaTypeMap.put("json",MediaType.APPLICATION_JSON); mediaTypeMap.put("xml",MediaType.APPLICATION_XML); mediaTypeMap.put("x-type",MediaType.parseMediaType("application/x-type;charset=UTF-8")); //支持参数请求内容协商 ParameterContentNegotiationStrategy parameterContentNegotiationStrategy = new ParameterContentNegotiationStrategy(mediaTypeMap); //支持请求头内容协商 HeaderContentNegotiationStrategy headerContentNegotiationStrategy = new HeaderContentNegotiationStrategy(); configurer.strategies(Arrays.asList(parameterContentNegotiationStrategy,headerContentNegotiationStrategy)); } @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { //添加自定义内容协商 converters.add(new XTypeHttpMessageConverter()); //设置优先级 //converters.add(0,new XTypeHttpMessageConverter()); }
写如何使用:
首先请求头的Accept的参数值要为application/x-type或者开启了基于参数的请求内容协商format为x-type
控制类(被Controller修饰的类)中的方法返回类型为自定义HttpMessageConverter的泛型
@RequestMapping("httpMessageConverter") public ReUser index(){ ReUser reUser = new ReUser(); return reUser; }
读如何使用:
读需要配合@RequestBody使用
@RequestMapping("index") public ReUser index(@RequestBody ReUser reUser){ System.out.println(reUser); return reUser; }
posted on 2022-12-29 17:09 Mikasa-Ackerman 阅读(123) 评论(0) 编辑 收藏 举报