多个SpringBoot项目采用redis实现Session共享功能
有时我们可能有多个不同的Web应用,可以相互调用,这时如果每个应用都有自己的session,那用户跳转到另一个应用时就又需要登陆一次,这样会带来很不好的体验,因此我们需要在不同的应用中共享session。这里,我们采用redis来实现。
前置说明
由于只用到redis和springboot的整合,所以只能实现一个URL下的不同端口的应用之间的session共享,如果连应用名称都完全不同的两个应用要实现session共享,在这个基础上还需要使用到Nginx,这种方式我暂时还没有试过。(SpringBoot项目默认就是不带应用名称的,除非自己在配置文件中修改过)
需要提前在本地安装好redis,或者连接远程redis服务器。这里就不写安装教程了,可以自行去网上搜索。
添加依赖
需要为springboot项目添加以下两个依赖,参与session共享的项目都需要添加。
org.springframework.boot spring-boot-starter-data-redis org.springframework.session spring-session-data-redis
一个是redis的依赖,一个是spring-session-data-redis的依赖。
配置redis参数
在SpringBoot项目的application.properties配置文件中配置redis参数:
#Redis数据库索引(默认为0) spring.redis.database=0 #Redis服务器地址,如果是远程redis服务器,就改成服务器地址 spring.redis.host=127.0.0.1 #Redis服务器连接端口,默认是6379 spring.redis.port=6379 #连接池最大连接数(使用负值表示没有限制) spring.redis.lettuce.pool.max-active=8 #连接池最大阻塞等待时间(使用负值表示没有限制) spring.redis.lettuce.pool.max-wait=-1ms #连接池中的最大空闲连接 spring.redis.lettuce.pool.max-idle=5 #连接池中的最小空闲连接 spring.redis.lettuce.pool.min-idle=0 #连接超时时间(毫秒) spring.redis.timeout=5000 spring.session.store-type=redis
如果你的项目使用的是application.yml,就进行如下配置:
spring: redis: database:0 host:127.0.0.1 port:6379 lettuce: pool: max-idle:8 min-idle:0 max-active:8 max-wait:-1ms timeout:5000 session: store-type:redis
配置session过期时间
创建一个用于配置session过期时间的配置类:
importorg.springframework.context.annotation.Configuration; importorg.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; @Configuration @EnableRedisHttpSession(maxInactiveIntervalInSeconds=86400*30) publicclassSessionConfig{ }
简单的登录逻辑
@RequestMapping("/doLogin") publicStringdoLogin(HttpServletRequestrequest,Modelmodel){ Stringusername=request.getParameter("username"); Stringpassword=request.getParameter("password"); if(StringUtils.isEmpty(username)||StringUtils.isEmpty(password)){ model.addAttribute("errorMsg","用户名和密码不能为空"); return"login"; } //查找该用户,成功后根据该用户的类别返回到对应页面 Useruser=userService.getUserByUsernameAndPassword(username,password); if(user==null){ model.addAttribute("errorMsg","用户名或密码错误"); return"login"; }else{ request.getSession().setAttribute("currentUser",user); model.addAttribute("currentUser",user); Stringidentity=user.getIdentity(); if("admin".equals(identity)){ return"admin"; }else{ return"user"; } } }
直接按照原来的方式将对象存入session:request.getSession().setAttribute("currentUser",user);此时session会存入redis。
登录过滤器
@Component publicclassLoginInterceptorimplementsHandlerInterceptor{ @Override publicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler) throwsException{ HttpSessionsession=request.getSession(); UsercurrentUser=(User)session.getAttribute("currentUser"); if(currentUser==null){ response.sendRedirect(request.getContextPath()+"/toLogin"); returnfalse; }else{ returntrue; } } @Override publicvoidpostHandle(HttpServletRequesthttpServletRequest,HttpServletResponsehttpServletResponse, Objecto,ModelAndViewmodelAndView)throwsException{ } @Override publicvoidafterCompletion(HttpServletRequesthttpServletRequest,HttpServletResponsehttpServletResponse, Objecto,Exceptione)throwsException{ } }
同样按原来的方式从session中取出对象:UsercurrentUser=(User)session.getAttribute("currentUser");此时会从redis中取出该对象。
注意
如果只是存字符串等redis可以直接解析的对象,那就不会有什么问题,但是如果是存取对象就需要进行序列化了,比如上文中存的是我自定义的一个User对象,那么在存的时候,是会对该对象进行序列化的,取出时也会进行反序列化,因此该对象要实现Serializable接口,并且需要进行session共享的项目中都要有一个一模一样的对象,比如我的User定义如下:
importjava.io.Serializable; publicclassUserimplementsSerializable{ privateStringid; privateStringusername; privateStringpassword; privateStringemail; privateStringidentity; privatestaticfinallongserialVersionUID=-5809782578272943999L; //省略getter、setter方法 }
注意这个序列号serialVersionUID,不同应用中的User对象的这个序列号必须相同,否则无法正确进行反序列化。
小结
之所以要实现这个功能是因为在我搭建自己的网站时想集成之前做过的另一个应用,把它作为一个功能嵌入这个应用中,通过http互通。中间遇到了很多坑,这种方式的主要缺点就是不能支持不同应用名称的应用之间的session共享,下一次可以尝试一下加入Nginx。
到此这篇关于多个SpringBoot项目采用redis实现Session共享功能的文章就介绍到这了,更多相关SpringBootSession共享内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。