前言
由于HTTP协议是无状态的协议,一次浏览器和服务器的交互过程就是一次会话,对话完成后,这次会话就结束了,服务器端并不能记住这个人,下次再对话时,服务器端并不知道是上一次的这个人,所以服务端需要记录用户的状态时,就需要用某种机制来识别具体的用户,这个机制就是Session,服务端如何识别特定的客户?这个时候需要使用Cookie;每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session时,服务端会在HTTP协议中向客户端 Cookie 中记录一个Session ID,以后每次请求把这个会话ID发送到服务器,这样服务端就知道客户端是谁了;那么如果客户端的浏览器禁用了 Cookie 怎么办? 一般这种情况下,会使用一种叫做URL重写的技术来进行session会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如 sessionId=xxxxx 这样的参数,服务端据此来识别客户端是谁;
Session会话管理
在Web项目开发中,Session会话管理是一个很重要的部分,用于存储与记录用户的状态或相关的数据;通常情况下session交由容器(tomcat)来负责存储和管理,但是如果项目部署在多台tomcat中,则session管理存在很大的问题;1、多台tomcat之间无法共享session,比如用户在tomcat A服务器上已经登录了,但当负载均衡跳转到tomcat B时,由于tomcat B服务器并没有用户的登录信息,session就失效了,用户就退出了登录;2、一旦tomcat容器关闭或重启也会导致session会话失效;因此如果项目部署在多台tomcat中,就需要解决session共享的问题;
Session会话共享方案
第一种是使用容器扩展插件来实现,比如基于Tomcat的tomcat-redis-session-manager插件,基于Jetty的jetty-session-redis插件、memcached-session-manager插件;这个方案的好处是对项目来说是透明的,无需改动代码,但是由于过于依赖容器,一旦容器升级或者更换意味着又得重新配置;
第二种是使用Nginx负载均衡的ip_hash策略实现用户每次访问都绑定到同一台具体的后台tomcat服务器实现session总是存在;
第三种是自己写一套Session会话管理的工具类,在需要使用会话的时候都从自己的工具类中获取,而工具类后端存储可以放到Redis中,这个方案灵活性很好,但开发需要一些额外的时间。
第四种是使用框架的会话管理工具,也就是本文所使用的Spring session,这个方案既不依赖tomcat容器,又不需要改动代码,由Spring session框架为我们提供,可以说是目前非常完美的session共享解决方案;
Spring Session简介
Spring Session 是Spring家族中的一个子项目,Spring Session提供了用于管理用户会话信息的API和实现。
它把servlet容器实现的httpSession替换为spring-session,专注于解决 session管理问题,Session信息存储在Redis中,可简单快速且无缝的集成到我们的应用中;
spring session官网地址:https://spring.io/projects/spring-session
Spring Session的特性:
1、提供用户session管理的API和实现;
2、提供HttpSession,以中立的方式取代web容器的session,比如tomcat中的session;
3、支持集群的session处理,不必绑定到具体的web容器去解决集群下的session共享问题;
Spring Session示例
使用Spring session管理session,开发步骤如下:
1、添加案例所需要的maven依赖
org.springframework.session
spring-session
1.3.1.RELEASE
org.springframework.session
spring-session-data-redis
1.3.1.RELEASE
org.springframework.data
spring-data-redis
1.8.8.RELEASE
redis.clients
jedis
2.9.0
org.springframework
spring-web
5.0.0.RELEASE
javax.servlet
javax.servlet-api
3.1.0
javax.servlet.jsp
javax.servlet.jsp-api
2.3.1
javax.servlet
jstl
1.2
2、在web.xml文件文件中配置springSessionRepositoryFilter过滤器
springSessionRepositoryFilter
org.springframework.web.filter.DelegatingFilterProxy
springSessionRepositoryFilter
/*
3、在web.xml文件中加载Spring配置文件
contextConfigLocation
classpath:applicationContext.xml
org.springframework.web.context.ContextLoaderListener
4、Spring配置文件配置一个RedisHttpSessionConfiguration类
5、Spring配置文件配置Spring-data-redis
6、redis配置文件
redis.hostName=192.168.184.133
redis.port=6379
redis.password=123456
redis.usePool=true
redis.timeout=10000
7、编写一个Servlet或JSP验证session共享问题
@WebServlet(name = "SessionServlet", urlPatterns = "/session")
public class SessionServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String sesssionID = request.getSession().getId();
//部署两份,把这个地方8081改成8080就行了,只是为了区分
response.getWriter().write("8081 Server SessionID"+sesssionID);
}
}
演示案例:
1、同域名下相同项目实现Session共享
795b073c-0e27-4339-bf01-2fb7d39a3ed2f
2、同域名下不同项目实现Session共享
3、同根域名不同二级子域名下的项目实现Session共享
4、不同根域名下的项目实现Session共享