一.SpringBoot集成Redis
1.pom.xml文件添加spring-boot-starter-data-redis依赖
<dependencies> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-data-redisartifactId> dependency> <dependency> <groupId>org.apache.commonsgroupId> <artifactId>commons-pool2artifactId> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-webartifactId> dependency> <dependency> <groupId>org.springframework.sessiongroupId> <artifactId>spring-session-data-redisartifactId> dependency> <dependency> <groupId>org.projectlombokgroupId> <artifactId>lombokartifactId> <optional>trueoptional> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-testartifactId> <scope>testscope> dependency>dependencies>
依赖说明:
- spring-boot-starter-data-redis:在Spring Boot 2.x 以后底层不再使用 Jedis,而是换成了Lettuce。
- commons-pool2:用作 Redis 连接池,如不引入启动会报错。
- spring-session-data-redis:Spring Session 引入,用作共享 Session。
2.配置文件application.properties
## Redis部分# Redis数据库索引(默认为0)spring.redis.database=0# Redis服务器地址spring.redis.host=106.14.72.179# Redis服务器连接端口spring.redis.port=6379# Redis服务器连接密码(默认为空)spring.redis.password=# 连接池最大连接数(使用负值表示没有限制)spring.redis.jedis.pool.max-active=8# 连接池最大阻塞等待时间(使用负值表示没有限制)spring.redis.jedis.pool.max-wait=-1ms# 连接池中的最大空闲连接spring.redis.jedis.pool.max-idle=8# 连接池中的最小空闲连接spring.redis.jedis.pool.min-idle=0# 连接超时时间(毫秒)spring.redis.timeout=5000
3.配置RedisConfig(加载方式,推荐使用方式一)
方式一:使用Autoconfiguration自动加载
因为上面引入了spring-boot-start-data-redis,所以可以使用RedisAutoConfiguration类加载properties文件的配置。因此我们只要在使用的地方注入即可。
@AutowiredStringRedisTemplate stringRedisTemplate; //操作 k-v 字符串@AutowiredRedisTemplate redisTemplate; //k- v 都是对象
说明:
Spring Boot关于Spring Data Redis的自动配置类。该自动配置类检测到包spring-boot-start-data-redis被使用时才应用。并且导入了另外两个配置类LettuceConnectionConfiguration,JedisConnectionConfiguration,这两个配置类是用于配置底层Redis连接组件RedisConnectionFactory,一种基于Lettuce Redis客户端实现,一种基于Jedis Redis客户端实现,不会同时生效。因为包spring-boot-starter-data-redis自身依赖lettuce,所以缺省情况下,LettuceConnectionConfiguration会生效,JedisConnectionConfiguration不生效。
RedisAutoConfiguration自身主要的作用是确保以下bean存在于容器中 :
- RedisTemplate redisTemplate – 基于容器中的redisConnectionFactory bean
- StringRedisTemplate stringRedisTemplate – 基于容器中的redisConnectionFactory bean
源代码(spring-boot-autoconfigure-2.1.3.RELEASE):
package org.springframework.boot.autoconfigure.data.redis;// 省略 import 行/** * EnableAutoConfiguration Auto-configuration for Spring Data's Redis support. * */@Configuration@ConditionalOnClass(RedisOperations.class)@EnableConfigurationProperties(RedisProperties.class)@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })public class RedisAutoConfiguration { // 定义 bean RedisTemplate redisTemplate @Bean // 仅在该 bean 不存在的情况下才定义 @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); return template; } // 定义 bean StringRedisTemplate stringRedisTemplate @Bean // 仅在该 bean 不存在的情况下才定义 @ConditionalOnMissingBean public StringRedisTemplate stringRedisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; }}
方式二:自己写代码加载
package com.guige.core.conf;import com.guige.core.ext.common.redis.MyCacheErrorHandler;import com.guige.core.ext.common.redis.MyKeyGenerator;import com.guige.core.ext.common.redis.MyRedisCacheManager;import com.guige.core.ext.common.redis.MyRedisTemplate;import org.springframework.beans.factory.annotation.Value;import org.springframework.cache.interceptor.CacheErrorHandler;import org.springframework.cache.interceptor.KeyGenerator;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import redis.clients.jedis.JedisPoolConfig;@Configurationpublic class RedisConf { @Value("${spring.redis.database}") private Integer database; @Value("${spring.redis.host}") private String host; @Value("${spring.redis.password}") private String password; @Value("${spring.redis.port}") private Integer port; @Value("${spring.redis.timeout}") private Integer timeout; @Value(value = "${spring.redis.expire:300}") private Integer expiration; @Value("${spring.redis.pool.maxactive}") private int maxActive; @Value("${spring.redis.pool.minidle}") private int minIdle; @Value("${spring.redis.pool.maxidle}") private int maxIdle; @Bean public JedisPoolConfig jedisPoolConfig(){ JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxIdle(this.maxIdle); poolConfig.setMinIdle(this.minIdle); poolConfig.setTestOnCreate(true); poolConfig.setTestOnBorrow(true); poolConfig.setTestOnReturn(true); poolConfig.setTestWhileIdle(true); return poolConfig; } @Bean public JedisConnectionFactory jedisConnectionFactory(){ JedisPoolConfig config = jedisPoolConfig(); JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(config); jedisConnectionFactory.setDatabase(this.database); jedisConnectionFactory.setHostName(this.host); jedisConnectionFactory.setPassword(this.password); jedisConnectionFactory.setPort(this.port); jedisConnectionFactory.setTimeout(this.timeout); return jedisConnectionFactory; } @Bean public RedisTemplate redisTemplate(){ MyRedisTemplate myRedisTemplate = new MyRedisTemplate(); myRedisTemplate.setConnectionFactory(jedisConnectionFactory()); return myRedisTemplate; }}##或者如下方式@Configurationpublic class RedisConf { @Bean public StringRedisTemplate stringRedisTemplate(@Autowired JedisConnectionFactory jedisConnectionFactory) { StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(); stringRedisTemplate.setConnectionFactory(jedisConnectionFactory); return stringRedisTemplate; }}
4.Controller
package com.platform.app.member.web;@RestController@RequestMapping(value = "/memberForGoddess")public class MemberForGoddessController { private Logger logger = LoggerFactory.getLogger(MemberForGoddessController.class); @Autowired private RedisTemplate redisCacheTemplate; private static final String RECEIVE_KEY = "receive:list";//缓存的key, @PostMapping(value = "/checkSsinsureCode") public Rst checkCodeForSsinsure(@RequestBody Map phonemap){ logger.info("100001-femaleHelp-校验验证码:入参手机号和验证码:" + phonemap); String phone = ""; String phoneCode = ""; if (StringUtil.isEmpty(phonemap)){ return Rst.error("手机号或验证码为空"); }else { phone = phonemap.get("phone"); phoneCode = phonemap.get("phoneCode"); Rst rst = memberForGoddessServivce.checkIPhoneCode(phone,phoneCode); if(rst.getSts() == 1){ List list = redisCacheTemplate.opsForList().range(RECEIVE_KEY,0,-1); if(list!=null && !list.isEmpty()){ if(!list.contains(phone)){ redisCacheTemplate.opsForList().rightPush(RECEIVE_KEY,phone); } }else{ redisCacheTemplate.opsForList().rightPush(RECEIVE_KEY,phone); } } return rst; } }}
以上就是SpringBoot集成Redis的基本方法!!!
5.StringRedisTemplate和RedisTemplate的区别
使用时只需使用maven依赖包spring-boot-starter-data-redis即可,然后在service中注入StringRedisTemplate或者RedisTemplate即可。
StringRedisTemplate继承了RedisTemplate,所以两者对Redis的操作方法具有相同之处:
- 两者的数据是不共通的
也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。 - 其实他们两者之间的区别主要在于他们使用的序列化类
RedisTemplate使用的是JdkSerializationRedisSerializer 存入数据会将数据先序列化成字节数组然后在存入Redis数据库。StringRedisTemplate使用的是StringRedisSerializer,反序列化,则是一个得到 String,一个得到 Object。 - 使用时注意事项
当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可。但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。 - RedisTemplate使用时常见问题
redisTemplate 中存取数据都是字节数组。当redis中存入的数据是可读形式而非字节数组时,使用redisTemplate取值的时候会无法获取导出数据,获得的值为null。可以使用 StringRedisTemplate 试试。
StringRedisTemplate对于Redis的操作方法:
StringRedisTemplate.opsForValue() //操作String字符串类型StringRedisTemplate.delete(key/collection) //根据key/keys删除StringRedisTemplate.opsForList() //操作List类型StringRedisTemplate.opsForHash() //操作Hash类型StringRedisTemplate.opsForSet() //操作set类型StringRedisTemplate.opsForZSet() //操作有序set
6.RedisTemplate类常用方法封装
package com.example.demo.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Service;import org.springframework.util.CollectionUtils;import java.util.Collection;import java.util.List;import java.util.Map;import java.util.Set;import java.util.concurrent.TimeUnit;@Servicepublic class RedisService { @Autowired private RedisTemplate redisTemplate; // =============================common============================ /** * 指定缓存失效时间 * @param key 键 * @param time 时间(秒) * @return */ public boolean expire(String key, long time) { try { if (time > 0) { redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据key 获取过期时间 * @param key 键 不能为null * @return 时间(秒) 返回0代表为永久有效 */ public long getExpire(String key) { return redisTemplate.getExpire(key, TimeUnit.SECONDS); } /** * 判断key是否存在 * @param key 键 * @return true 存在 false不存在 */ public boolean hasKey(String key) { try { return redisTemplate.hasKey(key); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除缓存 * @param key 可以传一个值 或多个 */ @SuppressWarnings("unchecked") public void del(String... key) { if (key != null && key.length > 0) { if (key.length == 1) { redisTemplate.delete(key[0]); } else { redisTemplate.delete(CollectionUtils.arrayToList(key)); } } } /** * 删除缓存 * @param keys 可以传一个值 或多个 */ @SuppressWarnings("unchecked") public void del(Collection keys) { if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(keys)) { redisTemplate.delete(keys); } } // ============================String============================= /** * 普通缓存获取 * @param key 键 * @return 值 */ public Object get(String key) { return key == null ? null : redisTemplate.opsForValue().get(key); } /** * 普通缓存放入 * @param key 键 * @param value 值 * @return true成功 false失败 */ public boolean set(String key, Object value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 普通缓存放入并设置时间 * @param key 键 * @param value 值 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 * @return true成功 false 失败 */ public boolean set(String key, Object value, long time) { try { if (time > 0) { redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); } else { set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 递增 * @param key 键 * @param delta 要增加几(大于0) * @return */ public long incr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForValue().increment(key, delta); } /** * 递减 * @param key 键 * @param delta 要减少几(小于0) * @return */ public long decr(String key, long delta) { if (delta < 0) { throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForValue().increment(key, -delta); } // ================================Map================================= /** * HashGet * @param key 键 不能为null * @param item 项 不能为null * @return 值 */ public Object hget(String key, String item) { return redisTemplate.opsForHash().get(key, item); } /** * 获取hashKey对应的所有键值 * @param key 键 * @return 对应的多个键值 */ public Map hmget(String key) { return redisTemplate.opsForHash().entries(key); } /** * HashSet * @param key 键 * @param map 对应多个键值 * @return true 成功 false 失败 */ public boolean hmset(String key, Map map) { try { redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * HashSet 并设置时间 * @param key 键 * @param map 对应多个键值 * @param time 时间(秒) * @return true成功 false失败 */ public boolean hmset(String key, Map map, long time) { try { redisTemplate.opsForHash().putAll(key, map); if (time > 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * @param key 键 * @param item 项 * @param value 值 * @return true 成功 false失败 */ public boolean hset(String key, String item, Object value) { try { redisTemplate.opsForHash().put(key, item, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * @param key 键 * @param item 项 * @param value 值 * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 * @return true 成功 false失败 */ public boolean hset(String key, String item, Object value, long time) { try { redisTemplate.opsForHash().put(key, item, value); if (time > 0) { expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除hash表中的值 * @param key 键 不能为null * @param item 项 可以使多个 不能为null */ public void hdel(String key, Object... item) { redisTemplate.opsForHash().delete(key, item); } /** * 删除hash表中的值 * @param key 键 不能为null * @param items 项 可以使多个 不能为null */ public void hdel(String key, Collection items) { redisTemplate.opsForHash().delete(key, items.toArray()); } /** * 判断hash表中是否有该项的值 * @param key 键 不能为null * @param item 项 不能为null * @return true 存在 false不存在 */ public boolean hHasKey(String key, String item) { return redisTemplate.opsForHash().hasKey(key, item); } /** * hash递增 如果不存在,就会创建一个 并把新增后的值返回 * @param key 键 * @param item 项 * @param delta 要增加几(大于0) * @return */ public double hincr(String key, String item, double delta) { if (delta < 0) { throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForHash().increment(key, item, delta); } /** * hash递减 * @param key 键 * @param item 项 * @param delta 要减少记(小于0) * @return */ public double hdecr(String key, String item, double delta) { if (delta < 0) { throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForHash().increment(key, item, -delta); } // ============================set============================= /** * 根据key获取Set中的所有值 * @param key 键 * @return */ public Set sGet(String key) { try { return redisTemplate.opsForSet().members(key); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 根据value从一个set中查询,是否存在 * @param key 键 * @param value 值 * @return true 存在 false不存在 */ public boolean sHasKey(String key, Object value) { try { return redisTemplate.opsForSet().isMember(key, value); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将数据放入set缓存 * @param key 键 * @param values 值 可以是多个 * @return 成功个数 */ public long sSet(String key, Object... values) { try { return redisTemplate.opsForSet().add(key, values); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 将数据放入set缓存 * @param key 键 * @param values 值 可以是多个 * @return 成功个数 */ public long sSet(String key, Collection values) { try { return redisTemplate.opsForSet().add(key, values.toArray()); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 将set数据放入缓存 * @param key 键 * @param time 时间(秒) * @param values 值 可以是多个 * @return 成功个数 */ public long sSetAndTime(String key, long time, Object... values) { try { Long count = redisTemplate.opsForSet().add(key, values); if (time > 0) expire(key, time); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 获取set缓存的长度 * @param key 键 * @return */ public long sGetSetSize(String key) { try { return redisTemplate.opsForSet().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 移除值为value的 * @param key 键 * @param values 值 可以是多个 * @return 移除的个数 */ public long setRemove(String key, Object... values) { try { Long count = redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } // ===============================list================================= /** * 获取list缓存的内容 * @param key 键 * @param start 开始 * @param end 结束 0 到 -1代表所有值 * @return */ public List lGet(String key, long start, long end) { try { return redisTemplate.opsForList().range(key, start, end); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 获取list缓存的长度 * @param key 键 * @return */ public long lGetListSize(String key) { try { return redisTemplate.opsForList().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 通过索引 获取list中的值 * @param key 键 * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 * @return */ public Object lGetIndex(String key, long index) { try { return redisTemplate.opsForList().index(key, index); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 将list放入缓存 * @param key 键 * @param value 值 * @return */ public boolean lSet(String key, Object value) { try { redisTemplate.opsForList().rightPush(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, Object value, long time) { try { redisTemplate.opsForList().rightPush(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * @param key 键 * @param value 值 * @return */ public boolean lSet(String key, List value) { try { redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, List value, long time) { try { redisTemplate.opsForList().rightPushAll(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据索引修改list中的某条数据 * @param key 键 * @param index 索引 * @param value 值 * @return */ public boolean lUpdateIndex(String key, long index, Object value) { try { redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 移除N个值为value * @param key 键 * @param count 移除多少个 * @param value 值 * @return 移除的个数 */ public long lRemove(String key, long count, Object value) { try { Long remove = redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception e) { e.printStackTrace(); return 0; } }}
二.SpringBoot集成Redis缓存
1.pom.xml加入依赖
org.springframework.boot spring-boot-starter-data-redis org.springframework.boot spring-boot-starter-cache
2.application.properties
server: port: 8081#数据库连接spring: datasource: url: jdbc:mysql://localhost:3306/mytest_springboot_cache?useUnicode=true driver-class-name: com.mysql.jdbc.Driver username: root password: lzh ## Redis 配置 redis: ## Redis数据库索引(默认为0) database: 0 ## Redis服务器地址 host: 192.168.126.129 ## Redis服务器连接端口 port: 6379 ## Redis服务器连接密码(默认为空) password: jedis: pool: ## 连接池最大连接数(使用负值表示没有限制) #spring.redis.pool.max-active=8 max-active: 8 ## 连接池最大阻塞等待时间(使用负值表示没有限制) #spring.redis.pool.max-wait=-1 max-wait: -1 ## 连接池中的最大空闲连接 #spring.redis.pool.max-idle=8 max-idle: 8 ## 连接池中的最小空闲连接 #spring.redis.pool.min-idle=0 min-idle: 0 ## 连接超时时间(毫秒) timeout: 1200 #将themilef的默认缓存禁用,热加载生效 thymeleaf: cache: false #mybatis的下划线转驼峰配置 configuration: map-underscore-to-camel-case: true #另外一种打印语句的方式 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl#打印sql时的语句logging: level: com: acong: dao: debug file: d:/logs/bsbdj.log
3.配置类
package com.example.demo2.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.cache.CacheManager;import org.springframework.cache.annotation.CachingConfigurerSupport;import org.springframework.cache.annotation.EnableCaching;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheConfiguration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.cache.RedisCacheWriter;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import java.time.Duration;@Configuration@EnableCachingpublic class RedisConfig extends CachingConfigurerSupport { //缓存管理器,确定使用何种缓冲 @Bean public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时 return RedisCacheManager .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)) .cacheDefaults(redisCacheConfiguration).build(); } @Bean public RedisTemplate redisTemplate(RedisConnectionFactory factory){ StringRedisTemplate template = new StringRedisTemplate(factory); setSerializer(template);//设置序列化工具 template.afterPropertiesSet(); return template; } private void setSerializer(StringRedisTemplate template){ @SuppressWarnings({ "rawtypes", "unchecked" }) Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setValueSerializer(jackson2JsonRedisSerializer); }}
说明:
- @EnableCaching:注解是spring framework中的注解驱动的缓存管理功能。自spring版本3.1起加入了该注解。如果你使用了这个注解,那么你就不需要在XML文件中配置cache manager了,表示缓冲功能开启,可以用在启动类或配置类上。
- @Cacheable:在方法执行前Spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;没有则调用方法并将方法返回值放进缓存。用在方法上。
- @CacheEvict:调用方法后从缓存中删除对应key的数据。用在方法上。
- @Caching:当一个方法需要查询多个缓存或者删除多个缓存时使用。
- @CacheConfig:抽取类中的所有@CachePut@Cacheable@CacheEvict的公共配置,配置一些共有的缓存配置。
4.Mapper持久层Dao,这里主要用注解写比较方便,也可以使用mybatis的xml配置文件写sql语句。
@Mapperpublic interface ProductMapper { @Select("select * from tb_product where product_id=#{id}") Product getProductById(Long id); @Update("update tb_product set product_name=#{productName},product_desc=#{productDesc} WHERE product_id=#{productId}") int updateProduct(Product product); @Delete("delete from tb_product where product_id=#{id}") void deleteProductById(Long id); @Select("select * from tb_product where product_name=#{productName}") Product getProductByName(String productName);}
5.Service
package com.sl.cache.service;import com.sl.cache.entity.Product;import com.sl.cache.mapper.ProductMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.annotation.CacheConfig;import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.springframework.cache.annotation.Caching;import org.springframework.stereotype.Service;@Service@CacheConfig(cacheNames = "product")public class ProductService { @Autowired private ProductMapper productMapper; @Cacheable(/*cacheNames = "product",*/key = "#root.methodName+'['+#id+']'") //@Cacheable(cacheNames = {"product","product2"})// 默认key为参数,多个参数SimpleKey [arg1,arg2] //@Cacheable(cacheNames = "product",key = "#root.methodName+'['+#id+']'") //@Cacheable(cacheNames = "product",keyGenerator = "myKeyGenerator") //@Cacheable(cacheNames = "product",key = "#root.methodName+'['+#id+']'",condition="#a0>10",unless = "#a0==11") //或者condition="#id>10") public Product getProductById(Long id){ Product product =productMapper.getProductById(id); System.out.println(product); return product; } @CachePut(/*value="product",*/key = "#result.productId",condition = "#result!=null") public Product updateProduct(Product product){ int count = productMapper.updateProduct(product); System.out.println("影响行数:"+count); if(count>0){ return product; }else{ return null; } } //@CacheEvict(value="product",key="#id") //@CacheEvict(value="product",allEntries = true) //清楚所有缓存 @CacheEvict(/*value="product",*/allEntries = true,beforeInvocation = true) //清楚所有缓存 public boolean deleteProductById(Long id) { productMapper.deleteProductById(id); return true; } //含有CachePut注解,所以执行这个方法时一定会查询数据库,即使有cacheable注解 @Caching( cacheable = {@Cacheable(/*value="product",*/key="#productName")}, put = { @CachePut(/*value="product",*/key="#result.productId"), @CachePut(/*value="product",*/key="#result.productName") } ) public Product getProductByName(String productName){ Product product =productMapper.getProductByName(productName); return product; }}
6.Controller
package com.sl.cache.controller;import com.sl.cache.entity.Product;import com.sl.cache.service.ProductService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.stereotype.Service;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class ProductController { @Autowired private ProductService productService; @GetMapping("/product/{id}") public Product getProduct(@PathVariable("id") Long id) { Product product = productService.getProductById(id); return product; } //prooduct?productid=1&productName= & @GetMapping("/product") public Product updateProduct(Product product) { productService.updateProduct(product); return product; } @GetMapping("/delproduct") public String delProduct(@RequestParam(value="id") Long id) { productService.deleteProductById(id); return "ok"; } @GetMapping("/product/name/{productName}") public Product getEmpByLastName(@PathVariable("productName") String productName){ return productService.getProductByName(productName); }}
7.启动类
@MapperScan("com.sl.cache.mapper")@SpringBootApplication//@EnableCachingpublic class SpringbootCacheApplication { public static void main(String[] args) { SpringApplication.run(SpringbootCacheApplication.class, args); }}
总结:以上介绍了两种使用Redis的方式,第一种是直接将数据存到Redis数据库中,第二种是基于数据库使用Redis缓冲!!!