赞
踩
基于 SpringBoot 平台开发的项目数不胜数,与常规的基于Spring开发的项目最大的不同之处,SpringBoot 里面提供了大量的注解用于快速开发,而且非常简单,基本可以做到开箱即用!
那 SpringBoot 为开发者提供了多少注解呢?我们该如何使用?
针对此问题,小编特意对其进行了一番整理,内容如下,个人感觉还是比较清晰的,今天我们就一起来整一整每个注解的含义和用法,以免踩坑!
2.1. SpringMVC 相关注解
通常用于修饰controller层的组件,由控制器负责将用户发来的URL请求转发到对应的服务接口,通常还需要配合注解@RequestMapping使用。
提供路由信息,负责URL到Controller中具体函数的映射,当用于方法上时,可以指定请求协议,比如GET、POST、PUT、DELETE等等。
表示请求体的Content-Type必须为application/json格式的数据,接收到数据之后会自动将数据绑定到Java对象上去
表示该方法的返回结果直接写入HTTP response body中,返回数据的格式为application/json。
比如,请求参数为json格式,返回参数也为json格式,示例代码如下:
/** * 登录服务 */ @Controller @RequestMapping("api") public class LoginController { /** * 登录请求,post请求协议,请求参数数据格式为json * @param request */ @RequestMapping(value = "login", method = RequestMethod.POST) @ResponseBody public ResponseEntity login(@RequestBody UserLoginDTO request){ //...业务处理 return new ResponseEntity(HttpStatus.OK); } }
和@Controller一样,用于标注控制层组件,不同的地方在于:它是@ResponseBody和@Controller的合集,也就是说,在当@RestController用在类上时,表示当前类里面所有对外暴露的接口方法,返回数据的格式都为application/json,示范代码如下:
@RestController @RequestMapping("api") public class LoginController { /** * 登录请求,post请求协议,请求参数数据格式为json * @param request */ @RequestMapping(value = "login", method = RequestMethod.POST) public ResponseEntity login(@RequestBody UserLoginDTO request){ //...业务处理 return new ResponseEntity(HttpStatus.OK); } }
用于接收请求参数为表单类型的数据,通常用在方法的参数前面,示范代码如下:
/** * 登录请求,post请求协议,请求参数数据格式为表单 */ @RequestMapping(value = "login", method = RequestMethod.POST) @ResponseBody public ResponseEntity login(@RequestParam(value = "userName",required = true) String userName, @RequestParam(value = "userPwd",required = true) String userPwd){ //...业务处理 return new ResponseEntity(HttpStatus.OK); }
用于获取请求路径中的参数,通常用于restful风格的api上,示范代码如下:
/** * restful风格的参数请求 * @param id */ @RequestMapping(value = "queryProduct/{id}", method = RequestMethod.POST) @ResponseBody public ResponseEntity queryProduct(@PathVariable("id") String id){ //...业务处理 return new ResponseEntity(HttpStatus.OK); }
除了@RequestMapping可以指定请求方式之外,还有一些其他的注解,可以用于标注接口路径请求,比如GetMapping用在方法上时,表示只支持get请求方法,等价于@RequestMapping(value="/get",method=RequestMethod.GET)。
@GetMapping("get") public ResponseEntity get(){ return new ResponseEntity(HttpStatus.OK); }
用在方法上,表示只支持post方式的请求。
@PostMapping("post") public ResponseEntity post(){ return new ResponseEntity(HttpStatus.OK); }
用在方法上,表示只支持put方式的请求,通常表示更新某些资源的意思。
@PutMapping("put") public ResponseEntity put(){ return new ResponseEntity(HttpStatus.OK); }
用在方法上,表示只支持delete方式的请求,通常表示删除某些资源的意思。
@DeleteMapping("delete") public ResponseEntity delete(){ return new ResponseEntity(HttpStatus.OK); }
2.2. bean 相关注解
通常用于修饰service层的组件,声明一个对象,会将类对象实例化并注入到bean容器里面。
@Service public class DeptService { //具体的方法 }
泛指组件,当组件不好归类的时候,可以使用这个注解进行标注,功能类似于于@Service。
@Component public class DeptService { //具体的方法 }
通常用于修饰dao层的组件,@Repository注解属于Spring里面最先引入的一批注解,它用于将数据访问层 (DAO层 ) 的类标识为Spring Bean,具体只需将该注解标注在 DAO类上即可,示例代码如下:
@Repository public interface RoleRepository extends JpaRepository<Role,Long> { //具体的方法 }
为什么现在使用的很少呢?
主要是因为当我们配置服务启动自动扫描dao层包时,Spring会自动帮我们创建一个实现类,然后注入到bean容器里面。当某些类无法被扫描到时,我们可以显式的在数据持久类上标注@Repository注解,Spring会自动帮我们声明对象。
相当于 xml 中配置 Bean,意思是产生一个 bean 对象,并交给spring管理,示例代码如下:
@Configuration public class AppConfig { //相当于 xml 中配置 Bean @Bean public Uploader initFileUploader() { return new FileUploader(); } }
自动导入依赖的bean对象,默认时按照byType方式导入对象,而且导入的对象必须存在,当需要导入的对象并不存在时,我们可以通过配置required = false来关闭强制验证。
@Autowired private DeptService deptService;
也是自动导入依赖的bean对象,由JDK提供,默认是按照byName方式导入依赖的对象;而@Autowired默认时按照byType方式导入对象,当然@Resource还可以配置成通过byType方式导入对象。
/** * 通过名称导入(默认通过名称导入依赖对象) */ @Resource(name = "deptService") private DeptService deptService; /** * 通过类型导入 */ @Resource(type = RoleRepository.class) private DeptService deptService;
当有多个同一类型的bean时,使用@Autowired导入会报错,提示当前对象并不是唯一,Spring不知道导入哪个依赖,这个时候,我们可以使用@Qualifier进行更细粒度的控制,选择其中一个候选者,一般于@Autowired搭配使用,示例如下:
@Autowired @Qualifier("deptService") private DeptService deptService;
用于生命一个spring bean的作用域,作用的范围一共有以下几种:
/** * 单例对象 */ @RestController @Scope("singleton") public class HelloController { }
2.3. JPA 相关注解
表明这是一个实体类,这两个注解一般一块使用,但是如果表名和实体类名相同的话,@Table可以省略。
表示该属性字段对应数据库表中的主键字段。
表示该属性字段对应的数据库表中的列名,如果字段名与列名相同,则可以省略。
表示主键的生成策略,有四个选项,分别如下:
用来定义一个生成主键的序列,它需要与@GeneratedValue联合使用才有效,以TB_ROLE表为例,对应的注解配置如下:
@Entity @Table(name = "TB_ROLE") @SequenceGenerator(name = "id_seq", sequenceName = "seq_repair",allocationSize = 1) public class Role implements Serializable { private static final long serialVersionUID = 1L; /** * 主键ID,采用【id_seq】序列函数自增长 */ @Id @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "id_seq") private Long id; /* 角色名称 */ @Column(nullable = false) private String roleName; /** * 角色类型 */ @Column(nullable = false) private String roleType; }
表示该属性并非与数据库表的字段进行映射,ORM 框架会将忽略该属性。
/** * 忽略该属性 */ @Column(nullable = false) @Transient private String lastTime;
用在某些属性上,可以实现懒加载的效果,也就是当用到这个字段的时候,才会装载这个属性,如果配置成fetch=FetchType.EAGER,表示即时加载,也是默认的加载方式!
/** * 延迟加载该属性 */ @Column(nullable = false) @Basic(fetch = FetchType.LAZY) private String roleType;
用于标注表与表之间关系的字段,通常与@OneToOne、@OneToMany搭配使用,例如如下:
@Entity @Table(name = "tb_login_log") public class LoginLog implements Serializable { /** * 查询登录的用户信息 */ @OneToOne @JoinColumn(name = "user_id") private User user; //...get、set }
这三个注解,相当于hibernate配置文件中的一对一,一对多,多对一配置,比如下面的客户地址表,通过客户 ID,实现客户信息的查询。
@Entity @Table(name="address") public class AddressEO implements java.io.Serializable { @ManyToOne(cascade = { CascadeType.ALL }) @JoinColumn(name="customer_id") private CustomerEO customer; //...get、set }
2.4. 配置相关注解
表示声明一个 Java 形式的配置类,Spring Boot 提倡基于 Java 的配置,相当于你之前在 xml 中配置 bean,比如声明一个配置类AppConfig,然后初始化一个Uploader对象。
@Configuration public class AppConfig { @Bean public Uploader initOSSUploader() { return new OSSUploader(); } }
@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置类,全部都加载到当前SpringBoot里,并创建对应配置类的Bean,并把该Bean实体交给IoC容器进行管理。
某些场景下,如果我们想要避开某些配置类的扫描(包括避开一些第三方jar包下面的配置,可以这样处理。
@Configuration @EnableAutoConfiguration(exclude = { org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class}) public class AppConfig { //具有业务方法 }
标注哪些路径下的类需要被Spring扫描,用于自动发现和装配一些Bean对象,默认配置是扫描当前文件夹下和子目录下的所有类,如果我们想指定扫描某些包路径,可以这样处理。
@ComponentScan(basePackages = {"com.xxx.a", "com.xxx.b", "com.xxx.c"})
等价于使用@Configuration、@EnableAutoConfiguration、@ComponentScan这三个注解,通常用于全局启动类上,示例如下:
@SpringBootApplication public class PropertyApplication { public static void main(String[] args) { SpringApplication.run(PropertyApplication.class, args); } }
把@SpringBootApplication换成@Configuration、@EnableAutoConfiguration、@ComponentScan这三个注解,一样可以启动成功,@SpringBootApplication只是将这三个注解进行了简化!
表示开启事务支持,等同于 xml 配置方式的:
@SpringBootApplication @EnableTransactionManagement` public class PropertyApplication { public static void main(String[] args) { SpringApplication.run(PropertyApplication.class, args); } }
从 Spring4 开始,可以通过@Conditional注解实现按条件装载bean对象,目前 Spring Boot 源码中大量扩展了@Condition注解,用于实现智能的自动化配置,满足各种使用场景。下面我给大家列举几个常用的注解:
具体的应用案例如下:
@Configuration public class ConditionalConfig { /** * 当AppConfig对象存在时,创建一个A对象 * @return */ @ConditionalOnBean(AppConfig.class) @Bean public A createA(){ return new A(); } /** * 当AppConfig对象不存在时,创建一个B对象 * @return */ @ConditionalOnMissingBean(AppConfig.class) @Bean public B createB(){ return new B(); } /** * 当KafkaTemplate类存在时,创建一个C对象 * @return */ @ConditionalOnClass(KafkaTemplate.class) @Bean public C createC(){ return new C(); } /** * 当KafkaTemplate类不存在时,创建一个D对象 * @return */ @ConditionalOnMissingClass(KafkaTemplate.class) @Bean public D createD(){ return new D(); } /** * 当enableConfig的配置为true,创建一个E对象 * @return */ @ConditionalOnExpression("${enableConfig:false}") @Bean public E createE(){ return new E(); } /** * 当filter.loginFilter的配置为true,创建一个F对象 * @return */ @ConditionalOnProperty(prefix = "filter",name = "loginFilter",havingValue = "true") @Bean public F createF(){ return new F(); } }
可以在任意 Spring 管理的 Bean 中通过这个注解获取任何来源配置的属性值,比如你在application.properties文件里,定义了一个参数变量!
config.name=zhangsan
在任意的bean容器里面,可以通过@Value注解注入参数,获取参数变量值。
@RestController public class HelloController { @Value("${config.name}") private String config; @GetMapping("config") public String config(){ return JSON.toJSONString(config); } }
上面@Value在每个类中获取属性配置值的做法,其实是不推荐的。
一般在企业项目开发中,不会使用那么杂乱无章的写法而且维护也麻烦,通常会一次性读取一个 Java 配置类,然后在需要使用的地方直接引用这个类就可以多次访问了,方便维护,示例如下:
首先,在application.properties文件里定义好参数变量。
config.name=demo_1 config.value=demo_value_1
然后,创建一个 Java 配置类,将参数变量注入即可!
@Component @ConfigurationProperties(prefix = "config") public class Config { public String name; public String value; //...get、set }
最后,在需要使用的地方,通过ioc注入Config对象即可!
这个注解是用来读取我们自定义的配置文件的,比如导入test.properties和bussiness.properties两个配置文件,用法如下:
@SpringBootApplication @PropertySource(value = {"test.properties","bussiness.properties"}) public class PropertyApplication { public static void main(String[] args) { SpringApplication.run(PropertyApplication.class, args); } }
用来加载 xml 配置文件,比如导入自定义的aaa.xml文件,用法如下:
@ImportResource(locations = "classpath:aaa.xml") @SpringBootApplication public class PropertyApplication { public static void main(String[] args) { SpringApplication.run(PropertyApplication.class, args); } }
2.5. 异常处理相关注解
通常组合使用,用于处理全局异常,示例代码如下:
@ControllerAdvice @Configuration @Slf4j public class GlobalExceptionConfig { private static final Integer GLOBAL_ERROR_CODE = 500; @ExceptionHandler(value = Exception.class) @ResponseBody public void exceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception e) throws Exception { log.error("【统一异常处理器】", e); ResultMsg<Object> resultMsg = new ResultMsg<>(); resultMsg.setCode(GLOBAL_ERROR_CODE); if (e instanceof CommonException) { CommonException ex = (CommonException) e; if(ex.getErrCode() != 0) { resultMsg.setCode(ex.getErrCode()); } resultMsg.setMsg(ex.getErrMsg()); }else { resultMsg.setMsg(CommonErrorMsg.SYSTEM_ERROR.getMessage()); } WebUtil.buildPrintWriter(response, resultMsg); } }
2.6. 测试相关注解
一般作用于测试类上, 用于声明生效的 Spring 配置文件,比如指定application-dev.properties配置文件。
一般作用于测试类上, 用于单元测试用,示例如下:
@ActiveProfiles("dev") @RunWith(SpringRunner.class) @SpringBootTest public class TestJunit { @Test public void executeTask() { //测试... } }
三、小结
整个篇幅内容比较多,比较干,大家在看的过程中,也没有必要去记住,可以先收藏起来,等到需要用到的时候,再把它拿出来看看!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。