文章简介
本文主要介绍springboot框架学习和工作中常用的核心注解,对注解进行了清晰地分类,配以简易代码和易懂的解释,能够让你掌握每个核心注解的用法,并可以迁移到学习和工作中加以使用。本文注解偏向于实用性。
springboot一大特点在于约定大于配置,这使得该框架不需要繁杂的配置而简单易上手,集中体现在通过注解实现各种功能代替配置和冗余代码,因此掌握核心注解的用法,就相当于掌握该框架的基本使用。本文使用了用户/书本查询这一简单功能逻辑作为注解说明示例。
文章目录
- 一、Http请求/SpringMVC注解
- @RequestMapping、@GetMapping、@PostMapping、@PutMapping、@DeleteMapping
- 二、参数传递类注解
- 1.@RequestParam
- 2.@PathVariable
- 3.@RequestBody
- 4.@ResponseBody
- 三、Bean处理注解
- @Autowired、@Qualifier、@Resource
- 四、配置读取
- @Value
- @ConfigurationProperties + @ProperySource
- 五、参数校验注解
- @Valid 、@Validated、@NotEmpty等
- 六、统一异常处理注解
- @ControllerAdvice、@ExceptionHandler、@ResponseStatus
- 七、JSON相关注解
- @JsonProperty
- @JsonInclude
- @JsonIgnore
- @JsonIgnoreProperties
- 八、其他核心注解
- @SpringBootApplication
- 九、注解快速一览回顾
一、Http请求/SpringMVC注解
@RequestMapping、@GetMapping、@PostMapping、@PutMapping、@DeleteMapping
注解 | 说明 |
---|---|
@RequestMapping | 将Web请求与请求处理类中的方法进行映射,常用配置属性有value和method,分别指代映射的请求URL和HTTP的方法名 |
@GetMapping | 用于处理HTTP GET请求,等同于@RequestMapping(method=RequestMethod.GET) |
@PostMapping | 用于处理HTTP POST请求等同于@RequestMapping(method=RequestMethod.POST) |
@PutMapping | 用于处理HTTP PUT请求 等同于@RequestMapping(method=RequestMethod.PUT) |
@DeleteMapping | 用于处理HTTP DELETE请求等同于@RequestMapping(method=RequestMethod.DELETE) |
使用示例:
@RequestMapping
@RequestMapping(value = "/get_name", method = RequestMethod.GET)
public ResponseEntity<String> getUserName() {
return ResponseEntity.status(HttpStatus.OK).body("zhangsan");
}
@GetMapping
@GetMapping(value = "/get_name")
public ResponseEntity<String> getUserName() {
return ResponseEntity.status(HttpStatus.OK).body("zhangsan");
}
以上请求的URL和结果均如下所示:
————————————————————————————————————
————————————————————————————————————
小结:从以上可以看到,@RequestMapping通过配置method属性,可以与其余四类等价使用。
二、参数传递类注解
注解 | 说明 |
---|---|
@RequestParam | 用于将方法的参数与Web请求的传递的参数进行绑定 |
@PathVariable | 将方法中的参数绑定到请求URI中的模板变量上 |
@RequestBody | 在处理请求方法的参数列表中使用,它可以将请求主体中的参数绑定到一个对象中 |
@ResponseBody | 自动将控制器中方法的返回值写入到HTTP响应中。一般是将java对象转为json格式的数据,然后直接写入HTTP response 的body中 |
1.@RequestParam
用于将方法的参数与Web请求的传递的参数进行绑定
@RequestMapping(value = "/get_id", method = RequestMethod.GET)
public ResponseEntity<User> getUserById(@RequestParam(value = "id") String userId) {
User user = new User();
user.setId(Integer.valueOf(userId));
return ResponseEntity.status(HttpStatus.OK).body(user);
}
对应前端的URL请求为
http://localhost:8081/get_id?id=1
故该注解从前端请求的URL中获取查询参数的值,并作为传参赋给userId。
2.@PathVariable
将方法中的参数绑定到请求URI中的模板变量上
@RequestMapping(value = "/get_id/{id}", method = RequestMethod.GET)
public ResponseEntity<User> getUserByPathId(@PathVariable("id") String userId) {
User user = new User();
user.setId(Integer.valueOf(userId));
return ResponseEntity.status(HttpStatus.OK).body(user);
}
对应前端的URL请求为
http://localhost:8081/get_id/1
故该注解从前端请求的URL中的路径中获取属性名为id的值,并作为传参赋给userId。
3.@RequestBody
在处理请求方法的参数列表中使用,它可以将请求主体中的参数绑定到一个对象中
@RequestMapping(value = "/get_user", method = RequestMethod.POST)
public ResponseEntity<User> getUser(@RequestBody User user) {
return ResponseEntity.status(HttpStatus.OK).body(user);
}
对应前端的body体内容为
————————————————————————————————————
————————————————————————————————————
故该注解可以从前端请求的BODY体中将参数与注解作用处的User对象相绑定。
4.@ResponseBody
自动将控制器中方法的返回值写入到HTTP响应中。一般是将java对象转为json格式的数据,然后直接写入HTTP response 的body中
@Controller
@ResponseBody
public class UserController {
@RequestMapping(value = "/get_id", method = RequestMethod.GET)
public ResponseEntity<User> getUserById(@RequestParam(value = "id") String userId) {
User user = new User();
user.setId(Integer.valueOf(userId));
return ResponseEntity.status(HttpStatus.OK).body(user);
}
}
前端请求后,得到的返回体如下,是一个user对象的JSON体。
————————————————————————————————————
————————————————————————————————————
三、Bean处理注解
注解 | 说明 |
---|---|
@Autowired | 它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。不适用于一个接口多个实现类的情形,可以通过配合@Qualifier 解决该问题。 |
@Qualifier | 用于配合@Autowired注解来指定要注入的具体 Bean 。使用场景:一般是一个接口有多个实现类,这时需要指定使用哪个实现类,如不指明则spring容器会因为不知道装配哪个而报错。 |
@Resource | 既可以根据类型注入,也可以根据名称注入。写了name属性,就根据名称注入,不写就根据类型注入。 写name属性的情况等价于@Autowired+@Qualifier。bean的名称,一般如果我们不手动给,就会使用类名,首字母小写作为bean的名称。 |
@Controller | 对应 Spring MVC 控制层,一般标注在Controller层的类上 |
@RestController | 继承于 @Controller,标注后整个类所有方法将直接返回 JSON 数据,相当于@Controller + @ResponseBody |
@Service | 对应服务层,主要涉及一些复杂的逻辑 |
@Repository | 对应持久层即 Dao 层,主要用于数据库相关操作 |
@Component | 普通pojo注入spring容器。通用的注解,可标注任意类为 Spring 组件 |
@Configuration | 标注是 Java 代码的配置类 |
@Autowired、@Qualifier、@Resource
@Autowired是最常用的自动注入注解,使用示例:
@Autowired
private IUserService userService;
需要注意的是,以上适用于一个接口含一个实现类的情形。如果有两个实现类,例如UserServiceImpl1和UserServiceImpl2,同时实现了IUserService接口,就会编译报错,提升如下:
解决该办法有两种,以下等价:
1.@Autowired配合@Qualifier注解使用,并在@Qualifier的value属性填上具体实现类的类名,并将首字母改为小写。这样调用的就是UserServiceImpl1实现类中的方法。
@Autowired
@Qualifier(value = "userServiceImpl1")
private IUserService userService;
2.使用@Resource来声明
@Resource(name = "userServiceImpl1")
private IUserService userService;
除了上述3个注解,其他Bean注解都是标注在类上,用于被Spring容器管理,整体功能一样,故不再展开,只需要注意对应注解标记在对应层的类上即可,这样更加规范清晰。
例如@Service注解,标注在service层的类上:
@Service
public class UserServiceImpl1 implements IUserService{
@Override
public User getUser(String userId) {
User user = new User();
user.setId(Integer.valueOf(userId));
return user;
}
}
四、配置读取
注解 | 说明 |
---|---|
@Value | 可以在任意 Spring 管理的 Bean 中通过这个注解获取任何来源配置的属性值。用于获取bean的属性,一般用于读取配置文件的数据,作用在变量上 |
@ConfigurationProperties | 用于注入Bean属性,然后再通过当前Bean获取注入值,作用在类上 。相对于@Value逐个属性获取,可以通过该注解获取一系列属性值 |
@ProperySource | 用来指定读取我们自定义的配置文件 |
使用示例:
@Value
配置文件application.yaml中配置参数-环境变量
book:
id: 12
name: "World"
代码中使用注解并采用${变量}的形式来获取配置文件中的变量,以下为Controller层代码。
@Value("${book.name}")
private String bookName;
@RequestMapping(value = "/book", method = RequestMethod.GET)
public ResponseEntity<String> getBookName(){
return ResponseEntity.status(HttpStatus.OK).body(bookName);
}
以上代码请求最终返回的结果为:“World”
@ConfigurationProperties + @ProperySource
配置文件application.yaml中配置参数,可以看到以book为前缀的变量有一系列,如果使用@Value会导致繁琐,此时可以考虑用以下方式。此处同时演示含多级属性的情况。
book:
id: "12"
name: "World"
address: "Shanghai"
page: "54"
size: "20X20"
publish:
date: "2024.3.30"
name: "zhangsan"
新建一个配置类,用于获取配置文件中的属性值。这里我们在注解@ConfigurationProperties的prefix标注变量的共同前缀book,在@PropertySource声明我们的配置文件名。在类中的属性名面要跟环境变量名保持一致。有多级属性则使用静态内部类的形式声明变量。
@Component
@ConfigurationProperties(prefix = "book", ignoreUnknownFields = false)
@PropertySource(value = {"classpath:application.yaml"})
@Data
public class BookConfiguration {
private String id;
private String name;
private String address;
private String page;
private String size;
private Publish publish;
@Data
public static class Publish {
private String date;
private String name;
}
}
Controller层代码:
@Autowired
private BookConfiguration bookConfiguration;
@RequestMapping(value = "/book", method = RequestMethod.GET)
public ResponseEntity<String> getBookPublishName(){
return ResponseEntity.status(HttpStatus.OK).body(bookConfiguration.getPublish().getName());
}
以上返回结果为:“zhangsan”
说明:上面出现的@Data注解为lombok框架注解,如未接触过,可以简单理解为该注解代替了bean的所有get/set和构造方法。
五、参数校验注解
注解 | 说明 |
---|---|
@Valid | 可以实现数据的验证,在实体类属性上添加校验规则,从而开启校验功能 |
@Validated | 标记在类上,告诉 Spring 去校验方法参数,校验规则可以通过配合以下注解使用 |
@NotEmpty | 被注释的字符串的不能为 null 也不能为空 |
@NotBlank | 被注释的字符串非 null,并且必须包含一个非空白字符 |
@Null | 被注释的元素必须为 null |
@NotNull | 被注释的元素必须不为 null |
@Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@Valid 、@Validated、@NotEmpty等
实体类如下,我们在id和name上标注这两个属性不能为空:
@Data
public class Book {
@NotBlank
private String id;
@NotBlank
private String name;
private String publishName;
private String publishDate;
}
Controller层代码,在传参处增加@Valid注解,实现校验。如果此处使用@Validated注解,结果也是一样的。
@RequestMapping(value = "/book", method = RequestMethod.POST)
public ResponseEntity<Book> getBookInfo(@Valid @RequestBody Book book) {
log.info("book publish name is: " + book.getPublishName());
return ResponseEntity.status(HttpStatus.OK).body(book);
}
模拟前端请求,传入body体如下
{
"id":"12",
"name":"",
"publish_name":null,
"publish_date":null
}
请求后,后端发生报错,提示name不能为空,符合校验预期
javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint 'javax.validation.constraints.NotBlank' validating type 'java.lang.String'.
@Validated还可以标注在类上,以下通过正则校验来检查前端传入的bookId是否符合规则。
@RestController
@Validated
public class TestController {
@RequestMapping(value = "/book/{bookId}", method = RequestMethod.GET)
public ResponseEntity<String> getBook(@Pattern(regexp = "^[0-9]{2}$", message = "书本编号不正确") @PathVariable("bookId") String bookId) {
return ResponseEntity.status(HttpStatus.OK).body(bookId);
}
}
前端请求“/book/123”时,后端报错,符合预期,因为我们id限制为2位数。报错如下
javax.validation.ConstraintViolationException: getBook.bookId: 书本编号不正确
@Valid与@Validated的区别:
1.@Validated是对@Valid的拓展,相对于@Valid来说,提供了分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制。
2.在Controller中校验方法参数时,使用@Valid和@Validated并无特殊差异(若不需要分组校验的话)
3.@Validated注解可以用于类级别,用于支持Spring进行方法级别的参数校验。@Valid可以用在属性级别约束,用来表示级联校验。
4.@Validated只能用在类、方法和参数上,而@Valid可用于方法、字段、构造器和参数上
其他注解如@NotBlank 、@NotNull 、@Min(value)、@Max(value)使用规则与上面@NotEmpty相似,不再赘述。
六、统一异常处理注解
注解 | 说明 |
---|---|
@ControllerAdvice | 定义全局异常处理类 |
@ExceptionHandler | 声明异常处理方法,表示遇到这个异常,就执行标注的方法 |
@ResponseStatus | 通过在自定义的异常类上使用@ResponseStatus注解来设置HTTP状态 |
@RestControlAdvice | 等同于@ControllerAdvice + @ResponseBody |
@ControllerAdvice、@ExceptionHandler、@ResponseStatus
注解使用示例如下,一般我们会建一个GlobalExceptionHandler类,用于捕获全局异常,即所有异常都可以走到该类中,并在处理后返回一个统一的异常格式给前端。
@ControllerAdvice用于声明者是一个全局异常处理类。
@ExceptionHandler则相当于一个筛选器,内部定义相关异常类,当程序抛出对应异常时,就会进入该方法中。
@ResponseStatus则是用于自定义设置要返回的HTTP状态。
例如此处我们自定义了一个校验类异常,并且返回的是BAD_REQUEST状态给前端。
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
@ExceptionHandler(DateValidationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Exception handleBindException(DateValidationException e) {
// 对异常e进行解析,
return xxx;
}
}
这里仅对注解做简洁说明。后续将会专门做一期全局统一异常处理的代码逻辑演示,这样我们的所有异常情况就可以得到完整封装,不会将一些敏感信息或堆栈直接返回给前端。
七、JSON相关注解
注解 | 说明 |
---|---|
@JsonProperty | 作用在属性上,用于起别名,自定义 JSON 属性名称,以及在序列化和反序列化过程中控制属性的包含。通过使用这个注解,可以确保 JSON 数据与 Java 对象之间正确映射。 |
@JsonInclude | 注解用于指定仅在某些条件下才包含属性。例如,您可以要求仅在属性具有非空值时才包含它。 |
@JsonIgnore | 注解用于在序列化和反序列化过程中忽略某个属性。这在处理敏感数据或不需要序列化的字段时非常有用。 |
@JsonIgnoreProperties | 注解用于在类级别忽略一个或多个属性。这对于在处理来自外部系统的 JSON 数据时忽略未知属性很有用。 |
@JsonProperty
作用在属性上,用于起别名,自定义 JSON 属性名称,以及在序列化和反序列化过程中控制属性的包含。通过使用这个注解,可以确保 JSON 数据与 Java 对象之间正确映射。
这个注解很好地解决了前端传参与后端参数直接的映射,因为前端JSON中的属性一般使用下划线,而后端使用驼峰来表示一个变量。
实体类代码:
@Data
public class Book {
private String id;
private String name;
@JsonProperty("publish_name")
private String publishName;
@JsonProperty("publish_date")
private String publishDate;
}
Controller层代码:
@RequestMapping(value = "/book", method = RequestMethod.POST)
public ResponseEntity<Book> getBookInfo(@RequestBody Book book) {
log.info("book publish name is: " + book.getPublishName());
return ResponseEntity.status(HttpStatus.OK).body(book);
}
前端请求示例,前端在body体中塞入数据:
最后日志打印 book publish name is: zhangsan,说明后端成功获取到前端所传入的数据。如果没有@JsonProperty(“publish_name”)注解,那么打印结果为 book publish name is: null,说明后端不识别前端传入的publish_name变量。
@JsonInclude
注解用于指定仅在某些条件下才包含属性。例如,您可以要求仅在属性具有非空值时才包含它。在上面代码的基础上,增加注解@JsonInclude(JsonInclude.Include.NON_NULL),其他代码不动,继续运行测试。
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Book {
private String id;
private String name;
@JsonProperty("publish_name")
private String publishName;
@JsonProperty("publish_date")
private String publishDate;
}
经过Controller层代码的处理,返回Book实体类时受到@JsonInclude(JsonInclude.Include.NON_NULL)的影响,空值不会返回给前端。因此前端收到的数据为:
{
"id": "12",
"name": "World"
}
@JsonIgnore
注解用于在序列化和反序列化过程中忽略某个属性。这在处理敏感数据或不需要序列化的字段时非常有用。
当前端要求返回json格式的数据,后端在转化数据成json格式时,发现实体类属性上贴有@JsonIgnore ,则不转化,且该属性的值不会传递给前端。
继续基于上述的代码做测试,在name属性上加上该注解
@JsonIgnore
private String name;
那么返回结果为:
{
"id": "12"
}
@JsonIgnoreProperties
跟上一个注解一样,不过可以一次性标注多个属性不序列化。注解用于在类级别忽略一个或多个属性。这对于在处理来自外部系统的 JSON 数据时忽略未知属性很有用。
继续基于上述的代码做测试,在实体类上加上该注解
@JsonIgnoreProperties({"name", "publish_name", "publish_date"})
public class Book {
// ..
}
返回结果仅剩下一个id属性,其余三个属性不返回。
{
"id": "12"
}
八、其他核心注解
注解 | 说明 |
---|---|
@SpringBootApplication | = @Configuration + @EnableAutoConfiguration + @ComponentScan |
@ComponentScan | 用来自动扫描被这些注解标识的类,最终生成ioc容器里的bean,默认扫描范围是@ComponentScan注解所在配置类包及子包的类 |
@SpringBootConfiguration | 与@Configuration作用相同,都是用来声明当前类是一个配置类,这里表明是springboot主类使用的配置类 |
@EnableAutoConfiguration | 是springboot实现自动化配置的核心注解,通过这个注解把spring应用所需的bean注入容器中 |
@SpringBootApplication
我们经常可以在项目的启动方法中看到该注解
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
后续如果还有其他遗漏的重要注解,会在这里补充。
觉得文章有帮助可以点个赞或者关注支持一下哟~
九、注解快速一览回顾
注解 | 说明 |
---|---|
@RequestMapping | 将Web请求与请求处理类中的方法进行映射,常用配置属性有value和method,分别指代映射的请求URL和HTTP的方法名 |
@GetMapping | 用于处理HTTP GET请求,等同于@RequestMapping(method=RequestMethod.GET) |
@PostMapping | 用于处理HTTP POST请求等同于@RequestMapping(method=RequestMethod.POST) |
@PutMapping | 用于处理HTTP PUT请求 等同于@RequestMapping(method=RequestMethod.PUT) |
@DeleteMapping | 用于处理HTTP DELETE请求等同于@RequestMapping(method=RequestMethod.DELETE) |
注解 | 说明 |
---|---|
@RequestParam | 用于将方法的参数与Web请求的传递的参数进行绑定 |
@PathVariable | 将方法中的参数绑定到请求URI中的模板变量上 |
@RequestBody | 在处理请求方法的参数列表中使用,它可以将请求主体中的参数绑定到一个对象中 |
@ResponseBody | 自动将控制器中方法的返回值写入到HTTP响应中。一般是将java对象转为json格式的数据,然后直接写入HTTP response 的body中 |
注解 | 说明 |
---|---|
@Autowired | 它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。不适用于一个接口多个实现类的情形,可以通过配合@Qualifier 解决该问题。 |
@Qualifier | 用于配合@Autowired注解来指定要注入的具体 Bean 。使用场景:一般是一个接口有多个实现类,这时需要指定使用哪个实现类,如不指明则spring容器会因为不知道装配哪个而报错。 |
@Resource | 既可以根据类型注入,也可以根据名称注入。写了name属性,就根据名称注入,不写就根据类型注入。 写name属性的情况等价于@Autowired+@Qualifier。bean的名称,一般如果我们不手动给,就会使用类名,首字母小写作为bean的名称。 |
@Controller | 对应 Spring MVC 控制层,一般标注在Controller层的类上 |
@RestController | 继承于 @Controller,标注后整个类所有方法将直接返回 JSON 数据,相当于@Controller + @ResponseBody |
@Service | 对应服务层,主要涉及一些复杂的逻辑 |
@Repository | 对应持久层即 Dao 层,主要用于数据库相关操作 |
@Component | 普通pojo注入spring容器。通用的注解,可标注任意类为 Spring 组件 |
@Configuration | 标注是 Java 代码的配置类 |
注解 | 说明 |
---|---|
@Validated | 标记在类上,告诉 Spring 去校验方法参数,校验规则可以通过配合以下注解使用 |
@NotEmpty | 被注释的字符串的不能为 null 也不能为空 |
@NotBlank | 被注释的字符串非 null,并且必须包含一个非空白字符 |
@Null | 被注释的元素必须为 null |
@NotNull | 被注释的元素必须不为 null |
@Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
注解 | 说明 |
---|---|
@Value | 可以在任意 Spring 管理的 Bean 中通过这个注解获取任何来源配置的属性值。用于获取bean的属性,一般用于读取配置文件的数据,作用在变量上 |
@ConfigurationProperties | 用于注入Bean属性,然后再通过当前Bean获取注入值,作用在类上 。相对于@Value逐个属性获取,可以通过该注解获取一系列属性值 |
@ProperySource | 用来指定读取我们自定义的配置文件 |
注解 | 说明 |
---|---|
@ControllerAdvice | 定义全局异常处理类 |
@ExceptionHandler | 声明异常处理方法,表示遇到这个异常,就执行标注的方法 |
@ResponseStatus | 通过在自定义的异常类上使用@ResponseStatus注解来设置HTTP状态 |
注解 | 说明 |
---|---|
@JsonProperty | 作用在属性上,用于起别名,自定义 JSON 属性名称,以及在序列化和反序列化过程中控制属性的包含。通过使用这个注解,可以确保 JSON 数据与 Java 对象之间正确映射。 |
@JsonInclude | 注解用于指定仅在某些条件下才包含属性。例如,您可以要求仅在属性具有非空值时才包含它。 |
@JsonIgnore | 注解用于在序列化和反序列化过程中忽略某个属性。这在处理敏感数据或不需要序列化的字段时非常有用。 |
@JsonIgnoreProperties | 注解用于在类级别忽略一个或多个属性。这对于在处理来自外部系统的 JSON 数据时忽略未知属性很有用。 |
注解 | 说明 |
---|---|
@SpringBootApplication | = @Configuration + @EnableAutoConfiguration + @ComponentScan |
@ComponentScan | 用来自动扫描被这些注解标识的类,最终生成ioc容器里的bean,默认扫描范围是@ComponentScan注解所在配置类包及子包的类 |
@SpringBootConfiguration | 与@Configuration作用相同,都是用来声明当前类是一个配置类,这里表明是springboot主类使用的配置类 |
@EnableAutoConfiguration | 是springboot实现自动化配置的核心注解,通过这个注解把spring应用所需的bean注入容器中 |