Java SpringBoot

一、简介

基于 SpringBoot 平台开发的项目数不胜数,与常规的基于Spring开发的项目最大的不同之处,SpringBoot 里面提供了大量的注解用于快速开发,而且非常简单,基本可以做到开箱即用!
那 SpringBoot 为开发者提供了多少注解呢?该如何使用?这里进行了一番整理,内容如下:
SpringBoot注解最全详解 - 图1

二、注解总结

2.1、SpringMVC 相关注解

@Controller

通常用于修饰Controller层的组件,由控制器负责将用户发来的URL请求转发到对应的服务接口,通常还需要配合注解@RequestMapping使用。

@RequestMapping

提供路由信息,负责URL到Controller中具体函数的映射,当用于方法上时,可以指定请求协议,比如GET、POST、PUT、DELETE等等。

@RequestBody

表示请求体的Content-Type必须为application/json格式的数据,接收到数据之后会自动将数据绑定到Java对象上去

@ResponseBody

表示该方法的返回结果直接写入HTTP response body中,返回数据的格式为application/json
比如,请求参数为json格式,返回参数也为json格式,示例代码如下:

  1. /**
  2. * 登录服务
  3. */
  4. @Controller
  5. @RequestMapping("api")
  6. public class LoginController {
  7. /**
  8. * 登录请求,post请求协议,请求参数数据格式为json
  9. * @param request
  10. */
  11. @RequestMapping(value = "login", method = RequestMethod.POST)
  12. @ResponseBody
  13. public ResponseEntity login(@RequestBody UserLoginDTO request){
  14. //...业务处理
  15. return new ResponseEntity(HttpStatus.OK);
  16. }
  17. }

@RestController

@Controller一样,用于标注控制层组件,不同的地方在于:它是@ResponseBody@Controller的合集,也就是说,在当@RestController用在类上时,表示当前类里面所有对外暴露的接口方法,返回数据的格式都为application/json,示范代码如下:

  1. @RestController
  2. @RequestMapping("api")
  3. public class LoginController {
  4. /**
  5. * 登录请求,post请求协议,请求参数数据格式为json
  6. * @param request
  7. */
  8. @RequestMapping(value = "login", method = RequestMethod.POST)
  9. public ResponseEntity login(@RequestBody UserLoginDTO request){
  10. //...业务处理
  11. return new ResponseEntity(HttpStatus.OK);
  12. }
  13. }

@RequestParam

用于接收请求参数为表单类型的数据,通常用在方法的参数前面,示范代码如下:

  1. /**
  2. * 登录请求,post请求协议,请求参数数据格式为表单
  3. */
  4. @RequestMapping(value = "login", method = RequestMethod.POST)
  5. @ResponseBody
  6. public ResponseEntity login(@RequestParam(value = "userName",required = true) String userName,
  7. @RequestParam(value = "userPwd",required = true) String userPwd){
  8. //...业务处理
  9. return new ResponseEntity(HttpStatus.OK);
  10. }

@PathVariable

用于获取请求路径中的参数,通常用于restful风格的api上,示范代码如下:

  1. /**
  2. * restful风格的参数请求
  3. * @param id
  4. */
  5. @RequestMapping(value = "queryProduct/{id}", method = RequestMethod.POST)
  6. @ResponseBody
  7. public ResponseEntity queryProduct(@PathVariable("id") String id){
  8. //...业务处理
  9. return new ResponseEntity(HttpStatus.OK);
  10. }

@GetMapping

除了@RequestMapping可以指定请求方式之外,还有一些其他的注解,可以用于标注接口路径请求,比如GetMapping用在方法上时,表示只支持get请求方法,等价于@RequestMapping(value="/get",method=RequestMethod.GET)

  1. @GetMapping("get")
  2. public ResponseEntity get(){
  3. return new ResponseEntity(HttpStatus.OK);
  4. }

@PostMapping

用在方法上,表示只支持post方式的请求。

  1. @PostMapping("post")
  2. public ResponseEntity post(){
  3. return new ResponseEntity(HttpStatus.OK);
  4. }

@PutMapping

用在方法上,表示只支持put方式的请求,通常表示更新某些资源的意思

  1. @PutMapping("put")
  2. public ResponseEntity put(){
  3. return new ResponseEntity(HttpStatus.OK);
  4. }

@DeleteMapping

用在方法上,表示只支持delete方式的请求,通常表示删除某些资源的意思

  1. @DeleteMapping("delete")
  2. public ResponseEntity delete(){
  3. return new ResponseEntity(HttpStatus.OK);
  4. }

2.2、bean 相关注解

@Service

通常用于修饰service层的组件,声明一个对象,会将类对象实例化并注入到bean容器里面

  1. @Service
  2. public class DeptService {
  3. //具体的方法
  4. }

@Component

