SpringBoot中整合Redis

超、凢脫俗 2022-12-17 10:53 182阅读 0赞

实际开发中缓存处理是必须的,不可能我们每次客户端去请求一次服务器,服务器每次都要去数据库中进行查找,为什么要使用缓存?说到底是为了提高系统的运行速度。将用户频繁访问的内容存放在离用户最近,访问速度最快的地方,提高用户的响 应速度,今天先来讲下在springboot中整合redis的详细步骤。

一、安装

首先要在本地安装一个redis程序,redis下载地址,安装过程十分简单(略过),安装完成后进入到redis文件夹中可以看到如下:

f4da68d9a5dfca4c3e1084867df05e2a.png

点击redis-server.exe开启redis服务,可以看到如下图所示即代表开启redis服务成功:

149084f0ebf6158d3792166028e4b3bc.png

那么我们可以开启redis客户端进行测试:

8e09732f911627134efd4194608d831a.png

二、整合到springboot

1、在项目中加入redis依赖,pom文件中添加如下:

  1. <!-- 整合Redis缓存支持 -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-data-redis</artifactId>
  5. </dependency>

2、在application.yml中添加redis配置:

  1. ##默认密码为空
  2. redis:
  3. host: 127.0.0.1
  4. # Redis服务器连接端口
  5. port: 6379
  6. jedis:
  7. pool:
  8. #连接池最大连接数(使用负值表示没有限制)
  9. max-active: 100
  10. # 连接池中的最小空闲连接
  11. max-idle: 10
  12. # 连接池最大阻塞等待时间(使用负值表示没有限制)
  13. max-wait: 100000
  14. # 连接超时时间(毫秒)
  15. timeout: 5000
  16. #默认是索引为0的数据库
  17. database: 0

3、新建RedisConfiguration配置类,继承CachingConfigurerSupport,@EnableCaching开启注解

  1. @Configuration
  2. @EnableCaching
  3. public class RedisConfiguration extends CachingConfigurerSupport {
  4. /**
  5. * 自定义生成key的规则
  6. */
  7. @Override
  8. public KeyGenerator keyGenerator() {
  9. return new KeyGenerator() {
  10. @Override
  11. public Object generate(Object o, Method method, Object... objects) {
  12. //格式化缓存key字符串
  13. StringBuilder sb = new StringBuilder();
  14. //追加类名
  15. sb.append(o.getClass().getName());
  16. //追加方法名
  17. sb.append(method.getName());
  18. //遍历参数并且追加
  19. for (Object obj : objects) {
  20. sb.append(obj.toString());
  21. }
  22. System.out.println("调用Redis缓存Key : " + sb.toString());
  23. return sb.toString();
  24. }
  25. };
  26. }
  27. /**
  28. * 采用RedisCacheManager作为缓存管理器
  29. * @param connectionFactory
  30. */
  31. @Bean
  32. public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
  33. RedisCacheManager redisCacheManager = RedisCacheManager.create(connectionFactory);
  34. return redisCacheManager;
  35. }
  36. @Bean
  37. public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
  38. 解决键、值序列化问题
  39. StringRedisTemplate template = new StringRedisTemplate(factory);
  40. Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
  41. ObjectMapper om = new ObjectMapper();
  42. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  43. om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  44. jackson2JsonRedisSerializer.setObjectMapper(om);
  45. template.setValueSerializer(jackson2JsonRedisSerializer);
  46. template.afterPropertiesSet();
  47. return template;
  48. }
  49. }

