美文网首页
spring session-使用Redis

spring session-使用Redis

作者: 非典型_程序员 | 来源:发表于2019-05-26 16:35 被阅读0次

前面说到了使用Redis处理项目中缓存的问题,其中我说过也可以使用Redis实现session共享,今天就来看下使用Redis怎么实现session共享。其实session共享的方案都是比较成熟了,去年自己的项目中也使用到了Redis实现session共享,但是因为这方面并不是自己负责,对具体实现并不是很了解,所以今天就一起来学习一下。spring的生态可以说越来越完善,不管什么样的问题,基本都能找到相应的解决方案,不得不佩服。
spring session可选的存储方案也是比较多的,比如JDBC、MongoDB、Redis等等,建议多看一下spring的文档。自己MongoDB不怎么了解,所以还是从熟悉的Redis开始吧。


spring session提供了用于管理用户会话信息的API和实现。它还提供透明集成:
1、HttpSession:允许在应用程序容器(即Tomcat)以中立方式中替换HttpSession。
2、WebSocket:提供在接收WebSocket消息时保持HttpSession活动的能力。
3、WebSession:允许以应用程序容器中立方式替换Spring WebFlux的WebSession。
我们主要说下HttpSession,因为目前开发它使用的还是最多的。

一、创建项目

首先还是创建一个spring boot项目,选择依赖spring session、Redis等依赖。这里需要说明一点必须还要选择security,不然项目启动会报错:

java.lang.ClassNotFoundException: org.springframework.security.web.authentication.RememberMeServices

自己网上找了很久也没找到答案,后来看了官方文档才知道,spring session默认提供了与spring security的集成,详情可以参考文档spring-session
下面是项目的一些配置:

server.port=9090

# redis
spring.redis.database=5
spring.redis.host=localhost
spring.redis.port=6379

# spring session
spring.session.store-type=redis
spring.session.timeout=5m
spring.session.redis.flush-mode=on_save
spring.session.redis.namespace=redis:session
#server.servlet.session.timeout=10m

# database
spring.datasource.password=123456
spring.datasource.username=postgres
spring.datasource.url=jdbc:postgresql://localhost:5432/gosql?useSSL=false&characterEncoding=utf8
spring.datasource.driver-class-name=org.postgresql.Driver

# mybatis
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.ypc.redis.springsession.model

# security
spring.security.user.name=user
spring.security.user.password=123456

# view
spring.thymeleaf.mode=HTML
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false

因为项目添加了spring security的依赖,当使用security时spring默认给我们提供了一个登录页,当然也可以换成自定义的登录页,这里为了简便,直接就使用了默认的登录页,并且用户名和密码也写死到配置文件了。自己以前看过一点security的内容,感觉还是非常复杂的...当然这次学习主要是学习spring session,关于security我建议还是单独的系统学习一下,自己感觉还是挺难的。
上面的配置文件主要说下spring session相关配置:

spring.session.store-type=redis,指定spring session的存储类型为Redis
spring.session.timeout=5m,指定spring session的超时时间,如果不指定单位,默认时间为s
spring.session.redis.flush-mode=on_save,session刷新模式,一个是on_save一个是immediate,前者是保存时刷新,即响应结束后刷新;后者实时刷新。
spring.session.redis.namespace=redis:session,存储session的命名空间,默认是spring:session。
server.servlet.session.timeout=10m,也是指定session超时时间,如果没有配置spring.session.timeout时会使用该配置

二、测试

因为使用了security,因此每次会话时必须先登录,因此只能通过浏览器访问了。自定义两个接口,代码如下:

@RestController
@RequestMapping("/session")
public class SessionController {

    private static final Logger LOGGER = LoggerFactory.getLogger(SessionController.class);

    @Autowired
    private SessionService sessionService;

    @GetMapping("/get/list/{name}")
    public List<Book> getByName(@PathVariable("name") String name,HttpServletRequest httpServletRequest) {
        LOGGER.info(">>>> query book list by author name={} <<<<",name);

        HttpSession httpSession = httpServletRequest.getSession();
        String sessionId = httpSession.getId();
        httpSession.setAttribute("name",name);
        LOGGER.info(">>>> sessionId in '/get/list/{name}' request mapping, sessionId={} <<<<",sessionId);
        return sessionService.getByName(name);
    }

    @GetMapping("/get/{title}")
    public Book getOneByTitle(@PathVariable("title")String title, HttpServletRequest httpServletRequest) {

        HttpSession httpSession = httpServletRequest.getSession();
        String sessionId = httpSession.getId();
        String name = (String) httpSession.getAttribute("name");
        LOGGER.info(">>>> get name from session, name={},sessionId={} <<<<",name,sessionId);
        return sessionService.getOneByTitle(title);
    }

}

我们先直接通过浏览器直接调用接口,结果直接返回到登录页面了,看下请求头

图-1.png
我们看到响应码是302,即服务端进行了重定向,location是:http://localhost:9090/login
再试试使用rest client调用,如下:
图-2.png
显示没有授权,也就是没有权限访问,也就是说必须先登录以后才能访问接口。
输入用户名和密码,登录之后再访问http://localhost:9090/session/get/list/ypc,结果如下:
图-3.png
然后看看控制台输出的sessionId:sessionId=838a928a-60f8-4bc5-87bf-f728f6876425
我们再查看Redis中的session信息:
图-4.png
看Redis中session的命名空间和我们配置的一样都是redis:session,session中的hash中就是sessionId的值。说明session存储到Redis成功了。
不过因为自己只有一个用户,而且服务也只有一个,没办法测试多个用户登录情况,还有就是集群情况下,session共享的问题,不过原理应该是一样的。
下面通过启动两个服务来测试session,一个端口为8080,一个端口为9090。使用本地nginx进行负载均衡,负载均衡策略使用nginx默认的轮询,一个是用idea启动,端口9090,另一个通过命令行启动,端口8080。启动前先清空redis的session数据。先访问localhost/session/get/list/ypc,(为了向session中添加属性)这个请求被打到了9090端口:
图-5.png
接着访问localhost/session/get/learn spring,这个请求会被打到8080端口服务上,我们看下日志输出
图-6.png
根据上面两张图片可以看出不同端口的两个服务,用户访问时使用的是相同的session,也说明使用spring session成功实现了session共享。

到这里关于spring session的学习结束了,其实spring session这块还是比较简单的。不过因为集成了security,加上对security不熟悉,不像spring cache那么简单明了。有一点我比较好奇就是spring session存储session的时候能不能自定义序列化策略(比如json),目前看到的都是二进制的,这个等有时间再研究下。内容不多,但是感觉自己写的比较乱,希望大家见谅。

相关文章

网友评论

      本文标题:spring session-使用Redis

      本文链接:https://www.haomeiwen.com/subject/tfsxtctx.html