Spring Boot 注解

1. @RestController@Controller

都用来表示 Spring 某个类是否可以接收HTTP请求

  • @RestController
    等价于@ResponseBody + @Controller。如果需要返回JSONXML或自定义mediaType内容到页面,它会自动将对象实体转换为JSON格式
  • @Controller
    使用在对应的方法上,视图解析器可以解析 returnjsp或者html页面,并跳转到相应页面

2. @RequestMapping@GetMapping , @PostMapping

@GetMapping@PostMapping是组合注解,将HTTP get/put 请求映射到特定处理程序的方法注解,即

  • @GetMapping = @RequestMapping(method = RequestMethod.GET)
  • @PostMapping = @RequestMapping(method = RequestMethod.PUT)

3. @Configuration

用于定义配置类,定义的配置类可以替换xml文件,一般和@Bean注解联合使用

  • @Configuration注解主要标注在某个类上,相当于xml配置文件中的<beans>
  • @Configuration不可以是final类型,不可以是匿名类,嵌套使用必须是静态类
  • @Bean注解主要标注在某个方法上,相当于xml配置文件中的<bean>,将方法返回的 POJO 装配到 IoC 容器中

例如:基于 XML 配置的方式

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-lazy-init="true">
<bean id="mockService" class="..MockServiceImpl">
<propery name ="dependencyService" ref="dependencyService" />
</bean>
<bean id="dependencyService" class="DependencyServiceImpl"></bean>
</beans>

基于 JavaConfig 配置的方式

1
2
3
4
5
6
7
8
9
10
11
@Configuration
public class MockConfiguration{
@Bean
public MockService mockService(){
return new MockServiceImpl(dependencyService());
}
@Bean
public DependencyService dependencyService(){
return new DependencyServiceImpl();
}
}

4. @Component 相关

@Component

可以使用此注解描述Spring中的Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次,使用时只需将该注解标注在相应类上即可

  • 此注解表明这个类将被 Spring IoC 容器扫描装配,如果不配置名称,则 IoC 容器就会把类名首字母小写,其他的不变作为 Bean 名称放入到容器中

@Repository

用于将数据访问层(DAO层)的类标识为Spring中的Bean,其功能与@Component相同

@Service

通常作用在业务层(Service层),用于将业务层的类标识为Spring中的Bean,其功能与@Component相同

@Controller

通常作用在控制层(如Spring MVC Controller),用于将控制层的类标识为Spring中的Bean,其功能与@Component相同

@Autowired

  • 用在参数上
    用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作 默认按照Bean的类型进行装配
  • 用在方法上
    spring 容器会在类加载后自动注入这个方法的参数,并执行一遍方法。这就像 static{} 块语句会初始化执行,但执行阶段不一样。

@Resource

作用与@Autowired一样,其区别在于@Autowired默认按照Bean类型装配,而@Resource默认按照Bean实例名称进行装配。

@Resource中有两个重要属性:nametypename属性解析为Bean实例名称,type属性解析为Bean实例类型。

  • 如果指定name 属性,则按实例名称进行装配
  • 如果指定type属性,则按Bean类型进行装配
  • 如果都不指定,则先按Bean实例名称装配
  • 如果不能匹配,再按照Bean类型进行装配
  • 如果都无法匹配,则抛出NoSuchBeanDefinitionException异常

@Qualifier

@Autowired注解配合使用,会将默认的按Bean类型装配修改为接Bean的实例名称装配,Bean的实例名称由@Qualifier 注解的参数指定。

注意

在上面几个注解中,虽然@Repository@Service@Controller功能与@Component注解的功能相同,但为了使标注类本身用途更加清晰,建议在实际开发中分别对实现类进行标注

5. 读取配置信息

5.1. @ConfigurationProperties

5.2. @Value

5.3. @PropertySource@PropertySources

将 properties 配置文件中的值存储到 Environment中,但不支持 .yml 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 读取单个属性
@PropertySource(ignoreResourceNotFound = true, value = "classpath:xxx.properties")

// 读取多个属性
@PropertySource(value={"classpath:xxx.properties", "classpath:yyy.properties"})

@PropertySources(value={
@PropertySource(value={"classpath:xxx.properties"}),
@PropertySource(value={"classpath:yyy.properties"}),
})

// 赋值
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PropertyValueConfig.class);
Environment environment = context.getEnvironment();

@Autowired
private Environment environment;

environment.getProperty("person.name");

5.4. 注:

  1. @ConfigurationProperties@Value 只能读取默认配置文件的属性值,即 application.yml 或 application.properties 的属性值

6. @PathVariable@PathParam

  • @PathVariable: 会将 url 占位符的的参数,按名绑定到相应同名形参
  • @PathParam: 从 request 中以键值对方式取值
  • 两者区别:在没有对应属性时,@PathVariable 会 404,@PathParam 是 null 值
