《Spring 5 官方文档》18. Web MVC 框架(四)

使用@ResponseBody注释映射响应体

@ResponseBody注释是类似@RequestBody。该注释可以放在一个方法上,并指示返回类型应该直接写入HTTP响应体(而不是放在模型中,或者解释为视图名称)。例如:

@GetMapping(“/ something”)
@ResponseBody
 public String helloWorld(){
	 return  “Hello World” ; 
}

上述示例将导致文本Hello World被写入HTTP响应流。

与之一样@RequestBody,Spring通过使用一个转换将返回的对象转换为响应体HttpMessageConverter。有关这些转换器的更多信息,请参阅上一部分和消息转换器

使用@RestController注释创建REST控制器

控制器实现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.

与常规@ControllerS,A @RestController可以通过协助 @ControllerAdvice@RestControllerAdvice豆类。有关 更多详细信息,请参阅“使用@ControllerAdvice和@RestControllerAdvice建议控制器”一节。

使用HttpEntity

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

@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 @RequestMappingmethods, 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建议控制器”一节。

《Spring 5 官方文档》18. Web MVC 框架(四)
当没有明确指定模型属性名称时会发生什么?在这种情况下,根据其类型将默认名称分配给模型属性。例如,如果该方法返回类型的对象Account,则使用的默认名称为“account”。您可以通过@ModelAttribute注释的值更改它。如果直接添加属性Model,请使用适当的重载addAttribute(..)方法 – 即,带有或不带有属性名称。

@ModelAttribute批注可在使用@RequestMapping方法为好。在这种情况下,@RequestMapping方法的返回值将被解释为模型属性而不是视图名称。视图名称是基于视图名称约定导出的,非常类似于返回的方法void - 请参见第18.13.3节“View – RequestToViewNameTranslator”

在方法参数上使用@ModelAttribute

如上一节所述@ModelAttribute,可以在方法或方法参数上使用。本节介绍了其在方法参数中的用法。

一个@ModelAttribute上的方法参数指示参数应该从模型中检索。如果模型中不存在,参数首先被实例化,然后添加到模型中。一旦出现在模型中,参数的字段应该从具有匹配名称的所有请求参数中填充。这被称为Spring MVC中的数据绑定,这是一种非常有用的机制,可以节省您逐个解析每个表单字段。

@PostMapping(“/ owners / {ownerId} / pets / {petId} / edit”)
 public String processSubmit( @ModelAttribute Pet pet){}

鉴于上述例子,宠物实例可以从哪里来?有几个选择:

一种@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将模型属性存储在请求之间的HTTP会话中

类型级@SessionAttributes注释声明特定处理程序使用的会话属性。这通常将列出模型属性或模型属性的类型,这些模型属性或类型应该透明地存储在会话或某些会话存储中,作为后续请求之间的格式支持bean。

以下代码片段显示了此注释的用法,指定了模型属性名称:

@Controller 
@RequestMapping(“/ editPet.do”)
@SessionAttributes(“pet”)
 public class EditPetForm {
	// ...
}

使用@SessionAttribute访问预先存在的全局会话属性

如果您需要访问全局管理的预先存在的会话属性,即控制器外部(例如,通过过滤器),并且可能存在或可能不存在,@SessionAttribute则会使用方法参数上的注释:

@RequestMapping(“/”)
 public String handle( @SessionAttribute User user){
	 // ... 
}

对于需要添加或删除会话属性的用例,请考虑注入 org.springframework.web.context.request.WebRequest或 javax.servlet.http.HttpSession控制方法。

为了在会话中临时存储模型属性作为控制器工作流的一部分,请考虑使用“使用@SessionAttributes将模型属性存储在请求之间的HTTP会话中”SessionAttributes中 所述的一节

使用@RequestAttribute来访问请求属性

到类似@SessionAttribute@RequestAttribute注释可以被用于访问由滤波器或拦截器创建的预先存在的请求属性:

@RequestMapping(“/”)
 public String handle( @RequestAttribute Client client){
	 // ... 
}

使用“application / x-www-form-urlencoded”数据

以前的章节介绍了@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*()一系列方法使表单数据可用 。

《Spring 5 官方文档》18. Web MVC 框架(四)
由于HttpPutFormContentFilter消耗了请求的正文,因此不应配置为依赖其他转换器的PUT或PATCH URL application/x-www-form-urlencoded。这包括@RequestBody MultiValueMap<String, String>HttpEntity<MultiValueMap<String, String>>

使用@CookieValue注释映射Cookie值

@CookieValue注释允许将方法参数绑定到HTTP cookie的值。

让我们考虑以下cookie已被接收到http请求:

JSESSIONID = 415A4AC178C59DACE0B2C9CA727CDD84

以下代码示例演示如何获取JSESSIONIDcookie 的值:

@RequestMapping(“/ displayHeaderInfo.do”)
 public  void displayHeaderInfo( @CookieValue(“JSESSIONID”) String cookie){
	 // ... 
}

如果目标方法参数类型不是,则会自动应用类型转换 String。请参阅“方法参数和类型转换”一节

使用@RequestHeader注释映射请求标头属性

@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参数,则地图被填充有所有标头值。

《Spring 5 官方文档》18. Web MVC 框架(四)
内置支持可用于将逗号分隔的字符串转换为字符串或类型转换系统已知的其他类型的数组/集合。例如,注释的方法参数@RequestHeader("Accept")可以是类型String,也可以是 String[]List<String>

方法参数和类型转换

从请求中提取的基于字符串的值(包括请求参数,路径变量,请求标头和cookie值)可能需要转换为方法参数或字段的目标类型(例如,将请求参数绑定到参数中的字段@ModelAttribute)他们一定会。如果目标类型不是String,Spring将自动转换为相应的类型。支持所有简单的类型,如int,long,Date等。您可以进一步自定义通过转换过程WebDataBinder(见称为“定制WebDataBinder初始化”一节),或者通过注册FormattersFormattingConversionService(参见5.6节,“春字段格式”)。

上一篇:互联网聊天群管理试行规则


下一篇:阿里云并非“套路云”!购买不要太着急,常见问题要注意!