1、在springBoot中可以使用注解式开发缓存,默认没有开启缓存中间件,那么使用的就是存储在Map中的原理,但是我们还可以配置自己的缓存中间件,比如redis
2、引入依赖,启动器
<!--导入缓存的启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
3、开启缓存,在主配置类上添加 EnableCaching
这个注解即可,如下:
//批量扫描com.tellwess.springbootserver.mappers这个包下面的所有mapper @MapperScan(value ="com.tellwess.springbootserver.mappers") @EnableCaching //开启缓存注解 @SpringBootApplication public class SpringbootServerApplication{
4、使用注解版本的mybatis和数据库进行交互,其中的UserMapper如下:
/** * User对应的Mapper */ public interface UserMapper{ @Select("select * from t_user where user_id=#{userId}") public User selectUserById(Integer userId); @Options(useGeneratedKeys = true,keyProperty = "userId") @Insert({"insert into t_user(name,gender,age) values(#{name},#{gender},#{age})"}) public int insertUser(User user); @Delete("delete from t_user where user_id=#{userId}") public int deleteUser(Integer userId); @Select("select * from t_user where name=#{name}") public User selectUserByName(String name); }
5、在service层中使用缓存的各种注解实现缓存的操作,如下:
/** * @CacheConfig : 这个注解用于指定这个service类中的缓存操作的公共属性,比如缓存的名字可以使用cacheNames指定,那么在下面的每一个注解中都可以不指定,默认使用的就是这个指定的 */ @Service //@CacheConfig(cacheNames = "user",keyGenerator = "myGenerate") public class UserService{ @Resource private UserMapper userMapper; /** *@Cacheable : 这个注解是在方法运行之前检查缓存中是否存在指定的key的数据,如果存在,那么直接返回 * 如果不存在,那么执行方法体,最后将方法体返回的结果添加到缓存中 * 1、 cacheNames/value : 指定cache的名字,指定将方法的返回值放在那个缓存中,是数组的方式 * 2、key : 指定缓存的key,如果不指定的,那么默认使用方法参数的值,当然也是可以使用一些表达式指定这个key的值 * 1、spEL表达式: * 1、当前被调用的方法名称 ---- #root.methodName ---- #root.method.name * 2、当前目标对象 ---- #root.target * 3、当前目标对象的类 ----- #root.targetClass * 4、当前被调用对象的参数列表 ---- #root.args[index] * 5、方法参数的名字,直接使用`#名字`即可获取参数的值 ------ `#userId` * 6、方法的返回值 ----- #result * 3、keyGenerator : key的生成器,这个和key只能同时指定一个,当然也是可以自定义这个生成器 * 4、condition : 指定缓存的条件,只有满足这个条件的时候才会使用缓存 --- condition = "#userId>2" * 5、unless : 当这个条件为true的时候就不缓存,这个和condition条件相反。 * 1、这个可以使用返回的结果进行判断,比如当我们对返回结果为空的时候不使用缓存,那么可以写成unless = "#result==null" * * 6、cacheManager : 指定缓存管理器 * 7、sync : 是否使用异步模式 * 8、注意:springBoot默认是将返回值为null的时候也会将其缓存起来,我们可以使用unless条件对结果进行判断是否缓存 * * */ @Cacheable(value = {"user"},key = "#userId",condition = "#userId>2",unless = "#result==null") public User getUser(Integer userId){ System.out.println("查询数据库"); return userMapper.selectUserById(userId); } /** * @CachePut : 这个注解的作用是,在方法体执行完成之后,将返回的结果添加到缓存中,可以用于添加和修改操作 * 其中可以设置的参数和@cacheable差不多 * 注意:**只要是标注了这个注解之后,那么这个方法一定是要执行的,因为需要将方法执行的结果添加到缓存中** * */ @CachePut(value = "user",key = "#user.userId") public User addUser(User user){ System.out.println("添加用户"); userMapper.insertUser(user); return user; } /** * @CacheEvict : 这个注解的作用是清除缓存,默认是在执行方法体之后清除缓存,如果执行的代码出现了异常,那么这个清除缓存将不会执行 * 1、vaue : 指定缓存的名字 * 2、key : 指定需要删除的key * 3、allEntries : 是否删除指定缓存中的全部缓存,默认为false,一旦指定为true,那么将会删除value指定的cache中的全部缓存 * 4、beforeInvocation : 是否在执行方法体的代码之前执行清除缓存,默认为false,如果指定了为true,那么就会在方法执行之前清除缓存, * 此时如果方法体运行出错,那么缓存中的数据将不能回滚 */ @CacheEvict(value = "user",key = "#userId") public void deleteUser(Integer userId){ System.out.println("调用了删除的方法"); userMapper.deleteUser(userId); } /** * @Caching : 这个是一个组合注解,针对一个方法逻辑中多种的缓存操作 * 1、cacheable : 一个数组,其中指定@Cacheable这个注解,可以指定多个,用于在执行方法之前先查询缓存,如果没有才会执行方法体,并且将结果缓存起来 * 2、put: 一个数组,其中只能指定@CachePut这个注解,可以指定多个,用于在执行方法之后将返回的结果添加到缓存中 * 3、evict : 一个数组,其中只能指定@CacheEvict这个注解,用于在方法执行完成之后清除缓存 */ @Caching( cacheable = { @Cacheable(value = "user",key = "#name") //首先根据name从缓存中获取数据,如果没有将会把缓存的结果添加到缓存中 }, put = { @CachePut(value = "user",key = "#result.age"), @CachePut(value = "user",key = "#result.gender"), } ) public User getUserByName(String name){ System.out.println("调用getUserByName方法"); return userMapper.selectUserByName(name); } }
1、添加场景启动器,如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
2、在全局配置文件中配置redis的连接配置,如下:
# Redis数据库索引(默认为0) spring.redis.database=0 # Redis服务器地址 spring.redis.host=172.31.19.222 # Redis服务器连接端口 spring.redis.port=6379 # Redis服务器连接密码(默认为空) spring.redis.password= # 连接池最大连接数(使用负值表示没有限制) spring.redis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.pool.max-wait=-1 # 连接池中的最大空闲连接 spring.redis.pool.max-idle=8 # 连接池中的最小空闲连接 spring.redis.pool.min-idle=0 # 连接超时时间(毫秒) spring.redis.timeout=0
3、一旦注入这个场景启动器,那么将会为我们自动配置,我们可以直接使用spring-data-redis操作redis,如下:
@RunWith(SpringRunner.class) @SpringBootTest public class SpringbootCacheApplicationTests{ @Resource private StringRedisTemplate stringRedisTemplate; //存储key和value都是字符串的数据 @Resource private RedisTemplate<String,Object> redisTemplate; //操作key和value都是Object的数据 @Test public void contextLoads(){ stringRedisTemplate.opsForValue().append("hello","hello world"); } }
4、springBoot默认是使用的jdk的序列化方式将数据保存在Redis中,但是我们可以自定义自己的序列化规则,可以指定的json序列化器,如下:
//指定一个redis的配置类 @Configuration public class RedisConfig{ //指定自己的RedisTemplate,并且指定默认的序列化器为json的,只需要设置默认的即可,因为value和key的序列化器和默认的是一样的,不需要重复指定 @Bean public RedisTemplate<Object, User> redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, User> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); //指定json的序列化器 Jackson2JsonRedisSerializer<User> serializer=new Jackson2JsonRedisSerializer<User>(User.class); template.setDefaultSerializer(serializer); //设置为默认的序列化器 return template; } }
5、只要引入redis的场景启动器,那么就会为我们配置一个RedisCache这个名字的缓存管理器,因此不需要重新配置了,那么我们可以直接使用缓存的注解了。此时使用缓存注解的时候就会将数据存储在redis中了。但是默认的保存的数据还是使用jdk序列化后的结果。
6、个人觉得使用缓存不需要使用注解,手写代码应该更加灵活一些。