1. 简介

当我们对redis的基本知识有一定的了解后,我们再通过实战的角度学习一下在SpringBoot环境下,如何优雅的使用redis。

我们通过使用SpringBoot内置的Redis注解(文章最后有解释)来操作User相关的信息,

再通过Redis工具类的方式操作Role相关信息来全面的学习Redis的使用。

嫌篇幅太长的 可以直接跳到2.6查看具体逻辑即可。

2. 开撸

2.1 项目结构

结构说明:

  1. ├── src
  2.    └── main
  3.    ├── java
  4.       └── com
  5.       └── ldx
  6.       └── redis
  7.       ├── RedisApplication.java # 启动类
  8.       ├── config
  9.          └── RedisConfig.java # redis 配置类
  10.       ├── constant
  11.          └── CacheConstant.java # 缓存key常量类
  12.       ├── controller
  13.          ├── RoleController.java # 角色管理控制器
  14.          └── UserController.java # 用户管理控制器
  15.       ├── entity
  16.          ├── SysRole.java # 角色entity
  17.          └── SysUser.java # 用户entity
  18.       ├── mapper
  19.          ├── SysRoleMapper.java # 角色持久层
  20.          └── SysUserMapper.java # 用户持久层
  21.       ├── service
  22.          ├── SysRoleService.java # 角色接口层
  23.          ├── SysUserService.java # 用户接口层
  24.          └── impl
  25.          ├── SysRoleServiceImpl.java # 角色接口实现层
  26.          └── SysUserServiceImpl.java # 用户接口实现层
  27.       └── util
  28.       └── RedisUtil.java # redis 工具类
  29.    └── resources
  30.    └── application.yaml # 系统配置文件
  31. └── pom.xml # 依赖管理

2.2 导入依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.5.3</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.ldx</groupId>
  12. <artifactId>redis</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>redis</name>
  15. <description>Demo project for Spring Boot</description>
  16. <properties>
  17. <java.version>1.8</java.version>
  18. </properties>
  19. <dependencies>
  20. <!--spring-web-->
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter-web</artifactId>
  24. </dependency>
  25. <!-- redis -->
  26. <dependency>
  27. <groupId>org.springframework.boot</groupId>
  28. <artifactId>spring-boot-starter-data-redis</artifactId>
  29. </dependency>
  30. <!-- lettuce pool -->
  31. <dependency>
  32. <groupId>org.apache.commons</groupId>
  33. <artifactId>commons-pool2</artifactId>
  34. </dependency>
  35. <!-- mybatis-plus -->
  36. <dependency>
  37. <groupId>com.baomidou</groupId>
  38. <artifactId>mybatis-plus-boot-starter</artifactId>
  39. <version>3.4.2</version>
  40. </dependency>
  41. <!-- mysql驱动 -->
  42. <dependency>
  43. <groupId>mysql</groupId>
  44. <artifactId>mysql-connector-java</artifactId>
  45. </dependency>
  46. <!-- lombok 工具包 -->
  47. <dependency>
  48. <groupId>org.projectlombok</groupId>
  49. <artifactId>lombok</artifactId>
  50. <optional>true</optional>
  51. </dependency>
  52. </dependencies>
  53. <build>
  54. <plugins>
  55. <plugin>
  56. <groupId>org.springframework.boot</groupId>
  57. <artifactId>spring-boot-maven-plugin</artifactId>
  58. <configuration>
  59. <excludes>
  60. <exclude>
  61. <groupId>org.projectlombok</groupId>
  62. <artifactId>lombok</artifactId>
  63. </exclude>
  64. </excludes>
  65. </configuration>
  66. </plugin>
  67. </plugins>
  68. </build>
  69. </project>

2.3 项目基本配置

