当前位置: 代码迷 >> 综合 >> Spring @RequestBody @ResponseBody深入理解
  详细解决方案

Spring @RequestBody @ResponseBody深入理解

热度:95   发布时间:2023-12-01 00:35:27.0

Spring @RequestBody @ResponseBody深入理解

这篇文章展示了Spring MVC @RequestBody,@ ResseseBody注释用法,ResponseEntity,默认的HttpMessageConverteres,以及编写自定义消息转换器。我们开始吧。

 

@RequestBody@ResponseBody注释用于将HTTP请求/响应主体与方法参数或返回类型中的域对象绑定。在幕后,这些注释使用HTTP消息转换器将HTTP请求/响应的主体转换为域对象。
 

@RequestBody

 

 

如果使用@RequestBody注释方法参数,Spring会将传入的HTTP请求主体(对于该方法的@RequestMapping中提到的URL)绑定到该参数。在这样做时,Spring将[在幕后]使用HTTP消息转换器将HTTP请求主体转换为域对象[反序列化请求主体到域对象],基于请求中存在的Accept头。

 

  • 接受头使用HTTP客户端[浏览],告诉他们将接受什么样的内容类型的服务器。
  • 服务器发送回响应,该响应将包括一个Content-Type标头,告诉客户端返回内容的内容类型实际上是什么。在POST或PUT请求的情况下,浏览器会在请求中发送数据,因此它们实际上也会发送内容类型。

以此方法为例:

 

@RequestMapping(value="/user/create", method=RequestMethod.POST)public ResponseEntity<Void> createUser(@RequestBody User user, UriComponentsBuilder ucBuilder){System.out.println("Creating User "+user.getName());if(userService.isUserExist(user)){System.out.println("A User with name "+user.getName()+" already exist");return new ResponseEntity<Void>(HttpStatus.CONFLICT);}userService.saveUser(user);HttpHeaders headers = new HttpHeaders();headers.setLocation(ucBuilder.path("/user/{id}").buildAndExpand(user.getId()).toUri());return new ResponseEntity<Void>(headers, HttpStatus.CREATED);}

这是处理典型HTTP Post请求[用于URL / user / create]的控制器方法。在纯REST导向方法中,此控制器方法创建用户,并返回HTTP 201 [CREATED]以及包含新创建的用户[/ app-address / user / 1例如]的位置的LocationHeader。

现在回到我们原来的讨论,HTTP Post请求正文包含要创建的用户的详细信息。当客户端发送请求[/ user / create]来创建用户时,它将在此方法中被截获。方法参数user用@RequestBody注释标记。感谢这个注释,Spring将尝试将请求主体[可以是JSON / XML / Other]绑定到用户对象[意味着创建一个新的用户对象,其中包含请求正文中的详细信息,如用户名,年龄等。] ,基于Http请求中的Content-Type标头。

但Spring需要帮助将请求体转换为用户对象。它需要一个转换器,它可以将HTTP请求体[可以是JSON / XML / Other]中的数据转换为用户对象。

Spring提供了许多默认的HttpMessageConverters,它们将用于转换,具体取决于项目类路径中某些库的存在。

例如,如果请求标题中的Content-Type是application / json或application / xml之一,则表示POST正文包含json或XML [Popular formats],如果在类路径中找到Jackson库,Spring将委派转换为MappingJackson2HttpMessageConverter [for json]或MappingJackson2XmlHttpMessageConverter [for xml]。

声明对Jackson库(jackson-databind)的依赖包括在pom.xml中的以下依赖项

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version></dependency>

ResponseEntity(在上面的示例中使用)表示整个HTTP响应。关于它的好处是你可以控制进入它的任何东西。您可以指定状态代码,标题和正文。下一篇文章通过一个完整的工作示例详细介绍了它。

 

@ResponseBody

 

如果使用@ResponseBody注释方法,Spring会将返回值绑定到传出的HTTP响应主体。在执行此操作时,Spring将[在幕后]使用HTTP消息转换器将返回值转换为HTTP响应主体[将对象序列化为响应主体],基于请求HTTP标头中存在的Content-Type

以此方法为例:

 

@RequestMapping(value = "/user/all", method = RequestMethod.GET)public @ResponseBody List<User> listAllUsers() {return userService.findAllUsers();}

这是处理典型HTTP GET请求[用于URL / user / all]以检索所有用户的控制器方法。在这种情况下,Spring将根据内容类型使用可用的转换器将用户列表转换为适当的格式[JSON / XML / Other]。

