使用Redis来实现Session共享,其实网上已经有不少例子了,这是确保在集群部署中最典型的redis使用场景。在SpringBoot项目中,其实能够一行运行代码都不用写,只须要简单添加添加依赖和一行注解就能够实现(固然配置信息仍是须要的)。 而后简单地把该项目部署到不一样的tomcat下,好比不一样的端口(A、B),但项目访问路径是相同的。此时在A中使用set方法,而后在B中使用get方法,就能够发现B中能够获取A中设置的内容。html
但若是就把这样的一个项目在多个tomcat中的部署说实现了单点登陆,那就不对了。java
所谓单点登陆是指在不一样的项目中,只须要任何一个项目登陆了,其余项目不须要登陆。redis
一样是上面的例子,咱们把set和get两个方法分别放到两个项目(set、get)中,而且以集群方式把两个项目都部署到服务器A和B中,而后分别访问A服务器的set和B服务器的get,你就会发现彻底得不到你想要的结果。spring
依赖添加就不说了,直接使用最简单的方式tomcat
@SpringBootApplication @EnableRedisHttpSession @RestController public class SessionShareApplication { public static void main(String[] args) { SpringApplication.run(SessionShareApplication.class, args); } @Autowired HttpSession session; @Autowired HttpServletRequest req; @GetMapping("/set") public Object set() { session.setAttribute("state", "state was setted."); Map<String, Object> map = new TreeMap<>(); map.put("msg", session.getAttribute("state")); map.put("serverPort", req.getLocalPort()); return map; } @GetMapping("/get") public Object get() { Map<String, Object> map = new TreeMap<>(); map.put("msg", session.getAttribute("state")); map.put("serverPort", req.getLocalPort()); return map; } }
将该项目打war包,分别部署在tomcatA(端口8080),tomcatB(端口8081),而后经过tomcatA/set 方法设置session,再使用 tomcatB/get 方法便可得到session的值。但这只是实现了同一项目session的共享。并非单点登陆。springboot
为了验证,咱们不仿将set/get方法拆分为两个项目。服务器
@SpringBootApplication @EnableRedisHttpSession @RestController public class SetApplication { public static void main(String[] args) { SpringApplication.run(SetApplication.class, args); } @Autowired HttpSession session; @Autowired HttpServletRequest req; @GetMapping("/") public Object set() { session.setAttribute("state", "state was setted."); Map<String, Object> map = new TreeMap<>(); map.put("msg", session.getAttribute("state")); map.put("serverPort", req.getLocalPort()); return map; } }
将该项目打包为set.warcookie
@SpringBootApplication @EnableRedisHttpSession @RestController public class GetApplication { public static void main(String[] args) { SpringApplication.run(GetApplication.class, args); } @Autowired HttpSession session; @Autowired HttpServletRequest req; @GetMapping("/") public Object get() { Map<String, Object> map = new TreeMap<>(); map.put("msg", session.getAttribute("state")); map.put("serverPort", req.getLocalPort()); return map; } }
将该项目打包为get.war 再分别将set.war,get.war部署在tomcatA和tomcatB,再经过 tomcatA/set 设置session内容, 而后经过 tomcatB/get 就发现没法得到session的值。session
尽管咱们使用的路径都是同样的,但实际上是两个项目,与前面的一个项目是彻底不一样的,问题就在于 session和cookie在默认状况下是与项目路径相关的,在同一个项目的状况下两个方法所须要的cookie依赖的项目路径是相同的,因此获取session的值就没有问题,但在后一种状况下,cookie的路径是分别属于不一样的项目的,因此第二个项目就没法得到第一个项目中设置的session内容了。app
解决方法在springboot项目中其实也很是简单。既然cookie路径发生了变化,那咱们让它配置为相同的路径就解决了。 在每一个子项目中都添加一个配置类或者直接设置cookie的路径,若是有域名还能够设置域名的限制,好比 set.xxx.com 与 get.xxx.com 这种状况与咱们就须要设置cookie的域名为 xxx.com,以确保没法在哪一个项目下都可以获取 xxx.com 这个域名下的cookie值。这样就确保可以正常得到共享的session值了。
@Configuration public class CookieConfig { @Bean public static DefaultCookieSerializer defaultCookieSerializer() { DefaultCookieSerializer serializer = new DefaultCookieSerializer(); serializer.setCookiePath("/"); //serializer.setDomainName("xxx.com"); //若是使用域名访问,建议对这一句进行设置 return serializer; } }
以上才是正直的redis实现单点登陆的正确打开方式。
原文出处:https://www.cnblogs.com/askmiw/p/11229437.html