Spring mvc 之 AbstractHttpMessageConverter 自定义Http消息转化器

场景:获取网络数据时,发现如下错误

{
  "timestamp": "2018-04-13T05:43:23.256+0000",
  "status": 500,
  "error": "Internal Server Error",
  "exception": "feign.codec.DecodeException",
  "message": "Could not extract response: no suitable HttpMessageConverter found for response type [class com.alibaba.fastjson.JSONObject] and content type [text/html;charset=UTF-8]",
  "path": "/get2"
}

但是,实际上该数据是JSON形式的字符串,只是类型为 text/html 为了解决该问题,可以指定Http的消息转化器,来解析,如下:

1.编写处理类

public class TestHtmlToJsonObjectConver extends AbstractHttpMessageConverter<JSONObject> {

    @Autowired
    private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;

    /**
     * 自定义支持的媒体类型
     * 也就是只有此种类型的数据才会被处理
     */
    public TestHtmlToJsonObjectConver() {
        super(new MediaType("text", "html", Charset.forName("UTF-8")));
    }

    /**
     * 判断是否为支持的类型
     *
     * @param clazz
     * @return
     */
    @Override
    protected boolean supports(Class<?> clazz) {
        return JSONObject.class.isAssignableFrom(clazz);
    }

    /**
     * 用于读取定义的类型的资源,将其转化为JSONObject对象
     *
     * @param aClass
     * @param httpInputMessage
     * @return
     * @throws IOException
     * @throws HttpMessageNotReadableException
     */
    @Override
    protected JSONObject readInternal(Class<? extends JSONObject> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
        String message = StreamUtils.copyToString(httpInputMessage.getBody(), Charset.forName("UTF-8"));
        return JSONObject.parseObject(message);
    }

    /**
     * 用于在推送此种类型的资源时,将JSONObject对象转化为自定义的格式返回给调用者
     * 这里所有的返回JSONObject对象给前端的请求,都会执行此方法
     * 因而调用Spring的默认的mappingJackson2HttpMessageConverter来处理
     *
     * @param jsonObject
     * @param httpOutputMessage
     * @throws IOException
     * @throws HttpMessageNotWritableException
     */
    @Override
    protected void writeInternal(JSONObject jsonObject, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
        System.out.println("方法被调用");
        mappingJackson2HttpMessageConverter.write(jsonObject, new MediaType("application", "*+json"), httpOutputMessage);
    }
}

2.件对象注入到容器

   @Bean
    public TestHtmlToJsonObjectConver testHtmlToJsonObjectConver() {
        return new TestHtmlToJsonObjectConver();
    }

在Spring boot直接注入到容器,容器就会自动加载该消息转换器而不需要再次注册。当然也可以再次注册


3.注册(非必要)

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {


    @Bean
    public TestHtmlToJsonObjectConver testHtmlToJsonObjectConver() {
        return new TestHtmlToJsonObjectConver();
    }

    /**
     * 配置configureMessageConverters默认不加载默认的消息转换器
     * 配置extendMessageConverters仅仅添加一个默认的消息转换器,当然也会加载默认的消息转换器
     * @param converters
     */
//    @Override
//    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//        super.configureMessageConverters(converters);
//        converters.add(testHtmlToJsonObjectConver());
//    }

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.extendMessageConverters(converters);
        converters.add(testHtmlToJsonObjectConver());
    }
}

### Spring Boot 序列化配置示例 在 Spring Boot 中,序列化和反序列化的配置可以通过自定义 `HttpMessageConverter` 来实现。以下是具体的例子: #### 自定义消息转换器 通过创建一个自定义消息转换器类来处理特定的数据格式(如 YAML 或 JSON)。下面是一个基于 YAML 的消息转换器的例子。 ```java import org.yaml.snakeyaml.Yaml; 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.util.Map; public class YamlMessageConverter extends AbstractHttpMessageConverter<Map<String, Object>> { private final Yaml yaml = new Yaml(); public YamlMessageConverter() { super(MediaType.parseMediaType("application/x-yaml")); } @Override protected boolean supports(Class<?> clazz) { return Map.class.isAssignableFrom(clazz); } @Override protected Map<String, Object> readInternal(Class<? extends Map<String, Object>> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { return yaml.loadAs(inputMessage.getBody(), Map.class); } @Override protected void writeInternal(Map<String, Object> map, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { yaml.dump(map, outputMessage.getBody()); } } ``` 此代码片段展示了如何构建一个支持 YAML 数据类型的 `HttpMessageConverter`[^1]。 #### 配置消息转换器 为了使上述自定义消息转换器生效,需要将其注册为 Bean 并添加到全局的 `HttpMessageConverters` 列表中。 ```java @Configuration public class AppConfig { @Bean public WebMvcConfigurer webMvcConfigurer() { return new WebMvcConfigurer() { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(new YamlMessageConverter()); } }; } } ``` 这段代码将自定义的 `YamlMessageConverter` 添加到了 Spring MVC消息转换器列表中[^2]。 #### 使用 @RequestBody 进行数据绑定 当客户端发送请求时,Spring 可以自动将请求体中的数据解析并映射到控制器方法的参数上。例如,在更新用户的场景下,可以接收一个 JSON 数组并将它转化为 Java 对象列表。 ```java @RestController @RequestMapping("/api/users") public class UserController { @PostMapping(value = "/update", consumes = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Integer> updateUser(@RequestBody List<User> users) { return ResponseEntity.ok(users.size()); } } ``` 在这个例子中,`@RequestBody` 注解会触发默认的 Jackson 消息转换器,从而完成从 JSON 字符串到对象集合的转化过程[^3]。 如果希望更改默认的行为,比如使用 GSON 而不是 Jackson,则需替换掉默认的 `MappingJackson2HttpMessageConverter`。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值