Spring 注解汇总

1、声明

您可以通过在Servlet的WebApplicationContext中使用标准的Springbean定义来定义控制器bean。@Controller原型允许自动检测,与Spring在类路径中检测@Component类并自动注册bean定义的一般支持保持一致。它还充当注释类的原型,指示其作为web组件的角色。

要启用此类@Controllerbean的自动检测,可以将组件扫描添加到Java配置中,如下例所示:


@Configuration
@ComponentScan("org.example.web")
public class WebConfig {

    // ...
}

@RestController是一个复合注释,它本身用@Controller和@ResponseBody进行元注释,以指示其每个方法都继承类型级别@ResponsBody注释的控制器,因此,与视图解析和HTML模板渲染相比,它直接写入响应体。

2、请求映射

您可以使用@RequestMapping注释将请求映射到控制器方法。它具有各种属性,可通过URL、HTTP方法、请求参数、标头和媒体类型进行匹配。您可以在类级别使用它来表示共享映射,或者在方法级别使用它缩小到特定的端点映射。

@RequestMapping还有特定于HTTP方法的快捷方式变体:

  • @GetMapping

  • @PostMapping

  • @PutMapping

  • @DeleteMapping

  • @PatchMapping

提供快捷方式是自定义注释,因为可以说,大多数控制器方法应该映射到特定的HTTP方法,而不是使用@RequestMapping,默认情况下,@RequestMapping与所有HTTP方法匹配。在类级别仍然需要@RequestMapping来表示共享映射。


@RestController
@RequestMapping("/persons")
class PersonController {

    @GetMapping("/{id}")
    public Person getPerson(@PathVariable Long id) {
        // ...
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public void add(@RequestBody Person person) {
        // ...
    }
}

3、URI 模式

@RequestMapping可以使用 URL 模式映射方法。有两种选择:

  • PathPattern  — 与URL路径匹配的预解析模式也预解析为PathContainer。此解决方案专为web使用而设计,可有效处理编码和路径参数,并有效匹配。

  • AntPathMatcher  — 根据字符串路径匹配字符串模式。这是Spring配置中用于选择类路径、文件系统和其他位置上的资源的原始解决方案。它的效率较低,字符串路径输入对于有效处理URL的编码和其他问题是一个挑战。

PathPattern是web应用程序的推荐解决方案,也是SpringWebFlux中的唯一选择。它从5.3版开始在SpringMVC中启用,默认情况下从6.0版开始启用。有关路径匹配选项的自定义,请参阅MVC配置。

PathPattern支持与AntPathMatcher相同的模式语法。此外,它还支持捕获模式,例如{*spring},用于匹配路径末端的0个或多个路径段。PathPattern还限制使用**来匹配多个路径段,以便只允许在模式末尾使用。这消除了为给定请求选择最佳匹配模式时的许多不确定性。有关完整模式语法,请参阅PathPattern和AntPathMatcher。

示例模式:

  • “/resources/ima?e.png”-匹配路径段中的一个字符