泛指组件,当组件不好归类的时候,可以使用这个注解进行标注,功能类似于于@Service

  1. @Component
  2. public class DeptService {
  3. //具体的方法
  4. }

@Repository

通常用于修饰dao层的组件,
@Repository注解属于Spring里面最先引入的一批注解,它用于将数据访问层 (DAO层 ) 的类标识为Spring Bean,具体只需将该注解标注在 DAO类上即可,示例代码如下:

  1. @Repository
  2. public interface RoleRepository extends JpaRepository<Role,Long> {
  3. //具体的方法
  4. }

为什么现在使用的很少呢?
主要是因为当配置服务启动自动扫描dao层包时,Spring会自动创建一个实现类,然后注入到bean容器里面。当某些类无法被扫描到时,可以显式的在数据持久类上标注@Repository注解,Spring会自动声明对象。

@Bean

相当于 xml 中配置 Bean,意思是产生一个 bean 对象,并交给spring管理,示例代码如下:

  1. @Configuration
  2. public class AppConfig {
  3. //相当于 xml 中配置 Bean
  4. @Bean
  5. public Uploader initFileUploader() {
  6. return new FileUploader();
  7. }
  8. }

@Autowired

自动导入依赖的bean对象,默认时按照byType方式导入对象,而且导入的对象必须存在,当需要导入的对象并不存在时,可以通过配置required = false来关闭强制验证。

  1. @Autowired
  2. private DeptService deptService;

@Resource

也是自动导入依赖的bean对象,由JDK提供,默认是按照byName方式导入依赖的对象;而@Autowired默认时按照byType方式导入对象,当然@Resource还可以配置成通过byType方式导入对象。

  1. /**
  2. * 通过名称导入(默认通过名称导入依赖对象)
  3. */
  4. @Resource(name = "deptService")
  5. private DeptService deptService;
  6. /**
  7. * 通过类型导入
  8. */
  9. @Resource(type = RoleRepository.class)
  10. private DeptService deptService;

@Qualifier

当有多个同一类型的bean时,使用@Autowired导入会报错,提示当前对象并不是唯一,Spring不知道导入哪个依赖,这个时候,可以使用@Qualifier进行更细粒度的控制,选择其中一个候选者,一般于@Autowired搭配使用,示例如下:

  1. @Autowired
  2. @Qualifier("deptService")
  3. private DeptService deptService;

@Scope

用于生命一个spring bean的作用域,作用的范围一共有以下几种:

  • singleton:唯一 bean 实例,Spring 中的 bean 默认都是单例的。
  • prototype:每次请求都会创建一个新的 bean 实例,对象多例。
  • request:每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
  • session:每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。 ```java /**
    • 单例对象 */ @RestController @Scope(“singleton”) public class HelloController {

}

  1. <a name="ZdkZZ"></a>
  2. ### 2.3、JPA 相关注解
  3. <a name="vz6Un"></a>
  4. #### `@Entity`和`@Table`
  5. 表明这是一个实体类,这两个注解一般一块使用,但是如果表名和实体类名相同的话,`@Table`可以省略。
  6. <a name="e8v08"></a>
  7. #### `@Id`
  8. 表示该属性字段对应数据库表中的主键字段。
  9. <a name="d6p7B"></a>
  10. #### `@Column`
  11. 表示该属性字段对应的数据库表中的列名,如果字段名与列名相同,则可以省略。
  12. <a name="H9Gmk"></a>
  13. #### `@GeneratedValue`
  14. 表示主键的生成策略,有四个选项,分别如下:
  15. - **AUTO:表示由程序控制,是默认选项 ,不设置就是这个**
  16. - **IDENTITY:表示由数据库生成,采用数据库自增长,Oracle 不支持这种方式**
  17. - **SEQUENCE:表示通过数据库的序列生成主键ID,MYSQL 不支持**
  18. - **Table:表示由特定的数据库产生主键,该方式有利于数据库的移植**
  19. <a name="zkPIh"></a>
  20. #### `@SequenceGeneretor`
  21. 用来定义一个生成主键的序列,它需要与`@GeneratedValue`联合使用才有效,以`TB_ROLE`表为例,对应的注解配置如下:
  22. ```java
  23. @Entity
  24. @Table(name = "TB_ROLE")
  25. @SequenceGenerator(name = "id_seq", sequenceName = "seq_repair",allocationSize = 1)
  26. public class Role implements Serializable {
  27. private static final long serialVersionUID = 1L;
  28. /**
  29. * 主键ID,采用【id_seq】序列函数自增长
  30. */
  31. @Id
  32. @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "id_seq")
  33. private Long id;
  34. /* 角色名称
  35. */
  36. @Column(nullable = false)
  37. private String roleName;
  38. /**
  39. * 角色类型
  40. */
  41. @Column(nullable = false)
  42. private String roleType;
  43. }

@Transient

