Spring Boot 使用Redis缓存 配置问题

背景

我想要在当前的Spring Boot项目中使用Redis作为缓存。目前所了解到的内容是Redis缓存有两种实现方式,一种是使用Spring Cache注解,需要加一个配置文件,另一种是使用RedisTemplate,想要两种方式混合使用。

相关版本

Spring Boot:Spring Boot 2.0.0.M7

Redis依赖包:

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

主要问题:

application中yml文件我按照书上和官方文档的推荐方式在Application.yml里面做了如下配置,因为我使用的Spring Boot版本比较新,因为配置方式与之前的稍微有点不一样:

 spring:
  redis:
      host: 127.0.0.1
      port: 6379
      password: 123456
      #timeout: 0
      #Spring Boot 2.0.0.M7中原有的redis配置方法过时,加了一层jedis
      jedis:
        pool:
          max-active: 8
          max-wait: -1
          min-idle: 8
          max-idle: 0

而为了使用Spring Cache注解,需要启用注解并且设置数据在Redis数据库的有效期限,需要如下配置:
图片说明
无论是我看的书籍还是查阅的很多博客都是这种配置方式,但是如图报错了。我猜想很大可能是版本原因,因此去查看了Spring提供的官方文档(2.0.0.M1的文档,是最新的文档):
https://docs.spring.io/spring-data/redis/docs/2.1.0.M1/api/
里面的RedisCacheManager的构造方法显然没有上面图片中的那种,文档所提供的的构造方法我有看不太懂应该怎么获取或者使用。
因为第一次配置我了解的相关知识也比较少,希望有大神能够指导一下在这里具体应该怎么配置Redis数据的过期时间?
感谢阅读问题~

4个回答

配置redis数据过期时间简单,不需要在配置文件中配置,你可以在调用service存储数据时使用redis的setex方法,当中第二个参数是表示过期的,单位是秒

andy_lushun
andy_ls 回复桐小目: 解决了吗?我配置的时候也遇到这个问题了
大约 2 年之前 回复
chen1092248901
chen1092248901 回复桐小目: 这个怎么弄我也碰到了
大约 2 年之前 回复
hwq_19890818
little_strong13 回复桐小目: 上面这种方法是在set缓存数据时添加过期时间,这是可行的,或者你还可以使用cacheManager.setDefaultExpiration(30);添加默认超时时间
2 年多之前 回复
qq_33171970
桐小目 感谢回答,也就是配置文件只需要重写key的生成策略,配置过期时间在存储数据时设置对吧,我去尝试一下~先采纳了~
2 年多之前 回复

https://blog.csdn.net/sy793314598/article/details/80719224
spring boot 2.0以上版本的缘故

这是springboot1.5前的配置吧,2.0以后这样配置会报红

切面aop,配置就可以
原始代码不用修改

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
spring boot 配置redis缓存

环境:spring boot+java8,spring版本为4以上 用spring boot 配置redis缓存时报错如下: java.lang.IllegalStateException: No CacheResolver specified, and no unique bean of type CacheManager found. Mark one as primary (or give it the name 'cacheManager') or declare a specific CacheManager to use, that serves as the default one. 有哪位大神有遇到类似异常信息的,可否提供解决方案?

求助!Spring boot 集成 redis 使用注解

@CachePut(value="demoInfo") 无效,数据库数据已经更新,但是缓存数据没有更新。

关于spring boot redis存取问题,求大神帮忙!!

