1. 程式人生 > >自定義一個自己的訊息轉換器

自定義一個自己的訊息轉換器

1.自定義個訊息轉換器,支援自己定義的content-type型別.首先準備好測試的controller類;

    @PostMapping("/")
    public Object test(@RequestBody UserInfo userInfo) {
        return userInfo;
    }

實體類

public class UserInfo {
    private String age;
    private String name;
    setter,getter...
}

注意,在接收引數那裡要使用@RequestBody,(@requestBody註解常用來處理content-type不是預設的application/x-www-form-urlcoded),支援自定義或者預設的json的資料格式;

2.自定義訊息轉換器;我們的目的是把請求的引數為user=26-高楊的引數傳入物件,並且content-type為application/gao;

public class MyConverter extends AbstractHttpMessageConverter<Object> {

    public MyConverter(){    //只有appplication/gao的請求會到此轉換器
        super(new MediaType("application","gao", Charset.forName("utf-8")));
    }

    @Override    //判斷是否進行轉換操作
    protected boolean supports(Class<?> aClass) {
        System.out.println(aClass.isAssignableFrom(UserInfo.class));
        return aClass.isAssignableFrom(UserInfo.class);
    }

    @Override    //將請求引數讀入物件
    protected Object readInternal(Class<? extends Object> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
        InputStream body = httpInputMessage.getBody();
        BufferedReader b = new BufferedReader(new InputStreamReader(body));
        String s = b.readLine();
        System.out.println(s);
        String s1 = s.split("=")[1];
        UserInfo u = new UserInfo();
        u.setName(s1.split("-")[0]);
        u.setAge(s1.split("-")[1]);
        return u;
    }

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

    @Override
    protected boolean canRead(MediaType mediaType) {
        return super.canRead(mediaType);
    }


    @Override     //如果需要返回引數,這裡返回json
    protected void writeInternal(Object s, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
        httpOutputMessage.getBody().write(new ObjectMapper().writeValueAsString(s).getBytes());
    }
}

當然如果我們不寫返回引數的方法,那麼預設也會走返回json的方式,因為使用了@RestController,會自動判斷以何種方式轉換;

3.將轉換器配置到spring,有幾種方式(下面引用網上的文章):

    // 新增converter的第一種方式,程式碼很簡單,也是推薦的方式
    // 這樣做springboot會把我們自定義的converter放在順序上的最高優先順序(List的頭部)
    // 即有多個converter都滿足Accpet/ContentType/MediaType的規則時,優先使用我們這個
    @Bean
    public MyConverter() {
        return new MyConverter();
    }

    // 新增converter的第二種方式
    // 通常在只有一個自定義WebMvcConfigurerAdapter時,會把這個方法裡面新增的converter(s)依次放在最高優先順序(List的頭部)
    // 雖然第一種方式的程式碼先執行,但是bean的新增比這種方式晚,所以方式二的優先順序 大於 方式一
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // add方法可以指定順序,有多個自定義的WebMvcConfigurerAdapter時,可以改變相互之間的順序
        // 但是都在springmvc內建的converter前面
        converters.add(new MyConverter());
    }

    // 新增converter的第三種方式
    // 同一個WebMvcConfigurerAdapter中的configureMessageConverters方法先於extendMessageConverters方法執行
    // 可以理解為是三種方式中最後執行的一種,不過這裡可以通過add指定順序來調整優先順序,也可以使用remove/clear來刪除converter,功能強大
    // 使用converters.add(xxx)會放在最低優先順序(List的尾部)
    // 使用converters.add(0,xxx)會放在最高優先順序(List的頭部)
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new MyConverter());
    }

___________________________________________________________________________________________________

還有一種接收form/data或application/x-www-form-urlencoded的轉換方式:

   @Component
   public class New implements Converter<String, String> {
        @Override
        public String convert(String s) {
            return s + "測試";
        }
    }

在泛型上新增需要接收和轉換的型別;或者用Bean的方式註冊也是可以的;這種方式處理簡單的轉換,一般用在接收轉換時間;不需要@RequestBody的引數;