spring boot學習(7)— 自定義中的 HttpMessageConverter

在我們開發自己的應用時,有時候,我們可能需要自定義一些自己的數據格式來傳輸,這時,自定義的數據傳輸和類的實例之間進行轉化就需要統一起來了, Spring MVC 中的 HttpMessageConverter 就派上用場了。

HttpMessageConverter 的聲明:

public interface HttpMessageConverter<T> {

    /**
     * Indicates whether the given class can be read by this converter.
     * @param clazz the class to test for readability
     * @param mediaType the media type to read (can be {@code null} if not specified);
     * typically the value of a {@code Content-Type} header.
     * @return {@code true} if readable; {@code false} otherwise
     */
    boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);

    /**
     * Indicates whether the given class can be written by this converter.
     * @param clazz the class to test for writability
     * @param mediaType the media type to write (can be {@code null} if not specified);
     * typically the value of an {@code Accept} header.
     * @return {@code true} if writable; {@code false} otherwise
     */
    boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);

    /**
     * Return the list of {@link MediaType} objects supported by this converter.
     * @return the list of supported media types
     */
    List<MediaType> getSupportedMediaTypes();

    /**
     * Read an object of the given type from the given input message, and returns it.
     * @param clazz the type of object to return. This type must have previously been passed to the
     * {@link #canRead canRead} method of this interface, which must have returned {@code true}.
     * @param inputMessage the HTTP input message to read from
     * @return the converted object
     * @throws IOException in case of I/O errors
     * @throws HttpMessageNotReadableException in case of conversion errors
     */
    T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
            throws IOException, HttpMessageNotReadableException;

    /**
     * Write an given object to the given output message.
     * @param t the object to write to the output message. The type of this object must have previously been
     * passed to the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
     * @param contentType the content type to use when writing. May be {@code null} to indicate that the
     * default content type of the converter must be used. If not {@code null}, this media type must have
     * previously been passed to the {@link #canWrite canWrite} method of this interface, which must have
     * returned {@code true}.
     * @param outputMessage the message to write to
     * @throws IOException in case of I/O errors
     * @throws HttpMessageNotWritableException in case of conversion errors
     */
    void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
            throws IOException, HttpMessageNotWritableException;

}

裏面有四個方法:

  1. canRead: 查看對應的類型和 content-type 頭部類型是否支持被讀取.
  2. canWrite: 查看對應的類型和 content-type 頭部類型是否支持輸出.
  3. getSupportedMediaTypes: 獲取支持的類型
  4. read: 從 http 請求中,讀取數據,並轉化爲指定類型。
  5. write: 將指定類型的實例寫入到response中。

內置的常用HttpMessageConverter 類型:

  1. ByteArrayHttpMessageConverter – 轉換 byte array 類型數據
  2. StringHttpMessageConverter – 根據編碼格式,轉化Strings
  3. ResourceHttpMessageConverter – converts org.springframework.core.io.Resource for any type of octet stream
  4. SourceHttpMessageConverter – 轉換 javax.xml.transform.Source 類型的數據。
  5. FormHttpMessageConverter – 轉換 application/x-www-form-urlencodedmultipart/form-data 類型的消息.
  6. Jaxb2RootElementHttpMessageConverter – 將對象和xml轉換。
  7. MappingJackson2HttpMessageConverter – 使用 jackson2 轉換 json 數據和 對象實例

自定義 HttpMessageConverter 並使用

  1. 首先,自定義 HttpMessageConverter:
    需要轉化的對象爲:
public class TestRequestInfo {
    private String key;
    private int value;
    private MultipartFile file;

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public MultipartFile getFile() {
        return file;
    }

    @Override
    public String toString() {
        return "TestRequestInfo{" +
                "key='" + key + '\'' +
                ", value=" + value +
                '}';
    }
}

Converter

public class TestMessageConverter extends AbstractHttpMessageConverter<TestRequestInfo> {

    public TestMessageConverter(){
        super(new MediaType("application", "test-converter", Charset.forName("UTF-8")));
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        return true;
    }

    @Override
    protected TestRequestInfo readInternal(Class<? extends TestRequestInfo> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        String temp = StreamUtils.copyToString(inputMessage.getBody(), Charset.forName("UTF-8"));
        TestRequestInfo test = new TestRequestInfo();
        test.setKey(temp);
        return test;
    }

    @Override
    protected void writeInternal(TestRequestInfo testRequestInfo, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        outputMessage.getBody().write(testRequestInfo.toString().getBytes());
    }
}

  1. 註冊 HttpMessageConverter:
@EnableWebMvc
@Configuration
@ComponentScan
public class MVCConfig implements WebMvcConfigurer {

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new TestMessageConverter());
    }
}
  1. 定義 Controller:
@RestController
public class TestController {
    @RequestMapping(
        value="/reports",
        method = {RequestMethod.GET, RequestMethod.POST}
    )
    public @ResponseBody
    TestRequestInfo getReports(@RequestBody TestRequestInfo requestInfo){
        System.out.println(requestInfo);
        return requestInfo;
    }
}

請求結果爲:
{"key":"sdfasfasdf","value":0,"file":null}.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章