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; }