SpringMVC中HttpMessageConverter使用实践详解

简介: SpringMVC中HttpMessageConverter使用实践详解

HttpMessageConverter,报文信息转换器,将请求报文转换为Java对象,或将Java对象转换为响应报

文。HttpMessageConverter提供了两个注解和两个类型:@RequestBody,@ResponseBody,RequestEntity,ResponseEntity


【1】两个注解和两个类型

① HttpEntity


HttpEntity封装了headers和body,用于暴露(获取)请求头(响应头)和请求体(响应体)。下面的列表显示了一个示例:

@PostMapping("/accounts")
public void handle(HttpEntity<Account> entity) {
    // ...
}


HttpEntity主要属性和构造方法

public class HttpEntity<T> {
   //The empty {@code HttpEntity}, with no body or headers.
  public static final HttpEntity<?> EMPTY = new HttpEntity<>();
  //请求头 响应头
  private final HttpHeaders headers;
  //请求体  响应体
  @Nullable
  private final T body;
   //创建一个空的HttpEntity
  protected HttpEntity() {
    this(null, null);
  }
   //使用body创建HttpEntity,此时headers为null
  public HttpEntity(T body) {
    this(body, null);
  }
   //使用headers创建HttpEntity,此时body为null
  public HttpEntity(MultiValueMap<String, String> headers) {
    this(null, headers);
  }
   //使用body和headers创建HttpEntity
  public HttpEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers) {
    this.body = body;
    this.headers = HttpHeaders.readOnlyHttpHeaders(headers != null ? headers : new HttpHeaders());
  }
//...
} 


其类继承树图示如下

与template整合使用

//POST
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
HttpEntity<String> entity = new HttpEntity<String>(helloWorld, headers);
URI location = template.postForLocation("https://example.com", entity);
//GET
HttpEntity<String> entity = template.getForEntity("https://example.com", String.class);
String body = entity.getBody();
MediaType contentType = entity.getHeaders().getContentType();


作为SpringMVC中方法的返回值

@RequestMapping("/handle")
public HttpEntity<String> handle() {
   HttpHeaders responseHeaders = new HttpHeaders();
   responseHeaders.set("MyResponseHeader", "MyValue");
   return new HttpEntity<String>("Hello World", responseHeaders);
}


② @RequestBody

你可以使用@RequestBody注解获取请求体并通过HttpMessageConverter将其反序列化到Object对象。


您可以使用@RequestBody注解,通过HttpMessageConverter将请求body读取并反序列化为对象。以下示例使用@RequestBody参数:


@PostMapping("/accounts")
public void handle(@RequestBody Account account) {
    // ...
}

您可以使用MVC Config的 Message Converters选项来配置或自定义消息转换。


您可以将@RequestBody与javax.validation.Valid结合使用,或者使用Spring的@Validated注解,这两种注解都会应用Standard Bean Validation验证。默认情况下,验证错误会导致MethodArgumentNotValidException,该异常会转换为400(BAD_REQUEST)响应。或者,您可以通过Errors 或BindingResult 参数在控制器内本地处理验证错误,如下例所示:

@PostMapping("/accounts")
public void handle(@Valid @RequestBody Account account, BindingResult result) {
    // ...
}

③ @ResponseBody

可以在方法上使用@ResponseBody注解,通过HttpMessageConverter将返回序列化到响应体。下面的列表显示了一个示例:

@GetMapping("/accounts/{id}")
@ResponseBody
public Account handle() {
    // ...
}


在类级别上也支持@ResponseBody,在这种情况下,它由所有控制器方法继承。这就是@RestController的效果,它只不过是一个用@Controller和@ResponseBody标记的元注解。


你可以将@ResponseBody与reactive 类型一起使用,更多参考 Asynchronous Requests和 Reactive Types。

你可以使用MVC Config的Message Converters选项配置或者自定义信息转换。


您可以将@ResponseBody方法与JSON序列化视图相结合。

④ ResponseEntity

ResponseEntity类似于@ResponseBody,但有Statusheader。例如:

@GetMapping("/something")
public ResponseEntity<String> handle() {
    String body = ... ;
    String etag = ... ;
    return ResponseEntity.ok().eTag(etag).build(body);
}

Spring MVC支持使用单值反应类型异步生成响应,和/或为主体生成单值和多值反应类型。这允许以下类型的异步响应:


ResponseEntity<Mono<T>> 或ResponseEntity<Flux<T>>可在稍后异步提供主体时立即了解响应状态和头。如果主体由0..1个值组成,则使用Mono;如果主体可以生成多个值,则使用Flux。

Mono<ResponseEntity<T>>提供了这三种功能 — response status, headers, and body。这允许response status and headers根据异步请求处理的结果而变化。通过使用可通过静态方法created访问的生成器来获取ResponseEntity:

@RequestMapping("/handle")
public ResponseEntity<String> handle() {
  URI location = ...;
  return ResponseEntity.created(location).header("MyResponseHeader", "MyValue").body("Hello World");
}


SpringMVC中作为方法的返回值(直接返回response,不跳页面):

@PostMapping("test")
public ResponseEntity test(@RequestParam List name) throws URISyntaxException {
    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.setLocation(new URI("/test/location"));
    responseHeaders.set("MyResponseHeader", "MyValue");
    ResponseEntity<String> responseEntity = new ResponseEntity<>("hello", responseHeaders, HttpStatus.CREATED);
    return responseEntity;
}

⑤ RequestEntity

RequestEntity类似于@RequestBody,但是多了HTTP methodtarget URL

如下所示,与RestTemplate结合使用

MyRequest body = ...
RequestEntity<MyRequest> request = RequestEntity
    .post("https://example.com/{foo}", "bar")
    .accept(MediaType.APPLICATION_JSON)
    .body(body);
ResponseEntity<MyResponse> response = template.exchange(request, MyResponse.class)

在SpringMVC的Controller中使用:

@RequestMapping("/handle")
public void handle(RequestEntity<String> request) {
  HttpMethod method = request.getMethod();
  URI url = request.getUrl();
  String body = request.getBody();
}

【2】HttpMessageConverter<T>

其是Spring3.0新添加的一个接口,负责将请求信息转换为一个对象(类型为T),将对象(类型为T)输出为响应信息。

其是一个策略接口哦。

① 接口源码

public interface HttpMessageConverter<T> {
   // 指示此转换器是否可以读取给定类。mediaType通常是Content-Type header
  boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
   // 指示给定类是否可以由此转换器写入。mediaType是 Accept header
  boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
   //返回此转换器支持的MediaType
  List<MediaType> getSupportedMediaTypes();
   // 从给定的输入消息中读取给定类型的对象,并返回该对象。
  T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
      throws IOException, HttpMessageNotReadableException;
   // 将给定对象写入给定的输出消息
  void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
      throws IOException, HttpMessageNotWritableException;
}

② 运行流程



使用HttpMessageConverter<T>将请求信息转化并绑定到处理方法的入参中,或将响应结果转换为对应类型的响应信息,Spring提供了两种途径:


① 使用@RequestBody/@ResponseBody对处理方法进行标注;


② 使用RequestEntity<T> / ResponseEntity<T>作为处理方法的入参或返回值;


当控制器处理方法使用到了① 或② 时,Spring首先根据请求头Content-Type属性或响应头的Accept属性选择匹配的HttpMessageConverter,进而根据参数类型和泛型类型的过滤得到匹配的HttpMessageConverter。若找不到可用的HttpMessageConverter,将报错。

③ 接口实现类继承树

④ 常用实现类功能说明


① StringHttpMessageConverter:支持的MediaType:text/plain,*/*,将请求信息转换为字符串;


② ByteArrayHttpMessageConverter:支持的MediaType:application/octet-stream,*/*读写二进制数据;


③ SourceHttpMessageConverter:支持的MediaType:application/xml,text/xml,application/*+xml,读写javax.xml.transform.Source类型的数据;


④ FormHttpMessageConverter :支持的MediaType:application/x-www-form-urlencoded,multipart/form-data 将表单数据读取到MultiValueMap中;


⑤ ResourceHttpMessageConverter:支持的MediaType:*/*,读写org.springframework.core.io.Resource对象;


