spring boot使用cache缓存

第一步:几个重要概念&缓存注解

 

Cache缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、 ConcurrentMapCache等
CacheManager缓存管理器,管理各种缓存(Cache)组件
@Cacheable主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
@CacheEvict清空缓存
@CachePut保证方法被调用,又希望结果被缓存。
@EnableCaching开启基于注解的缓存
keyGenerator缓存数据时key生成策略
serialize缓存数据时value序列化策略

        @Cacheable、@CachePut、@CacheEvict主要的参数

value缓存的名称,在 spring 配置文件中定义,必须指定 至少一个例如: @Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”}
key缓存的 key,可以为空,如果指定要按照 SpEL 表达 式编写,如果不指定,则缺省按照方法的所有参数 进行组合例如: @Cacheable(value=”testcache”,key=”#userName”)
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存/清除缓存,在 调用方法之前之后都能判断例如: @Cacheable(value=”testcache”,condition=”#userNam e.length()>2”)
allEntries (@CacheEvict )是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存例如:@CachEvict(value=”testcache”,allEntries=true)
beforeInvocation (@CacheEvict)是否在方法执行前就清空,缺省为 false,如果指定 为 true,则在方法还没有执行的时候就清空缓存, 缺省情况下,如果方法执行抛出异常,则不会清空 缓存例如:@CachEvict(value=”testcache”, beforeInvocation=true)
unless (@CachePut) (@Cacheable)用于否决缓存的,不像condition,该表达式只在方 法执行之后判断,此时可以拿到返回值result进行判 断。条件为true不会缓存,fasle才缓存例如:@Cacheable(value=”testcache”,unless=”#result == null”)

       Cache SpEL available metadata

名字位置描述实例
methodName root object当前被调用的方法名 #root.methodName
method root object当前被调用的方法#root.method.name
target root object当前被调用的目标对象#root.target
targetClass root object当前被调用的目标对象类 #root.targetClass
args root object当前被调用的方法的参数列表#root.args[0]
caches root object 当前方法调用使用的缓存列表(如@Cacheable(value={"cache1", "cache2"})),则有两个cache。#root.caches[0].name
argument nameevaluation context方法参数的名字. 可以直接 #参数名 ,也可以使用 #p0或#a0 的 形式,0代表参数的索引。#a0、#p0
resultevaluation context方法执行后的返回值(仅当方法执行之后的判断有效,如 ‘unless’,’cache put’的表达式 ’cache evict’的表达式 beforeInvocation=false)#result

第二步:在spring boot中使用cache

       1):添加maven依赖

     <!-- 开添加缓存依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>

       2):@EnableCaching开启缓存

@SpringBootApplication
@EnableCaching//开启缓存
public class Startup {
    public static void main( String[] args )
    {
    	SpringApplication.run(Startup.class, args);
    }
}
  

       3):@Cacheable缓存注解的使用 (标注在service业务层方法上)

       执行流程:先执行@Cacheable注解中的getCache(String name)方法,根据name判断ConcurrentMap中是否有此缓存,如果没有缓存那么创建缓存并保存数据,另外service层的方法也会执行。如果有缓存不再创建缓存,另外service层的方法也不会执行

       总结:先执行@Cacheable--------------------再执行service层的方法

service层代码

第一次查询数据库数据打印结果信息,并把数据保存到Cache中

第二次传入相同的参数不再执行service类的方法,不会再有结果信息,查询的数据直接从缓存中获取

       controller层 

    @RequestMapping("/selectById")
	public String selectUser() {
		User user = userService.selectUserById(25);
		System.out.println(user.toString());
		return "selectUser";
	}

       service层 

@Service
public class UserServiceImpl implements UserService {

	@Autowired
	UserMapper mapper;

    /* @Cacheable的几个属性详解:
      *       cacheNames/value:指定缓存组件的名字
      *       key:缓存数据使用的key,可以用它来指定。默认使用方法参数的值,一般不需要指定
      *       keyGenerator:作用和key一样,二选一
      *       cacheManager和cacheResolver作用相同:指定缓存管理器,二选一
      *       condition:指定符合条件才缓存,比如:condition="#id>3"
      *                   也就是说传入的参数id>3才缓存数据
      *      unless:否定缓存,当unless为true时不缓存,可以获取方法结果进行判断
      *      sync:是否使用异步模式
    */
	@Cacheable(cacheNames="userCache",key="#id")
	public User selectUserById(Integer id) {
		System.out.println("查询单条记录!");
		return mapper.selectUserById(id);
	}

}

调用两次,查询结果如下,并没有执行两次service层的方法

       4):@CachePut必须结合@Cacheable一起使用,否则没什么意义

@CachePut:既调用方法,又更新缓存数据,修改了数据库中的数据,同时又更新了缓存

