在我们开发自己的应用时,有时候,我们可能需要自定义一些自己的数据格式来传输,这时,自定义的数据传输和类的实例之间进行转化就需要统一起来了,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;
}
里面有四个方法:
-
canRead
: 查看对应的类型和content-type
头部类型是否支持被读取. -
canWrite
: 查看对应的类型和content-type
头部类型是否支持输出. -
getSupportedMediaTypes
: 获取支持的类型 -
read
: 从http
请求中,读取数据, 并转化为指定类型。 -
write
: 将指定类型的实例写入到 response 中。
内置的常用 HttpMessageConverter
类型:
-
ByteArrayHttpMessageConverter
– 转换byte array
类型数据 -
StringHttpMessageConverter
– 根据编码格式,转化Strings
-
ResourceHttpMessageConverter
– converts org.springframework.core.io.Resource for any type of octet stream -
SourceHttpMessageConverter
– 转换javax.xml.transform.Source
类型的数据。 -
FormHttpMessageConverter
– 转换application/x-www-form-urlencoded
和multipart/form-data
类型的消息. -
Jaxb2RootElementHttpMessageConverter
– 将对象和 xml 转换。 -
MappingJackson2HttpMessageConverter
– 使用jackson2
转换json
数据和 对象实例
自定义 HttpMessageConverter
并使用
- 首先,自定义
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());
}
}
- 注册
HttpMessageConverter
:
@EnableWebMvc
@Configuration
@ComponentScan
public class MVCConfig implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(new TestMessageConverter());
}
}
- 定义
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}
.