https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-controller
1.3.1. Declaration
您可以通过在Servlet的WebApplicationContext中使用标准Spring bean定义来定义controller bean
@Controller原型允许自动检测,与Spring的通用支持一致,它可以检测类路径中的@Component类,并为它们自动注册bean定义。它还充当带注释类的原型,指示其作为web组件的角色。
要启用自动检测此类@Controller bean,可以将组件扫描添加到Java配置中,如下例所示:
@Configuration @ComponentScan("org.example.web") public class WebConfig { // ... }
AOP Proxies
在某些情况下,您可能需要在运行时使用AOP代理来装饰控制器。一个例子是,如果您选择在控制器上直接使用@Transactional注释。在这种情况下,特别是对于控制器,我们建议使用基于类的代理。这通常是控制器的默认选择。
1.3.2. Request Mapping
您可以使用@RequestMapping注释将请求映射到控制器方法。它有各种属性可以通过URL、HTTP方法、请求参数、头和媒体类型进行匹配。可以在类级别使用它来表示共享映射,也可以在方法级别使用它来缩小到特定的端点映射。
@RequestMapping还有一些特定于HTTP方法的快捷方式变体:
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
URI patterns
@RequestMapping方法可以使用URL模式进行映射。有两种选择:
- PathPattern — 与URL路径匹配的预解析模式也预解析为PathContainer。该解决方案专为web使用而设计,可以有效地处理编码和路径参数,并进行高效匹配。
- AntPathMatcher — 根据字符串路径匹配字符串模式。这是Spring配置中用于选择类路径、文件系统和其他位置上的资源的原始解决方案。它的效率较低,而且字符串路径输入对于有效处理URL的编码和其他问题是一个挑战。
一些示例模式(patterns):
"/resources/ima?e.png"
- match one character in a path segment"/resources/*.png"
- match zero or more characters in a path segment"/resources/**"
- match multiple path segments"/projects/{project}/versions"
- match a path segment and capture it as a variable"/projects/{project:[a-z]+}/versions"
- match and capture a variable with a regex
捕获的URI变量可以通过@PathVariable访问。例如:
@GetMapping("/owners/{ownerId}/pets/{petId}") public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) { // ... }
您可以在类和方法级别声明URI变量,如下例所示:
@Controller @RequestMapping("/owners/{ownerId}") public class OwnerController { @GetMapping("/pets/{petId}") public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) { // ... } }
URI变量会自动转换为适当的类型,或者引发TypeMissatchException。默认情况下支持简单类型(int、long、Date等),您可以注册对任何其他数据类型的支持。请参阅类型转换和DataBinder(Type Conversion and DataBinder
)
您可以显式地命名URI变量(例如@PathVariable("customId")),但如果名称相同,并且您的代码是使用调试信息或Java 8上的-parameters编译器标志编译的,则可以省略该细节。
Parameters, headers
可以根据请求参数条件缩小请求映射范围。您可以测试是否存在请求参数(myParam)、是否没有(!myParam)或是否存在特定值(myParam=myValue)。以下示例显示了如何测试特定值:
@GetMapping(path = "/pets/{petId}", params = "myParam=myValue") public void findPet(@PathVariable String petId) { // ... }
您也可以将其用于请求头条件,如下例所示:
@GetMapping(path = "/pets", headers = "myHeader=myValue") public void findPet(@PathVariable String petId) { // ... }
1.3.3. Handler Methods
@RequestMapping处理程序方法具有灵活的签名,可以从一系列受支持的控制器方法参数和返回值中进行选择。
Method Arguments
下表描述了受支持的控制器方法参数。
Type Conversion
一些表示基于字符串的请求输入的带注释控制器方法参数(例如@RequestParam、@RequestHeader、@PathVariable、@MatrixVariable和@CookieValue)如果被声明为字符串以外的内容,则可能需要进行类型转换。
在这种情况下,类型转换会根据配置的转换器自动应用。默认情况下,支持简单类型(int、long、Date等)。您可以通过WebDataBinder(请参阅DataBinder
)或通过向FormattingConversionService注册格式化程序来自定义类型转换。请参见Spring字段格式。
类型转换中的一个实际问题是空字符串源值的处理。如果由于类型转换而变为null,则此类值将被视为缺失。对于Long、UUID和其他目标类型,情况可能就是这样。如果希望允许注入null,可以在参数注释上使用required标志,或者将参数声明为@Nullable。
Matrix Variables
RFC 3986讨论了路径段中的名称-值对(name-value pairs)。在Spring MVC中,我们根据Tim Berners Lee的“旧帖子”将它们称为“矩阵变量”,但它们也可以称为URI路径参数。
@RequestParam
可以使用@RequestParam注释将Servlet请求参数(即查询参数或表单数据)绑定到控制器中的方法参数。
默认情况下,使用此注释的方法参数是必需的,但您可以通过将@RequestParam注释的required标志设置为false或或使用java.util.Optional声明参数来指定方法参数是可选的。
如果目标方法参数类型不是字符串,则会自动应用类型转换。参见类型转换。
将参数类型声明为数组或列表可以解析同一参数名的多个参数值。
如果@RequestParam注释被声明为Map<String,String>或MultiValueMap<String,String>,且注释中未指定参数名称,则会使用每个给定参数名称的请求参数值填充该映射。
注意@RequestParam的使用是可选的(例如,设置其属性)。默认情况下,任何简单值类型(由BeanUtils#isSimpleProperty确定)且未由任何其他参数解析程序解析的参数都会被视为使用@RequestParam注释。
@ModelAttribute
您可以在方法参数上使用@ModelAttribute注释来访问模型中的属性,如果不存在属性,也可以将其实例化。model属性还覆盖了HTTP Servlet请求参数的值,这些参数的名称与字段名称匹配。这被称为数据绑定,它使您不必解析和转换单个查询参数和表单字段。以下示例显示了如何执行此操作:
@PostMapping("/owners/{ownerId}/pets/{petId}/edit") public String processSubmit(@ModelAttribute Pet pet) { // method logic... }
上述Pet实例的来源如下:详见原文
请注意,使用@ModelAttribute是可选的(例如,设置其属性)。默认情况下,任何不是简单值类型(由BeanUtils#isSimpleProperty确定)且未由任何其他参数解析程序解析的参数都将被视为使用@ModelAttribute注释。
1.3.5. DataBinder
@Controller或@ControllerAdvice类可以使用@InitBinder方法初始化WebDataBinder实例,而这些方法反过来可以:
- Bind request parameters (that is, form or query data) to a model object.
- Convert String-based request values (such as request parameters, path variables, headers, cookies, and others) to the target type of controller method arguments.
- 在呈现HTML表单时,将模型对象值格式化为字符串值。
@InitBinder方法可以注册特定于控制器的java.beans.PropertyEditor或Spring转换器和格式化组件。此外,可以使用MVC config在全局共享的FormattingConversionService中注册转换器和格式化程序类型。
@InitBinder方法支持许多与@RequestMapping方法相同的参数,但@ModelAttribute(命令对象)参数除外。通常,它们是用WebDataBinder参数(用于注册)和void返回值声明的。下面的列表显示了一个示例:
@Controller public class FormController { @InitBinder public void initBinder(WebDataBinder binder) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); dateFormat.setLenient(false); binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false)); } // ... }
或者,当您通过共享FormattingConversionService使用基于格式化程序的设置时,您可以重复使用相同的方法并注册特定于控制器的格式化程序实现,如下例所示:
@Controller public class FormController { @InitBinder protected void initBinder(WebDataBinder binder) { binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd")); } // ... }