2.3.1 application.yaml

  1. spring:
  2. datasource:
  3. driver-class-name: com.mysql.cj.jdbc.Driver
  4. url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
  5. username: root
  6. password: 123456
  7. type: com.zaxxer.hikari.HikariDataSource
  8. # redis 配置
  9. redis:
  10. # 地址
  11. host: localhost
  12. # 端口,默认为6379
  13. port: 6379
  14. # 密码
  15. password:
  16. # 连接超时时间
  17. timeout: 10s
  18. lettuce:
  19. pool:
  20. # 连接池中的最小空闲连接
  21. min-idle: 0
  22. # 连接池中的最大空闲连接
  23. max-idle: 8
  24. # 连接池的最大数据库连接数
  25. max-active: 8
  26. # #连接池最大阻塞等待时间(使用负值表示没有限制)
  27. max-wait: -1ms
  28. mybatis-plus:
  29. # 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
  30. mapper-locations: classpath*:mapper/*.xml
  31. # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  32. type-aliases-package: com.ldx.redis.entity
  33. configuration:
  34. # 控制台sql打印
  35. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  36. # 日志配置
  37. logging:
  38. level:
  39. com.ldx.redis.service.impl: debug
  40. org.springframework: warn

2.3.2 启动类

@EnableCaching:激活缓存支持

@MapperScan: 扫描mapper接口层

  1. import org.mybatis.spring.annotation.MapperScan;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cache.annotation.EnableCaching;
  5. /**
  6. * 启动类
  7. * @author ludangxin
  8. * @date 2021/8/11
  9. */
  10. @EnableCaching
  11. @MapperScan(basePackages = "com.ldx.redis.mapper")
  12. @SpringBootApplication
  13. public class RedisApplication {
  14. public static void main(String[] args) {
  15. SpringApplication.run(RedisApplication.class, args);
  16. }
  17. }

2.4 redis配置

2.4.1 RedisConfig

我们除了在application.yaml中加入redis的基本配置外,一般还需要配置redis key和value的序列化方式,如下:

注解:

  1. 其默认的序列化方式为JdkSerializationRedisSerializer,这种方式跨语言和可读性都不太好,我们将其切换为Jackson2JsonRedisSerializer

  2. 可以使用entryTtl()为对应的模块设置过期时长。

redisTemplate:参考redisTemplate()

  1. import com.fasterxml.jackson.annotation.JsonAutoDetect;
  2. import com.fasterxml.jackson.annotation.PropertyAccessor;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import com.ldx.redis.constant.CacheConstant;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. import org.springframework.data.redis.cache.RedisCacheConfiguration;
  8. import org.springframework.data.redis.cache.RedisCacheManager;
  9. import org.springframework.data.redis.cache.RedisCacheWriter;
  10. import org.springframework.data.redis.connection.RedisConnectionFactory;
  11. import org.springframework.data.redis.core.RedisTemplate;
  12. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
  13. import org.springframework.data.redis.serializer.RedisSerializationContext;
  14. import org.springframework.data.redis.serializer.StringRedisSerializer;
  15. import java.time.Duration;
  16. import java.util.HashMap;
  17. import java.util.Map;
  18. /**
  19. * redis配置类
  20. * @author ludangxin
  21. * @date 2021/8/11
  22. */
  23. @Configuration
  24. public class RedisConfig {
  25. @Bean
  26. public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
  27. //设置不同cacheName的过期时间
  28. Map<String, RedisCacheConfiguration> configurations = new HashMap<>(16);
  29. // 序列化方式
  30. Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = getJsonRedisSerializer();
  31. RedisSerializationContext.SerializationPair<Object> serializationPair =
  32. RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer);
  33. // 默认的缓存时间
  34. Duration defaultTtl = Duration.ofSeconds(20L);
  35. // 用户模块的缓存时间
  36. Duration userTtl = Duration.ofSeconds(50L);
  37. // 默认的缓存配置
  38. RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
  39. //.entryTtl(defaultTtl)
  40. .serializeValuesWith(serializationPair);
  41. // 自定义用户模块的缓存配置 自定义的配置可以覆盖默认配置(当前的模块)
  42. configurations.put(CacheConstant.USER_CACHE_NAME, RedisCacheConfiguration.defaultCacheConfig()
  43. //.entryTtl(userTtl)
  44. .serializeValuesWith(serializationPair)
  45. );
  46. return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory))
  47. .cacheDefaults(redisCacheConfiguration)
  48. .withInitialCacheConfigurations(configurations)
  49. // 事物支持
  50. .transactionAware()
  51. .build();
  52. }
  53. @Bean
  54. public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {
  55. RedisTemplate<Object, Object> template = new RedisTemplate<>();
  56. template.setConnectionFactory(factory);
  57. Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = getJsonRedisSerializer();
  58. StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
  59. // key采用String的序列化方式
  60. template.setKeySerializer(stringRedisSerializer);
  61. // hash的key也采用String的序列化方式
  62. template.setHashKeySerializer(stringRedisSerializer);
  63. // value序列化方式采用jackson
  64. template.setValueSerializer(jsonRedisSerializer);
  65. // hash的value序列化方式采用jackson
  66. template.setHashValueSerializer(jsonRedisSerializer);
  67. // 支持事物
  68. //template.setEnableTransactionSupport(true);
  69. template.afterPropertiesSet();
  70. return template;
  71. }
  72. /**
  73. * 设置jackson的序列化方式
  74. */
  75. private Jackson2JsonRedisSerializer<Object> getJsonRedisSerializer() {
  76. Jackson2JsonRedisSerializer<Object> redisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
  77. ObjectMapper om = new ObjectMapper();
  78. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  79. redisSerializer.setObjectMapper(om);
  80. return redisSerializer;
  81. }
  82. }

2.4.1 CacheConstant

我们为了防止redis中key的重复,尽量会给不同的数据主体加上不同的前缀,这样我们在查看和统计的时候也方便操作。

  1. /**
  2. * 缓存key 常量类
  3. * @author ludangxin
  4. * @date 2021/8/11
  5. */
  6. public interface CacheConstant {
  7. /**
  8. * 用户cache name
  9. */
  10. String USER_CACHE_NAME = "user_cache";
  11. /**
  12. * 用户信息缓存key前缀
  13. */
  14. String USER_CACHE_KEY_PREFIX = "user_";
  15. /**
  16. * 角色cache name
  17. */
  18. String ROLE_CACHE_NAME = "role_cache";
  19. /**
  20. * 角色信息缓存key前缀
  21. */
  22. String ROLE_CACHE_KEY_PREFIX = "role_";
  23. /**
  24. * 获取角色cache key
  25. * @param suffix 后缀
  26. * @return key
  27. */
  28. static String getRoleCacheKey(String suffix) {
  29. return ROLE_CACHE_NAME + "::" + ROLE_CACHE_KEY_PREFIX + suffix;
  30. }
  31. }

2.4.2 RedisUtil

  1. import lombok.RequiredArgsConstructor;
  2. import org.springframework.data.redis.core.*;
  3. import org.springframework.stereotype.Component;
  4. import java.util.*;
  5. import java.util.concurrent.TimeUnit;
  6. /**
  7. * spring redis 工具类
  8. * @author ludangxin
  9. **/
  10. @Component
  11. @RequiredArgsConstructor
  12. @SuppressWarnings(value = { "unchecked", "rawtypes" })
  13. public class RedisUtil {
  14. public final RedisTemplate redisTemplate;
  15. /**
  16. * 缓存基本的对象,Integer、String、实体类等
  17. * @param key 缓存的键值
  18. * @param value 缓存的值
  19. * @return 缓存的对象
  20. */
  21. public <T> ValueOperations<String, T> setCacheObject(String key, T value) {
  22. ValueOperations<String, T> operation = redisTemplate.opsForValue();
  23. operation.set(key, value);
  24. return operation;
  25. }
  26. /**
  27. * 缓存基本的对象,Integer、String、实体类等
  28. * @param key 缓存的键值
  29. * @param value 缓存的值
  30. * @param timeout 时间
  31. * @param timeUnit 时间颗粒度
  32. * @return 缓存的对象
  33. */
  34. public <T> ValueOperations<String, T> setCacheObject(String key, T value, Integer timeout, TimeUnit timeUnit) {
  35. ValueOperations<String, T> operation = redisTemplate.opsForValue();
  36. operation.set(key, value, timeout, timeUnit);
  37. return operation;
  38. }
  39. /**
  40. * 获得缓存的基本对象。
  41. * @param key 缓存键值
  42. * @return 缓存键值对应的数据
  43. */
  44. public <T> T getCacheObject(String key) {
  45. ValueOperations<String, T> operation = redisTemplate.opsForValue();
  46. return operation.get(key);
  47. }
  48. /**
  49. * 删除单个对象
  50. * @param key
  51. */
  52. public void deleteObject(String key) {
  53. redisTemplate.delete(key);
  54. }
  55. /**
  56. * 删除集合对象
  57. * @param collection
  58. */
  59. public void deleteObject(Collection collection) {
  60. redisTemplate.delete(collection);
  61. }
  62. /**
  63. * 缓存List数据
  64. * @param key 缓存的键值
  65. * @param dataList 待缓存的List数据
  66. * @return 缓存的对象
  67. */
  68. public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList) {
  69. ListOperations listOperation = redisTemplate.opsForList();
  70. if (null != dataList) {
  71. int size = dataList.size();
  72. for (int i = 0; i < size; i++) {
  73. listOperation.leftPush(key, dataList.get(i));
  74. }
  75. }
  76. return listOperation;
  77. }
  78. /**
  79. * 获得缓存的list对象
  80. * @param key 缓存的键值
  81. * @return 缓存键值对应的数据
  82. */
  83. public <T> List<T> getCacheList(String key) {
  84. List<T> dataList = new ArrayList<T>();
  85. ListOperations<String, T> listOperation = redisTemplate.opsForList();
  86. Long size = listOperation.size(key);
  87. for (int i = 0; i < size; i++) {
  88. dataList.add(listOperation.index(key, i));
  89. }
  90. return dataList;
  91. }
  92. /**
  93. * 缓存Set
  94. * @param key 缓存键值
  95. * @param dataSet 缓存的数据
  96. * @return 缓存数据的对象
  97. */
  98. public <T> BoundSetOperations<String, T> setCacheSet(String key, Set<T> dataSet) {
  99. BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
  100. Iterator<T> it = dataSet.iterator();
  101. while (it.hasNext()) {
  102. setOperation.add(it.next());
  103. }
  104. return setOperation;
  105. }
  106. /**
  107. * 获得缓存的set
  108. * @param key
  109. * @return
  110. */
  111. public <T> Set<T> getCacheSet(String key) {
  112. Set<T> dataSet = new HashSet<T>();
  113. BoundSetOperations<String, T> operation = redisTemplate.boundSetOps(key);
  114. dataSet = operation.members();
  115. return dataSet;
  116. }
  117. /**
  118. * 缓存Map
  119. * @param key
  120. * @param dataMap
  121. * @return
  122. */
  123. public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap) {
  124. HashOperations hashOperations = redisTemplate.opsForHash();
  125. if (null != dataMap) {
  126. for (Map.Entry<String, T> entry : dataMap.entrySet()) {
  127. hashOperations.put(key, entry.getKey(), entry.getValue());
  128. }
  129. }
  130. return hashOperations;
  131. }
  132. /**
  133. * 获得缓存的Map
  134. * @param key
  135. * @return
  136. */
  137. public <T> Map<String, T> getCacheMap(String key) {
  138. Map<String, T> map = redisTemplate.opsForHash().entries(key);
  139. return map;
  140. }
  141. /**
  142. * 获得缓存的基本对象列表
  143. * @param pattern 字符串前缀
  144. * @return 对象列表
  145. */
  146. public Collection<String> keys(String pattern) {
  147. return redisTemplate.keys(pattern);
  148. }
  149. }

2.5 controller

2.5.1 UserController

  1. import com.ldx.redis.entity.SysUser;
  2. import com.ldx.redis.service.SysUserService;
  3. import lombok.RequiredArgsConstructor;
  4. import org.springframework.web.bind.annotation.*;
  5. import java.util.List;
  6. /**
  7. * 用户管理
  8. * @author ludangxin
  9. * @date 2021/8/11
  10. */
  11. @RestController
  12. @RequestMapping("user")
  13. @RequiredArgsConstructor
  14. public class UserController {
  15. private final SysUserService userService;
  16. @GetMapping
  17. public List<SysUser> queryAll() {
  18. return userService.queryAll();
  19. }
  20. @GetMapping("{userId}")
  21. public SysUser getUserInfo(@PathVariable Long userId) {
  22. return userService.getUserInfo(userId);
  23. }
  24. @PostMapping
  25. public String add(@RequestBody SysUser user) {
  26. userService.add(user);
  27. return "新增成功~";
  28. }
  29. @PutMapping("{userId}")
  30. public String update(@PathVariable Long userId, @RequestBody SysUser user) {
  31. userService.update(userId, user);
  32. return "更新成功~";
  33. }
  34. @DeleteMapping("{userId}")
  35. public String del(@PathVariable Long userId) {
  36. userService.delete(userId);
  37. return "删除成功~";
  38. }
  39. }

2.5.2 RoleController

  1. import com.ldx.redis.entity.SysRole;
  2. import com.ldx.redis.service.SysRoleService;
  3. import lombok.RequiredArgsConstructor;
  4. import org.springframework.web.bind.annotation.*;
  5. import java.util.List;
  6. /**
  7. * 角色管理
  8. * @author ludangxin
  9. * @date 2021/8/12
  10. */
  11. @RestController
  12. @RequestMapping("role")
  13. @RequiredArgsConstructor
  14. public class RoleController {
  15. private final SysRoleService roleService;
  16. @GetMapping
  17. public List<SysRole> queryAll() {
  18. return roleService.queryAll();
  19. }
  20. @GetMapping("{roleId}")
  21. public SysRole getUserInfo(@PathVariable Long roleId) {
  22. return roleService.getRoleInfo(roleId);
  23. }
  24. @PostMapping
  25. public String add(@RequestBody SysRole role) {
  26. roleService.add(role);
  27. return "新增成功~";
  28. }
  29. @PutMapping("{roleId}")
  30. public String update(@PathVariable Long roleId, @RequestBody SysRole role) {
  31. roleService.update(roleId, role);
  32. return "更新成功~";
  33. }
  34. @DeleteMapping("{roleId}")
  35. public String del(@PathVariable Long roleId) {
  36. roleService.delete(roleId);
  37. return "删除成功~";
  38. }
  39. }

2.6 service.impl

2.6.1 UserServiceImpl

优雅的使用redis注解实现对数据的缓存

@Cacheable:unless:当unless成立时则不缓存。这里判断size主要是不想将空值存入redis。

CacheConstant.USER_CACHE_KEY_PREFIX + "' + #userId":其key = 指定前缀 + 当前方法实参(userId)。

  1. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  2. import com.ldx.redis.constant.CacheConstant;
  3. import com.ldx.redis.entity.SysUser;
  4. import com.ldx.redis.mapper.SysUserMapper;
  5. import com.ldx.redis.service.SysUserService;
  6. import lombok.RequiredArgsConstructor;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.cache.annotation.CacheConfig;
  9. import org.springframework.cache.annotation.CacheEvict;
  10. import org.springframework.cache.annotation.Cacheable;
  11. import org.springframework.cache.annotation.Caching;
  12. import org.springframework.stereotype.Service;
  13. import java.util.List;
  14. /**
  15. * 用户管理实现
  16. * @author ludangxin
  17. * @date 2021/8/11
  18. */
  19. @Slf4j
  20. @Service
  21. @RequiredArgsConstructor
  22. @CacheConfig(cacheNames = CacheConstant.USER_CACHE_NAME)
  23. public class SysUserServiceImpl implements SysUserService {
  24. private final SysUserMapper userMapper;
  25. @Override
  26. @Cacheable(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "all'", unless = "#result.size() == 0")
  27. public List<SysUser> queryAll() {
  28. log.debug("查询全部用户信息~");
  29. LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
  30. return userMapper.selectList(queryWrapper);
  31. }
  32. @Override
  33. @Cacheable(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "' + #userId", unless = "#result == null")
  34. public SysUser getUserInfo(Long userId) {
  35. log.debug("查询用户:{} 详情", userId);
  36. return userMapper.selectById(userId);
  37. }
  38. @Override
  39. @CacheEvict(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "all'")
  40. public void add(SysUser user) {
  41. log.debug("新增用户:{}", user.getNickName());
  42. userMapper.insert(user);
  43. }
  44. @Override
  45. @Caching(evict = {@CacheEvict(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "all'"),
  46. @CacheEvict(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "' + #userId")
  47. })
  48. public void update(Long userId, SysUser user) {
  49. log.debug("更新用户:{}", user.getNickName());
  50. user.setId(userId);
  51. userMapper.updateById(user);
  52. }
  53. @Override
  54. @Caching(evict = {@CacheEvict(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "all'"),
  55. @CacheEvict(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "' + #userId")
  56. })
  57. public void delete(Long userId) {
  58. log.debug("删除用户:{}", userId);
  59. userMapper.deleteById(userId);
  60. }
  61. }

2.6.2 SysRoleServiceImpl

使用redis工具类实现对数据的缓存。

  1. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  2. import com.ldx.redis.constant.CacheConstant;
  3. import com.ldx.redis.entity.SysRole;
  4. import com.ldx.redis.mapper.SysRoleMapper;
  5. import com.ldx.redis.service.SysRoleService;
  6. import com.ldx.redis.util.RedisUtil;
  7. import lombok.RequiredArgsConstructor;
  8. import lombok.extern.slf4j.Slf4j;
  9. import org.springframework.stereotype.Service;
  10. import org.springframework.util.CollectionUtils;
  11. import java.util.Collections;
  12. import java.util.List;
  13. import java.util.Objects;
  14. /**
  15. * 角色管理
  16. * @author ludangxin
  17. * @date 2021/8/11
  18. */
  19. @Slf4j
  20. @Service
  21. @RequiredArgsConstructor
  22. public class SysRoleServiceImpl implements SysRoleService {
  23. private final SysRoleMapper roleMapper;
  24. private final RedisUtil redisUtil;
  25. String allKey = CacheConstant.getRoleCacheKey("all");
  26. @Override
  27. public List<SysRole> queryAll() {
  28. List<SysRole> roles = redisUtil.getCacheList(allKey);
  29. if(!CollectionUtils.isEmpty(roles)) {
  30. return roles;
  31. }
  32. log.debug("查询全部角色信息~");
  33. LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
  34. List<SysRole> sysRoles = roleMapper.selectList(queryWrapper);
  35. if(CollectionUtils.isEmpty(sysRoles)) {
  36. return Collections.emptyList();
  37. }
  38. redisUtil.setCacheList(allKey, sysRoles);
  39. return sysRoles;
  40. }
  41. @Override
  42. public SysRole getRoleInfo(Long roleId) {
  43. String roleCacheKey = CacheConstant.getRoleCacheKey(String.valueOf(roleId));
  44. SysRole role = redisUtil.getCacheObject(roleCacheKey);
  45. if(Objects.nonNull(role)) {
  46. return role;
  47. }
  48. log.debug("查询角色:{} 详情", roleId);
  49. SysRole sysRole = roleMapper.selectById(roleId);
  50. if(Objects.isNull(sysRole)) {
  51. return null;
  52. }
  53. redisUtil.setCacheObject(roleCacheKey, sysRole);
  54. return sysRole;
  55. }
  56. @Override
  57. public void add(SysRole role) {
  58. log.debug("新增角色:{}", role.getName());
  59. roleMapper.insert(role);
  60. redisUtil.deleteObject(allKey);
  61. }
  62. @Override
  63. public void update(Long roleId, SysRole role) {
  64. log.debug("更新角色:{}", role.getName());
  65. String roleCacheKey = CacheConstant.getRoleCacheKey(String.valueOf(roleId));
  66. role.setId(roleId);
  67. roleMapper.updateById(role);
  68. // 更新缓存
  69. redisUtil.setCacheObject(roleCacheKey,role);
  70. // 清除缓存
  71. redisUtil.deleteObject(allKey);
  72. }
  73. @Override
  74. public void delete(Long roleId) {
  75. log.debug("删除角色:{}", roleId);
  76. roleMapper.deleteById(roleId);
  77. // 清除缓存
  78. redisUtil.deleteObject(CacheConstant.getRoleCacheKey(String.valueOf(roleId)));
  79. redisUtil.deleteObject(allKey);
  80. }
  81. }

2.7 启动测试

这里只测试了user模块(都测试并且贴图会显得篇幅太长且繁琐),role模块本人测试后结果正确。

查询列表:

​ 调用接口返回全部数据并缓存完成,再次调用无查询日志输出,符合预期。

​ 接口调用:

​ 查看缓存:

查看用户详情:

​ 接口调用返回用户详情信息并缓存完成,再次调用无查询日志输出,符合预期。

​ 接口调用:

​ 查看缓存:

更新数据:

​ 接口调用返回更新成功,并且查看全部的缓存被清除。符合预期。

​ 接口调用:

​ 查看缓存:

3. 内置缓存注解

3.1 @CacheConfig

@Cacheable()里面都有一个value=“xxx”的属性,这显然如果方法多了,写起来也是挺累的,如果可以一次性声明完 那就省事了, 所以,有了@CacheConfig这个配置,@CacheConfig is a class-level annotation that allows to share the cache names,如果你在你的方法写别的名字,那么依然以方法的名字为准。

3.2 @Cacheable

@Cacheable(value="myCache"),这个注释的意思是,当调用这个方法的时候,会从一个名叫myCache 的缓存中查询,如果没有,则执行实际的方法(即查询数据库),并将执行的结果存入缓存中,否则返回缓存中的对象。

3.3 @CachePut

@CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用。

3.4 @CacheEvict

@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空。

  1. // 清空当前cache name下的所有key
  2. @CachEvict(allEntries = true)

3.5 @Caching

@Caching可以使注解组合使用,比如根据id查询用户信息,查询完的结果为{key = id,value = userInfo},但我们现在为了方遍,想用用户的手机号,邮箱等缓存对应用户的信息,这时候我们就要使用@Caching。例:

  1. @Caching(put = {
  2. @CachePut(value = "user", key = "#user.id"),
  3. @CachePut(value = "user", key = "#user.username"),
  4. @CachePut(value = "user", key = "#user.email")
  5. })
  6. public User getUserInfo(User user){
  7. ...
  8. return user;
  9. }

Redis实战-详细配置-优雅的使用Redis注解/RedisTemplate的更多相关文章

  1. Redis实战总结-配置、持久化、复制

    Redis的配置主要放置在redis.conf,可以通过修改配置文件实现Redis许多特性,比如复制,持久化,集群等. redis.conf部分配置详解 # 启动redis,显示加载配置redis.c ...

  2. 小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_39、SpringBoot2.x整合redis实战讲解

    笔记 3.SpringBoot2.x整合redis实战讲解 简介:使用springboot-starter整合reids实战 1.官网:https://docs.spring.io/spring-bo ...

  3. Redis实战篇(一)搭建Redis实例

    今天是Redis实战系列的第一讲,先从如何搭建一个Redis实例开始. 下面介绍如何在Docker.Windows.Linux下安装. Docker下安装 1.查看可用的 Redis 版本 访问 Re ...

  4. Redis实战阅读笔记——第二章(redis重构web)

    在性能的要求下,如何用redis重构已有的已有的部分,其实整个例子背后的思路挺好的.在应用缓存的过程中,还有一指标个需要考虑,读写比.

  5. Redis实战总结-Redis的高可用性

    在之前的博客<Redis实战总结-配置.持久化.复制>给出了一种Redis主从复制机制,简单地实现了Redis高可用.然后,如果Master服务器宕机,会导致整个Redis瘫痪,这种方式的 ...

  6. redis的主从复制配置

    redis的主从复制配置 一.     原理 Redis的主从复制功能非常强大,一个master可以拥有多个slave,而一个slave又可以拥有多个slave,如此下去,形成了强大的多级服务器集群架 ...

  7. 【转载】Redis Sentinel服务配置

    转载地址:http://blog.csdn.net/vtopqx/article/details/49247285 redis官网文档:http://www.redis.cn/topics/senti ...

  8. Spring集成Redis集群(含spring集成redis代码)

    代码地址如下:http://www.demodashi.com/demo/11458.html 一.准备工作 安装 Redis 集群 安装参考: http://blog.csdn.net/zk6738 ...

  9. 在centos7中安装redis,并通过node.js操作redis

    引言 最近在学习node.js 连接redis的模块,所以尝试了一下在虚拟机中安装cent OS7,并安装redis,并使用node.js 操作redis.所以顺便做个笔记. 如有不对的地方,欢迎大家 ...

随机推荐

  1. 100、nginx_https安全链接配置

    100.1. tcp的三次握手和四次挥手的过程: 1.三次握手(建立连接): 第一次:建立连接时,客户端发送SYN包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次:服务器 ...

  2. IDEA中Springboot启动热部署

    在IDEA中开发springboot项目时,每次修改代码后都需要手动重启项目比较麻烦,可以通过添加一定的配置使每次修改代码后项目进行自动重启 在IDEA中开发springboot项目时,每次修改代码后 ...

  3. MySql:使用Navicat定时备份数据库

    Navicat自带就有备份  还可以直接计划任务,很方便. 1. 新建计划 打开navicat客户端,连上mysql后,双击左边你想要备份的数据库.点击"计划",再点击" ...

  4. Windows软件包管理工具:Scoop

    前言 删库跑路后,Windows系统如何快速安装应用程序,部署环境呢? 以前想过这个问题,最近在安装Hugo时发现使用软件包管理工具可以解决这个问题. 阅读建议 首先需要测试下载速度,尝试从官网下载, ...

  5. ROS2学习之旅(12)——创建工作空间

    workspace(工作空间)是包含ROS2 packages(包)的文件夹.在使用ROS 2之前,有必要在终端中source一下ROS 2的安装工作区,这样就可以在该终端中使用ROS 2的软件包. ...

  6. 如何修改Windows 11 任务栏大小

    1.首先Win+R输入regedit打开注册表编辑器         2.进入注册表编辑器后,在地址栏中输入: HKEY_CURRENT_USER\Software\Microsoft\ Window ...

  7. Java基础00-分支语句6

    1. 流程控制 1.1 流程控制语句概述 1.2 流程控制语句分类 1.3 顺序结构 2. if语句 2.1 if语句格式1 适合一种情况的判断 执行流程图: 2.2 if语句格式2 适合两种情况的判 ...

  8. [010] - JavaSE面试题(十):集合之Map

    第一期:Java面试 - 100题,梳理各大网站优秀面试题.大家可以跟着我一起来刷刷Java理论知识 [010] - JavaSE面试题(十):集合之Map 第1问:HashMap和HashTable ...

  9. .netcore第三方登录授权:10分钟急速接入

    前言 很多对外应用的开发都考虑接入第三方登录来提高用户的体验感,避免用户进行繁琐的注册登录(登录后的完善资料必不可免). 而QQ.微信.支付宝.淘宝.微博等应用就是首选目标(无他,用户群体大,支持发开 ...

  10. TypeScript——原始数据类型

    TypeScript原始数据类型 原始数据类型包括:布尔值.数值.字符串.null.undefined. Symbol.BigInt. 布尔值: let isDone: boolean = false ...