测试步骤:

       1:先查询指定id的user信息

       2:更新指定id的user信息

       3:查询指定id的user信息

       4:查询到的user信息是查的缓存数据且是更新后的数据

       controller层

        @RequestMapping("/selectById")
	public String selectUser() {
		User user = userService.selectUserById(26);
		System.out.println(user.toString());
		return "selectUser";
	}

        @RequestMapping("/modifyUser")
	public String modifyUser() {
		User user = userService.selectUserById(26);
		user.setName(user.getName());
		user.setAge(user.getAge()+1);
		user.setPassword(user.getPassword());
		userService.updateUserById(user);
		System.out.println(user);
		return "modifyUser";
	}

       service层

        @Cacheable(cacheNames="userCache",key="#id")
	public User selectUserById(Integer id) {
		System.out.println("查询单条记录!");
		return mapper.selectUserById(id);
	}

        @CachePut(cacheNames="userCache",key="#result.id")
	public User updateUserById(User user) {
		System.out.println("更新数据");
		mapper.updateUserById(user);
		return user;
	}

       执行结果如图所示:

       5):@CacheEvict也是结合@Cacheable一起使用才有意义

@CacheEvict:清除缓存中的指定数据或者清除缓存中的所有数据

测试步骤:

       1:先查询指定id的user信息,确保数据是从数据库查询来的

       2:再查询指定id的user信息,这次查询确保数据是从缓存查出来的

       3:删除缓存中指定id的user信息

       4:再查询指定id的user信息,看看是否从数据库中读取

       controller层

        @RequestMapping("/deleteUserById")
	public String deleUser() {
		userService.deleteUserById(26);
		return "deleteUser";
	}
	@RequestMapping("/selectById")
	public String selectUser() {
		User user = userService.selectUserById(26);
		System.out.println(user.toString());
		return "selectUser";
	}

       service层

        @Cacheable(cacheNames="userCache",key="#id")
	public User selectUserById(Integer id) {
		System.out.println("查询单条记录!");
		return mapper.selectUserById(id);
	}
        /*
        @CacheEvict:清除缓存
         1.key:指定要清除缓存中的某条数据
         2.allEntries=true:删除缓存中的所有数据
         3.beforeInvocation=false:默认是在方法之后执行清除缓存
         4.beforeInvocation=true:现在是在方法执行之前执行清除缓存,
			作用是:只清除缓存、不删除数据库数据
		*/
        //@CacheEvict(cacheNames = "userCache",allEntries=true)
        @CacheEvict(cacheNames = "userCache",key="#id")
	public int deleteUserById(int id) {
		System.out.println("删除一条数据");
		//mapper.deleteUserById(id);
		return 0; 
	}

       执行结果如图所示:

       6):@Caching是@Cacheable、@CachePut、@CacheEvict注解的组合

@Caching:此注解用在复杂的缓存操作

       1:当使用指定字段查询数据库后,将返回的数据保存到缓存中

       2:现在使用age、password就可以直接查询缓存,而不是查询数据库

测试步骤:

       1:先查询指定id的user信息,数据是从数据库查询来的

       2:再根据指定的age查询user信息,查看数据是否是从缓存查出来的

       3:再根据指定的password查询user信息,看看数据是否从缓存查出来

   

       controller层

        @RequestMapping("/selectById")
	public String selectUser() {
		User user = userService.selectUserById(26);
		System.out.println(user.toString());
		return "selectUser";
	}
	@RequestMapping("/selectByName")
	public String selectUserByName() {
		User user = userService.selectUserByName("2");
		System.out.println(user.toString());
		return "selectByName";
	}
	
	@RequestMapping("/selectByPassword")
	public String selectByAge() {
		User user = userService.selectUserByPassword("a");
		System.out.println(user.toString());
		return "selectByPassword";
	}

       service层

       @Caching(
	            cacheable = {@Cacheable(value = "userCache",key="#id")},
	            put={ @CachePut(value = "userCache",key = "#result.name"),
	                  @CachePut(value = "userCache",key = "#result.password")
	            })
	public User selectUserById(Integer id) {
		System.out.println("通过id查询单条记录!");
		return mapper.selectUserById(id);
	}
	 
	@Cacheable(value="userCache",key="#name")
	public User selectUserByName(String name) {
		System.out.println("通过name参数查询单条记录!");
		return mapper.selectUserByName(name);
	}
	
	@Cacheable(value="userCache",key="#password")
	public User selectUserByPassword(String  password){
		System.out.println("通过password参数查询单条记录!");
		return mapper.selectUserByPassword(password);
	}

       分别调用selectUserByIdselectUserByNameselectUserByPassword方法结果如下:

       发现第二三次的调用查询的是缓存里面的数据

       6):@CacheConfig主要用于配置该类中会用到的一些共用的缓存配置

@CacheConfig:抽取@Cacheable、@CachePut、@CacheEvict的公共属性值

       service层

@Service
@CacheConfig(cacheNames = {"userCache"})//将cacheNames抽取出来
public class UserServiceImpl implements UserService {

	@Autowired
	UserMapper mapper;

	@Cacheable(key="#name")
	public User selectUserByName(String name) {
		System.out.println("通过name参数查询单条记录!");
		return mapper.selectUserByName(name);
	}
	
	@Cacheable(key="#password")
	public User selectUserByPassword(String  password){
		System.out.println("通过password参数查询单条记录!");
		return mapper.selectUserByPassword(password);
	}
}

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐的小三菊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值