![图片说明](https://img-ask.csdn.net/upload/201712/05/1512460707_782764.png) 当直接访问这个controller的时候redis存取无问题。 ![图片说明](https://img-ask.csdn.net/upload/201712/05/1512460736_786580.png) 当调用这个方法访问的时候则会报空指针。 ![图片说明](https://img-ask.csdn.net/upload/201712/05/1512460761_324967.png) 是不是这个方法中需要加上什么注解,我理解是调用这个方法没有实例化redis的一些配置所以导致空指针,但是不知道需要加上什么注解来自动加载

使用redis缓存替代mybatis系统缓存的优点

为什么要使用redis替代mubatis系统缓存 ,使用redis缓存替代mybatis系统缓存的优点

springboot+redis缓存问题

``` @JsonIgnore @OneToMany(mappedBy = "school",fetch = FetchType.LAZY) private List<Student> students = new ArrayList<>(); ``` 这里可以缓存,但是读缓存的时候list就为空了。又没有其他什么方法能处理的。

springboot项目集成springsession+redis后,刷新页面会导致session丢失

项目中集成了springsession,用redis实现session共享,登录的时候把session存到redis中,之后的请求在拦截器中获取session来判断,但是每次刷新页面或者新弹出页面的时候,请求中的cookie和session都会为null。在谷歌浏览器没有问题。 ``` DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer(); cookieSerializer.setSameSite(null) ``` 各种百度查询和查看了部分源码,设置了这个之后就可以,但是这个会有不安全,有人可以解释一下原因么?

当SpringBootCache同时引入了Ehcache和Redis后,方法的缓存到底是使用谁的或者如何区分

在pom同时引入cache, ehcache,redis 后 ![图片说明](https://img-ask.csdn.net/upload/202003/09/1583738822_87579.png) 这些缓存注解操作的是 redis还是ehcache ? 或者怎么去设置让它使用redis还是

spring boot整合redis获取异常或者获取不到

系统异常:org.springframework.data.redis.RedisConnec tionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool 刚启动系统运行正常,过几天就会出现这个异常,以下是关于redise的配置: # redis.properties文件中的内容如下: redis.hostName=127.0.0.1 redis.password= #端口号 redis.port=6379 #客户端超时时间单位是毫秒 默认是2000 redis.timeout=10000 #最大空闲数 redis.maxIdle=300 #连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal #redis.maxActive=600 #控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性 redis.maxTotal=300 #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。 redis.maxWaitMillis=1000 #连接的最小空闲时间 默认1800000毫秒(30分钟) redis.minEvictableIdleTimeMillis=300000 #每次释放连接的最大数目,默认3 redis.numTestsPerEvictionRun=1024 #逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1 redis.timeBetweenEvictionRunsMillis=30000 #是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个 redis.testOnBorrow=true #在空闲时检查有效性, 默认false redis.testWhileIdle=true # pom.xml中整合redis内容如下: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> # redisConfig内容如下: package com.brons.trans.redis; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import redis.clients.jedis.JedisPoolConfig; @Configuration @PropertySource("classpath:redis.properties") public class RedisConfig { Logger logger = LoggerFactory.getLogger(RedisConfig.class); @Value("${redis.hostName}") private String hostName; @Value("${redis.port}") private Integer port; @Value("${redis.password}") private String password; @Value("${redis.timeout}") private Integer timeout; @Value("${redis.maxIdle}") private Integer maxIdle; @Value("${redis.maxTotal}") private Integer maxTotal; @Value("${redis.maxWaitMillis}") private Integer maxWaitMillis; @Value("${redis.minEvictableIdleTimeMillis}") private Integer minEvictableIdleTimeMillis; @Value("${redis.numTestsPerEvictionRun}") private Integer numTestsPerEvictionRun; @Value("${redis.timeBetweenEvictionRunsMillis}") private long timeBetweenEvictionRunsMillis; @Value("${redis.testOnBorrow}") private boolean testOnBorrow; @Value("${redis.testWhileIdle}") private boolean testWhileIdle; // @Value("${spring.redis.cluster.nodes}") // private String clusterNodes; // // @Value("${spring.redis.cluster.max-redirects}") // private Integer mmaxRedirectsac; /** * JedisPoolConfig 连接池 * * @return */ @Bean public JedisPoolConfig jedisPoolConfig() { logger.info("初始化RedisConfig.JedisPoolConfig 连接池===="); JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); // 最大空闲数 jedisPoolConfig.setMaxIdle(maxIdle); // 连接池的最大数据库连接数 jedisPoolConfig.setMaxTotal(maxTotal); // 最大建立连接等待时间 jedisPoolConfig.setMaxWaitMillis(maxWaitMillis); // 逐出连接的最小空闲时间 默认1800000毫秒(30分钟) jedisPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); // 每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3 jedisPoolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun); // 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1 jedisPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); // 是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个 jedisPoolConfig.setTestOnBorrow(testOnBorrow); // 在空闲时检查有效性, 默认false jedisPoolConfig.setTestWhileIdle(testWhileIdle); return jedisPoolConfig; } /** * 单机版配置 @Title: JedisConnectionFactory @param @param * jedisPoolConfig @param @return @return JedisConnectionFactory @autor * lpl @date 2018年2月24日 @throws */ @Bean public JedisConnectionFactory JedisConnectionFactory(JedisPoolConfig jedisPoolConfig) { logger.info("初始化RedisConfig.JedisConnectionFactory单机版配置===="); JedisConnectionFactory JedisConnectionFactory = new JedisConnectionFactory(jedisPoolConfig); // 连接池 JedisConnectionFactory.setPoolConfig(jedisPoolConfig); // IP地址 JedisConnectionFactory.setHostName(hostName); // 端口号 JedisConnectionFactory.setPort(port); // 如果Redis设置有密码 JedisConnectionFactory.setPassword(password); // 客户端超时时间单位是毫秒 JedisConnectionFactory.setTimeout(timeout); return JedisConnectionFactory; } /** * 实例化 RedisTemplate 对象 * * @return */ @Bean public RedisTemplate<String, Object> functionDomainRedisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); initDomainRedisTemplate(redisTemplate, redisConnectionFactory); return redisTemplate; } /** * 设置数据存入 redis 的序列化方式,并开启事务 * * @param redisTemplate * @param factory */ private void initDomainRedisTemplate(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) { // 如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to // String! redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); // 开启事务 redisTemplate.setEnableTransactionSupport(true); redisTemplate.setConnectionFactory(factory); } /** * 注入封装RedisTemplate @Title: redisUtil @return RedisUtil @autor lpl @date * 2017年12月21日 @throws */ @Bean(name = "redisUtil") public RedisUtil redisUtil(RedisTemplate<String, Object> redisTemplate) { RedisUtil redisUtil = new RedisUtil(); redisUtil.setRedisTemplate(redisTemplate); return redisUtil; } } # RedisUtil工具类文件内容如下: package com.brons.trans.redis; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.util.CollectionUtils; public class RedisUtil { private RedisTemplate<String, Object> redisTemplate; public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } //=============================common============================ /** * 指定缓存失效时间 * @param key 键 * @param time 时间(秒) * @return */ public boolean expire(String key,long time){ try { if(time>0){ redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据key 获取过期时间 * @param key 键 不能为null * @return 时间(秒) 返回0代表为永久有效 */ public long getExpire(String key){ return redisTemplate.getExpire(key,TimeUnit.SECONDS); } /** * 判断key是否存在 * @param key 键 * @return true 存在 false不存在 */ public boolean hasKey(String key){ try { return redisTemplate.hasKey(key); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除缓存 * @param key 可以传一个值 或多个 */ @SuppressWarnings("unchecked") public void del(String ... key){ if(key!=null&&key.length>0){ if(key.length==1){ redisTemplate.delete(key[0]); }else{ redisTemplate.delete(CollectionUtils.arrayToList(key)); } } } //============================String============================= /** * 普通缓存获取 * @param key 键 * @return 值 */ public Object get(String key){ return key==null?null:redisTemplate.opsForValue().get(key); } /** * 普通缓存放入 * @param key 键 * @param value 值 * @return true成功 false失败 */ public boolean set(String key,Object value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 普通缓存放入并设置时间 * @param key 键 * @param value 值 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 * @return true成功 false 失败 */ public boolean set(String key,Object value,long time){ try { if(time>0){ redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); }else{ set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 递增 * @param key 键 * @param by 要增加几(大于0) * @return */ public long incr(String key, long delta){ if(delta<0){ throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForValue().increment(key, delta); } /** * 递减 * @param key 键 * @param by 要减少几(小于0) * @return */ public long decr(String key, long delta){ if(delta<0){ throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForValue().increment(key, -delta); } //================================Map================================= /** * HashGet * @param key 键 不能为null * @param item 项 不能为null * @return 值 */ public Object hget(String key,String item){ return redisTemplate.opsForHash().get(key, item); } /** * 获取hashKey对应的所有键值 * @param key 键 * @return 对应的多个键值 */ public Map<Object,Object> hmget(String key){ return redisTemplate.opsForHash().entries(key); } /** * HashSet * @param key 键 * @param map 对应多个键值 * @return true 成功 false 失败 */ public boolean hmset(String key, Map<String,Object> map){ try { redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * HashSet 并设置时间 * @param key 键 * @param map 对应多个键值 * @param time 时间(秒) * @return true成功 false失败 */ public boolean hmset(String key, Map<String,Object> map, long time){ try { redisTemplate.opsForHash().putAll(key, map); if(time>0){ expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * @param key 键 * @param item 项 * @param value 值 * @return true 成功 false失败 */ public boolean hset(String key,String item,Object value) { try { redisTemplate.opsForHash().put(key, item, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * @param key 键 * @param item 项 * @param value 值 * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 * @return true 成功 false失败 */ public boolean hset(String key,String item,Object value,long time) { try { redisTemplate.opsForHash().put(key, item, value); if(time>0){ expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除hash表中的值 * @param key 键 不能为null * @param item 项 可以使多个 不能为null */ public void hdel(String key, Object... item){ redisTemplate.opsForHash().delete(key,item); } /** * 判断hash表中是否有该项的值 * @param key 键 不能为null * @param item 项 不能为null * @return true 存在 false不存在 */ public boolean hHasKey(String key, String item){ return redisTemplate.opsForHash().hasKey(key, item); } /** * hash递增 如果不存在,就会创建一个 并把新增后的值返回 * @param key 键 * @param item 项 * @param by 要增加几(大于0) * @return */ public double hincr(String key, String item,double by){ return redisTemplate.opsForHash().increment(key, item, by); } /** * hash递减 * @param key 键 * @param item 项 * @param by 要减少记(小于0) * @return */ public double hdecr(String key, String item,double by){ return redisTemplate.opsForHash().increment(key, item,-by); } //============================set============================= /** * 根据key获取Set中的所有值 * @param key 键 * @return */ public Set<Object> sGet(String key){ try { return redisTemplate.opsForSet().members(key); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 根据value从一个set中查询,是否存在 * @param key 键 * @param value 值 * @return true 存在 false不存在 */ public boolean sHasKey(String key,Object value){ try { return redisTemplate.opsForSet().isMember(key, value); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将数据放入set缓存 * @param key 键 * @param values 值 可以是多个 * @return 成功个数 */ public long sSet(String key, Object...values) { try { return redisTemplate.opsForSet().add(key, values); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 将set数据放入缓存 * @param key 键 * @param time 时间(秒) * @param values 值 可以是多个 * @return 成功个数 */ public long sSetAndTime(String key,long time,Object...values) { try { Long count = redisTemplate.opsForSet().add(key, values); if(time>0) expire(key, time); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 获取set缓存的长度 * @param key 键 * @return */ public long sGetSetSize(String key){ try { return redisTemplate.opsForSet().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 移除值为value的 * @param key 键 * @param values 值 可以是多个 * @return 移除的个数 */ public long setRemove(String key, Object ...values) { try { Long count = redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } //===============================list================================= /** * 获取list缓存的内容 * @param key 键 * @param start 开始 * @param end 结束 0 到 -1代表所有值 * @return */ public List<Object> lGet(String key,long start, long end){ try { return redisTemplate.opsForList().range(key, start, end); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 获取list缓存的长度 * @param key 键 * @return */ public long lGetListSize(String key){ try { return redisTemplate.opsForList().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 通过索引 获取list中的值 * @param key 键 * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 * @return */ public Object lGetIndex(String key,long index){ try { return redisTemplate.opsForList().index(key, index); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 将list放入缓存 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, Object value) { try { redisTemplate.opsForList().rightPush(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, Object value, long time) { try { redisTemplate.opsForList().rightPush(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, List<Object> value) { try { redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, List<Object> value, long time) { try { redisTemplate.opsForList().rightPushAll(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据索引修改list中的某条数据 * @param key 键 * @param index 索引 * @param value 值 * @return */ public boolean lUpdateIndex(String key, long index,Object value) { try { redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 移除N个值为value * @param key 键 * @param count 移除多少个 * @param value 值 * @return 移除的个数 */ public long lRemove(String key,long count,Object value) { try { Long remove = redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception e) { e.printStackTrace(); return 0; } } }

spring-boot shiro,后面登录的用户使用的权限是最开始登录用户的权限。

请问一下, spring boot ,集成shiro ,缓存用redis, 在权限这一块 先登录的用户,后面登录的用户,用的权限也是最先登录用户的权限,请问这个是怎么回事呢?

springboot、netty、redis

springboot 整合netty搭建socket,使用redis缓存,可以正常启动,在不适用缓存时可以交互,使用缓存出异常 ``` java.lang.NoSuchMethodError: io.netty.bootstrap.Bootstrap.channel(Ljava/lang/Class;)Lio/netty/bootstrap/AbstractBootstrap; at io.lettuce.core.AbstractRedisClient.channelType(AbstractRedisClient.java:179) ~[lettuce-core-5.1.4.RELEASE.jar:?] at io.lettuce.core.RedisClient.connectStatefulAsync(RedisClient.java:304) ~[lettuce-core-5.1.4.RELEASE.jar:?] at io.lettuce.core.RedisClient.connectStandaloneAsync(RedisClient.java:271) ~[lettuce-core-5.1.4.RELEASE.jar:?] at io.lettuce.core.RedisClient.connect(RedisClient.java:204) ~[lettuce-core-5.1.4.RELEASE.jar:?] at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection$1(StandaloneConnectionProvider.java:113) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at java.util.Optional.orElseGet(Optional.java:267) ~[?:1.8.0_201] at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:113) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1085) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1065) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:865) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getConnection(LettuceConnectionFactory.java:340) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:132) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:95) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:82) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:211) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:95) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:53) ~[spring-data-redis-2.1.5.RELEASE.jar:2.1.5.RELEASE] at com.viewhigh.hiot.elec.service.serviceimp.RedisServiceImpl.get(RedisServiceImpl.java:76) ~[classes/:?] at com.viewhigh.hiot.elec.protocol.ProtocolElecService.isCheck(ProtocolElecService.java:177) ~[classes/:?] at com.viewhigh.hiot.elec.protocol.ProtocolElecService.checkMsg(ProtocolElecService.java:161) ~[classes/:?] at com.viewhigh.hiot.elec.server.SocketServerHandler.channelRead(SocketServerHandler.java:89) ~[classes/:?] at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:74) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:138) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:320) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:154) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:74) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:138) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:320) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:253) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:74) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:138) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:320) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:127) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:485) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:452) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:346) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:794) [netty-all-5.0.0.Alpha1.jar:5.0.0.Alpha1] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_201] ``` 可能是个包冲突,但是不确定也没有找到是那个冲突,求助,帮看看

请问,docker部署后如何修改spring boot 的应用配置文件?

  我是个java开发菜鸟,以前一直维护的是spring mvc+tomcat在linux的web项目,最近在学习spring boot +docker(docker-compose),试图改造我手上的Web项目,但遇到一个问题百思不得其解,还希望哪位大神伸手援助。   先说说我的需求,很简单,以前维护pring mvc+tomcat的时候,只是先在Linux部署tomcat、mysql等组件,然后将我的spring应用放至tomcat/webapps下就可以正常运行,因为部署环境不同,该应用经常需要根据现场实际情况,修改web的config等配置文件然后重启,如果应用报错还可以在指定目录下查看项目打印的各类log日志(log4j输出不同的日志)。虽然前期部署麻烦了一些,但有安装脚本什么的,维护起来也方便。  这段时间接触了spring boot +docker以后,也能够将应用通过docker(docker-compose)方式部署起来,但后续的问题怎么也搞不定,比如我想修改应用配置文件中的某一参数,然后重启docker容器就可以正常运行项目,但不知道如何修改application.xml。   我能想到的方法有三种:   1、通过volume将tomcat映射出来,docker-compose配置如下 ``` #docker-compose的版本 version: '3' #定义服务 services: #服务名称,可随意定义 gwqserive: build: #dockerfile的路径 context: gwqapp #dockerfile的名称 dockerfile: appDockerfile #相当于docker run -v的作用 volumes: - "./jar:/tmp" #容器名称 container_name: gwq-compose-app-container #该服务依赖的其他服务,该配置选项可修改启动顺序 depends_on: - mysqldbserver - redisServer links: - mysqldbserver - redisServer ``` appDockerfile: ``` FROM java:8-jre-alpine #维护者信息 MAINTAINER Gaowq VOLUME /tmp ADD SpringBootRedisDemo-0.0.1-SNAPSHOT.jar app.jar #为构建镜像设置监听端口,使容器在运行时监听 EXPOSE 8080 ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] ``` 好吧,然后容器运行以后,前往/tmp或jar目录下,发现全是tomcat缓存类似的文件,没啥用,跟之前的webapps完全不是一回事  2、想docker exec进去看看,然后。。。一脸meng bi!完全不知道需要的文件在哪  3、我能想到的方式,就是修改好应用配置文件,重新打包jar生成新的镜像,但。。。未免有点太复杂了吧!而且也没有解决我获取不同各类log4j日志的问题。   因为项目最终打包完毕后,将交于专门技术人员安装与维护,故上述情况经常会遇到,由于本人技术太菜,还请各位大神不吝赐教!谢谢!

springboot项目打包成jar之后,显示redis连接失败无法连接到192.168.5.8但是我配置文件redis配置端口是127.0.0.1这是什么情况?

如题,我的springboot中配置的redis明明是127.0.0.1的地址服务器上redis也是127.0.0.1 但是jar启动报错是 无法连接到192.168.5.8 难道是项目缓存嘛? 但是我用ide检索192.168.5.8检索不到,用的是intellij ![图片说明](https://img-ask.csdn.net/upload/201909/24/1569294513_355959.jpg) ![图片说明](https://img-ask.csdn.net/upload/201909/24/1569294523_67987.jpg)

spring boot设置了Access-Control-Allow-Origin还是有跨域问题

最近使用spring cloud框架进行前后端分离开发,因为我们是通过网关去访问后台接口,ip 、端口都相同,所以没有出现过跨域问题,但是前端的同事把项目用webstrom打开以后(端口和ip就成了webstrom分配的)就有了跨域问题无法请求到后台,浏览器报"CORS 头缺少 'Access-Control-Allow-Origin'",但是我们已经在网关里设置了Access-Control-Allow-Origin为*,代码如下: ``` @Service public class AuthFilter extends ZuulFilter { /** * 日志对象 */ private static final Logger logger = LoggerFactory.getLogger(AuthFilter.class); @Autowired private FilterConfig filterConfig; /** * redis缓存 */ @Autowired private RedisService redisService; @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); HttpServletResponse response = ctx.getResponse(); //解决浏览器跨域问题 response.addHeader("Access-Control-Allow-Origin", "*"); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); // response.addHeader("Access-Control-Allow-Credentials", "true"); // response.addHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH"); // response.addHeader("Access-Control-Max-Age", "3600"); // response.addHeader("Vary", "Origin"); response.addHeader("Access-Control-Allow-Headers", "token,accesstoken,Content-type"); //请求接口URL时登录token有效性校验 return null; } @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 0; } } ``` 对此我在本地随便写了个小项目还原了当时的情景,我把代码以及报错贴出来麻烦各位看一下哪里有不对的; 前端代码: ``` <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script src="js/jquery-1.9.1.min.js"></script> </head> <script> function t1(){ $.ajax({ url:'http://localhost:9001/xzw/say', type:'post', contentType : 'application/json;charset=utf-8', dataType:'json', data : JSON.stringify({ batch_id : 'ncveirugheasolvgil' }), success : function(data){ alert('成功跨域'); alert(data); }, error : function(){ alert('error'); } }) } </script> <body> <input type="button" value="测试跨域是否能获取数据" onclick="t1()"/> </body> </html> ``` 后台代码: ``` @RestController @RequestMapping("/xzw") public class PageDemoController { @RequestMapping("/say") public String say(HttpServletRequest request,HttpServletResponse response,@RequestParam(value="batch_id")String batch_id){ response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.addHeader("Access-Control-Allow-Headers", "*"); System.out.println("batch_id="+batch_id); return "hello world"; } } ``` 浏览器报错 > 已拦截跨源请求:同源策略禁止读取位于 http://localhost:9001/xzw/say 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。[详细了解] > > 已拦截跨源请求:同源策略禁止读取位于 http://localhost:9001/xzw/say 的远程资源。(原因:CORS 请求未能成功)。[详细了解] 我们项目里的拦截器原本除了设置Access-Control-Allow-Origin还有验证token的代码,前端如果先进行登陆然后在ajax请求的时候把token拿到放在header里就不会有跨域问题,我把token验证的代码去掉了就出现了跨域问题,但是我看验证token的逻辑判断对跨域没有什么特殊的处理,一下为拦截器原代码: ``` public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); HttpServletResponse response = ctx.getResponse(); //解决浏览器跨域问题 response.addHeader("Access-Control-Allow-Origin", "*"); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); // response.addHeader("Access-Control-Allow-Credentials", "true"); // response.addHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH"); // response.addHeader("Access-Control-Max-Age", "3600"); // response.addHeader("Vary", "Origin"); response.addHeader("Access-Control-Allow-Headers", "token,accesstoken,Content-type"); //请求接口URL时登录token有效性校验 Object token = request.getHeader("token"); if(token==null||token.equals("")) { token = null; } boolean flag = false;//请求路径是否在过滤范围标识 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { ctx.setSendZuulResponse(false); return null; } String ignores = filterConfig.getIgnores(); if(!StringUtilHelper.isEmpty(ignores)) { String[] ignores_arr = ignores.split(","); for(String ignore:ignores_arr) { if(request.getRequestURI().toString().contains(ignore)) { //无需token校验 flag = true; break; } } } logger.info("网关日志:method={}, uri={},result={},token={}",request.getMethod(), request.getRequestURI(), (true==flag?"无需token校验":"需要token校验"),token); if(!flag) { //需要校验token有效性 if(token==null) { ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(HttpServletResponse.SC_UNAUTHORIZED); ctx.setResponseBody("token为空,未认证用户"); return null; } else { //redis校验 if(redisService.check(token.toString())!=ServiceConstants.STATE_1) { ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(HttpServletResponse.SC_UNAUTHORIZED); ctx.setResponseBody("token超时,请重新登录"); return null; } } } return null; } ```

Redis去重算法Bloom Filter算法的通用工具类(java实现),有木有

基于Redis去重算法Bloom Filter算法的通用工具类(java实现),可以拿来直接调用的,大神们有木有?

SpringBoot集成shiro-redis遇到的问题(已解决)

在通过***(SysUser) SecurityUtils.getSubject().getPrincipal()*** 获取当前登录对象时,**SecurityUtils.getSubject().getPrincipal()**是正确的对象。 当强转时报错com.spring.model.system.SysUser cannot be cast to com.spring.model.system.SysUser。 求解本人猜测是redis对象序列化反序列化导致,因为shiro没有集成redis时是正确的,但是经过测试,不走shiro单独存储读取对象是没有问题的,这块不是太懂,求大神解答 下面是相关的配置代码 redis配置 ``` @Configuration @EnableCaching @EnableRedisHttpSession public class RedisConfig extends CachingConfigurerSupport { @Bean public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) { RedisCacheManager manager = new RedisCacheManager(redisTemplate); manager.setDefaultExpiration(3600);//设置默认过期时间 return manager; } @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } @Bean public KeyGenerator keyGenerator() { return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); for (Object obj : params) { sb.append(obj.toString()); } return sb.toString(); } }; } } ``` ``` shiro配置 @Configuration public class ShiroConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.timeout}") private int timeout; @Value("${spring.redis.password}") private String password; @Bean public ShiroDialect shiroDialect() { return new ShiroDialect(); } @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); //拦截器. Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); // 配置不会被拦截的链接 顺序判断 filterChainDefinitionMap.put("/doLogin", "anon"); filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/images/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/libs/**", "anon"); // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 shiroFilterFactoryBean.setLoginUrl("/login"); //未授权界面; shiroFilterFactoryBean.setUnauthorizedUrl("/403"); // 配置需要验证登录后访问的链接 filterChainDefinitionMap.put("/**", "authc"); // 从数据库获取 // List<AdminMenu> list = systemService.selectAllMenu(); // // for (AdminMenu menu : list) { // filterChainDefinitionMap.put(menu.getMenuUrl(), "authc"); // } shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } /** * 凭证匹配器 * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了) * * @return */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法; hashedCredentialsMatcher.setHashIterations(1);//散列的次数 return hashedCredentialsMatcher; } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); // 自定义缓存实现 使用redis securityManager.setCacheManager(cacheManager()); // 自定义session管理 使用redis securityManager.setSessionManager(sessionManager()); //注入记住我管理器; securityManager.setRememberMeManager(rememberMeManager()); return securityManager; } /** * 身份认证realm; (自定义,账号密码校验;权限等) * * @return */ @Bean public MyShiroRealm myShiroRealm() { MyShiroRealm myShiroRealm = new MyShiroRealm(); myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return myShiroRealm; } /** * 配置shiro redisManager * <p> * 使用的是shiro-redis开源插件 * * @return */ public RedisManager redisManager() { RedisManager redisManager = new RedisManager(); redisManager.setHost(host); redisManager.setPort(port); redisManager.setExpire(1800);// 配置缓存过期时间 redisManager.setTimeout(timeout); redisManager.setPassword(password); return redisManager; } /** * cacheManager 缓存 redis实现 * <p> * 使用的是shiro-redis开源插件 * * @return */ @Bean public RedisCacheManager cacheManager() { RedisCacheManager redisCacheManager = new RedisCacheManager(); redisCacheManager.setRedisManager(redisManager()); return redisCacheManager; } /** * RedisSessionDAO shiro sessionDao层的实现 通过redis * <p> * 使用的是shiro-redis开源插件 */ @Bean public RedisSessionDAO redisSessionDAO() { RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); redisSessionDAO.setRedisManager(redisManager()); return redisSessionDAO; } /** * Session Manager * <p> * 使用的是shiro-redis开源插件 */ @Bean public DefaultWebSessionManager sessionManager() { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); sessionManager.setSessionDAO(redisSessionDAO()); return sessionManager; } /** * cookie对象; * * @return */ public SimpleCookie rememberMeCookie() { //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); //<!-- 记住我cookie生效时间7天 ,单位秒;--> simpleCookie.setMaxAge(604800); return simpleCookie; } /** * cookie管理对象;记住我功能 * * @return */ @Bean public CookieRememberMeManager rememberMeManager() { CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); cookieRememberMeManager.setCookie(rememberMeCookie()); //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位) cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag==")); return cookieRememberMeManager; } /** * 开启shiro aop注解支持. * 使用代理方式;所以需要开启代码支持; * * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } } ``` # 去除spring-boot-devtools热部署jar包即可,具体原因不详

关于redis集群 no reachable node in cluster的错误

代码如下 private static JedisCluster jedisCluster = null; static{ Set<HostAndPort> nodes = new HashSet<>(); nodes.add(new HostAndPort("114.112.69.204", 7001)); nodes.add(new HostAndPort("114.112.69.204", 7002)); nodes.add(new HostAndPort("114.112.69.204", 7003)); nodes.add(new HostAndPort("114.112.69.204", 7004)); nodes.add(new HostAndPort("114.112.69.204", 7005)); nodes.add(new HostAndPort("114.112.69.204", 7006)); // 1、创建一个JedisCluster对象,构造方法,需要指定一个Set对象,set中包含HostAndPort对象。每个HostAndPort就是一个节点的地址。 jedisCluster = new JedisCluster(nodes); /*JedisPoolConfig config = new JedisPoolConfig(); config.setMaxActive(1000); config.setMaxIdle(300); config.setMaxWait(10000); config.setTestOnBorrow(false); jedisPool =new JedisPool(config, "114.112.69.204", 6379);*/ } @RequestMapping("/index.html") @ResponseBody //加入redis缓存 public Map<String, Object> index(HttpServletRequest request, HttpServletResponse response) throws IOException { Map<String, Object> result = new HashMap<String, Object>(); ObjectMapper objectMapper = new ObjectMapper(); IndexResult indexResult = null; String indexJson = jedisCluster.hget("indexResult_KEY","indexResult666"); if (StringUtils.isNotBlank(indexJson)) { try {//取出redis中的数据 indexResult = objectMapper.readValue(indexJson, IndexResult.class); } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ if (jedisCluster != null) { jedisCluster.close(); } } 在正常请求时会报错!!!!主要错误如下 严重: Servlet.service() for servlet [goutrip_api] in context with path [] threw exception [Request processing failed; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: no reachable node in cluster] with root cause redis.clients.jedis.exceptions.JedisConnectionException: no reachable node in cluster at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnection(JedisSlotBasedConnectionHandler.java:54) at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:113) at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:131) at redis.clients.jedis.JedisClusterCommand.run(JedisClusterCommand.java:30) at redis.clients.jedis.JedisCluster.hget(JedisCluster.java:361) at com.goutrip.controller.index.IndexController.index(IndexController.java:95) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) 而使用命令行取出数据是没有问题的 ![图片说明](https://img-ask.csdn.net/upload/201603/25/1458879946_317708.png) 要崩溃了啊!!!!快来救救我!!!!!!!!

请教Mybatis清空一级缓存清空不掉

下面我的测试代码 ``` //测试一级缓存:sqlSession的更新操作 @org.junit.Test public void testUpdate() throws IOException { //5.使用代理对象执行方法 User users1 = userDao.findById(41); System.out.println(users1); users1.setUsername("SqlSession update3"); userDao.updateByUser(users1); User users2 = userDao.findById(41); System.out.println(users2); System.out.println(users1 == users2); //true } //测试一级缓存:sqlSession的删除操作 @org.junit.Test public void testDelete() throws IOException { //5.使用代理对象执行方法 User users1 = userDao.findById(41); System.out.println(users1); userDao.deleteById(49); User users2 = userDao.findById(41); System.out.println(users2); System.out.println(users1 == users2); //true } ``` SqlSession的增删改操作按理说不是会清空一级缓存嘛。。 为什么我的这两个操作均不能清空缓存,数据在数据库中是有发生变化,两次获取到的user都是同一个 这是为什么??

请教下,怎样用ThreadLocal缓存用户信息啊?

请教下,能不能绕过action,不传参,直接在service中获得session中的用户信息?? 我的做法是:每次用户登录后,就将用户缓存到ThreadLocal里,用户登出就清ThreadLocal;但是失败了,每次用户登录后,第一次点击菜单就报错!之后再点击就正常了! 不得已,用了比较土的办法先凑合着:action里传用户给service

Springboot2.2.2不能连接数据库

1.写一个体验redis缓存的demo,不能连接数据库。 导入其他人的项目可以,连接自己的数据库,可以连接成功。确定数据库连接信息没有写错。参考网上,修改mysql-connector-java的版本也没有用。 系统环境:java-1.8; mysql-5.1.62; IDEA 2019-1.4;SpringBoot 2.2.2; 2.pom文件: <?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.2.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>cache</artifactId> <version>0.0.1-SNAPSHOT</version> <name>cache</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 3.配置文件 ![图片说明](https://img-ask.csdn.net/upload/202001/06/1578275877_830078.png) 4.报错信息 ![图片说明](https://img-ask.csdn.net/upload/202001/06/1578276565_257380.png) ![图片说明](https://img-ask.csdn.net/upload/202001/06/1578275918_258494.png) ![图片说明](https://img-ask.csdn.net/upload/202001/06/1578275931_720085.png) ![图片说明](https://img-ask.csdn.net/upload/202001/06/1578275953_50439.png) ![图片说明](https://img-ask.csdn.net/upload/202001/06/1578275966_288013.png)

大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了

大学四年,看课本是不可能一直看课本的了,对于学习,特别是自学,善于搜索网上的一些资源来辅助,还是非常有必要的,下面我就把这几年私藏的各种资源,网站贡献出来给你们。主要有:电子书搜索、实用工具、在线视频学习网站、非视频学习网站、软件下载、面试/求职必备网站。 注意:文中提到的所有资源,文末我都给你整理好了,你们只管拿去,如果觉得不错,转发、分享就是最大的支持了。 一、电子书搜索 对于大部分程序员...

在中国程序员是青春饭吗?

今年,我也32了 ,为了不给大家误导,咨询了猎头、圈内好友,以及年过35岁的几位老程序员……舍了老脸去揭人家伤疤……希望能给大家以帮助,记得帮我点赞哦。 目录: 你以为的人生 一次又一次的伤害 猎头界的真相 如何应对互联网行业的「中年危机」 一、你以为的人生 刚入行时,拿着傲人的工资,想着好好干,以为我们的人生是这样的: 等真到了那一天,你会发现,你的人生很可能是这样的: ...

程序员请照顾好自己,周末病魔差点一套带走我。

程序员在一个周末的时间,得了重病,差点当场去世,还好及时挽救回来了。

ArrayList源码分析(入门篇)

ArrayList源码分析 前言: 写这篇博客的主要原因是,在我上一次参加千牵科技Java实习生面试时,有被面试官问到ArrayList为什么查找的速度较快,插入和删除的速度较慢?当时我回答得不好,很大的一部分原因是因为我没有阅读过ArrayList源码,虽然最后收到Offer了,但我拒绝了,打算寒假学得再深入些再广泛些,下学期开学后再去投递其他更好的公司。为了更加深入理解ArrayList,也为

我以为我学懂了数据结构,直到看了这个导图才发现,我错了

数据结构与算法思维导图

String s = new String(" a ") 到底产生几个对象?

老生常谈的一个梗,到2020了还在争论,你们一天天的,哎哎哎,我不是针对你一个,我是说在座的各位都是人才! 上图红色的这3个箭头,对于通过new产生一个字符串(”宜春”)时,会先去常量池中查找是否已经有了”宜春”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此”宜春”对象的拷贝对象。 也就是说准确答案是产生了一个或两个对象,如果常量池中原来没有 ”宜春” ,就是两个。...

技术大佬:我去,你写的 switch 语句也太老土了吧

昨天早上通过远程的方式 review 了两名新来同事的代码,大部分代码都写得很漂亮,严谨的同时注释也很到位,这令我非常满意。但当我看到他们当中有一个人写的 switch 语句时,还是忍不住破口大骂:“我擦,小王,你丫写的 switch 语句也太老土了吧!” 来看看小王写的代码吧,看完不要骂我装逼啊。 private static String createPlayer(PlayerTypes p...

和黑客斗争的 6 天!

互联网公司工作,很难避免不和黑客们打交道,我呆过的两家互联网公司,几乎每月每天每分钟都有黑客在公司网站上扫描。有的是寻找 Sql 注入的缺口,有的是寻找线上服务器可能存在的漏洞,大部分都...

讲一个程序员如何副业月赚三万的真实故事

loonggg读完需要3分钟速读仅需 1 分钟大家好,我是你们的校长。我之前讲过,这年头,只要肯动脑,肯行动,程序员凭借自己的技术,赚钱的方式还是有很多种的。仅仅靠在公司出卖自己的劳动时...

上班一个月,后悔当初着急入职的选择了

最近有个老铁,告诉我说,上班一个月,后悔当初着急入职现在公司了。他之前在美图做手机研发,今年美图那边今年也有一波组织优化调整,他是其中一个,在协商离职后,当时捉急找工作上班,因为有房贷供着,不能没有收入来源。所以匆忙选了一家公司,实际上是一个大型外包公司,主要派遣给其他手机厂商做外包项目。**当时承诺待遇还不错,所以就立马入职去上班了。但是后面入职后,发现薪酬待遇这块并不是HR所说那样,那个HR自...

女程序员,为什么比男程序员少???

昨天看到一档综艺节目,讨论了两个话题:(1)中国学生的数学成绩,平均下来看,会比国外好?为什么?(2)男生的数学成绩,平均下来看,会比女生好?为什么?同时,我又联想到了一个技术圈经常讨...

副业收入是我做程序媛的3倍,工作外的B面人生是怎样的?

提到“程序员”,多数人脑海里首先想到的大约是:为人木讷、薪水超高、工作枯燥…… 然而,当离开工作岗位,撕去层层标签,脱下“程序员”这身外套,有的人生动又有趣,马上展现出了完全不同的A/B面人生! 不论是简单的爱好,还是正经的副业,他们都干得同样出色。偶尔,还能和程序员的特质结合,产生奇妙的“化学反应”。 @Charlotte:平日素颜示人,周末美妆博主 大家都以为程序媛也个个不修边幅,但我们也许...

MySQL数据库面试题(2020最新版)

文章目录数据库基础知识为什么要使用数据库什么是SQL?什么是MySQL?数据库三大范式是什么mysql有关权限的表都有哪几个MySQL的binlog有有几种录入格式?分别有什么区别?数据类型mysql有哪些数据类型引擎MySQL存储引擎MyISAM与InnoDB区别MyISAM索引与InnoDB索引的区别?InnoDB引擎的4大特性存储引擎选择索引什么是索引?索引有哪些优缺点?索引使用场景(重点)...

如果你是老板,你会不会踢了这样的员工?

有个好朋友ZS,是技术总监,昨天问我:“有一个老下属,跟了我很多年,做事勤勤恳恳,主动性也很好。但随着公司的发展,他的进步速度,跟不上团队的步伐了,有点...

我入职阿里后,才知道原来简历这么写

私下里,有不少读者问我:“二哥,如何才能写出一份专业的技术简历呢?我总感觉自己写的简历太烂了,所以投了无数份,都石沉大海了。”说实话,我自己好多年没有写过简历了,但我认识的一个同行,他在阿里,给我说了一些他当年写简历的方法论,我感觉太牛逼了,实在是忍不住,就分享了出来,希望能够帮助到你。 01、简历的本质 作为简历的撰写者,你必须要搞清楚一点,简历的本质是什么,它就是为了来销售你的价值主张的。往深...

玩转springboot启动banner定义所得

最近接手了一个springboot项目,不是不熟悉这个框架,启动时打印的信息吸引了我。 这不是我熟悉的常用springboot的打印信息啊,我打开自己的项目: 还真是的,不用默认的感觉也挺高大上的。一时兴起,就去研究了一下源代码,还正是有些收获,稍后我会总结一下。正常情况下做为一个老程序员,是不会对这种小儿科感兴趣的,不就是一个控制台打印嘛。哈哈! 于是出于最初的好奇,研究了项目的源代码。看到

带了6个月的徒弟当了面试官,而身为高级工程师的我天天修Bug......

即将毕业的应届毕业生一枚,现在只拿到了两家offer,但最近听到一些消息,其中一个offer,我这个组据说客户很少,很有可能整组被裁掉。 想问大家: 如果我刚入职这个组就被裁了怎么办呢? 大家都是什么时候知道自己要被裁了的? 面试软技能指导: BQ/Project/Resume 试听内容: 除了刷题,还有哪些技能是拿到offer不可或缺的要素 如何提升面试软实力:简历, 行为面试,沟通能...

离职半年了,老东家又发 offer,回不回?

有小伙伴问松哥这个问题,他在上海某公司,在离职了几个月后,前公司的领导联系到他,希望他能够返聘回去,他很纠结要不要回去? 俗话说好马不吃回头草,但是这个小伙伴既然感到纠结了,我觉得至少说明了两个问题:1.曾经的公司还不错;2.现在的日子也不是很如意。否则应该就不会纠结了。 老实说,松哥之前也有过类似的经历,今天就来和小伙伴们聊聊回头草到底吃不吃。 首先一个基本观点,就是离职了也没必要和老东家弄的苦...

男生更看重女生的身材脸蛋,还是思想?

往往,我们看不进去大段大段的逻辑。深刻的哲理,往往短而精悍,一阵见血。问:产品经理挺漂亮的,有点心动,但不知道合不合得来。男生更看重女生的身材脸蛋,还是...

为什么程序员做外包会被瞧不起?

二哥,有个事想询问下您的意见,您觉得应届生值得去外包吗?公司虽然挺大的,中xx,但待遇感觉挺低,马上要报到,挺纠结的。

当HR压你价,说你只值7K,你该怎么回答?

当HR压你价,说你只值7K时,你可以流畅地回答,记住,是流畅,不能犹豫。 礼貌地说:“7K是吗?了解了。嗯~其实我对贵司的面试官印象很好。只不过,现在我的手头上已经有一份11K的offer。来面试,主要也是自己对贵司挺有兴趣的,所以过来看看……”(未完) 这段话主要是陪HR互诈的同时,从公司兴趣,公司职员印象上,都给予对方正面的肯定,既能提升HR的好感度,又能让谈判气氛融洽,为后面的发挥留足空间。...

面试:第十六章:Java中级开发(16k)

HashMap底层实现原理,红黑树,B+树,B树的结构原理 Spring的AOP和IOC是什么?它们常见的使用场景有哪些?Spring事务,事务的属性,传播行为,数据库隔离级别 Spring和SpringMVC,MyBatis以及SpringBoot的注解分别有哪些?SpringMVC的工作原理,SpringBoot框架的优点,MyBatis框架的优点 SpringCould组件有哪些,他们...

面试阿里p7,被按在地上摩擦,鬼知道我经历了什么?

面试阿里p7被问到的问题(当时我只知道第一个):@Conditional是做什么的?@Conditional多个条件是什么逻辑关系?条件判断在什么时候执...

终于懂了TCP和UDP协议区别

终于懂了TCP和UDP协议区别

你打算用Java 8一辈子都不打算升级到Java 14,真香

我们程序员应该抱着尝鲜、猎奇的心态,否则就容易固步自封,技术停滞不前。

无代码时代来临,程序员如何保住饭碗?

编程语言层出不穷,从最初的机器语言到如今2500种以上的高级语言,程序员们大呼“学到头秃”。程序员一边面临编程语言不断推陈出新,一边面临由于许多代码已存在,程序员编写新应用程序时存在重复“搬砖”的现象。 无代码/低代码编程应运而生。无代码/低代码是一种创建应用的方法,它可以让开发者使用最少的编码知识来快速开发应用程序。开发者通过图形界面中,可视化建模来组装和配置应用程序。这样一来,开发者直...

面试了一个 31 岁程序员,让我有所触动,30岁以上的程序员该何去何从?

最近面试了一个31岁8年经验的程序猿,让我有点感慨,大龄程序猿该何去何从。

大三实习生,字节跳动面经分享,已拿Offer

说实话,自己的算法,我一个不会,太难了吧

程序员垃圾简历长什么样?

已经连续五年参加大厂校招、社招的技术面试工作,简历看的不下于万份 这篇文章会用实例告诉你,什么是差的程序员简历! 疫情快要结束了,各个公司也都开始春招了,作为即将红遍大江南北的新晋UP主,那当然要为小伙伴们做点事(手动狗头)。 就在公众号里公开征简历,义务帮大家看,并一一点评。《启舰:春招在即,义务帮大家看看简历吧》 一石激起千层浪,三天收到两百多封简历。 花光了两个星期的所有空闲时...

《经典算法案例》01-08:如何使用质数设计扫雷(Minesweeper)游戏

我们都玩过Windows操作系统中的经典游戏扫雷(Minesweeper),如果把质数当作一颗雷,那么,表格中红色的数字哪些是雷(质数)?您能找出多少个呢?文中用列表的方式罗列了10000以内的自然数、质数(素数),6的倍数等,方便大家观察质数的分布规律及特性,以便对算法求解有指导意义。另外,判断质数是初学算法,理解算法重要性的一个非常好的案例。

立即提问
相关内容推荐