微信搜一搜:科技猫,获取第一时间更新
本文源码地址:github.com/jonssonyan/…
事先需要自己部署一个Redis,用于之后测试连接,本文操作Redis使用Spring Data Redis框架
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- spring-boot redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
复制代码
Spring Boot配置文件 application.properties
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis数据库索引(默认为0)
#spring.redis.database=
# Redis服务器连接用户名(默认为空)
#spring.redis.username=
# Redis服务器连接密码(默认为空)
#spring.redis.password=
# 连接超时时间(毫秒)
spring.redis.timeout=0
复制代码
Redis配置文件 RedisConfig
@Configuration
@ConditionalOnClass(RedisService.class)
public class RedisConfig {
private RedisTemplate<String, Object> redisTemplate;
@Bean
@ConditionalOnMissingBean
public RedisService redisService() {
return new RedisService(redisTemplate);
}
@Autowired
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
// redis configuration
// -----------------------------------------------------------------------------------------------------------------
/**
* key 的序列化器
*/
private final StringRedisSerializer keyRedisSerializer = new StringRedisSerializer();
/**
* value 的序列化器
*/
private final RedisFastJsonSerializer<Object> valueRedisSerializer = new RedisFastJsonSerializer<>(Object.class);
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// RedisCacheWriter
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
// RedisCacheConfiguration - 值的序列化方式
RedisSerializationContext.SerializationPair<Object> serializationPair = RedisSerializationContext.SerializationPair.fromSerializer(valueRedisSerializer);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(serializationPair);
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 配置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 值序列化-RedisFastJsonSerializer
redisTemplate.setValueSerializer(valueRedisSerializer);
redisTemplate.setHashValueSerializer(valueRedisSerializer);
// 键序列化-StringRedisSerializer
redisTemplate.setKeySerializer(keyRedisSerializer);
redisTemplate.setHashKeySerializer(keyRedisSerializer);
return redisTemplate;
}
}
复制代码
RedisFastJsonSerializer
RedisFastJsonSerializer 是自定义的序列化和反序列化工具,为了往 Redis 中设值的时候, 自动将对象序列化, 取值的时候自动反序列化
public class RedisFastJsonSerializer<T> implements RedisSerializer<T> {
// 新建的GenericFastJson2JsonRedisSerializer里面添加白名,防止fastjson 反序列化报错
static {
ParserConfig.getGlobalInstance().addAccept("com.springboot");
}
private final Class<T> clazz;
public RedisFastJsonSerializer(Class<T> clazz) {
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (Objects.isNull(t)) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (Objects.isNull(bytes) || ArrayUtils.isEmpty(bytes)) {
return null;
}
return JSON.parseObject(new String(bytes, StandardCharsets.UTF_8), clazz);
}
}
复制代码
RedisService
封装一些Redis的常用方法
@Service
public class RedisService {
private final RedisTemplate<String, Object> redisTemplate;
public RedisService(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* Description: 设值
*
* @param key 缓存 {@link RedisKey}
* @param value 值
* @param seconds 有效时长 (秒)
* @return T 放入缓存中的值
*/
public <T> T setValue(RedisKey key, T value, long seconds) {
redisTemplate.opsForValue().set(key.of(), value, seconds, TimeUnit.SECONDS);
return value;
}
private Object getValue(String key) {
if (!Optional.ofNullable(redisTemplate.hasKey(key)).orElse(Boolean.FALSE)) {
return null;
}
return redisTemplate.opsForValue().get(key);
}
/**
* Description: 取值
*
* @param key 缓存 {@link RedisKey}
* @param clazz 缓存对应的对象的 class 对象
* @return T or null
* @see RedisService#getValue(String)
*/
public <T> T getValue(RedisKey key, Class<T> clazz) {
return clazz.cast(getValue(key.of()));
}
/**
* Description: 删除
*
* @param key 缓存 {@link RedisKey}
* @return boolean
*/
public boolean delete(RedisKey key) {
return Optional.ofNullable(redisTemplate.delete(key.of())).orElse(false);
}
/**
* Description: 延长指定 key 的过期时间
*
* @param key {@link RedisKey}
* @param seconds 有效时长 (秒)
* @return boolean
*/
public boolean expire(RedisKey key, long seconds) {
return Optional.ofNullable(redisTemplate.expire(key.of(), seconds, TimeUnit.SECONDS)).orElse(false);
}
public class Files {
private static final String CACHE_KEY_PREFIX = "file:";
private static final String FIELD_FILE_NAME = "fileName";
private static final String FIELD_FILE_CONTENT = "fileContent";
/**
* Description: 缓存文件<br>
* Details: 将文件对象读入内存, 获取字节数组, 最后 {@code Base64} 编码. 以 缓存前缀 + 文件名 作为缓存 key
*
* @param file (Required) 文件对象
*/
@SneakyThrows
public void setFile(File file) {
final HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
final String fileName = Objects.requireNonNull(file, "文件不能为空").getName();
final String fileContent = new String(
Base64.getEncoder().encode(IOUtils.toByteArray(FileUtils.openInputStream(Objects.requireNonNull(file, "文件对象不能为空")))),
StandardCharsets.UTF_8
);
final HashMap<String, String> map = new HashMap<>(2);
map.put(FIELD_FILE_NAME, fileName);
map.put(FIELD_FILE_CONTENT, fileContent);
ops.putAll(CACHE_KEY_PREFIX + fileName, map);
}
/**
* Description: 获取文件
*
* @param fileName (Required) 文件名
* @return java.io.File 文件对象
*/
@SneakyThrows
public File getFile(String fileName) {
final HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
// 缓存 Key
final Map<Object, Object> entries = ops.entries(CACHE_KEY_PREFIX + Objects.requireNonNull(fileName, "文件名不能为空"));
if (MapUtils.isEmpty(entries)) {
return null;
}
final String cachedFileName = MapUtils.getString(entries, FIELD_FILE_NAME);
final String cachedFileContent = MapUtils.getString(entries, FIELD_FILE_CONTENT);
final File file = new File(FileUtils.getTempDirectoryPath() + cachedFileName);
try (
final FileOutputStream out = new FileOutputStream(file);
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(out)
) {
bufferedOutputStream.write(Base64.getDecoder().decode(cachedFileContent));
}
return file;
}
/**
* Description: 获取文件的字节数组
*
* @param fileName (Required) 文件名
* @return byte[] 文件的字节数组
*/
public byte[] getBytes(String fileName) {
final HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
final Map<Object, Object> entries = ops.entries(CACHE_KEY_PREFIX + Objects.requireNonNull(fileName, "文件名不能为空"));
return Base64.getDecoder().decode(MapUtils.getString(entries, FIELD_FILE_CONTENT));
}
}
}
复制代码
实体类
User
@Data
public class User implements Serializable {
private static final long serialVersionUID = -2961686750510451767L;
private Long id;
private String name;
private Integer age;
}
复制代码
RedisKey
@Data
@Builder
public class RedisKey {
public static final String SEPARATOR = ".";
/**
* Redis key 的前缀
*/
private String prefix;
/**
* Redis key 的内容
*/
private String suffix;
public String of() {
return String.format("%s.%s", prefix, suffix);
}
}
复制代码
ResultVO
视图类,返回json对象
@Data
public class ResultVO<T> {
private Integer code;
private String msg;
private T data;
public static ResultVO<Object> success(Object object) {
ResultVO<Object> resultVO = new ResultVO<>();
resultVO.setCode(1);
resultVO.setMsg("成功");
resultVO.setData(object);
return resultVO;
}
public static ResultVO<Object> success() {
return success(null);
}
public static ResultVO<Object> fail(Object object) {
ResultVO<Object> resultVO = new ResultVO<>();
resultVO.setCode(0);
resultVO.setMsg("失败");
resultVO.setData(object);
return resultVO;
}
public static ResultVO<Object> fail() {
return fail(null);
}
}
复制代码
Controller
@RestController
public class Controller {
@Autowired
private RedisService redisService;
@PostMapping("/redis/set")
public ResultVO<Object> set() {
User user = new User();
user.setId(1L);
user.setName("wang");
user.setAge(22);
redisService.setValue(RedisKey.builder().prefix("user").suffix("wang").build(), user, 10000L);
return ResultVO.success(redisService.getValue(RedisKey.builder().prefix("user").suffix("wang").build(), user.getClass()));
}
}
复制代码
References
[1] Redis: redis.io/
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END