首先,pom文件新增依赖
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--Slf4j-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
yml文件新增配置
redis:
database: 0
host: 127.0.0.1
password:
port: 6379
timeout: 5000
ssl: false
新增启动文件
@SpringBootApplication
public class RedisApplication {
public static void main(String[] args) {
// 只需要run一下,就能发布一个springboot应用
// 相当于之前将web工程发布到tomcat服务器,只是在springboot中集成了tomcat插件
SpringApplication.run(RedisApplication.class, args);
}
}
目录结构如图:
新增工具类文件:
@Service
public class RedisUtil {
@Autowired
private RedisTemplate redisTemplate;
/**
* 写入缓存
*
* @param key key
* @param value value
* @return
*/
public Boolean set(final String key, Object value) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 写入缓存设置失效时间
*
* @param key key
* @param value value
* @param expireTime expireTime
* @param timeUnit timeUnit
* @return
*/
public Boolean set(final String key, Object value, Long expireTime, TimeUnit timeUnit) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, timeUnit);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 批量删除对应的value
*
* @param keys keys
*/
public void remove(final String... keys) {
for (String key : keys) {
remove(keys);
}
}
/**
* 批量删除key
*
* @param pattern
*/
public void removePattern(final String pattern) {
Set<Serializable> keys = redisTemplate.keys(pattern);
if (keys.size() > 0) {
redisTemplate.delete(keys);
}
}
/**
* 删除对应的value
*
* @param key
*/
public void remove(final String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/**
* 判断缓存中是否有对应的value
*
* @param key
* @return
*/
public boolean exists(final String key) {
return redisTemplate.hasKey(key);
}
/**
* 读取缓存
*
* @param key
* @return
*/
public Object get(final String key) {
Object result = null;
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
result = operations.get(key);
return result;
}
/**
* 哈希 添加
*
* @param key
* @param hashKey
* @param value
*/
public void hmSet(String key, Object hashKey, Object value) {
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
hash.put(key, hashKey, value);
}
/**
* 哈希获取数据
*
* @param key
* @param hashKey
* @return
*/
public Object hmGet(String key, Object hashKey) {
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
return hash.get(key, hashKey);
}
/**
* 列表添加
*
* @param k
* @param v
*/
public void lPush(String k, Object v) {
ListOperations<String, Object> list = redisTemplate.opsForList();
list.rightPush(k, v);
}
/**
* 列表获取
*
* @param k
* @param l
* @param l1
* @return
*/
public List<Object> lRange(String k, long l, long l1) {
ListOperations<String, Object> list = redisTemplate.opsForList();
return list.range(k, l, l1);
}
/**
* 集合添加
*
* @param key
* @param value
*/
public void add(String key, Object value) {
SetOperations<String, Object> set = redisTemplate.opsForSet();
set.add(key, value);
}
/**
* 集合获取
*
* @param key
* @return
*/
public Set<Object> setMembers(String key) {
SetOperations<String, Object> set = redisTemplate.opsForSet();
return set.members(key);
}
/**
* 有序集合添加
*
* @param key
* @param value
* @param scoure
*/
public void zAdd(String key, Object value, double scoure) {
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
zset.add(key, value, scoure);
}
/**
* 有序集合获取
*
* @param key
* @param scoure
* @param scoure1
* @return
*/
public Set<Object> rangeByScore(String key, double scoure, double scoure1) {
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
return zset.rangeByScore(key, scoure, scoure1);
}
controller:
@RestController
@RequestMapping("/redis")
@Slf4j
public class TestController {
@Autowired
private RedisUtil redisUtil;
@GetMapping("/set")
public Boolean setKey(@RequestParam("key") String key, @RequestParam("value") Object value) {
try {
redisUtil.set(key, value);
} catch (Exception e) {
log.error("redis加入失败:{}", e.getStackTrace());
return false;
}
return true;
}
@GetMapping("/get")
public Object getKey(@RequestParam("key") String key) {
try {
return redisUtil.get(key);
} catch (Exception e) {
log.error("redis获取失败:{}", e.getStackTrace());
return false;
}
}
}
能成功插入本地redis数据
启动项目前,先启动本地redis.
这种方式容易有乱码,如上图
对于redis操作,springboot进行了很好的封装,那就是spring data redis。提供了一个高度封装的RedisTemplate类来进行一系列redis操作,连接池自动管理;同时将事务封装操作,交由容器进行处理.。
从图上能看出,出现乱码,因为,引用默认的RedisTemplate,它的默认序列化方式是JDK,而这种方式可读性差。
为了解决以上问题,需进行更改默认序列化:
有两种方式,一种是自定义RedisTemplate类,另一种使用 String RedisTemplate 进行序列化
先讲第二种: String RedisTemplate是spring自带的,直接引用
@Autowired
private StringRedisTemplate stringRedisTemplate;
spring只限于字符串结构,不建议使用。
再讲自定义redisTemplate类,可以更换序列化方式:
①JdkSerializationRedisSerializer。默认方式,无需变更
直接引入即可
@Autowired
private RedisTemplate redisTemplate;
自定义是更改为非JDK序列化,这里有以下几种选择:
①Jackson
②faskjson
③genericFastJson
其实还有一种是StringRedisSerializer,但是,我们直接引入StringRedisTemplate就解决了,无需自定义,所以这种方式多此一举,可以不讨论,但是key的赋值方式是用了string方式。
目录结构如图:
工具类依旧不动,自动注入redisTemplate
RedisConfig新增文件,代码如下:
这一步会在启动时,重写redisTemplate,所以叫自定义
package com.hyj.config;
import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.StringRedisSerializer;
@Configuration
@Slf4j
public class RedisConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
//为了开发方便,一般使用<String, Object>
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
// //Json方式的序列化
// Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// ObjectMapper objectMapper = new ObjectMapper();
// objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// //faskjskn方式序列化
// FastJson2JsonRedisSerializer fastJson2JsonRedisSerializer = new FastJson2JsonRedisSerializer(Object.class);
// ObjectMapper objectMapper = new ObjectMapper();
// objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// fastJson2JsonRedisSerializer.setObjectMapper(objectMapper);
//String方式的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
GenericFastJsonRedisSerializer jackson2JsonRedisSerializer = new GenericFastJsonRedisSerializer();
//------设置各模板的序列化方式------
//设置key的序列化方式为string(不设置的话会乱码)
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
//设置value的序列化方式为json
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
每一种方式的变更如图:
FastJson2JsonRedisSerializer需要新增文件,内容如下:
package com.hyj.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.util.Assert;
import java.nio.charset.Charset;
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
private ObjectMapper objectMapper = new ObjectMapper();
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
static {
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
ParserConfig.getGlobalInstance().addAccept("com.openailab.oascloud");
}
public FastJson2JsonRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz);
}
public void setObjectMapper(ObjectMapper objectMapper) {
Assert.notNull(objectMapper, "'objectMapper' must not be null");
this.objectMapper = objectMapper;
}
protected JavaType getJavaType(Class<?> clazz) {
return TypeFactory.defaultInstance().constructType(clazz);
}
}
至此,四种方式的序列化讲解完毕。
实际运行,
①Jackson序列化,list类型的数据如图:
读取:Jackson2JsonRedisSerializer报错
②FastJson2JsonRedisSerializer
读取:
③GenericFastJson
下面开始数据读取:
GenericFastJson:
综上所述:推荐FastJson和genericFastJson吧,Jackson肯定是不咋推荐的,反序列化报错