springboot核心注解示例详解

文章简介

本文主要介绍springboot框架学习和工作中常用的核心注解,对注解进行了清晰地分类,配以简易代码和易懂的解释,能够让你掌握每个核心注解的用法,并可以迁移到学习和工作中加以使用。本文注解偏向于实用性。

springboot一大特点在于约定大于配置,这使得该框架不需要繁杂的配置而简单易上手,集中体现在通过注解实现各种功能代替配置和冗余代码,因此掌握核心注解的用法,就相当于掌握该框架的基本使用。本文使用了用户/书本查询这一简单功能逻辑作为注解说明示例。

一、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注入容器中
  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值