springboot自定義消息轉換器HttpMessageConverter


 

在SpringMVC中,可以使用@RequestBody和@ResponseBody兩個注解,分別完成請求報文到對象和對象到響應報文的轉換,底層這種靈活的消息轉換機制就是利用HttpMessageConverter來實現的,Spring內置了很多HttpMessageConverter,比如MappingJackson2HttpMessageConverter,StringHttpMessageConverter等,下面我們來自定義自己的消息轉換器來滿足自己特定的需求,有兩種方式:1、使用spring或者第三方提供的現成的HttpMessageConverter,2、自己重寫一個HttpMessageConverter。

配置使用FastJson插件返回json數據

  在springboot項目里當我們在控制器類上加上@RestController注解或者其內的方法上加入@ResponseBody注解后,默認會使用jackson插件來返回json數據,下面我們利用fastjson為我們提供的FastJsonHttpMessageConverter來返回json數據。

  首先要引入fastjson的依賴:

     <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.31</version>
        </dependency>

  接下來通過實現WebMvcConfigurer接口來配置FastJsonHttpMessageConverter,springboot2.0版本以后推薦使用這種方式來進行web配置,這樣不會覆蓋掉springboot的一些默認配置。配置類如下:

復制代碼
package com.example.demo;

import java.util.List;

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 com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;

@Configuration
public class MyWebmvcConfiguration implements WebMvcConfigurer{

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter fjc = new FastJsonHttpMessageConverter();
        FastJsonConfig fj = new FastJsonConfig();
        fj.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
        fjc.setFastJsonConfig(fj);
        converters.add(fjc);
    }

}
復制代碼

  fastJson配置實體調用setSerializerFeatures方法可以配置多個過濾方式,常用的如下:

  1、WriteNullListAsEmpty  :List字段如果為null,輸出為[],而非null
  2、WriteNullStringAsEmpty : 字符類型字段如果為null,輸出為"",而非null
  3、DisableCircularReferenceDetect :消除對同一對象循環引用的問題,默認為false(如果不配置有可能會進入死循環)
  4、WriteNullBooleanAsFalse:Boolean字段如果為null,輸出為false,而非null
  5、WriteMapNullValue:是否輸出值為null的字段,默認為false。
  其它的相關類,我們引入了lombok插件
復制代碼
package com.example.demo;

import java.util.ArrayList;
import java.util.List;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @RequestMapping(value="/get",method=RequestMethod.GET)
    public Object getList(){
        List<UserEntity> list= new ArrayList<UserEntity>();
        UserEntity u1 = new UserEntity(null, "shanghai");
        list.add(u1);
        return list;
    }

}
復制代碼
復制代碼
package com.example.demo;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class UserEntity {
    private String name;
    private String address;
        
}
復制代碼

  設置端口為8888,啟動項目訪問http://localhost:8888/get,我們代碼中沒有配置WriteMapNullValue,所以如果返回結果中有null值則不顯示,結果如下:

  我們注釋掉fastjson配置,重新啟動項目並訪問,從結果可以看出我們配置的消息轉換器起作用了。

重寫HttpMessageConverter

  接下來我們繼承AbstractHttpMessageConverter來實現一個自己的消息轉換器,示例如下:

復制代碼
package com.example.demo;

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 org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.Charset;

public class MyMessageConverter extends AbstractHttpMessageConverter<UserEntity> {


    public MyMessageConverter() {
        // 新建一個我們自定義的媒體類型application/xxx-junlin
        super(new MediaType("application", "xxx-junlin", Charset.forName("UTF-8")));
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        // 表明只處理UserEntity類型的參數。
        return UserEntity.class.isAssignableFrom(clazz);
    }

    /**
     * 重寫readlntenal 方法,處理請求的數據。代碼表明我們處理由“-”隔開的數據,並轉成 UserEntity類型的對象。
     */
    @Override
    protected UserEntity readInternal(Class<? extends UserEntity> clazz,
            HttpInputMessage inputMessage) throws IOException,
            HttpMessageNotReadableException {
        String temp = StreamUtils.copyToString(inputMessage.getBody(), Charset.forName("UTF-8"));
        String[] tempArr = temp.split("-");

        return new UserEntity(tempArr[0],tempArr[1]);
    }

    /**
     * 重寫writeInternal ,處理如何輸出數據到response。
     */
    @Override
    protected void writeInternal(UserEntity userEntity,
            HttpOutputMessage outputMessage)
            throws IOException, HttpMessageNotWritableException {
        String out = "hello: " + userEntity.getName() + "-" + userEntity.getAddress();
        outputMessage.getBody().write(out.getBytes());
    }
}
復制代碼

  將自定義的消息轉換器加入到springmvc容器中,以便被使用。

復制代碼
package com.example.demo;

import java.util.List;

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 com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;

@Configuration
public class MyWebmvcConfiguration implements WebMvcConfigurer{

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter fjc = new FastJsonHttpMessageConverter();
        FastJsonConfig fj = new FastJsonConfig();
        fj.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
        fjc.setFastJsonConfig(fj);
        converters.add(fjc);
        converters.add(converter());
    }
    @Bean
    public MyMessageConverter converter() {
        return new MyMessageConverter();
    }

}
復制代碼

  UserController中加入測試的代碼

復制代碼
package com.example.demo;

import java.util.ArrayList;
import java.util.List;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @RequestMapping(value="/get",method=RequestMethod.GET)
    public Object getList(){
        List<UserEntity> list= new ArrayList<UserEntity>();
        UserEntity u1 = new UserEntity(null, "shanghai");
        list.add(u1);
        return list;
    }
    
    @RequestMapping(method = RequestMethod.POST, value = "/convert")
    public @ResponseBody UserEntity converter(@RequestBody UserEntity user) {
        return user;
    }
}
復制代碼

  啟動項目,使用postman來測試,從響應來看我們的消息轉換器已經起作用了,如下:

原文:springboot自定義消息轉換器HttpMessageConverter


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM