Redis实战-详细配置-优雅的使用Redis注解/RedisTemplate
1. 简介
当我们对redis的基本知识有一定的了解后,我们再通过实战的角度学习一下在SpringBoot环境下,如何优雅的使用redis。
我们通过使用SpringBoot内置的Redis注解(文章最后有解释)来操作User相关的信息,
再通过Redis工具类的方式操作Role相关信息来全面的学习Redis的使用。
嫌篇幅太长的 可以直接跳到2.6查看具体逻辑即可。
2. 开撸
2.1 项目结构
结构说明:
├── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── ldx
│ │ └── redis
│ │ ├── RedisApplication.java # 启动类
│ │ ├── config
│ │ │ └── RedisConfig.java # redis 配置类
│ │ ├── constant
│ │ │ └── CacheConstant.java # 缓存key常量类
│ │ ├── controller
│ │ │ ├── RoleController.java # 角色管理控制器
│ │ │ └── UserController.java # 用户管理控制器
│ │ ├── entity
│ │ │ ├── SysRole.java # 角色entity
│ │ │ └── SysUser.java # 用户entity
│ │ ├── mapper
│ │ │ ├── SysRoleMapper.java # 角色持久层
│ │ │ └── SysUserMapper.java # 用户持久层
│ │ ├── service
│ │ │ ├── SysRoleService.java # 角色接口层
│ │ │ ├── SysUserService.java # 用户接口层
│ │ │ └── impl
│ │ │ ├── SysRoleServiceImpl.java # 角色接口实现层
│ │ │ └── SysUserServiceImpl.java # 用户接口实现层
│ │ └── util
│ │ └── RedisUtil.java # redis 工具类
│ └── resources
│ └── application.yaml # 系统配置文件
└── pom.xml # 依赖管理
2.2 导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ldx</groupId>
<artifactId>redis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>redis</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--spring-web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- lettuce pool -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- lombok 工具包 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.3 项目基本配置
2.3.1 application.yaml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
type: com.zaxxer.hikari.HikariDataSource
# redis 配置
redis:
# 地址
host: localhost
# 端口,默认为6379
port: 6379
# 密码
password:
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
mybatis-plus:
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mapper-locations: classpath*:mapper/*.xml
# 设置别名包扫描路径,通过该属性可以给包中的类注册别名
type-aliases-package: com.ldx.redis.entity
configuration:
# 控制台sql打印
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 日志配置
logging:
level:
com.ldx.redis.service.impl: debug
org.springframework: warn
2.3.2 启动类
@EnableCaching
:激活缓存支持
@MapperScan
: 扫描mapper接口层
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
/**
* 启动类
* @author ludangxin
* @date 2021/8/11
*/
@EnableCaching
@MapperScan(basePackages = "com.ldx.redis.mapper")
@SpringBootApplication
public class RedisApplication {
public static void main(String[] args) {
SpringApplication.run(RedisApplication.class, args);
}
}
2.4 redis配置
2.4.1 RedisConfig
我们除了在application.yaml中加入redis的基本配置外,一般还需要配置redis key和value的序列化方式,如下:
注解:
其默认的序列化方式为
JdkSerializationRedisSerializer
,这种方式跨语言和可读性都不太好,我们将其切换为Jackson2JsonRedisSerializer
。可以使用
entryTtl()
为对应的模块设置过期时长。
redisTemplate:参考redisTemplate()
。
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ldx.redis.constant.CacheConstant;
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.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
* redis配置类
* @author ludangxin
* @date 2021/8/11
*/
@Configuration
public class RedisConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
//设置不同cacheName的过期时间
Map<String, RedisCacheConfiguration> configurations = new HashMap<>(16);
// 序列化方式
Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = getJsonRedisSerializer();
RedisSerializationContext.SerializationPair<Object> serializationPair =
RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer);
// 默认的缓存时间
Duration defaultTtl = Duration.ofSeconds(20L);
// 用户模块的缓存时间
Duration userTtl = Duration.ofSeconds(50L);
// 默认的缓存配置
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
//.entryTtl(defaultTtl)
.serializeValuesWith(serializationPair);
// 自定义用户模块的缓存配置 自定义的配置可以覆盖默认配置(当前的模块)
configurations.put(CacheConstant.USER_CACHE_NAME, RedisCacheConfiguration.defaultCacheConfig()
//.entryTtl(userTtl)
.serializeValuesWith(serializationPair)
);
return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory))
.cacheDefaults(redisCacheConfiguration)
.withInitialCacheConfigurations(configurations)
// 事物支持
.transactionAware()
.build();
}
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = getJsonRedisSerializer();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jsonRedisSerializer);
// 支持事物
//template.setEnableTransactionSupport(true);
template.afterPropertiesSet();
return template;
}
/**
* 设置jackson的序列化方式
*/
private Jackson2JsonRedisSerializer<Object> getJsonRedisSerializer() {
Jackson2JsonRedisSerializer<Object> redisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
redisSerializer.setObjectMapper(om);
return redisSerializer;
}
}
2.4.1 CacheConstant
我们为了防止redis中key的重复,尽量会给不同的数据主体加上不同的前缀,这样我们在查看和统计的时候也方便操作。
/**
* 缓存key 常量类
* @author ludangxin
* @date 2021/8/11
*/
public interface CacheConstant {
/**
* 用户cache name
*/
String USER_CACHE_NAME = "user_cache";
/**
* 用户信息缓存key前缀
*/
String USER_CACHE_KEY_PREFIX = "user_";
/**
* 角色cache name
*/
String ROLE_CACHE_NAME = "role_cache";
/**
* 角色信息缓存key前缀
*/
String ROLE_CACHE_KEY_PREFIX = "role_";
/**
* 获取角色cache key
* @param suffix 后缀
* @return key
*/
static String getRoleCacheKey(String suffix) {
return ROLE_CACHE_NAME + "::" + ROLE_CACHE_KEY_PREFIX + suffix;
}
}
2.4.2 RedisUtil
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* spring redis 工具类
* @author ludangxin
**/
@Component
@RequiredArgsConstructor
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public class RedisUtil {
public final RedisTemplate redisTemplate;
/**
* 缓存基本的对象,Integer、String、实体类等
* @param key 缓存的键值
* @param value 缓存的值
* @return 缓存的对象
*/
public <T> ValueOperations<String, T> setCacheObject(String key, T value) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
operation.set(key, value);
return operation;
}
/**
* 缓存基本的对象,Integer、String、实体类等
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
* @return 缓存的对象
*/
public <T> ValueOperations<String, T> setCacheObject(String key, T value, Integer timeout, TimeUnit timeUnit) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
operation.set(key, value, timeout, timeUnit);
return operation;
}
/**
* 获得缓存的基本对象。
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(String key) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 删除单个对象
* @param key
*/
public void deleteObject(String key) {
redisTemplate.delete(key);
}
/**
* 删除集合对象
* @param collection
*/
public void deleteObject(Collection collection) {
redisTemplate.delete(collection);
}
/**
* 缓存List数据
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList) {
ListOperations listOperation = redisTemplate.opsForList();
if (null != dataList) {
int size = dataList.size();
for (int i = 0; i < size; i++) {
listOperation.leftPush(key, dataList.get(i));
}
}
return listOperation;
}
/**
* 获得缓存的list对象
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public <T> List<T> getCacheList(String key) {
List<T> dataList = new ArrayList<T>();
ListOperations<String, T> listOperation = redisTemplate.opsForList();
Long size = listOperation.size(key);
for (int i = 0; i < size; i++) {
dataList.add(listOperation.index(key, i));
}
return dataList;
}
/**
* 缓存Set
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> BoundSetOperations<String, T> setCacheSet(String key, Set<T> dataSet) {
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
Iterator<T> it = dataSet.iterator();
while (it.hasNext()) {
setOperation.add(it.next());
}
return setOperation;
}
/**
* 获得缓存的set
* @param key
* @return
*/
public <T> Set<T> getCacheSet(String key) {
Set<T> dataSet = new HashSet<T>();
BoundSetOperations<String, T> operation = redisTemplate.boundSetOps(key);
dataSet = operation.members();
return dataSet;
}
/**
* 缓存Map
* @param key
* @param dataMap
* @return
*/
public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap) {
HashOperations hashOperations = redisTemplate.opsForHash();
if (null != dataMap) {
for (Map.Entry<String, T> entry : dataMap.entrySet()) {
hashOperations.put(key, entry.getKey(), entry.getValue());
}
}
return hashOperations;
}
/**
* 获得缓存的Map
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(String key) {
Map<String, T> map = redisTemplate.opsForHash().entries(key);
return map;
}
/**
* 获得缓存的基本对象列表
* @param pattern 字符串前缀
* @return 对象列表
*/
public Collection<String> keys(String pattern) {
return redisTemplate.keys(pattern);
}
}
2.5 controller
2.5.1 UserController
import com.ldx.redis.entity.SysUser;
import com.ldx.redis.service.SysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 用户管理
* @author ludangxin
* @date 2021/8/11
*/
@RestController
@RequestMapping("user")
@RequiredArgsConstructor
public class UserController {
private final SysUserService userService;
@GetMapping
public List<SysUser> queryAll() {
return userService.queryAll();
}
@GetMapping("{userId}")
public SysUser getUserInfo(@PathVariable Long userId) {
return userService.getUserInfo(userId);
}
@PostMapping
public String add(@RequestBody SysUser user) {
userService.add(user);
return "新增成功~";
}
@PutMapping("{userId}")
public String update(@PathVariable Long userId, @RequestBody SysUser user) {
userService.update(userId, user);
return "更新成功~";
}
@DeleteMapping("{userId}")
public String del(@PathVariable Long userId) {
userService.delete(userId);
return "删除成功~";
}
}
2.5.2 RoleController
import com.ldx.redis.entity.SysRole;
import com.ldx.redis.service.SysRoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 角色管理
* @author ludangxin
* @date 2021/8/12
*/
@RestController
@RequestMapping("role")
@RequiredArgsConstructor
public class RoleController {
private final SysRoleService roleService;
@GetMapping
public List<SysRole> queryAll() {
return roleService.queryAll();
}
@GetMapping("{roleId}")
public SysRole getUserInfo(@PathVariable Long roleId) {
return roleService.getRoleInfo(roleId);
}
@PostMapping
public String add(@RequestBody SysRole role) {
roleService.add(role);
return "新增成功~";
}
@PutMapping("{roleId}")
public String update(@PathVariable Long roleId, @RequestBody SysRole role) {
roleService.update(roleId, role);
return "更新成功~";
}
@DeleteMapping("{roleId}")
public String del(@PathVariable Long roleId) {
roleService.delete(roleId);
return "删除成功~";
}
}
2.6 service.impl
2.6.1 UserServiceImpl
优雅的使用redis注解实现对数据的缓存
@Cacheable:unless
:当unless
成立时则不缓存。这里判断size
主要是不想将空值存入redis。
CacheConstant.USER_CACHE_KEY_PREFIX + "' + #userId"
:其key = 指定前缀 + 当前方法实参(userId)。
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ldx.redis.constant.CacheConstant;
import com.ldx.redis.entity.SysUser;
import com.ldx.redis.mapper.SysUserMapper;
import com.ldx.redis.service.SysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 用户管理实现
* @author ludangxin
* @date 2021/8/11
*/
@Slf4j
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = CacheConstant.USER_CACHE_NAME)
public class SysUserServiceImpl implements SysUserService {
private final SysUserMapper userMapper;
@Override
@Cacheable(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "all'", unless = "#result.size() == 0")
public List<SysUser> queryAll() {
log.debug("查询全部用户信息~");
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
return userMapper.selectList(queryWrapper);
}
@Override
@Cacheable(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "' + #userId", unless = "#result == null")
public SysUser getUserInfo(Long userId) {
log.debug("查询用户:{} 详情", userId);
return userMapper.selectById(userId);
}
@Override
@CacheEvict(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "all'")
public void add(SysUser user) {
log.debug("新增用户:{}", user.getNickName());
userMapper.insert(user);
}
@Override
@Caching(evict = {@CacheEvict(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "all'"),
@CacheEvict(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "' + #userId")
})
public void update(Long userId, SysUser user) {
log.debug("更新用户:{}", user.getNickName());
user.setId(userId);
userMapper.updateById(user);
}
@Override
@Caching(evict = {@CacheEvict(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "all'"),
@CacheEvict(key = "'" + CacheConstant.USER_CACHE_KEY_PREFIX + "' + #userId")
})
public void delete(Long userId) {
log.debug("删除用户:{}", userId);
userMapper.deleteById(userId);
}
}
2.6.2 SysRoleServiceImpl
使用redis工具类实现对数据的缓存。
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ldx.redis.constant.CacheConstant;
import com.ldx.redis.entity.SysRole;
import com.ldx.redis.mapper.SysRoleMapper;
import com.ldx.redis.service.SysRoleService;
import com.ldx.redis.util.RedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* 角色管理
* @author ludangxin
* @date 2021/8/11
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl implements SysRoleService {
private final SysRoleMapper roleMapper;
private final RedisUtil redisUtil;
String allKey = CacheConstant.getRoleCacheKey("all");
@Override
public List<SysRole> queryAll() {
List<SysRole> roles = redisUtil.getCacheList(allKey);
if(!CollectionUtils.isEmpty(roles)) {
return roles;
}
log.debug("查询全部角色信息~");
LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
List<SysRole> sysRoles = roleMapper.selectList(queryWrapper);
if(CollectionUtils.isEmpty(sysRoles)) {
return Collections.emptyList();
}
redisUtil.setCacheList(allKey, sysRoles);
return sysRoles;
}
@Override
public SysRole getRoleInfo(Long roleId) {
String roleCacheKey = CacheConstant.getRoleCacheKey(String.valueOf(roleId));
SysRole role = redisUtil.getCacheObject(roleCacheKey);
if(Objects.nonNull(role)) {
return role;
}
log.debug("查询角色:{} 详情", roleId);
SysRole sysRole = roleMapper.selectById(roleId);
if(Objects.isNull(sysRole)) {
return null;
}
redisUtil.setCacheObject(roleCacheKey, sysRole);
return sysRole;
}
@Override
public void add(SysRole role) {
log.debug("新增角色:{}", role.getName());
roleMapper.insert(role);
redisUtil.deleteObject(allKey);
}
@Override
public void update(Long roleId, SysRole role) {
log.debug("更新角色:{}", role.getName());
String roleCacheKey = CacheConstant.getRoleCacheKey(String.valueOf(roleId));
role.setId(roleId);
roleMapper.updateById(role);
// 更新缓存
redisUtil.setCacheObject(roleCacheKey,role);
// 清除缓存
redisUtil.deleteObject(allKey);
}
@Override
public void delete(Long roleId) {
log.debug("删除角色:{}", roleId);
roleMapper.deleteById(roleId);
// 清除缓存
redisUtil.deleteObject(CacheConstant.getRoleCacheKey(String.valueOf(roleId)));
redisUtil.deleteObject(allKey);
}
}
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 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空。
// 清空当前cache name下的所有key
@CachEvict(allEntries = true)
3.5 @Caching
@Caching可以使注解组合使用,比如根据id查询用户信息,查询完的结果为{key = id,value = userInfo},但我们现在为了方遍,想用用户的手机号,邮箱等缓存对应用户的信息,这时候我们就要使用@Caching。例:
@Caching(put = {
@CachePut(value = "user", key = "#user.id"),
@CachePut(value = "user", key = "#user.username"),
@CachePut(value = "user", key = "#user.email")
})
public User getUserInfo(User user){
...
return user;
}
Redis实战-详细配置-优雅的使用Redis注解/RedisTemplate的更多相关文章
- Redis实战总结-配置、持久化、复制
Redis的配置主要放置在redis.conf,可以通过修改配置文件实现Redis许多特性,比如复制,持久化,集群等. redis.conf部分配置详解 # 启动redis,显示加载配置redis.c ...
- 小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 ...
- Redis实战篇(一)搭建Redis实例
今天是Redis实战系列的第一讲,先从如何搭建一个Redis实例开始. 下面介绍如何在Docker.Windows.Linux下安装. Docker下安装 1.查看可用的 Redis 版本 访问 Re ...
- Redis实战阅读笔记——第二章(redis重构web)
在性能的要求下,如何用redis重构已有的已有的部分,其实整个例子背后的思路挺好的.在应用缓存的过程中,还有一指标个需要考虑,读写比.
- Redis实战总结-Redis的高可用性
在之前的博客<Redis实战总结-配置.持久化.复制>给出了一种Redis主从复制机制,简单地实现了Redis高可用.然后,如果Master服务器宕机,会导致整个Redis瘫痪,这种方式的 ...
- redis的主从复制配置
redis的主从复制配置 一. 原理 Redis的主从复制功能非常强大,一个master可以拥有多个slave,而一个slave又可以拥有多个slave,如此下去,形成了强大的多级服务器集群架 ...
- 【转载】Redis Sentinel服务配置
转载地址:http://blog.csdn.net/vtopqx/article/details/49247285 redis官网文档:http://www.redis.cn/topics/senti ...
- Spring集成Redis集群(含spring集成redis代码)
代码地址如下:http://www.demodashi.com/demo/11458.html 一.准备工作 安装 Redis 集群 安装参考: http://blog.csdn.net/zk6738 ...
- 在centos7中安装redis,并通过node.js操作redis
引言 最近在学习node.js 连接redis的模块,所以尝试了一下在虚拟机中安装cent OS7,并安装redis,并使用node.js 操作redis.所以顺便做个笔记. 如有不对的地方,欢迎大家 ...
随机推荐
- 27、Tomcat服务的安装与配置
服务器名称 ip地址 slave-node1 172.16.1.91 27.1. Tomcat简介: Tomcat是Apache软件基金会(Apache Software Foundation)的Ja ...
- 9、解决mstsc卡顿的问题:
1.同时按住"win+r"键调出"运行",在方框内输入"cmd"后点击"确定"打开dos窗口: 2.在dos中输入&qu ...
- Centos下安装最新版本Git
git是一个分布式版本控制系统 我们在Centos上安装GIT有好几种方式.这里我们用最简单的yum命令方式 一步到位,省了下载编译安装这些繁琐过程. 输入命令: yum install -y git ...
- XCTF(MISC) 图片隐写
题目描述:菜猫给了菜狗一张图,说图下面什么都没有 1.给了个pdf,打开是这玩意 2.盲猜flag是图片后面,右键直接删除图片试试. 答案出来了.
- 160crackme002
一.查壳 结果:vb写的,并且无壳 二.运行程序 发现了这个程度调用了vb调用窗口的api.这时有两种方式: 1.再重新调试,运行到有窗口的时候,F12暂停,按ctrl+K,查看dll调用,再数据窗口 ...
- 保存TextBox中的文字为Path功能
保存TextBox中的文字为Path功能 今天再设计一个我自己程序的Icon时使用了Path+textbox做了图形,我不想导出为PNG,因为颜色比较单一,我又想通过代码控制颜色,所以我想完整的保存为 ...
- 2021最新WordPress安装教程(二):安装PHP和MySQL
这是 2021最新WordPress安装教程系列的第二篇文章,前一篇文章< 2021最新WordPress安装教程(一):Centos7安装Apache>已经完整的介绍了如何在Centos ...
- 攻防世界-crypto-Decrypt-the-Message(Poem Codes-诗歌密码)
题目来源:su-ctf-quals-2014题目描述:解密这段信息! 下载附件,内容如下 The life that I have Is all that I have And the life th ...
- 学习总结 NCRE二级和三级
NCRE二级C语言 证书 考试感想 2016年考的认证,5年过去了,"光阴荏苒真容易".趁着心有余力有余的时候,把一些个人的体会分享给大家,希望后来人能平稳前行. Windows ...
- 啥是 MySQL 事务隔离级别?
之前发过一篇文章,简单了解 MySQL 中相关的锁,里面提到了,如果我们使用的 MySQL 存储引擎为 InnoDB ,并且其事务隔离级别是 RR 可重复读的话,是可以避免幻读的. 但是没想到,都 1 ...