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编辑  收藏  举报

导航