4、创建自定义的接口来定义需要的redis的功能

  1. /**
  2. * K 指以hash结构操作时 键类型
  3. * T 为数据实体 应实现序列化接口,并定义serialVersionUID * RedisTemplate 提供了五种数据结构操作类型 hash / list / set / zset / value
  4. * 方法命名格式为 数据操作类型 + 操作 如 hashPut 指以hash结构(也就是map)想key添加键值对
  5. */
  6. public interface RedisHelper<HK, T> {
  7. /**
  8. * Hash结构 添加元素 * @param key key * @param hashKey hashKey * @param domain 元素
  9. */
  10. void hashPut(String key, HK hashKey, T domain);
  11. /**
  12. * Hash结构 获取指定key所有键值对 * @param key * @return
  13. */
  14. Map<HK, T> hashFindAll(String key);
  15. /**
  16. * Hash结构 获取单个元素 * @param key * @param hashKey * @return
  17. */
  18. T hashGet(String key, HK hashKey);
  19. void hashRemove(String key, HK hashKey);
  20. /**
  21. * List结构 向尾部(Right)添加元素 * @param key * @param domain * @return
  22. */
  23. Long listPush(String key, T domain);
  24. /**
  25. * List结构 向头部(Left)添加元素 * @param key * @param domain * @return
  26. */
  27. Long listUnshift(String key, T domain);
  28. /**
  29. * List结构 获取所有元素 * @param key * @return
  30. */
  31. List<T> listFindAll(String key);
  32. /**
  33. * List结构 移除并获取数组第一个元素 * @param key * @return
  34. */
  35. T listLPop(String key);
  36. /**
  37. * 对象的实体类
  38. * @param key
  39. * @param domain
  40. * @return
  41. */
  42. void valuePut(String key, T domain);
  43. /**
  44. * 获取对象实体类
  45. * @param key
  46. * @return
  47. */
  48. T getValue(String key);
  49. void remove(String key);
  50. /**
  51. * 设置过期时间 * @param key 键 * @param timeout 时间 * @param timeUnit 时间单位
  52. */
  53. boolean expirse(String key, long timeout, TimeUnit timeUnit);
  54. }

下面是创建RedisHelperImpl进行接口的实现

  1. @Service("RedisHelper")
  2. public class RedisHelperImpl<HK, T> implements RedisHelper<HK, T> {
  3. // 在构造器中获取redisTemplate实例, key(not hashKey) 默认使用String类型
  4. private RedisTemplate<String, T> redisTemplate;
  5. // 在构造器中通过redisTemplate的工厂方法实例化操作对象
  6. private HashOperations<String, HK, T> hashOperations;
  7. private ListOperations<String, T> listOperations;
  8. private ZSetOperations<String, T> zSetOperations;
  9. private SetOperations<String, T> setOperations;
  10. private ValueOperations<String, T> valueOperations;
  11. // IDEA虽然报错,但是依然可以注入成功, 实例化操作对象后就可以直接调用方法操作Redis数据库
  12. @Autowired
  13. public RedisHelperImpl(RedisTemplate<String, T> redisTemplate) {
  14. this.redisTemplate = redisTemplate;
  15. this.hashOperations = redisTemplate.opsForHash();
  16. this.listOperations = redisTemplate.opsForList();
  17. this.zSetOperations = redisTemplate.opsForZSet();
  18. this.setOperations = redisTemplate.opsForSet();
  19. this.valueOperations = redisTemplate.opsForValue();
  20. }
  21. @Override
  22. public void hashPut(String key, HK hashKey, T domain) {
  23. hashOperations.put(key, hashKey, domain);
  24. }
  25. @Override
  26. public Map<HK, T> hashFindAll(String key) {
  27. return hashOperations.entries(key);
  28. }
  29. @Override
  30. public T hashGet(String key, HK hashKey) {
  31. return hashOperations.get(key, hashKey);
  32. }
  33. @Override
  34. public void hashRemove(String key, HK hashKey) {
  35. hashOperations.delete(key, hashKey);
  36. }
  37. @Override
  38. public Long listPush(String key, T domain) {
  39. return listOperations.rightPush(key, domain);
  40. }
  41. @Override
  42. public Long listUnshift(String key, T domain) {
  43. return listOperations.leftPush(key, domain);
  44. }
  45. @Override
  46. public List<T> listFindAll(String key) {
  47. if (!redisTemplate.hasKey(key)) {
  48. return null;
  49. }
  50. return listOperations.range(key, 0, listOperations.size(key));
  51. }
  52. @Override
  53. public T listLPop(String key) {
  54. return listOperations.leftPop(key);
  55. }
  56. @Override
  57. public void valuePut(String key, T domain) {
  58. valueOperations.set(key, domain);
  59. }
  60. @Override
  61. public T getValue(String key) {
  62. return valueOperations.get(key);
  63. }
  64. @Override
  65. public void remove(String key) {
  66. redisTemplate.delete(key);
  67. }
  68. @Override
  69. public boolean expirse(String key, long timeout, TimeUnit timeUnit) {
  70. return redisTemplate.expire(key, timeout, timeUnit);
  71. }
  72. }