  • “/resources/*.png”-匹配路径段中的零个或多个字符

  • “/resources/**”-匹配多个路径段

  • “/projects/{project}/versions”-匹配路径段并将其捕获为变量

  • “/projects/{project:[a-z]+}/versions”-使用正则表达式匹配并捕获变量

可以使用@PathVariable访问捕获的URI变量。例如:


@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变量会自动转换为适当的类型,或引发TypeMismatchException。默认情况下支持简单类型(int、long、Date等),您可以注册对任何其他数据类型的支持。请参阅类型转换和DataBinder。

您可以显式地命名URI变量(例如,@PathVariable(“customId”)),但如果名称相同且代码使用-parameters编译器标志编译,则可以省略该细节。

语法{varName:regex}使用语法为{varName:regex}的正则表达式声明URI变量。例如,给定URL“/spring-web-3.0.5.jar”,以下方法提取名称、版本和文件扩展名:


@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String name, @PathVariable String version, @PathVariable String ext) {
    // ...
}

URI路径模式还可以嵌入${…​} 通过对本地、系统、环境和其他属性源使用PropertySourcesPlaceholderConfigurator在启动时解析的占位符。例如,您可以使用它根据某些外部配置参数化基本URL。

4、消耗型媒体类型

您可以根据请求的Content-Type缩小请求映射,如下例所示:


@PostMapping(path = "/pets", consumes = "application/json") (1)
public void addPet(@RequestBody Pet pet) {
    // ...
}

(1) 使用consumes属性按内容类型缩小映射。

consumers属性还支持否定表达式 — 例如text/plain是指除text/plaine之外的任何内容类型。

您可以在类级别声明共享消费属性。然而,与大多数其他请求映射属性不同,当在类级别使用时,方法级别使用属性重写,而不是扩展类级别声明。

5、Producible Media 类型

您可以根据Accept请求标头和控制器方法生成的内容类型列表缩小请求映射,如下例所示:


@GetMapping(path = "/pets/{petId}", produces = "application/json") (1)
@ResponseBody
public Pet getPet(@PathVariable String petId) {
    // ...
}

(1)使用products属性按内容类型缩小映射。

媒体类型可以指定字符集。支持否定表达式 — 例如text/plain是指除“text/plaine”以外的任何内容类型。

您可以在类级别声明共享的products属性。然而,与大多数其他请求映射属性不同,当在类级别使用时,方法级别生成属性重写,而不是扩展类级别声明。

6、Parameters, headers

您可以根据请求参数条件缩小请求映射。您可以测试是否存在请求参数(myParam)、是否缺少请求参数(!myParam)或是否存在特定值(myParam=myValue)。以下示例显示了如何测试特定值:


@GetMapping(path = "/pets/{petId}", params = "myParam=myValue") (1)
public void findPet(@PathVariable String petId) {
    // ...
}
(1) 测试myParam是否等于myValue。

也可以对请求头条件使用相同的方法,如下例所示:


@GetMapping(path = "/pets", headers = "myHeader=myValue") (1)
public void findPet(@PathVariable String petId) {
    // ...
}

(1)测试myHeader是否等于myValue。

7、HTTP HEAD, OPTIONS

@GetMapping(和@RequestMapping(method=HttpMethod.GET))对请求映射透明地支持HTTP HEAD。控制器方法无需更改。jakarta.servlet.http.HttpServlet中应用的响应包装器确保Content-Length标头设置为写入的字节数(而不实际写入响应)。

@GetMapping(和@RequestMapping(method=HttpMethod.GET))隐式映射到并支持HTTP HEAD。处理HTTP HEAD请求时,就像处理HTTP GET一样,只是不写入正文,而是计算字节数并设置Content-Length标头。

默认情况下,HTTP OPTIONS是通过将Allow响应头设置为所有@RequestMapping方法中列出的具有匹配URL模式的HTTP方法列表来处理的。

对于没有HTTP方法声明的@RequestMapping,Allow标头设置为GET、HEAD、POST、PUT、PATCH、DELETE、OPTIONS。控制器方法应始终声明支持的HTTP方法(例如,通过使用HTTP方法特定的变量:@GetMapping、@PostMapping和其他)。

您可以显式地将@RequestMapping方法映射到HTTP HEAD和HTTP OPTIONS,但在常见情况下这不是必需的。

8、自定义注释

SpringMVC支持使用组合注释进行请求映射。这些注释本身是用@RequestMapping进行元注释的,组成这些注释的目的是重新声明@RequestMapping属性的子集(或全部),以实现更窄、更具体的用途。

@GetMapping、@PostMapping、@PutMapping、@DeleteMapping和@PatchMapping是组合注释的示例。提供它们是因为,可以说,大多数控制器方法应该映射到特定的HTTP方法,而不是使用@RequestMapping,默认情况下,@RequestMapping与所有HTTP方法匹配。如果需要组合注释的示例,请查看这些注释是如何声明的。

SpringMVC还支持带有自定义请求匹配逻辑的自定义请求映射属性。这是一个更高级的选项,需要子类化RequestMappingHandlerMapping并重写getCustomMethodCondition方法,在这里您可以检查自定义属性并返回自己的RequestCondition。

9、显式注册

可以通过编程方式注册处理程序方法,这些方法可用于动态 注册或高级案例,例如同一处理程序的不同实例 在不同的网址下。下面的示例注册处理程序方法:


@Configuration
public class MyConfig {

    @Autowired
    public void setHandlerMapping(RequestMappingHandlerMapping mapping, UserHandler handler) (1)
            throws NoSuchMethodException {

        RequestMappingInfo info = RequestMappingInfo
                .paths("/user/{id}").methods(RequestMethod.GET).build(); (2)

        Method method = UserHandler.class.getMethod("getUser", Long.class); (3)

        mapping.registerMapping(info, handler, method); (4)
    }
}

(1)注入控制器的目标处理程序和处理程序映射。
(2)准备请求映射元数据。
(3) 获取处理程序方法。
(4) 添加注册。

10、@RequestParam

您可以使用@RequestParam注释将Servlet请求参数(即查询参数或表单数据)绑定到控制器中的方法参数。

以下示例显示了如何执行此操作:


@Controller
@RequestMapping("/pets")
public class EditPetForm {

    // ...

    @GetMapping
    public String setupForm(@RequestParam("petId") int petId, Model model) { (1)
        Pet pet = this.clinic.loadPet(petId);
        model.addAttribute("pet", pet);
        return "petForm";
    }

    // ...

}

(1)使用@RequestParam绑定petId。

默认情况下,使用此注释的方法参数是必需的,但可以通过将@RequestParam注释的required标志设置为false或使用java.util.optional包装器声明参数来指定方法参数是可选的。

如果目标方法参数类型不是String,则自动应用类型转换。请参见类型转换。

将参数类型声明为数组或列表允许解析同一参数名称的多个参数值。

如果@RequestParam注释声明为Map<String,String>或MultiValueMap<String、String>,而没有在注释中指定参数名称,则会使用每个给定参数名称的请求参数值填充映射。

注意,@RequestParam的使用是可选的(例如,设置其属性)。默认情况下,任何简单值类型(由BeanTils#isSimpleProperty确定)且未由任何其他参数解析器解析的参数都将被视为使用@RequestParam进行了注释。

11、@RequestHeader

可以使用@RequestHeader注释将请求头绑定到控制器中的方法参数。

考虑以下带有标题的请求:


Host                    localhost:8080
Accept                  text/html,application/xhtml+xml,application/xml;q=0.9
Accept-Language         fr,en-gb;q=0.7,en;q=0.3
Accept-Encoding         gzip,deflate
Accept-Charset          ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive              300

以下示例获取Accept Encoding和Keep Alive标头的值:


@GetMapping("/demo")
public void handle(
        @RequestHeader("Accept-Encoding") String encoding, (1)
        @RequestHeader("Keep-Alive") long keepAlive) { (2)
    //...
}
(1)获取Accept Encoding标头的值。
(2)获取Keep Alive标头的值。

如果目标方法参数类型不是String,则自动应用类型转换。请参见类型转换。

当@RequestHeader注释用于Map<String,String>、MultiValueMap<String、String>或HttpHeaders参数时,映射将填充所有标头值。

12、@CookieValue

您可以使用@CookieValue注释将HTTP cookie的值绑定到控制器中的方法参数。

考虑使用以下cookie的请求:


JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84

以下示例显示如何获取cookie值:


@GetMapping("/demo")
public void handle(@CookieValue("JSESSIONID") String cookie) { (1)
    //...
}
(1)获取JSESSIONID cookie的值。

如果目标方法参数类型不是String,则自动应用类型转换。

13、@ModelAttribute

您可以在方法参数上使用@ModelAttribute注释来访问模型中的属性,或者在不存在的情况下将其实例化。model属性还覆盖了名称与字段名称匹配的HTTPServlet请求参数的值。这被称为数据绑定,它使您不必处理解析和转换单个查询参数和表单字段。以下示例显示了如何执行此操作:


@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet) { (1)
    // method logic...
}
(1)绑定Pet的实例。

上述Pet实例的来源如下:

  • 从可能已通过@ModelAttribute方法添加的模型中检索。

  • 如果model属性列在class level@SessionAttributes注释中,则从HTTP会话中检索。

  • 通过Converter获得,其中模型属性名称与请求值(如路径变量或请求参数)的名称匹配(请参见下一个示例)。

  • 使用其默认构造函数实例化。

  • 通过具有与Servlet请求参数匹配的参数的“主构造函数”实例化。参数名称通过JavaBeans@ConstructorProperties或字节码中运行时保留的参数名称确定。

使用@ModelAttribute方法来提供它或依赖框架来创建模型属性的另一种选择是使用Converter<String,T>来提供实例。当模型属性名称与请求值(如路径变量或请求参数)的名称匹配,并且存在从字符串到模型属性类型的转换器时,将应用此选项。在以下示例中,模型属性名称是与URI路径变量account匹配的account,并且有一个注册的Converter<String,account>,它可以从数据存储中加载account:


@PutMapping("/accounts/{account}")
public String save(@ModelAttribute("account") Account account) { (1)
    // ...
}
(1)使用显式属性名称绑定Account的实例。

获得模型属性实例后,应用数据绑定。WebDataBinder类将Servlet请求参数名称(查询参数和表单字段)与目标Object上的字段名称相匹配。必要时,在应用类型转换后填充匹配字段。有关数据绑定(和验证)的详细信息,请参阅验证。有关自定义数据绑定的详细信息,请参阅DataBinder。

数据绑定可能会导致错误。默认情况下,引发BindException。但是,要检查控制器方法中的此类错误,可以在@ModelAttribute旁边立即添加BindingResult参数,如下例所示:


@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) { (1)
    if (result.hasErrors()) {
        return "petForm";
    }
    // ...
}
(1)在@ModelAttribute旁边添加BindingResult。

在某些情况下,您可能希望在没有数据绑定的情况下访问模型属性。对于这种情况,您可以将Model注入控制器并直接访问它,或者设置@ModelAttribute(binding=false),如下例所示:


@ModelAttribute
public AccountForm setUpForm() {
    return new AccountForm();
}

@ModelAttribute
public Account findAccount(@PathVariable String accountId) {
    return accountRepository.findOne(accountId);
}

@PostMapping("update")
public String update(@Valid AccountForm form, BindingResult result,
        @ModelAttribute(binding=false) Account account) { (1)
    // ...
}
(1)正在设置@ModelAttribute(binding=false)。

通过添加jakarta.validation.Valid注释或Spring的@Validated注释(Bean验证和Spring验证),可以在数据绑定后自动应用验证。以下示例显示了如何执行此操作:


@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) { (1)
    if (result.hasErrors()) {
        return "petForm";
    }
    // ...
}

注意,使用@ModelAttribute是可选的(例如,设置其属性)。默认情况下,任何不是简单值类型(由BeanTils#isSimpleProperty确定)且未被任何其他参数解析器解析的参数都将被视为使用@ModelAttribute进行了注释。

14、@SessionAttributes

@SessionAttributes用于在 HTTP Servlet 会话中存储模型属性 请求。它是一个类型级注释,用于声明 特定控制器。这通常列出模型属性的名称或类型 应透明地存储在会话中的模型属性以供后续使用 访问请求。

以下示例使用@SessionAttributes注释:


@Controller
@SessionAttributes("pet") (1)
public class EditPetForm {
    // ...
}
(1)使用@SessionAttributes注释。

在第一个请求中,当名称为pet的模型属性被添加到模型中时,它会自动升级并保存在HTTPServlet会话中。在另一个控制器方法使用SessionStatus方法参数清除存储之前,它将一直保持不变,如下例所示:


@Controller
@SessionAttributes("pet") (1)
public class EditPetForm {

    // ...

    @PostMapping("/pets/{id}")
    public String handle(Pet pet, BindingResult errors, SessionStatus status) {
        if (errors.hasErrors) {
            // ...
        }
        status.setComplete(); (2)
        // ...
    }
}

(1)在Servlet会话中存储pet值。
(2)从Servlet会话中清除pet值。

15、@SessionAttribute

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


@RequestMapping("/")
public String handle(@SessionAttribute User user) { (1)
    // ...
}
(1)使用@SessionAttribute注释。

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

对于作为控制器工作流的一部分在会话中临时存储模型属性,请考虑使用@SessionAttributes,如@SessionAttributes中所述。

16、@RequestAttribute

与@SessionAttribute类似,您可以使用@RequestAttribute注释访问先前创建的预先存在的请求属性(例如,通过Servlet筛选器或HandlerInterceptor):


@GetMapping("/")
public String handle(@RequestAttribute Client client) { (1)
    // ...
}
(1)使用@RequestAttribute注释。

17、Redirect Attributes

默认情况下,所有模型属性都被视为在重定向URL中公开为URI模板变量。在剩下的属性中,作为基本类型或基本类型的集合或数组的属性将自动附加为查询参数。

如果模型实例是专门为重定向准备的,则将基元类型属性附加为查询参数可能是所需的结果。但是,在带注释的控制器中,模型可以包含为渲染目的而添加的其他属性(例如,下拉字段值)。为了避免此类属性出现在URL中,@RequestMapping方法可以声明RedirectAttributes类型的参数,并使用它指定RedirectView可用的确切属性。如果该方法确实重定向,则使用RedirectAttributes的内容。否则,将使用模型的内容。

RequestMappingHandlerAdapter提供了一个名为ignoreDefaultModelOnRedirect的标志,您可以使用它来指示如果控制器方法重定向,则不应使用默认模型的内容。相反,控制器方法应该声明RedirectAttributes类型的属性,如果不这样做,则不应将任何属性传递给RedirectView。MVC命名空间和MVC Java配置都将此标志设置为false,以保持向后兼容性。但是,对于新应用程序,我们建议将其设置为true。

请注意,当前请求中的URI模板变量在扩展重定向URL时自动可用,您不需要通过Model或RedirectAttributes显式添加它们。以下示例显示了如何定义重定向:


@PostMapping("/files/{path}")
public String upload(...) {
    // ...
    return "redirect:files/{path}";
}

将数据传递到重定向目标的另一种方法是使用flash属性。与其他重定向属性不同,flash属性保存在HTTP会话中(因此不会显示在URL中)。有关详细信息,请参见Flash属性。

18、Flash Attributes

Flash属性为一个请求提供了一种方式来存储要在另一个请求中使用的属性。这是重定向时最常需要的 — 例如后重定向获取模式。Flash属性在重定向之前(通常在会话中)临时保存,以便在重定向后对请求可用,并立即删除。

Spring MVC有两个主要的抽象来支持flash属性。FlashMap用于保存flash属性,而FlashMapManager用于存储、检索和管理FlashMap实例。

Flash属性支持始终处于“开启”状态,不需要显式启用。但是,如果不使用,它将不会导致HTTP会话创建。在每个请求上,都有一个“输入”FlashMap和一个“输出”FlashMap,其中包含从上一个请求(如果有)传递的属性,以及一个要为后续请求保存的属性。这两个FlashMap实例都可以通过RequestContextUtils中的静态方法从Spring MVC中的任何位置访问。

带注释的控制器通常不需要直接使用FlashMap。相反,@RequestMapping方法可以接受RedirectAttributes类型的参数,并使用它为重定向场景添加flash属性。通过RedirectAttributes添加的Flash属性会自动传播到“输出”FlashMap。类似地,在重定向之后,来自“输入”FlashMap的属性会自动添加到为目标URL提供服务的控制器的模型中。

19、Multipart

启用MultipartResolver后,将解析包含多部分/表单数据的POST请求的内容,并将其作为常规请求参数进行访问。以下示例访问一个常规表单字段和一个上载的文件:


@Controller
public class FileUploadController {

    @PostMapping("/form")
    public String handleFormUpload(@RequestParam("name") String name,
            @RequestParam("file") MultipartFile file) {

        if (!file.isEmpty()) {
            byte[] bytes = file.getBytes();
            // store the bytes somewhere
            return "redirect:uploadSuccess";
        }
        return "redirect:uploadFailure";
    }
}

将参数类型声明为List<MultipartFile>允许解析同一参数名称的多个文件。

当@RequestParam注释声明为Map<String,MultipartFile>或MultiValueMap<String、MultipartFile>时,没有在注释中指定参数名,则映射将填充每个给定参数名的多部分文件。

您还可以将多部分内容用作到命令对象的数据绑定的一部分。例如,上一示例中的表单字段和文件可以是表单对象上的字段,如下例所示:


class MyForm {

    private String name;

    private MultipartFile file;

    // ...
}

@Controller
public class FileUploadController {

    @PostMapping("/form")
    public String handleFormUpload(MyForm form, BindingResult errors) {
        if (!form.getFile().isEmpty()) {
            byte[] bytes = form.getFile().getBytes();
            // store the bytes somewhere
            return "redirect:uploadSuccess";
        }
        return "redirect:uploadFailure";
    }
}

在RESTful服务场景中,也可以从非浏览器客户端提交多部分请求。以下示例显示了一个JSON文件:


POST /someUrl
Content-Type: multipart/mixed

--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp
Content-Disposition: form-data; name="meta-data"
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit

{
    "name": "value"
}
--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp
Content-Disposition: form-data; name="file-data"; filename="file.properties"
Content-Type: text/xml
Content-Transfer-Encoding: 8bit
... File Data ...

您可以使用@RequestParam作为字符串访问“元数据”部分,但您可能希望它从JSON反序列化(类似于@RequestBody)。使用HttpMessageConverter转换后,使用@RequestPart注释访问多部分:


@PostMapping("/")
public String handle(@RequestPart("meta-data") MetaData metadata,
        @RequestPart("file-data") MultipartFile file) {
    // ...
}

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


@PostMapping("/")
public String handle(@Valid @RequestPart("meta-data") MetaData metadata,
        BindingResult result) {
    // ...
}

20、@RequestBody

您可以使用@RequestBody注释通过HttpMessageConverter将请求体读取并反序列化为Object。以下示例使用@RequestBody参数:


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

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

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


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

21、HttpEntity

HttpEntity或多或少与使用 @RequestBody 相同,但基于 公开请求标头和正文的容器对象。下面的清单显示了一个示例:


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

22、@ResponseBody

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


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

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

您可以将@ResponseBody与反应类型一起使用。有关详细信息,请参阅异步请求和响应类型。

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

您可以将@ResponseBody方法与JSON序列化视图相结合。有关详细信息,请参见Jackson JSON。

23、Jackson JSON

Spring 提供对 Jackson JSON 库的支持。

JSON Views

SpringMVC为Jackson的序列化视图提供了内置支持,它只允许呈现Object中所有字段的子集。要将其与@ResponseBody或ResponseEntity控制器方法一起使用,可以使用Jackson的@JsonView注释来激活序列化视图类,如下例所示:


@RestController
public class UserController {

    @GetMapping("/user")
    @JsonView(User.WithoutPasswordView.class)
    public User getUser() {
        return new User("eric", "7!jd#h23");
    }
}

public class User {

    public interface WithoutPasswordView {};
    public interface WithPasswordView extends WithoutPasswordView {};

    private String username;
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @JsonView(WithoutPasswordView.class)
    public String getUsername() {
        return this.username;
    }

    @JsonView(WithPasswordView.class)
    public String getPassword() {
        return this.password;
    }
}

如果您希望以编程方式执行上述操作,而不是声明@JsonView注释,请使用MappingJacksonValue包装返回值,并使用它提供序列化视图:


@RestController
public class UserController {

    @GetMapping("/user")
    public MappingJacksonValue getUser() {
        User user = new User("eric", "7!jd#h23");
        MappingJacksonValue value = new MappingJacksonValue(user);
        value.setSerializationView(User.WithoutPasswordView.class);
        return value;
    }
}

对于依赖视图解析的控制器,可以将序列化视图类添加到模型中,如下例所示:


@Controller
public class UserController extends AbstractController {

    @GetMapping("/user")
    public String getUser(Model model) {
        model.addAttribute("user", new User("eric", "7!jd#h23"));
        model.addAttribute(JsonView.class.getName(), User.WithoutPasswordView.class);
        return "userView";
    }
}

24. Null-safety

尽管Java不允许您用其类型系统表达null安全性,但Spring Framework现在在org.springframework.lang包中提供了以下注释,允许您声明API和字段的可为null性:

  • @Nullable:用于指示特定参数、返回值或字段可以为null的注释。

  • @NonNull:用于指示特定参数、返回值或字段不能为null的注释(参数/返回值以及分别应用@NonNullApi和@NonNull fields的字段不需要)。

  • @NonNullApi:包级别的注释,声明非null为参数和返回值的默认语义。

  • @NonNullFields:包级别的注释,声明非null为字段的默认语义。

Spring Framework本身利用了这些注释,但它们也可以在任何基于Spring的Java项目中使用,以声明null安全API和可选的null安全字段。目前还不支持泛型类型参数、varargs和数组元素为null的能力,但应在即将发布的版本中提供,请参阅SPR-15942以获取最新信息。Nullability声明预计将在Spring Framework版本之间进行微调,包括次要版本。方法体内部使用的类型的可空性超出了此功能的范围。

大家好,我是Doker品牌的Sinbad,欢迎点赞和评论,您的鼓励是我们持续更新的动力!欢迎加微信进入技术群聊!