表示该属性并非与数据库表的字段进行映射,ORM 框架会将忽略该属性。

  1. /**
  2. * 忽略该属性
  3. */
  4. @Column(nullable = false)
  5. @Transient
  6. private String lastTime;

@Basic(fetch=FetchType.LAZY)

用在某些属性上,可以实现懒加载的效果,也就是当用到这个字段的时候,才会装载这个属性,如果配置成fetch=FetchType.EAGER,表示即时加载,也是默认的加载方式!

  1. /**
  2. * 延迟加载该属性
  3. */
  4. @Column(nullable = false)
  5. @Basic(fetch = FetchType.LAZY)
  6. private String roleType;

@JoinColumn

用于标注表与表之间关系的字段,通常与@OneToOne@OneToMany搭配使用,例如如下

  1. @Entity
  2. @Table(name = "tb_login_log")
  3. public class LoginLog implements Serializable {
  4. /**
  5. * 查询登录的用户信息
  6. */
  7. @OneToOne
  8. @JoinColumn(name = "user_id")
  9. private User user;
  10. //...get、set
  11. }

@OneToOne@OneToMany@ManyToOne

这三个注解,相当于hibernate配置文件中的一对一,一对多,多对一配置,比如下面的客户地址表,通过客户 ID,实现客户信息的查询。

  1. @Entity
  2. @Table(name="address")
  3. public class AddressEO implements java.io.Serializable {
  4. @ManyToOne(cascade = { CascadeType.ALL })
  5. @JoinColumn(name="customer_id")
  6. private CustomerEO customer;
  7. //...get、set
  8. }

2.4、配置相关注解

@Configuration

表示声明一个 Java 形式的配置类,Spring Boot 提倡基于 Java 的配置,相当于之前在 xml 中配置 bean,比如声明一个配置类AppConfig,然后初始化一个Uploader对象。

  1. @Configuration
  2. public class AppConfig {
  3. @Bean
  4. public Uploader initOSSUploader() {
  5. return new OSSUploader();
  6. }
  7. }

@EnableAutoConfiguration

@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置类,全部都加载到当前SpringBoot里,并创建对应配置类的Bean,并把该Bean实体交给IoC容器进行管理。
某些场景下,如果想要避开某些配置类的扫描(包括避开一些第三方jar包下面的配置,可以这样处理。

  1. @Configuration
  2. @EnableAutoConfiguration(exclude = { org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class})
  3. public class AppConfig {
  4. //具有业务方法
  5. }

@ComponentScan

标注哪些路径下的类需要被Spring扫描,用于自动发现和装配一些Bean对象,默认配置是扫描当前文件夹下和子目录下的所有类,如果想指定扫描某些包路径,可以这样处理。

  1. @ComponentScan(basePackages = {"com.xxx.a", "com.xxx.b", "com.xxx.c"})

@SpringBootApplication

等价于使用@Configuration@EnableAutoConfiguration@ComponentScan这三个注解,通常用于全局启动类上,示例如下:

  1. @SpringBootApplication
  2. public class PropertyApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(PropertyApplication.class, args);
  5. }
  6. }

@SpringBootApplication换成@Configuration@EnableAutoConfiguration@ComponentScan这三个注解,一样可以启动成功,@SpringBootApplication只是将这三个注解进行了简化!

@EnableTransactionManagement

