社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
1.配置pom.xml
<!--引用Jedis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2.配置spring.xml
##################Redis配置########
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=123456789
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
spring.redis.commandTimeout=5000
#连接的数据库
spring.redis.database=0
# redis.cluster
spring.redis.cluster.nodes=127.0.0.1:6379
##########################################################################
3.配置CacheManager
直接配置会提示错误:
new RedisCacheManager(redisTemplate)没有此构造
现在这么写会有报错The constructor RedisCacheManager(RedisTemplate<capture#1-of ?,capture#2-of ?>) is undefined。
这是因为Spring Boot 2.x版本删除了RedisCacheManager这个构造器, 也不可以通过之前的setDefaultExpiration方法设置默认的缓存过期时间等。
通过设置RedisConnectionFactory factory进行解决,最后RedisConfig.java如下:
/***
* 配置redis缓存
* @author Administrator
*
*/
@Configuration
@EnableCaching//启用缓存
public class RedisConfig extends CachingConfigurerSupport{
//注入 RedisConnectionFactory
@Autowired
public RedisConnectionFactory redisConnectionFactory;
//实例化 RedisTemplate 对象 设置数据存入 redis 的序列化方式
@Bean
public RedisTemplate<String, Object> functionDomainRedisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
//定义key生成策略
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
//缓存管理器 --》配置缓存时间
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(-1));
RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();
return cacheManager;
}
}
创建实体类,一定要实现Serializable序列化,因为redis保存对象的时候要求对象是序列化 如:
实体类配置好后,将redis的操作的接口类进行封装后,进行使用:
public interface RedisService{
public boolean set(final String key, Object value);
public boolean set(final String key, Object value, Long expireTime);
public void remove(final String... keys);
public void removePattern(final String pattern);
public void remove(final String key);
public boolean exists(final String key);
public Object get(final String key);
public void hmSet(String key, Object hashKey, Object value);
public Object hmGet(String key, Object hashKey);
public void lPush(String k,Object v);
public List<Object> lRange(String k, long l, long l1);
public void add(String key,Object value);
public Set<Object> setMembers(String key);
public void zAdd(String key,Object value,double scoure);
public Set<Object> rangeByScore(String key,double scoure,double scoure1);
}
package ***;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
@SuppressWarnings("all")
@Service
public class RedisServiceImpl implements RedisService{
@Autowired
private RedisTemplate redisTemplate;
/**
* 写入缓存
* @param key
* @param 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
* @param value
* @return
*/
public boolean set(final String key, Object value, Long expireTime) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 批量删除对应的value
* @param keys
*/
public void remove(final String... keys) {
for (String key : keys) {
remove(key);
}
}
/**
* 批量删除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);
}
}
便于redis-key的整理,创建一个key的管理文件,进行将所有要缓存的业务类进行统一管理,如
/****
* 整合redis缓存key文件
* @author Administrator
*
*/
public class RedisServiceKey {
public static final String Product_REDIS_KEY = "Product_KEY";
}
基本配置就全部完成,可以启动。
所有配置文件在资源中: 【 https://download.csdn.net/download/qq_31653405/12440229 】
启动后可能遇见的问题:
1.问题:HostAndPort need to be seperated by ':'.
解决
如上图,添加端口127.0.0.1:6379
扩展:host变成ip:port,集群多个ip和端口用“,”分割,
2.问题:再次启动出现问题:org.springframework.data.redis.core.HashOperations
解决:
原因就是,缺少redis中HashOperationsbean,其实在下面已经提示了,所以在redisconfig中注入bean,并同时在再调用下就可以了,
//实例化 HashOperations 对象,可以使用 Hash 类型操作
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
//实例化 ValueOperations 对象,可以使用 String 操作
@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForValue();
}
//实例化 ListOperations 对象,可以使用 List 操作
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
//实例化 SetOperations 对象,可以使用 Set 操作
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
//实例化 ZSetOperations 对象,可以使用 ZSet 操作
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
如上图的*Service.java文件中
访问这个文章【 https://blog.csdn.net/hello_world_qwp/article/details/81205921 】
3.问题:Cannot retrieve initial cluster partitions from initial URIs [RedisURI [host='127.0.0.1', port=6379]]
当前问题说:在配置redis集群时,地址用的是127的IP
解决 :在配置集群时,一定要用IP地址,不要用127/localhost等代替IP
4.问题:Command timed out 连接请求超时
将spring.xml中时间设长一点
# 连接超时时间(毫秒)
spring.redis.timeout=200
spring.redis.commandTimeout=500000
通过上面的配置完全解决这个问题的所在.
Redis中的 ListOperations<String, Object> ---------> 存list
在controller.java中引入RedisTemplate
@Autowired
protected RedisTemplate<String, Object> redisTemplate;
List<WxUsers> wxUserList = wxUsersService.findAll();
redisTemplate.opsForList().rightPushAll(RedisServiceKey.WxMemberList_REDIS_KEY, wxUserList);
当前方法执行成功之后,在redis查看工具【(原)Redis-【一】Redis的初始,安装及运行和使用】中进行查看对应的redis-key的值:(可能会出现乱码情况,出现则进行修改RedisConfig.java中的setValueSerializer()的属性)
@Bean
public RedisTemplate<String, Object> functionDomainRedisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//定义key生成策略
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
附 : Springboot 、redis 、 jwt 实现token验证
Redis中的 取出刚存的list ------------------------------>
判断是否存在 redisTemplate.hasKey( Constants.USER_TOKEN_KEY );
存在就取出 redisTemplate.opsForValue().get( Constants.USER_TOKEN_KEY );
List<WxUsers> wxUserList = redisTemplate.opsForList().range(RedisServiceKey.WxMemberList_REDIS_KEY, 0, -1);
log.info(">>>>>>>>>>>>>>>list = {}", wxUserList);
Iterator<WxUsers> it = wxUserList.iterator();
while(it.hasNext()){
WxUsers wxUser = it.next();
if(!token.equals(wxUser.getWx_userOpenId())) {
throw new RuntimeException(ErrorMessage.error_login_no_user);
}
}
通过引入 在拦截器中配置redis缓存机制 实现比对redis中值是否相同
/***
* 存入list- redis 并取出 list - redis - openid
*/
boolean hasKey = redisTemplate.hasKey(RedisServiceKey.WxMemberList_REDIS_KEY);
if(hasKey) {
//取list
List<WxUsers> wxUserList = redisTemplate.opsForList().range(RedisServiceKey.WxMemberList_REDIS_KEY, 0, -1);
log.info(">>>>>>>>>>>>>>>list = {}", wxUserList);
Iterator<WxUsers> it = wxUserList.iterator();
while(it.hasNext()){
WxUsers wxUser = it.next();
if(token.equals(wxUser.getWx_userOpenId())) {
break;
}
// // 验证 token
// JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(token)).build();
// try {
// jwtVerifier.verify(token);
// } catch (JWTVerificationException e) {
// throw new RuntimeException("401");
// }
}
}else {
//存list
List<WxUsers> wxUserList = wxUsersService.findAll();
redisTemplate.opsForList().rightPushAll(RedisServiceKey.WxMemberList_REDIS_KEY, wxUserList);
throw new RuntimeException(ErrorMessage.error_login_no_user);
}
以上代码是比对的所需内容,但是在启动项目时,会提示下面错误,
原因:
springboot拦截器是在Bean实例化之前执行的,所以Bean实例无法注入,也就是当我们想获取redis里面key是token的值时,发现redisTemplate没有是空的没有注入进来
解决:
知道拦截器执行在bean实例化前执行的,那么我们就让拦截器执行的时候实例化拦截器Bean,在拦截器配置类里面先实例化拦截器,然后再获取。
拦截器配置:WebAppConfig.java
@Configuration
public class WebAppConfig extends WebMvcConfigurerAdapter {
//访问图片方法
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String os = System.getProperty("os.name");
if (os.toLowerCase().startsWith("win")) { //如果是Windows系统
registry.addResourceHandler("/images/**")
// /apple/**表示在磁盘apple目录下的所有资源会被解析为以下的路径
.addResourceLocations("file:/D:/images/"); //媒体资源
} else { //linux 和mac
registry.addResourceHandler("/images/**")
.addResourceLocations("file:/usr/local/wwwroot/images/"); //媒体资源
}
super.addResourceHandlers(registry);
}
//引用拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(handlerInterceptor()).addPathPatterns( "/**");
}
//注册拦截器
@Bean
public HandlerInterceptor handlerInterceptor(){
return new HandlerInterceptor();
}
}
过滤器配置:HandlerInterceptor.java
@Component
public class HandlerInterceptor extends HandlerInterceptorAdapter {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(HandlerInterceptor.class);
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private ValueOperations<String,Object> opsForValue;
@Autowired
private WxUsersService wxUsersService;
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader(Constants.USER_OPENID_KEY);// 从 http 请求头中取出 token
// 如果是handler方法直接继续执行
if (!handler.getClass().isAssignableFrom(HandlerMethod.class)) {
log.debug("This is handler.");
System.out.println("-----This is handler.-----");
return true;
}
final HandlerMethod handlerMethod = (HandlerMethod) handler;
final Method method = handlerMethod.getMethod();
final Class<?> clazz = method.getDeclaringClass();
// 如果有auth注解,进行token登录验证
if (clazz.isAnnotationPresent(Auth.class) || method.isAnnotationPresent(Auth.class)) {
log.debug("-----Auth----token:" + Constants.USER_OPENID_KEY + "-----");
System.out.println("-----Auth----token:" + Constants.USER_OPENID_KEY + "-----");
// 如果没有token进行拦截。
if (token == null) {
throw new RuntimeException(ErrorMessage.error_fresh_user_login_all);
}
/***
* 存入list- redis 并取出 list - redis - openid
*/
boolean hasKey = redisTemplate.hasKey(RedisServiceKey.WxMemberList_REDIS_KEY);
if(hasKey) {
//取list
List<WxUsers> wxUserList = redisTemplate.opsForList().range(RedisServiceKey.WxMemberList_REDIS_KEY, 0, -1);
log.info(">>>>>>>>>>>>>>>list = {}", wxUserList);
Iterator<WxUsers> it = wxUserList.iterator();
while(it.hasNext()){
WxUsers wxUser = it.next();
if(token.equals(wxUser.getWx_userOpenId())) {
break;
}
// // 验证 token
// JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(token)).build();
// try {
// jwtVerifier.verify(token);
// } catch (JWTVerificationException e) {
// throw new RuntimeException("401");
// }
}
}else {
//存list
List<WxUsers> wxUserList = wxUsersService.findAll();
redisTemplate.opsForList().rightPushAll(RedisServiceKey.WxMemberList_REDIS_KEY, wxUserList);
throw new RuntimeException(ErrorMessage.error_login_no_user);
}
return true;
}
log.debug("-----Auth----No-----");
System.out.println("-----Auth----No-----");
return true;
}
/**
* 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// System.out.println("执行了TestInterceptor的afterCompletion方法");
}
}
在小程序端head中输入要传的参数值:
//获取小程序平台基本信息
wx.request({
url: base.path.www + 'WxPlatform/SelectWxPlatformInfo',
method: 'post',
data: { },
header: { 'content-type': 'application/json;charset=UTF-8' , 'wx_userOpenId': wx.getStorageSync('wxMemberOpenId') },
success(res) {
wx.setStorageSync('wxPlatformInfo', res.data.data.wxPlatformInfo);
that.setData({
wxPlatformInfo: res.data.data.wxPlatformInfo
});
}
}),
然后在后台服务器中通过拦截器进行取head中的wx_userOpenId并进行验证是否验证通过
stringRedisTemplate.opsForValue().set("test", "100",60*10,TimeUnit.SECONDS);//向redis里存入数据和设置缓存时间
stringRedisTemplate.opsForValue().get("test") //根据key获取缓存中的val
stringRedisTemplate.boundValueOps("test").increment(-1); //val做-1操作
stringRedisTemplate.boundValueOps("test").increment(1); //val +1
stringRedisTemplate.getExpire("test") //根据key获取过期时间
stringRedisTemplate.getExpire("test",TimeUnit.SECONDS) //根据key获取过期时间并换算成指定单位
stringRedisTemplate.delete("test"); //根据key删除缓存
stringRedisTemplate.hasKey("546545"); //检查key是否存在,返回boolean值
stringRedisTemplate.expire("red_123",1000 , TimeUnit.MILLISECONDS); //设置过期时间
stringRedisTemplate.opsForSet().add("red_123", "1","2","3"); //向指定key中存放set集合
stringRedisTemplate.opsForSet().isMember("red_123", "1") //根据key查看集合中是否存在指定数据
stringRedisTemplate.opsForSet().members("red_123"); //根据key获取set集合
以上是自己在项目中,一遍配置一边整理的,并测试过,可以直接用;
接下来陆续更新redis在springboot中如果实现基本的CRUD,及基本原理功能内容!
-------------------------------------------------- -------------------------------------------------- ------------
遗留问题就是 redis的客户端工具显示的key是乱码,正在解决,有知道的大佬请帮下谢谢了!!!
文章中,有问题,可以在评论区评论,一起探讨编程中奥秘!
-------------------------------------------------- ------------------------------------------------- ------------
如果我的文章有帮助到您,欢迎打赏一下鼓励博主。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!