⑥ BufferedImageHttpMessageConverter:读写BufferedImage对象;


⑦ MappingJackson2HttpMessageConverter:支持的MediaType:application/json,application/*+json,利用jackson开源包的objectMapper读写JSON数据。


⑧ Jaxb2RootElementHttpMessageConverte:支持的MediaType:application/xml,text/xml,application/*+xml

【3】HttpInputMessage 接口

表示HTTP输入消息,由headers和可读的body组成。通常由服务器端的HTTP请求处理器或客户端的HTTP响应处理器实现



① 接口源码

public interface HttpInputMessage extends HttpMessage {
  //把请求体转换为input stream
  InputStream getBody() throws IOException;
}

② 接口的继承树示意图


【4】HttpOutputMessage 接口

表示HTTP输出消息,由headers和body组成。通常由客户端的HTTP请求处理器或者服务端端的HTTP 响应处理器实现。


① 接口源码

public interface HttpOutputMessage extends HttpMessage {
   // 把消息体转换为output stream返回
  OutputStream getBody() throws IOException;
}


② 接口继承树示意图





目录
相关文章
|
7月前
|
Web App开发 JSON 前端开发
SpringMVC HttpMessageConverter
SpringMVC HttpMessageConverter
41 0
|
7月前
|
Web App开发 JSON 前端开发
SpringMVC之HttpMessageConverter
【1月更文挑战第19天】 HttpMessageConverter,报文信息转换器,将请求报文转换为Java对象,或将Java对象转换为响应报文 HttpMessageConverter提供了两个注解和两个类型:@RequestBody,@ResponseBody,RequestEntity, ResponseEntity
63 0
|
7月前
|
Web App开发 JSON 前端开发
springMVC之HttpMessageConverter
springMVC之HttpMessageConverter
|
Java 数据库 数据安全/隐私保护
SpringMVC中@ModelAttribute应用实践
SpringMVC中@ModelAttribute应用实践
77 2
|
JSON 前端开发 Java
详解 SpringMVC 的 HttpMessageConverter
HttpMessageConverter是Spring Framework中的一个接口,用于处理HTTP请求和响应的消息转换。 在Spring MVC中,HttpMessageConverter主要用于将HTTP请求的输入内容转换为指定的Java对象,以及将Java对象转换为HTTP响应的输出内容。它负责处理请求和响应的数据格式转换,例如将请求的JSON或XML数据转换为Java对象,并将Java对象转换为JSON或XML格式的响应数据。 Spring MVC提供了多个默认的HttpMessageConverter实现,包括处理JSON、XML、文本等格式的Converter。另外,我们也
|
JSON 前端开发 JavaScript
SpringMVC学习(九):HttpMessageConverter
HttpMessageConverter,报文信息转换器,将请求报文转换为Java对象,或将Java对象转换为响应报文 HttpMessageConverter提供了两个注解和两个类型:@RequestBody,@ResponseBody,RequestEntity,ResponseEntity
SpringMVC学习(九):HttpMessageConverter
QGS
|
存储 调度 数据安全/隐私保护
入门SpringMVC之Interceptor拦截器
SpringMVC中的Interceptor拦截器,它的主要作用是拦截指定的用户需求,并进行相应的预处理与后处理。
QGS
89 0
|
Java 数据安全/隐私保护
springMvc6-springMVC的常见注解
springMvc6-springMVC的常见注解
127 0
|
XML 前端开发 应用服务中间件
Servlet3.0实现注解开发
Servlet3.0中实现注解开发 Servlet3.0好处: 支持注解配置。可以不需要web.xml了。
82 0
|
Java Spring
享读SpringMVC源码4-感谢RequestMappingHandlerAdapter(下)
享读SpringMVC源码4-感谢RequestMappingHandlerAdapter(下)
享读SpringMVC源码4-感谢RequestMappingHandlerAdapter(下)