返回顶部
首页 > 资讯 > 后端开发 > Python >SpringBoot自定义MessageConverter与内容协商管理器contentNegotiationManager详解
  • 366
分享到

SpringBoot自定义MessageConverter与内容协商管理器contentNegotiationManager详解

2024-04-02 19:04:59 366人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录1、自定义消息转换器MessageConverter2、自定义内容协商管理器contentNeGotiationManager1、自定义消息转换器MessageConverter

1、自定义消息转换器MessageConverter

WEBmvcAutoConfiguration类中有一个方法configureMessageConverters(),它会配置默认的MessageConverter

public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
	this.messageConvertersProvider.ifAvailable((customConverters) -> {
		converters.addAll(customConverters.getConverters());
	});
}

假设我们现在有一个新的需求

想要后端返回我们自己定义的格式的数据,就叫x-decade,格式为使用分号拼接Person对象属性值

那么就要新建一个MessageConverter了

package com.decade.converters;
import com.decade.pojo.Person;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
public class DecadeConverter implements HttpMessageConverter<Person> {
	// 只考虑写出,所以这里默认写false
    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return false;
    }
    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return clazz.isAssignableFrom(Person.class);
    }
    
    @Override
    public List<MediaType> getSupportedMediaTypes() {
        return MediaType.parseMediaTypes("application/x-decade");
    }
	// 只考虑写出,所以这里默认写null
    @Override
    public Person read(Class<? extends Person> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }
    @Override
    public void write(Person person, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        // 自定义想要写出的数据格式
        String result = person.getName() + ";" + person.getAge() + ";" + person.getBirth();
        // 写出
        final OutputStream body = outputMessage.getBody();
        body.write(result.getBytes());
    }
}

我们发现,WebMvcConfigurer接口类下面有2个关于配置MessageConverter的方法

// 会覆盖默认的MessageConverter
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
// 不会覆盖,只会在默认的MessageConverter后面追加我们自定义的
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}

所以,我们选择在自定义配置类中重写extendMessageConverters()方法

package com.decade.config;
import com.decade.converters.DecadeConverter;
import org.springframework.context.annotation.Bean;
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(proxyBeanMethods = false)
public class MyMvcConfig implements WebMvcConfigurer {
    @Bean
    public WebMvcConfigurer createConvert() {
        return new WebMvcConfigurer() {
            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
                converters.add(new DecadeConverter());
            }
        };
    }
}

我们在请求头中设置Accept为我们自定义的格式application/x-decade

验证结果如下

2、自定义内容协商管理器contentNegotiationManager

问题:我们新建的x-decade格式是否只能通过postman调用才会生效呢?如果我们要使用浏览器参数方式,怎么才能生效呢?

因为我们之前的【Spring Boot】响应处理

它默认只能处理xml和JSON格式,所以为了解决这个问题,我们就要自定义内容协商管理器了

首先我们还是要在自定义配置类中重写相关方法

package com.decade.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
import org.springframework.web.accept.ParameterContentNegotiationStrategy;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@Configuration(proxyBeanMethods = false)
public class MyMvcConfig implements WebMvcConfigurer {
    @Bean
    public WebMvcConfigurer createConvert() {
        return new WebMvcConfigurer() {
            @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
                // 设置支持的浏览器参数类型
                Map<String, MediaType> mediaTypes = new HashMap<>();
                mediaTypes.put("json", MediaType.APPLICATION_JSON);
                mediaTypes.put("xml", MediaType.APPLICATION_XML);
                mediaTypes.put("decade", MediaType.parseMediaType("application/x-decade"));
                final ParameterContentNegotiationStrategy strategy = new ParameterContentNegotiationStrategy(mediaTypes);
                // 为了继续支持请求头参数类型,还需要往里面塞请求头内容协商管理器
                final HeaderContentNegotiationStrategy headerContentNegotiationStrategy = new HeaderContentNegotiationStrategy();
                configurer.strategies(Arrays.asList(strategy, headerContentNegotiationStrategy));
            }
        };
    }
}

可以看到,系统中的内容协商管理器下面还是原来的2种:获取请求头中的Accept和获取请求参数中的fORMat

但是获取请求参数format,除了能识别原来的json和xml,还能识别我们自定义的application/x-decade,它使用decade与之对应

可以看到,我们自定义的媒体类型成功加入服务器能解析出来的类型

我们写一个接口进行验证

@GetMapping(value = "/testPerson")
@ResponseBody
public Person testPerson() {
	Person person = new Person();
	person.setName("decade");
	person.setAge(24);
	person.setBirth(new Date());
	return person;
}

由验证结果可以知道,我们从postman和浏览器都可以获得我们指定格式的数据

到此这篇关于SpringBoot自定义MessageConverter与内容协商管理器contentNegotiationManager详解的文章就介绍到这了,更多相关SpringBoot MessageConverter内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: SpringBoot自定义MessageConverter与内容协商管理器contentNegotiationManager详解

本文链接: https://lsjlt.com/news/168922.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作