1
2
3
4
5
6
7
8
// 请求路径:http://localhost:8080/hello/show/1/james
// 占位符参数 {xxx} 绑定到处理器类的方法形参中 @PathVariable("xxx")
@RequestMapping("/show/{id}/{name}")
public Result<Void> test(@PathVariable("id") Long id, @PathVariable("name") String name) {}

// 请求路径:http://localhost:8080/hello/show?id=1&name=james
@RequestMapping("/show")
public Result<Void> test(@PathParam("id") Long id, @PathParam("name") String name) {}

在使用 @PathVariable 注解时,其方法参数是必需的,但是可以用几种方法来避免:

1
2
3
4
5
6
7
8
9
10
11
// 1. 设置 required 属性为 false
@GetMapping(value = { "/show", "/show/{name}" })
public Result<Void> test(@PathVariable(required = false) String name) {}

// 2. 使用 java.util.Optional
@GetMapping(value = { "/show", "/show/{name}" })
public Result<Void> test(@PathVariable Optional<String> name) {}

// 3. 使用 Map<String, String> 类型的方法参数
@GetMapping(value = { "/show", "/show/{name}" })
public Result<Void> test(@PathVariable Map<String, String> pathVarsMap) {}

7. @ModelAttribute

7.1 应用在方法的参数上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Controller
@RequestMapping(value = "/modelattribute")
public class ModelAttributeParamController {

@ModelAttribute(value = "attributeName")
public String myModel(@RequestParam(required = false) String abc) {
return abc;
}

@ModelAttribute
public void myModel3(Model model) {
model.addAttribute("name", "zong");
model.addAttribute("age", 20);
}

@RequestMapping(value = "/param")
public String param(@ModelAttribute("attributeName") String str,
@ModelAttribute("name") String str2,
@ModelAttribute("age") int str3) {
return "param";
}
}

如上代码,使用 @ModelAttribute 注解的参数,意思是从前面的 Model 中提取对应名称的属性

8. 关联用到的注解

  • @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  • @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")

9. @RestControllerAdvice

@RestControllerAdvice 是一个组合注解, 由 @ControllerAdvice@ResponseBody组成, 而 @ControllerAdvice 继承了 @Component, 因此 @RestControllerAdvice 本质上是个 @Component, 其将作用于所有使用 @RequestMapping 方法, 可以用来定义 3个 方法

  • @ExceptionHandler : 用于指定异常处理方法, 当与 @RestControllerAdvice 配合使用时, 用于全局处理控制器里的异常
  • @InitBinder : 用来设置 WebDataBinder, 用于自动绑定前台请求参数到 Model 中
  • @ModelAttribute : 本来作用是绑定键值对到 Model 中,当与 @ControllerAdvice 配合使用时,可以让全局的 @RequestMapping 都能获得在此处设置的键值对
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 全局数据绑定, 应用到所有 @RequestMapping 注解方法
*/
@RestControllerAdvice
public class GlobalController{

// 将键值对添加到全局,注解了@RequestMapping的方法都可以获得此键值对
@ModelAttribute
public void addUser(Model model) {
model.addAttribute("msg", "此处将键值对添加到全局,注解了@RequestMapping的方法都可以获得此键值对");
}

//用来设置 WebDataBinder
@InitBinder("user")
public void initBinder(WebDataBinder binder) {
}

// 定义全局异常处理,value 属性可以过滤拦截指定异常,此处拦截所有的 Exception
@ExceptionHandler(Exception.class)
public String handleException(Exception e) {
return "error";
}
}

常用可选参数

  • basePackages : 定一个或多个包,这些包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理
  • basePackageClasses : 是 basePackages 的一种变形,指定一个或多个 Controller 类,这些类所属的包及其子包下的所有 Controller 都被该 @ControllerAdvice 管理
  • annotations : 指定一个或多个注解,被这些注解所标记的 Controller 会被该 @ControllerAdvice 管理

10. @Transactional

可以作用在接口、类、类方法

1. 属性

1. propagation

代表事务的传播行为

  • Propagation.REQUIRED : 默认行为。如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。( 也就是说如果A方法和B方法都添加了注解,在默认传播模式下,A方法内部调用B方法,会把两个方法的事务合并为一个事务 )
  • Propagation.SUPPORTS : 如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。
  • Propagation.MANDATORY : 如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。
  • Propagation.REQUIRES_NEW : 重新创建一个新的事务,如果当前存在事务,暂停当前的事务。( 当类A中的a方法用默认 REQUIRED 模式,类B中的b方法加上采用 REQUIRES_NEW 模式,然后在a方法中调用b方法操作数据库,然而a方法抛出异常后,b方法并没有进行回滚,因为REQUIRES_NEW会暂停a方法的事务 )
  • Propagation.NOT_SUPPORTED : 以非事务的方式运行,如果当前存在事务,暂停当前的事务。
  • Propagation.NEVER : 以非事务的方式运行,如果当前存在事务,则抛出异常。
  • Propagation.NESTED : 和 REQUIRED 效果一样。

2. isolation

