SpringBoot2 学习笔记(6)——自定义内容协商

什么是内容协商呢 ? 简单来说,就是根据客户端接收能力不同,返回不同媒体类型的数据。

我想要他返回的是 xml 就返回 xml ,想要他返回图片就是图片,比如我现在客户端就只能接收json,那么他就必须给客户端返回json。

在这里插入图片描述

而告诉服务器本客户端可以接收的数据类型的字段被放在请求头的 Accept 字段中
在这里插入图片描述

默认情况下springboot返回的是 */ *

我们写一段程序来测试一下

自定义一个 Person 类,里面包含姓名,年龄和生日等信息,现在返回这个对象中的数据,看一下会是以哪种数据类型返回的。

	@ResponseBody
    @GetMapping("/test/person")
    public Person getPerson(){
        Person person=new Person();
        person.setAge(28);
        person.setUserName("zhangsan");
        person.setBirth(new Date());
        return person;
    }

在浏览器中我们访问这个 url ,发现它是以 json 的形式返回的
在这里插入图片描述
为什么会是 json 呢?* / *难道不是应该返回任意类型吗 ? 事实上也确实是返回了任意类型,即使我们将请求头的Accept改为了随便写的比如“aabc”,他也仍然会返回一个json数据。通过 debug 我们可以发现,他会默认的去选择MediaType列表中的第一个值,也就是当 Accept 是 * / * 的时候,不管你现在给他改为哪种类型,都是会以json的形式呈现。
在这里插入图片描述
当然在我们没有特定工具(这里我修改Accept是通过Postman完成的)的时候,如何通过 Url 参数传递的形式来实现返回我们想要的数据类型呢?

springboot 也有关于请求协商的配置管理,只不过默认情况下是false,我们需要在yaml文件中手动的去开启内容协商功能
在这里插入图片描述
我们现在以 xml 为例,来看看是如何通过修改Url参数来实现对返回的数据类型的修改

首先,引入关于 xml 的jar包,在pom.xml文件中加入

	<dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>

此时,便可以通过加上format=xx来实现相关数据类型的切换
在这里插入图片描述

但是,在这种方式下,默认只支持 xml 和 json 两种形式

通过debug我们可以发现,在 strategy 中只有两个mediaType ,一个是 xml ,另一个便是 json (感兴趣的话,可以点开源码去了解一下为什么会是这两个,而不是其他的)
在这里插入图片描述


那如果我们想要往里面再加入mediaType要怎么办呢 ? 现在我们以一个自定义的MessageConverter为例,看一下如何加入我们自定义的数据类型(实际开发中基本用不到,可以学习一下)

我们自定义一个类叫做GuiguMessageConverter,让他去实现HttpMessageConverter接口,在要重写的方法里面我们可以发现MessageConverter既支持读也支持写,本质上它也是一个IO流的操作

在这里插入图片描述
我们只是希望以某种形式的数据类型展现到浏览器页面上,所以不需要读,直接让canRead()返回一个false,为了让程序更加严谨,让canWrite()方法返回 Person 这个类是否已经存在,避免对不存在的对象进行操作

	@Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return clazz.isAssignableFrom(Person.class);
    }

然后,read()方法不需要去管他,让他返回 null ,我们来写我们想要返回的数据格式

例如我现在就想要直接返回姓名、年龄、生日这些数据,中间以分号隔开,那我们就可以这样写

	@Override
    public void write(Person person, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        //自定义协议数据的写出
        String data=person.getUserName()+";"+person.getAge()+";"+person.getBirth();

        OutputStream body = outputMessage.getBody();
        body.write(data.getBytes());
    }

最后,还需要在getSupportedMediaTypes()方法中返回我们这个MessageConverter的MediaType名字

	@Override
    public List<MediaType> getSupportedMediaTypes() {
        return MediaType.parseMediaTypes("application/x-guigu");
    }

    @Override
    public List<MediaType> getSupportedMediaTypes(Class<?> clazz) {
        return MediaType.parseMediaTypes("application/x-guigu");
    }

此时,GuiguMessageConverter已经定义完成了。然后我们还需要在strategy中去加入我们自定义的这个类型,这里我直接重写了他默认的配置策略(并不推荐小伙伴们这样做,因为修改默认配置可能会因为考虑不周而使应用的部分功能无法正常使用)

	@Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        Map<String, MediaType> map=new HashMap<>();
        map.put("json",MediaType.APPLICATION_JSON);
        map.put("xml",MediaType.APPLICATION_XML);
        map.put("gg",MediaType.parseMediaType("application/x-guigu"));
        //基于参数的策略
        ParameterContentNegotiationStrategy parameterstrategy=new ParameterContentNegotiationStrategy(map);

        //基于请求头Accept的策略
        HeaderContentNegotiationStrategy headerStrategy=new HeaderContentNegotiationStrategy();

        configurer.strategies(Arrays.asList(parameterstrategy,headerStrategy));
    }

现在,我们就能够在Url参数里面加入gg来返回我们写的这个叫做application/x-guigu的 MediaType 了
在这里插入图片描述

大功告成!!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值