使用@ResponseBody注释映射响应体
该@ResponseBody
注释是类似@RequestBody
。该注释可以放在一个方法上,并指示返回类型应该直接写入HTTP响应体(而不是放在模型中,或者解释为视图名称)。例如:
@GetMapping(“/ something”) @ResponseBody public String helloWorld(){ return “Hello World” ; }
上述示例将导致文本Hello World
被写入HTTP响应流。
与之一样@RequestBody
,Spring通过使用一个转换将返回的对象转换为响应体HttpMessageConverter
。有关这些转换器的更多信息,请参阅上一部分和消息转换器。
控制器实现REST API是一个非常常见的用例,因此仅提供JSON,XML或定制的MediaType内容。为方便起见,您可以使用以下@RequestMapping
方式@ResponseBody
来注释您的控制器类,而不是注释所有 方法@RestController
。
@RestController
is a stereotype annotation that combines @ResponseBody
and @Controller
. More than that, it gives more meaning to your Controller and also may carry additional semantics in future releases of the framework.
与常规@Controller
S,A @RestController
可以通过协助 @ControllerAdvice
或@RestControllerAdvice
豆类。有关 更多详细信息,请参阅“使用@ControllerAdvice和@RestControllerAdvice建议控制器”一节。
这HttpEntity
是相似的@RequestBody
和@ResponseBody
。除了访问请求和响应主体之外HttpEntity
(和响应特定子类ResponseEntity
)还允许访问请求和响应头,如下所示:
@RequestMapping(“/ something”) public ResponseEntity <String> handle(HttpEntity < byte []> requestEntity) throws UnsupportedEncodingException { String requestHeader = requestEntity.getHeaders()。getFirst( “MyRequestHeader”); byte [] requestBody = requestEntity.getBody(); //使用请求头和身体 做某事HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.set( “MyResponseHeader”, “MyValue”); 返回新的 ResponseEntity <String>( “Hello World”,responseHeaders,HttpStatus。创建); }
上述示例获取MyRequestHeader
请求标头的值,并将其作为字节数组读取。它将MyResponseHeader
响应添加到Hello World
响应流中,并将响应状态代码设置为201(已创建)。
至于@RequestBody
和@ResponseBody
,Spring使用HttpMessageConverter
从和请求和响应流转换。有关这些转换器的更多信息,请参阅上一部分和消息转换器。
该@ModelAttribute
注释可以对方法或方法的参数来使用。本节将介绍其在方法上的用法,下一节将介绍其在方法参数上的用法。
An @ModelAttribute
on a method indicates the purpose of that method is to add one or more model attributes. Such methods support the same argument types as @RequestMapping
methods but cannot be mapped directly to requests. Instead @ModelAttribute
methods in a controller are invoked before @RequestMapping
methods, within the same controller. A couple of examples:
//添加一个属性 //该方法的返回值被添加到名为“account”的模型中 //您可以通过@ModelAttribute(“myAccount”) @ModelAttribute 自定义名称@ModelAttribute public Account addAccount(@RequestParam String number) { return accountManager.findAccount(number); } //添加多个属性@ModelAttribute public void populateModel(@RequestParam String number,Model model){ model.addAttribute(accountManager.findAccount(number)); //添加更多... }
@ModelAttribute
方法用于填充具有常用属性的模型,例如使用状态或宠物类型填充下拉列表,或者检索诸如Account的命令对象,以便使用它来表示HTML表单上的数据。后一种情况在下一节进一步讨论。
注意两种风格的@ModelAttribute
方法。在第一个方法中,该方法通过返回它隐式地添加一个属性。在第二个方法中,该方法接受Model
并添加任意数量的模型属性。您可以根据需要选择两种风格。
控制器可以有多种@ModelAttribute
方法。所有这些方法都@RequestMapping
在相同控制器的方法之前被调用。
@ModelAttribute
方法也可以在一个@ControllerAdvice
注释类中定义,并且这种方法适用于许多控制器。有关更多详细信息,请参阅“使用@ControllerAdvice和@RestControllerAdvice建议控制器”一节。
当没有明确指定模型属性名称时会发生什么?在这种情况下,根据其类型将默认名称分配给模型属性。例如,如果该方法返回类型的对象Account ,则使用的默认名称为“account”。您可以通过@ModelAttribute 注释的值更改它。如果直接添加属性Model ,请使用适当的重载addAttribute(..) 方法 – 即,带有或不带有属性名称。 |
该@ModelAttribute
批注可在使用@RequestMapping
方法为好。在这种情况下,@RequestMapping
方法的返回值将被解释为模型属性而不是视图名称。视图名称是基于视图名称约定导出的,非常类似于返回的方法void
- 请参见第18.13.3节“View – RequestToViewNameTranslator”。
如上一节所述@ModelAttribute
,可以在方法或方法参数上使用。本节介绍了其在方法参数中的用法。
一个@ModelAttribute
上的方法参数指示参数应该从模型中检索。如果模型中不存在,参数首先被实例化,然后添加到模型中。一旦出现在模型中,参数的字段应该从具有匹配名称的所有请求参数中填充。这被称为Spring MVC中的数据绑定,这是一种非常有用的机制,可以节省您逐个解析每个表单字段。
@PostMapping(“/ owners / {ownerId} / pets / {petId} / edit”) public String processSubmit( @ModelAttribute Pet pet){}
鉴于上述例子,宠物实例可以从哪里来?有几个选择:
- 由于使用
@SessionAttributes
- 可能已经在模型中- 请参阅 “使用@SessionAttributes将模型属性存储在请求之间的HTTP会话中”一节。 - 由于
@ModelAttribute
在同一控制器中的方法,它可能已经在模型中 – 如上一节所述。 - 它可以基于URI模板变量和类型转换器(下面更详细地解释)来检索。
- 它可以使用其默认构造函数实例化。
一种@ModelAttribute
方法是从数据库中检索属性的常用方法,可以通过使用可选地在请求之间存储属性 @SessionAttributes
。在某些情况下,通过使用URI模板变量和类型转换器来检索属性可能很方便。这是一个例子:
@PutMapping(“/ accounts / {account}”) public String save( @ModelAttribute(“account”)帐户帐号){ // ... }
在此示例中,模型属性(即“account”)的名称与URI模板变量的名称相匹配。如果您注册Converter<String, Account>
,可以将 String
帐户值转换为一个Account
实例,则上述示例将无需使用@ModelAttribute
方法。
下一步是数据绑定。该WebDataBinder
级比赛要求参数名称-包括查询字符串参数和表单域-以模拟通过名称属性字段。在必要时已经应用了类型转换(从字符串到目标字段类型)之后填充匹配字段。数据绑定和验证在 第5章验证,数据绑定和类型转换中介绍。自定义控制器级别的数据绑定过程将在“自定义WebDataBinder初始化”一节中介绍。
由于数据绑定,可能会出现错误,例如缺少必填字段或类型转换错误。要检查这些错误,请在BindingResult
参数后立即添加一个@ModelAttribute
参数:
@PostMapping(“/ owners / {ownerId} / pets / {petId} / edit”) public String processSubmit( @ModelAttribute(“pet”)Pet Pet,BindingResult result){ if(result.hasErrors()){ return “petForm “ ; } // ... }
使用一个BindingResult
你可以检查是否发现错误,在这种情况下,渲染相同的形式通常是在Spring的<errors>
表单标签的帮助下显示错误的。
请注意,在某些情况下,在没有数据绑定的情况下获取模型中的属性可能是有用的。对于这种情况,您可以将其注入Model
控制器,或者使用注释上的binding
标志:
@ModelAttribute public AccountForm setUpForm(){ return new AccountForm(); } @ModelAttribute public Account findAccount( @PathVariable String accountId){ return accountRepository.findOne(accountId); } @PostMapping(“update”) public String update( @Valid AccountUpdateForm form,BindingResult result, @ModelAttribute(binding = false) Account account){ // ... }
除了数据绑定之外,您还可以使用自己的自定义验证器调用验证,传递与BindingResult
用于记录数据绑定错误相同的验证器。这允许在一个地方累积数据绑定和验证错误,并随后向用户报告:
@PostMapping( “/老板/ {} OWNERID /宠物/ {} petId /编辑”) 公共字符串processSubmit(新 PetValidator()验证(PET,结果); 如果(result.hasErrors()){ 回报“petForm” ; } // ... }@ModelAttribute("pet") Pet pet, BindingResult result) {
或者您可以通过添加JSR-303 @Valid
注释自动调用验证:
@PostMapping(“/ owners / {ownerId} / pets / {petId} / edit”) public String processSubmit( @Valid @ModelAttribute(“pet”)Pet pet,BindingResult result){ if(result.hasErrors()){ return “petForm” ; } // ... }
有关如何配置和使用验证的详细信息,请参见第5.8节“Spring验证”和第5章验证,数据绑定和类型转换。
类型级@SessionAttributes
注释声明特定处理程序使用的会话属性。这通常将列出模型属性或模型属性的类型,这些模型属性或类型应该透明地存储在会话或某些会话存储中,作为后续请求之间的格式支持bean。
以下代码片段显示了此注释的用法,指定了模型属性名称:
@Controller @RequestMapping(“/ editPet.do”) @SessionAttributes(“pet”) public class EditPetForm { // ... }
如果您需要访问全局管理的预先存在的会话属性,即控制器外部(例如,通过过滤器),并且可能存在或可能不存在,@SessionAttribute
则会使用方法参数上的注释:
@RequestMapping(“/”) public String handle( @SessionAttribute User user){ // ... }
对于需要添加或删除会话属性的用例,请考虑注入 org.springframework.web.context.request.WebRequest
或 javax.servlet.http.HttpSession
控制方法。
为了在会话中临时存储模型属性作为控制器工作流的一部分,请考虑使用“使用@SessionAttributes将模型属性存储在请求之间的HTTP会话中”SessionAttributes
中 所述的一节。
到类似@SessionAttribute
的@RequestAttribute
注释可以被用于访问由滤波器或拦截器创建的预先存在的请求属性:
@RequestMapping(“/”) public String handle( @RequestAttribute Client client){ // ... }
以前的章节介绍了@ModelAttribute
如何支持浏览器客户端的表单提交请求。建议与非浏览器客户端的请求一起使用相同的注释。然而,在使用HTTP PUT请求时,有一个显着的区别。浏览器可以通过HTTP GET或HTTP POST提交表单数据。非浏览器客户端也可以通过HTTP PUT提交表单。这提出了一个挑战,因为Servlet规范要求ServletRequest.getParameter*()
一系列方法仅支持HTTP POST的表单域访问,而不支持HTTP PUT。
为了支持HTTP PUT和PATCH请求,该spring-web
模块提供了HttpPutFormContentFilter
可以在以下配置中的过滤器 web.xml
:
<filter> <filter-name> httpPutFormFilter </ filter-name> <filter-class> org.springframework.web.filter.HttpPutFormContentFilter </ filter-class> </ filter> <filter-mapping> <filter-name> httpPutFormFilter </ filter-name> <servlet-name> dispatcherServlet </ servlet-name> </ filter-mapping> <servlet> <servlet-name> dispatcherServlet </ servlet-name> <servlet-class> org.springframework.web。 servlet.DispatcherServlet </ servlet-class> </ servlet>
上述过滤器拦截具有内容类型的HTTP PUT和PATCH请求application/x-www-form-urlencoded
,从请求的正文 中读取表单数据,并包装ServletRequest
以便通过ServletRequest.getParameter*()
一系列方法使表单数据可用 。
由于HttpPutFormContentFilter 消耗了请求的正文,因此不应配置为依赖其他转换器的PUT或PATCH URL application/x-www-form-urlencoded 。这包括@RequestBody MultiValueMap<String, String> 和HttpEntity<MultiValueMap<String, String>> 。 |
该@CookieValue
注释允许将方法参数绑定到HTTP cookie的值。
让我们考虑以下cookie已被接收到http请求:
JSESSIONID = 415A4AC178C59DACE0B2C9CA727CDD84
以下代码示例演示如何获取JSESSIONID
cookie 的值:
@RequestMapping(“/ displayHeaderInfo.do”) public void displayHeaderInfo( @CookieValue(“JSESSIONID”) String cookie){ // ... }
如果目标方法参数类型不是,则会自动应用类型转换 String
。请参阅“方法参数和类型转换”一节。
该@RequestHeader
注释允许将一个方法参数绑定到请求头。
以下是一个示例请求标头:
主机本地主机:8080 接受文本/ html应用程序/ xhtml + xml应用程序/ xml; q = 0.9 接受语言fr,en-gb; q = 0.7,en; q = 0.3 接受编码gzip,放大 Accept-Charset ISO -8859-1,utf-8; q = 0.7,*; q = 0.7 保持活力300
以下代码示例演示了如何获取Accept-Encoding
和 Keep-Alive
标题的值:
@RequestMapping(“/ displayHeaderInfo.do”) public void displayHeaderInfo( @RequestHeader(“Accept-Encoding”) String encoding, @RequestHeader(“Keep-Alive”) long keepAlive){ // ... }
Type conversion is applied automatically if the method parameter is not String
. See the section called “Method Parameters And Type Conversion”.
当@RequestHeader
注解上的使用Map<String, String>
, MultiValueMap<String, String>
或HttpHeaders
参数,则地图被填充有所有标头值。
内置支持可用于将逗号分隔的字符串转换为字符串或类型转换系统已知的其他类型的数组/集合。例如,注释的方法参数@RequestHeader("Accept") 可以是类型String ,也可以是 String[] 或List<String> 。 |
从请求中提取的基于字符串的值(包括请求参数,路径变量,请求标头和cookie值)可能需要转换为方法参数或字段的目标类型(例如,将请求参数绑定到参数中的字段@ModelAttribute
)他们一定会。如果目标类型不是String
,Spring将自动转换为相应的类型。支持所有简单的类型,如int,long,Date等。您可以进一步自定义通过转换过程WebDataBinder
(见称为“定制WebDataBinder初始化”一节),或者通过注册Formatters
与FormattingConversionService
(参见5.6节,“春字段格式”)。