三、测试

编写TestRedis类进行测试

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class TestRedis {
  4. @Autowired
  5. private StringRedisTemplate stringRedisTemplate;
  6. @Autowired
  7. private RedisTemplate redisTemplate;
  8. @Autowired
  9. private RedisHelperImpl redisHelper;
  10. @Test
  11. public void test() throws Exception{
  12. // 基本写法
  13. // stringRedisTemplate.opsForValue().set("aaa","111");
  14. // Assert.assertEquals("111",stringRedisTemplate.opsForValue().get("aaa"));
  15. // System.out.println(stringRedisTemplate.opsForValue().get("aaa"));
  16. Author user=new Author();
  17. user.setName("Alex");
  18. user.setIntro_l("不会打篮球的程序不是好男人");
  19. redisHelper.valuePut("aaa",user);
  20. System.out.println(redisHelper.getValue("aaa"));
  21. }
  22. @Test
  23. public void testObj() throws Exception {
  24. Author user=new Author();
  25. user.setName("Jerry");
  26. user.setIntro_l("不会打篮球的程序不是好男人!");
  27. ValueOperations<String, Author> operations=redisTemplate.opsForValue();
  28. operations.set("502", user);
  29. Thread.sleep(500);
  30. boolean exists=redisTemplate.hasKey("502");
  31. if(exists){
  32. System.out.println(redisTemplate.opsForValue().get("502"));
  33. }else{
  34. System.out.println("exists is false");
  35. }
  36. // Assert.assertEquals("aa", operations.get("com.neo.f").getUserName());
  37. }
  38. }

运行TestRedis测试类,结果如下:

1c7787cc4bf2fc9b7d568fc76061e176.png

注意:如果在RedisConfiguration中不配置redisTemplate(RedisConnectionFactory factory)注解,会造成键、值的一个序列化问题,有兴趣的可以去试一下。

四、项目实战

首先需要在程序的入口处Application中添加@EnableCaching开启缓存的注解

  1. @EnableCaching //开启缓存
  2. @SpringBootApplication
  3. public class PoetryApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(PoetryApplication.class, args);
  6. }
  7. }

上面的redis相关写法是我们自定义设置并获取的,那么我们经常要在访问接口的地方去使用redis进行缓存相关实体对象以及集合等,那么我们怎么实现呢?比如我现在想在AuthorController中去缓存作者相关信息的缓存数据,该怎么办呢?如下:

  1. @RestController
  2. @RequestMapping(value = "/poem")
  3. public class AuthorController {
  4. private final static Logger logger = LoggerFactory.getLogger(AuthorController.class);
  5. @Autowired
  6. private AuthorRepository authorRepository;
  7. @Cacheable(value="poemInfo") //自动根据方法生成缓存
  8. @PostMapping(value = "/poemInfo")
  9. public Result<Author> author(@RequestParam("author_id") int author_id, @RequestParam("author_name")String author_name) {
  10. if(StringUtils.isEmpty(author_id) || StringUtils.isEmpty(author_name)){
  11. return ResultUtils.error(ResultCode.INVALID_PARAM_EMPTY);
  12. }
  13. Author author;
  14. Optional<Author> optional = authorRepository.getAuthorByIdAndName(author_id, author_name);
  15. if (optional.isPresent()) {
  16. author = optional.get();
  17. //通过\n或者多个空格 进行过滤去重
  18. if (!StringUtils.isEmpty(author.getIntro_l())) {
  19. String s = author.getIntro_l();
  20. String intro = s.split("\\s +")[0];
  21. author.setIntro_l(intro);
  22. }
  23. } else {
  24. return ResultUtils.error(ResultCode.NO_FIND_THINGS);
  25. }
  26. return ResultUtils.ok(author);
  27. }
  28. }

这里 @Cacheable(value=”poemInfo”)这个注解的意思就是自动根据方法生成缓存,value就是缓存下来的key。

发表评论

表情:
评论列表 (有 0 条评论,182人围观)

还没有评论,来说两句吧...

相关阅读

    相关 SpringBoot整合Redis

    实际开发中缓存处理是必须的,不可能我们每次客户端去请求一次服务器,服务器每次都要去数据库中进行查找,为什么要使用缓存?说到底是为了提高系统的运行速度。将用户频繁访问的内容