事务的隔离级别

  • Isolation.DEFAULT : 使用底层数据库默认的隔离级别。
  • Isolation.READ_UNCOMMITTED
  • Isolation.READ_COMMITTED
  • Isolation.REPEATABLE_READ
  • Isolation.SERIALIZABLE

3. timeout

事务的超时时间,默认值为 -1。如果超过该时间限制但事务还没有完成,则自动回滚事务

4. readOnly

指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true

5. rollbackFor

用于指定能够触发事务回滚的异常类型,可以指定多个异常类型

4. noRollbackFor

抛出指定的异常类型,不回滚事务,可以指定多个异常类型

2. 失效

  1. 事务支持: 数据库不支持时
  2. spring 框架: 类不被 spring 管理、方法非 public、数据源没有配置事务管理器
  3. 填写错误: 属性设置错误、异常被捕捉

11. Spring Cache 相关

开启缓存注解 @EnableCaching,只有使用 public 定义的方法才可以被缓存,当在一个类上使用注解时,该类中每个公共方法的返回值都将被缓存到指定的缓存项中或者从中移除

1. @Cacheable

指定了被注解方法的返回值是可被缓存的。缓存名必要,可以使用引号、Value 或者 cacheNames 属性来定义名称

属性

  • cacheNames/value : 指定缓存的名字,缓存使用 CacheManager 管理多个缓存 Cache,其根据该属性进行区分。对缓存的真正增删改查操作在 Cache 中定义,每个缓存 Cache 都有自己唯一的名字
  • key : 缓存数据时的 key 的值,默认是使用方法所有入参的值,可以使用 SpEL 表达式表示
  • keyGenerator : 缓存键生成器,和 key 二选一,在默认情况下,缓存抽象使用(方法签名及参数值)作为一个键值,并将该键与方法调用的结果组成键/值对,可以通过实现 org.springframework.cache.interceptor.KeyGenerator 接口来定义自己实际需要的键生成器
  • cacheManager : 指定缓存管理器(例如ConcurrentHashMap、Redis等)
  • cacheResolver : 和 cacheManager 作用一样,使用时二选一
  • condition : 指定缓存的条件,满足条件时才缓存,可用 SpEL 表达式,例如:方法入参为对象 user 则表达式可以写为 condition = "#user.age>18",表示当入参对象user的属性age大于18才进行缓存
  • unless : 否定缓存的条件,即满足指定的条件时,对调用方法获取的结果不进行缓存,例如:unless = "result==null",表示如果结果为null时不缓存
  • sync : 是否使用异步模式进行缓存,默认false

2. @CachePut

@Cacheable 注解属性相比少了 sync 属性,其他用法基本相同。如果一个方法使用了 @Cacheable 注解,当重复(n>1)调用该方法时,由于缓存机制,并未再次执行方法体,其结果直接从缓存中找到并返回,即获取还的是第一次方法执行后放进缓存中的结果。

但实际业务并不总是如此,有些情况下要求方法一定会被调用,例如数据库数据的更新,系统日志的记录,确保缓存对象属性的实时性等。@CachePut 注解就确保方法调用即执行,执行后更新缓存。

3. @CacheEvict

@Cachable 注解的反向操作,它负责从给定的缓存中移除一个值。大多数缓存框架都提供了缓存数据的有效期,使用该注解可以显式地从缓存中删除失效的缓存数据。该注解通常用于更新或者删除用户的操作。

属性

  • cacheNames/value,key,keyGenerator,cacheManager,cacheResolver,condition 同上
  • allEntries : 布尔类型的,用来表示是否需要清除缓存中的所有元素。默认值为 false ,表示不需要。当指定为 true 时,Spring 将忽略指定的 key,清除缓存中的所有内容。
  • beforeInvocation : 清除操作默认是在对应方法执行成功后触发的(beforeInvocation = false),即方法如果因为抛出异常而未能成功返回时则不会触发清除操作。使用该属性可以改变触发清除操作的时间。当指定该属性值为 true 时,Spring 会在调用该方法之前清除缓存中的指定元素

4. @Caching

是一个组注解,可以为一个方法定义提供基于 @Cacheable,@CacheEvict,@CachePut 注解的数组

属性

  • cacheable : 取值为基于 @Cacheable 注解的数组,定义对方法返回结果进行缓存的多个缓存
  • put : 取值为基于 @CachePut 注解的数组,定义执行方法后,对返回方的方法结果进行更新的多个缓存
  • evict : 取值为基于 @CacheEvict 注解的数组。定义多个移除缓存

5. @CacheConfig

前面的注解都是基于方法的,如果在同一个类中需要缓存的方法注解属性都相似,则需要重复增加。Spring 4.0之后增加了 @CacheConfig 类级别的注解来解决这个问题

属性

  • cacheNames/value,key,keyGenerator,cacheManager,cacheResolver 同上

12. @PreDestroy

@PreDestroy 注解标注的方法会在服务器卸载 Servlet 时运行,并且只会被服务器调用一次,会在 Servlet 的 destroy() 之后,被彻底卸载之前执行