spring boot 中使用redis session

  spring boot 默认的httpsession是存在内存中。这种默认方式有几个缺点:1、当分布式部署时,存在session不一致的问题;2、当服务重启时session就会丢失,这时候用户就需要重新登陆,可能导致用户数据丢失。通常会使用redis来保存session。

  在spring boot中利用redis来保存session是非常简单。只需要简单的几步就可以了。可以参考官方教程。https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-redis.html

  配置流程:

  1、pom文件中添加依赖

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

  注意:如果pom文件没有引入 spring-boot-starter-data-redis,则需要引入,否则无法自动配置redis,出现这个错误'org.springframework.data.redis.connection.RedisConnectionFactory' that could not be found.

  2、在配置文件中添加相关配置

#配置sesion使用redis
spring.session.store-type=redis
设置session的一些属性
server.servlet.session.cookie.http-only=true
server.servlet.session.timeout= 15000
#设置session在redis中的Namespace,避免和其他key冲突
spring.session.redis.namespace=spring:session
配置redis的链接
spring.redis.host=localhost
spring.redis.password=
spring.redis.port=6379

  到这里,其实已经配置好了,可以直接使用httpsession了,没有特别的地方。

  开发过程遇到的问题。

  本地测试通过之后部署到测试环境发现无法正常运行,报如下异常:

Caused by: io.lettuce.core.RedisCommandExecutionException: ERR unknown command 'CONFIG'
	at io.lettuce.core.protocol.AsyncCommand.completeResult(AsyncCommand.java:118) ~[lettuce-core-5.0.3.RELEASE.jar:na]
	at io.lettuce.core.protocol.AsyncCommand.complete(AsyncCommand.java:109) ~[lettuce-core-5.0.3.RELEASE.jar:na]
	at io.lettuce.core.protocol.CommandHandler.complete(CommandHandler.java:601) ~[lettuce-core-5.0.3.RELEASE.jar:na]
	at io.lettuce.core.protocol.CommandHandler.decode(CommandHandler.java:559) ~[lettuce-core-5.0.3.RELEASE.jar:na]
	at io.lettuce.core.protocol.CommandHandler.channelRead(CommandHandler.java:511) ~[lettuce-core-5.0.3.RELEASE.jar:na]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459) ~[netty-transport-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886) ~[netty-common-4.1.23.Final.jar:4.1.23.Final]
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.23.Final.jar:4.1.23.Final]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_171]

  在github上有相关的issue,https://github.com/spring-projects/spring-session/issues/124,并且给了解决办法。

  一般是因为安全问题redis服务端禁用了CONFIG命令,而RedisHttpSessionConfiguration需要使用这个命令进行一些初始化。导致无法初始化。

  一个简单的解决方式是添加一个jiava配置

@Bean
public static ConfigureRedisAction configureRedisAction() {
    return ConfigureRedisAction.NO_OP;
}

  

  

  

 

posted @ 2018-10-21 23:18  lwli  阅读(1779)  评论(0编辑  收藏  举报