HttpMessageConverter 是一个对请求信息进行直接转换的一个接口,就是说不通过resolver直接将对象直接响应并进行转换,而且HttpMessageConverter接口也可以对请求进行对象的直接转换。有兴趣的同学可以细心研究其接口的方法并去实现自己的MessageConverter,但是Spring所提供的HttpMessageConverter已经足够强大。以下就列出以下Spring所提供的MessageConverter。
以下是接口的内容,这个来之于官网文档
public interface HttpMessageConverter<T> {
// Indicate whether the given class and media type can be read by this converter.
boolean canRead(Class<?> clazz, MediaType mediaType);
// Indicate whether the given class and media type can be written by this converter.
boolean canWrite(Class<?> clazz, MediaType mediaType);
// Return the list of MediaType objects supported by this converter.
List<MediaType> getSupportedMediaTypes();
// Read an object of the given type from the given input message, and returns it.
T read(Class<T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;
// Write an given object to the given output message.
void write(T t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;
}
StringHttpMessageConverter ----> 将请求信息转换为字符串 [可读取所有媒体类型,通过设置supportedMediaTypes属性指定媒体类型]
FormHttpMessageConverter -----> 将表达数据读取到MultiValueMap中。 [读写支持类型application/x-www-form-urlencoded 写支持multipart/form-data]
XmlAwareFormHttpMessageConverter ----> 扩展FormHttpMessageConverter,如果部分表单属性为XML数据,可用该转换器进行读取。
ResourceHttpMessageConverter ----> 读写 org.springframework.core.io.Resource 对象
BufferedImageHttpMessageConverter ----> 读写BuffereImage对象
ByteArrayHttpMessageConverter ---> 读写二进制数据将请求信息 [可读取所有媒体类型,通过设置supportedMediaTypes属性指定媒体类型]
SourceHttpMessageConvert ----> 读写javax.xml.transform.Source类型数据 [读写支持类型text/xml application/xml]
MarshallingHttpMessageConvert ----> 通过Spring的org.springframework.oxm.Marshaller 和 Unmarshaller 读写XML消息 [读写支持类型text/xml application/xml]
Jaxb2RootElementHttpMessageConvert ----> 通过JAXB2读写XML消息,将请求消息转换到标签XmlRootElement和XmlType [读写支持类型text/xml application/xml]
MappingJacksonHttpMessageConvert ---> 利用jackson开源包的ObjectMapping读写JSON数据 [读写application/json]
RssChannelHttpMessageConverter ----> 能够读写RSS种子消息 [读写application/rss+xml]
AtomFeedHttpMessageConverter ----> 和RssChannelHttpMessageConverter能够读写RSS种子信息 [读写application/atom+xml]
其实AnnotationMethodHandlerAdapter 默认已经装配了很多converter了,所以其实并没有必要自己定义messageConverter列表,这里还是写一下何如定义messageConverter列表:
<mvc:annotation-driven >
<mvc:message-converters>
<bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter" />
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
其实如果直接使用默认装配,只需要这样:
<mvc:annotation-driven />
需要注意的是Json也是默认支持的,但是我们需要自己添加jackson的包,POM的dependency如下:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.1.4</version>
</dependency>
使用也是非常简单通过@RequestBody进行请求转换 和 @ResponseBody进行相应对象的转换,以下就是几个比较常用的例子,包括转JSON 转字符串 转二进制 转图片:
JSON转换
@RequestMapping("/getRequestUser.json")
public @ResponseBody User getRequestUser(@RequestBody User user){
System.out.println(user.toString());
return user;
}
请求类型为JSON,accept类型也是JSON 请求和返回如下:
请求:
POST /springreview/user/getRequestUser.json HTTP/1.1
Content-Type: application/json
Host: localhost:8080
Connection: close
User-Agent: Paw/2.3.4 (Macintosh; OS X/10.12.5) GCDHTTPRequest
Content-Length: 50
{"userId":"123","username":"tony","pwd":"tonypwd"}
返回:
{"userId":"123","username":"tony","pwd":"tonypwd"}
返回二进制类型和bufferedImage类型,使用浏览器可以返回一张图片
@RequestMapping("/test.jpeg")
@ResponseBody
public byte[] testbyteArray() throws IOException {
Resource resource = new ClassPathResource("timg.jpeg");
return FileCopyUtils.copyToByteArray(resource.getInputStream());
}
@RequestMapping("/test_second.jpeg")
@ResponseBody
public BufferedImage test() throws IOException {
Resource resource = new ClassPathResource("timg.jpeg");
BufferedImage image = ImageIO.read(resource.getInputStream());
return image;
}
RestTemplate 是Spring3的新增模板,可以在客户端应用程序使用该类进行WEB服务的调用,它支持REST风格的URL。它和AnnotationMethodHandlerAdapter一样默认就会添加一堆的MessageConverter所以使用非常方便:
public void testUserJson(){
RestTemplate rest = new RestTemplate();
HttpHeaders entityHeader = new HttpHeaders();
entityHeader.setContentType(MediaType.APPLICATION_JSON_UTF8);
entityHeader.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8));
User user = new User();
user.setUserId(123);
user.setUsername("tony");
user.setPwd("tonypwd");
HttpEntity<User> requestEntity = new HttpEntity<User>(user,entityHeader);
String url = "http://localhost:8080/springreview/user/getRequestUser.json";
ResponseEntity<User> responseEntity = rest.exchange(url, HttpMethod.POST,requestEntity,User.class);
System.out.println(responseEntity.getBody().toString());
}
需要注意的是,我们使用了HttpEntity 这两个类主要的作用是对请求头进行描述,当然我们这里返回了一个responseEntity对象用户直接获得对象。然而我们在controller同样可以定义HttpEntity和ResponseEntity 去获得客户端的请求头部信息和其他返回信息,如果我们使用了responseEntity,HttpEntity 就不用打上annotation标记了:
@RequestMapping("/getRequestUser.json")
public ResponseEntity<User> getRequestUser(RequestEntity<User> entity){
System.out.println(entity.getHeaders().toString());
System.out.println(entity.getBody().toString());
ResponseEntity<User> responseEntity = new ResponseEntity<User>(entity.getBody(), HttpStatus.OK);
return responseEntity;
}
以下是关于字符串的例子:
@RequestMapping("/string.txt")
@ResponseBody
public String testStringConverter(String request){
System.out.println("request : " + request);
return request;
}
使用restTemplate:
public void testParam(){
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String,Object> multiValueMap = new LinkedMultiValueMap<String, Object>();
multiValueMap.add("request","TESTING");
String url = "http://localhost:8080/springreview/test/string.txt";
String response = restTemplate.postForObject(url,multiValueMap,String.class);
System.out.println(response);
}