表示开启事务支持,等同于 xml 配置方式的<tx:annotation-driven />

  1. @SpringBootApplication
  2. @EnableTransactionManagement`
  3. public class PropertyApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(PropertyApplication.class, args);
  6. }
  7. }

@Conditional

从 Spring4 开始,可以通过@Conditional注解实现按条件装载bean对象,目前 Spring Boot 源码中大量扩展了@Condition注解,用于实现智能的自动化配置,满足各种使用场景。下面列举几个常用的注解:

  • **@ConditionalOnBean**:当某个特定的**Bean**存在时,配置生效
  • **@ConditionalOnMissingBean**:当某个特定的**Bean**不存在时,配置生效
  • **@ConditionalOnClass**:当**Classpath**里存在指定的类,配置生效
  • **@ConditionalOnMissingClass**:当**Classpath**里不存在指定的类,配置生效
  • **@ConditionalOnExpression**:当给定的**SpEL**表达式计算结果为**true**,配置生效
  • **@ConditionalOnProperty**:当指定的配置属性有一个明确的值并匹配,配置生效

具体的应用案例如下:

  1. @Configuration
  2. public class ConditionalConfig {
  3. /**
  4. * 当AppConfig对象存在时,创建一个A对象
  5. * @return
  6. */
  7. @ConditionalOnBean(AppConfig.class)
  8. @Bean
  9. public A createA(){
  10. return new A();
  11. }
  12. /**
  13. * 当AppConfig对象不存在时,创建一个B对象
  14. * @return
  15. */
  16. @ConditionalOnMissingBean(AppConfig.class)
  17. @Bean
  18. public B createB(){
  19. return new B();
  20. }
  21. /**
  22. * 当KafkaTemplate类存在时,创建一个C对象
  23. * @return
  24. */
  25. @ConditionalOnClass(KafkaTemplate.class)
  26. @Bean
  27. public C createC(){
  28. return new C();
  29. }
  30. /**
  31. * 当KafkaTemplate类不存在时,创建一个D对象
  32. * @return
  33. */
  34. @ConditionalOnMissingClass(KafkaTemplate.class)
  35. @Bean
  36. public D createD(){
  37. return new D();
  38. }
  39. /**
  40. * 当enableConfig的配置为true,创建一个E对象
  41. * @return
  42. */
  43. @ConditionalOnExpression("${enableConfig:false}")
  44. @Bean
  45. public E createE(){
  46. return new E();
  47. }
  48. /**
  49. * 当filter.loginFilter的配置为true,创建一个F对象
  50. * @return
  51. */
  52. @ConditionalOnProperty(prefix = "filter",name = "loginFilter",havingValue = "true")
  53. @Bean
  54. public F createF(){
  55. return new F();
  56. }
  57. }

@Value

可以在任意 Spring 管理的 Bean 中通过这个注解获取任何来源配置的属性值,比如在application.properties文件里,定义了一个参数变量!

  1. config.name=zhangsan

在任意的bean容器里面,可以通过@Value注解注入参数,获取参数变量值。

  1. @RestController
  2. public class HelloController {
  3. @Value("${config.name}")
  4. private String config;
  5. @GetMapping("config")
  6. public String config(){
  7. return JSON.toJSONString(config);
  8. }
  9. }

@ConfigurationProperties

上面@Value在每个类中获取属性配置值的做法,其实是不推荐的。
一般在企业项目开发中,不会使用那么杂乱无章的写法而且维护也麻烦,通常会一次性读取一个 Java 配置类,然后在需要使用的地方直接引用这个类就可以多次访问了,方便维护,示例如下:
首先,在application.properties文件里定义好参数变量。

  1. config.name=demo_1
  2. config.value=demo_value_1

然后,创建一个 Java 配置类,将参数变量注入即可!

  1. @Component
  2. @ConfigurationProperties(prefix = "config")
  3. public class Config {
  4. public String name;
  5. public String value;
  6. //...get、set
  7. }

最后,在需要使用的地方,通过ioc注入Config对象即可!

@PropertySource

这个注解是用来读取自定义的配置文件的,比如导入test.properties和bussiness.properties两个配置文件,用法如下:

  1. @SpringBootApplication
  2. @PropertySource(value = {"test.properties","bussiness.properties"})
  3. public class PropertyApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(PropertyApplication.class, args);
  6. }
  7. }

@ImportResource

用来加载 xml 配置文件,比如导入自定义的aaa.xml文件,用法如下:

  1. @ImportResource(locations = "classpath:aaa.xml")
  2. @SpringBootApplication
  3. public class PropertyApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(PropertyApplication.class, args);
  6. }
  7. }

2.5、异常处理相关注解

@ControllerAdvice@ExceptionHandler

通常组合使用,用于处理全局异常,示例代码如下:

  1. @ControllerAdvice
  2. @Configuration
  3. @Slf4j
  4. public class GlobalExceptionConfig {
  5. private static final Integer GLOBAL_ERROR_CODE = 500;
  6. @ExceptionHandler(value = Exception.class)
  7. @ResponseBody
  8. public void exceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception e) throws Exception {
  9. log.error("【统一异常处理器】", e);
  10. ResultMsg<Object> resultMsg = new ResultMsg<>();
  11. resultMsg.setCode(GLOBAL_ERROR_CODE);
  12. if (e instanceof CommonException) {
  13. CommonException ex = (CommonException) e;
  14. if(ex.getErrCode() != 0) {
  15. resultMsg.setCode(ex.getErrCode());
  16. }
  17. resultMsg.setMsg(ex.getErrMsg());
  18. }else {
  19. resultMsg.setMsg(CommonErrorMsg.SYSTEM_ERROR.getMessage());
  20. }
  21. WebUtil.buildPrintWriter(response, resultMsg);
  22. }
  23. }

2.6、测试相关注解

@ActiveProfiles

一般作用于测试类上, 用于声明生效的 Spring 配置文件,比如指定application-dev.properties配置文件。

@RunWith@SpringBootTest

一般作用于测试类上, 用于单元测试用,示例如下:

  1. @ActiveProfiles("dev")
  2. @RunWith(SpringRunner.class)
  3. @SpringBootTest
  4. public class TestJunit {
  5. @Test
  6. public void executeTask() {
  7. //测试...
  8. }
  9. }