注意:从Spring 4开始,@ RestController是实现@ResponseBody早期提供的相同功能的首选方式。在引擎盖下,@ RestController是@Controller + @ResponseBody,它避免了为每个方法添加前缀@ResponseBody的需要。下一篇文章详细介绍了一个完整的工作示例。

 

默认HttpMessageConverters

 

Spring提供了Http消息转换器,它实现了HttpMessageConverter接口[Credit:Spring Reference ]。

  • StringHttpMessageConverter

     

    一个HttpMessageConverter实现,可以从HTTP请求和响应中读取和写入字符串。默认情况下,此转换器支持所有文本媒体类型(text / *),并使用Content-Type of text / plain进行写入。

  • FormHttpMessageConverter

     

    一个HttpMessageConverter实现,可以从HTTP请求和响应中读取和写入表单数据。默认情况下,此转换器读取和写入媒体类型application / x-www-form-urlencoded。表单数据从MultiValueMap读取并写入MultiValueMap。

  • ByteArrayHttpMessageConverter

     

    一个HttpMessageConverter实现,可以从HTTP请求和响应中读取和写入字节数组。默认情况下,此转换器支持所有媒体类型(* / *),并使用Content-Type of application / octet-stream写入。这可以通过设置supportedMediaTypes属性并覆盖getContentType(byte [])来覆盖。

  • MarshallingHttpMessageConverter

     

    一个HttpMessageConverter实现,可以使用org.springframework.oxm包中的Spring的Marshaller和Unmarshaller抽象来读写XML。该转换器需要Marshaller和Unmarshaller才能使用。这些可以通过构造函数或bean属性注入。默认情况下,此转换器支持(text / xml)和(application / xml)。

  • MappingJackson2HttpMessageConverter

     

    一个HttpMessageConverter实现,可以使用Jackson的ObjectMapper读写JSON。通过使用Jackson提供的注释,可以根据需要自定义JSON映射。当需要进一步控制时,可以通过ObjectMapper属性注入自定义ObjectMapper,以用于需要为特定类型提供自定义JSON序列化器/反序列化器的情况。默认情况下,此转换器支持(application / json)。

  • MappingJackson2XmlHttpMessageConverter

     

    一个HttpMessageConverter实现,可以使用Jackson XML扩展的XmlMapper读写XML。可以根据需要通过使用JAXB或Jackson提供的注释来自定义XML映射。当需要进一步控制时,可以通过ObjectMapper属性注入自定义XmlMapper,以用于需要为特定类型提供自定义XML序列化器/反序列化器的情况。默认情况下,此转换器支持(application / xml)。

  • SourceHttpMessageConverter

     

    一个HttpMessageConverter实现,可以从HTTP请求和响应中读取和写入javax.xml.transform.Source。仅支持DOMSource,SAXSource和StreamSource。默认情况下,此转换器支持(text / xml)和(application / xml)。

  • BufferedImageHttpMessageConverter

     

    一个HttpMessageConverter实现,可以从HTTP请求和响应中读取和写入java.awt.image.BufferedImage。此转换器读取和写入Java I / O API支持的媒体类型。

 

自定义HttpMessageConverters

 

大多数情况下,Spring提供的默认转换器就足够了。但是,如果您需要一些自定义行为,您可以推出自己的实现。

例如,在上面的示例中,MappingJackson2HttpMessageConverter用于处理JSON内容。默认情况下,如果JSON或域对象中缺少属性,则此转换器提供的Jackson ObjectMapper将失败。它根本无法转换。您可以通过告知对象映射器在缺少的属性上不失败来覆盖此行为,如下所示:

package com.websystique.springmvc.configuration;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;@Configuration@EnableWebMvc@ComponentScan(basePackages = "com.websystique.springmvc")public class HelloWorldConfiguration extends WebMvcConfigurerAdapter{@Overridepublic void extendMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(mappingJackson2HttpMessageConverter());}@Beanpublic MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();converter.setObjectMapper(new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false));return converter;}   }

这里我们重写了extendMessageConverters方法,它提供了一个钩子来添加你自己的验证器,而不会跳过所有现有的验证器。

这是关于REST的基本介绍。下一篇文章展示了一个RESTFUL CRUD Web服务,完整的示例包含HTTP GET,PUT,POST和DELETE方法映射。

  相关解决方案