我们使用**
@RequestBody
可以将请求体中的JSON字符串绑定到相应的bean,使用@ResponseBody
**可以使返回结果不会被解析为跳转路径,而是直接写入 HTTP response body 中,而整个数据绑定的过程其实是HttpMessageConverter在起作用。
MediaType,即是Internet Media Type,互联网媒体类型;也叫做MIME类型,在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。
@requestBody注解常用来处理content-type不是默认的application/x-www-form-urlcoded编码的内容,比如说:application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。
{
"question": "aaa",
"fromUser": "bbb"
}
<Request>
<question>aaaquestion>
<fromUser>bbbfromUser>
Request>
上面两种方式都是可以把数据映射到Bean中的。
Spring会根据MediaType查找合适的HttpMessageConverter的实现类进行序列化的操作
public interface HttpMessageConverter<T> {
boolean canRead(Class<?> clazz, MediaType mediaType);
boolean canWrite(Class<?> clazz, MediaType mediaType);
List<MediaType> getSupportedMediaTypes();
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
方法 | 作用 |
---|---|
getSupportedMediaTypes | 获取支持的MediaType |
read | 读取request的body |
write | 把数据写到response的body中 |
ResponseBody中的使用和RequestBody类似
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
/**
* 自定义message_convert
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// 把converter添加到converters的最后(SpringBoot会使用第一个匹配到的Converter)
converters.add(new XxxConverter());
// 把converter添加到converters的最前面
// converters.add(0, new XxxConverter());
}
}
到此为止,我们自定义的Converter已经生效了
3. 自定义MediaType
虽然我们已经编写Converter,但是我们一般会为自定义的Converter指定可以处理的媒体类型,可以指定自定义的媒体类型
public class XxxConverter implements HttpMessageConverter<Serializable> {
public static final String CUSTOM_MEDIA = "application/custom-media";
@Override
public boolean canRead(Class<?> clazz, MediaType mediaType) {
return true;
}
@Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return true;
}
@Override
public List<MediaType> getSupportedMediaTypes() {
return Lists.newArrayList(MediaType.parseMediaType(CUSTOM_MEDIA));
}
@Override
public Serializable read(Class<? extends Serializable> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return null;
}
@Override
public void write(Serializable serializable, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
}
}
这里一定要修改getSupportedMediaTypes方法,SpringBoot是根据这个方法的返回,以及Controller—@RequestMapping中指定的MediaType,判断是否可用于当前请求/返回。
@RestController
@RequestMapping(produces = CUSTOM_MEDIA, consumes = CUSTOM_MEDIA)
@Validated
public class HomeController {
@GetMapping(HOME)
JsonResult info(@RequestHeader("userId") Long userId) {
return JsonResult.ok();
}
}
consumes是指定请求的MediaType,需要调用方设置成我们提供的application/custom-media
produces是指定返回的MediaType,如果我们设置成application/custom-media
,那么方法返回的数据就会通过自定义的XxxConverter
进行转换。
注意:如果我们修改了
produces的MediaType
,那么HTTP返回中的MediaType
也会是我们自定义的类型,除非和调用方约定好,否则调用方是没有办法解析的。
解决办法:
public class XxxConverter implements HttpMessageConverter<Serializable> {
......
@Override
public void write(Serializable serializable, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
// 最后把Content-Type改成APPLICATION_JSON_UTF8_VALUE,要不然请求方会无法解析
((ServletServerHttpResponse) outputMessage)
.getServletResponse().setHeader("Content-Type",APPLICATION_JSON_UTF8_VALUE);
}
}
一般情况下,SpringBoot提供的默认转换器已经足够我们使用,但是在一些接口的参数需要加解密,调整返回体的结构等情况下会用到
我的个人博客,有空来坐坐