Spring session的学习与应用

session

概述

由于HTTP协议是无状态的协议,一次浏览器和服务器的交互过程就是:
发送请求
浏览器----------------------------->服务器
返回请求
浏览器----------------------------->服务器
这就是一次会话,对话完成后这次会话就结束了,服务器端并不能记住这个人的信息状态,下次再次对话时,服务器不能确定此次会话主人的信息,所以服务器端要记录用户的状态时,就要用某种机制来识别到具体的用户,这个机制就是Session。
Session是服务器为每个用户创建一个会话,存储用户的相关信息,以便多次请求能够定位到同一个上下文。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 内的客户信息将会被识别统一上下文,整个用户会话中一直存在下去,会话场景则不会丢失。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。

Web开发中,web-server可以自动为同一个浏览器的访问用户自动创建session,提供数据存储功能。最常见的,会把用户的登录信息、用户信息存储在session中,以保持登录状态。

服务器如何识别特定的客户?

这个时候则需要使用Cookie;
每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。
实际上大多数应用都是用Cookie来实现Session跟踪的,第一次创建Session时,服务端会在HTTP协议中向客户端Cookie中记录一个Session ID,以后每次请求把这个会话ID发送到服务器,这样服务端就会知道客户端是谁了;
如果客户端的浏览器禁用了Cookie,会使用一种叫URL重写的技术来进行session会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如sessionId=xxx的参数,服务端据此来识别客户端是谁。

Session会话管理

在Web项目中,Session会话管理时一个很重要的部分,用于存储与记录用户的状态或相关的数据信息;通常情况下Session交由容器(Tomcat)来负责存储和管理,但是如果项目部署到多台Tomcat中,Session管理则会存在很大的问题。如:多台Tomcat之间Session无法共享,运用负载均衡部署的话,用户会出现不确定的退出登录的状况;或一旦Tomcat关闭或重启也会导致session会话失效;因此如果项目部署在多台Tomcat中,就要解决Session共享的问题

Session会话共享方案

  • 使用容器扩展插件来实现,比如:基于Tomcat的tomcat-redis-session-manager插件(需要在tomcat中的server.xml中配置,是将session复制到所有服务器中),基于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家族中的子成员,它提供一组api和实现,用于管理用户的session信息;它把servlet容器实现的httpSession替换为spring-session,专注于解决session管理问题,Session信息存储在Redis中,可简单快速且无缝的集成到我们的应用中;

Spring 网址https://spring.io/

Spring Session 的特性:

  • 提供用户session管理的api和实现;
  • 提供HttpSession,以中立的方式取代web容器的session,比如tomcat中的session;
  • 支持集群的session处理,不必绑定到具体的web容器去解决集群下的session共享问题;

使用示例

使用Spring Session管理session开发步奏

  • spring MVC的配置
  1. 添加Spring Session的maven依赖:

    <!-- spring session 依赖-->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session</artifactId>
            <version>1.3.1.RELEASE</version>
        </dependency>
    
    
        <!-- spring session redis 依赖-->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
            <version>1.3.1.RELEASE</version>
        </dependency>
    
    
        <!-- spring-dataa-redis 依赖的JAR配置-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.8.8.RELEASE</version>
        </dependency>
    
    
        <!-- jedis依赖的JAR配置-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
    
    
        <!-- spring web 依赖的JAR配置-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.3.10.RELEASE</version>
        </dependency>
    
    
        <!-- servlet依赖的JAR配置-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
    
    
        <!-- jsp依赖的JAR配置-->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
        </dependency>
    

    2.在web.xml文件中配置springSessionRepositoryFilter过滤器
    全局过滤器

      	<!-- Spring session框架的全局的过滤器-->
      	<filter>
      		<filter-name>springSessionRepositoryFilter</filter-name>
      		<!-- 
      		DelegatingFilterProxy代理 springSessionRepositoryFilter类
      		springSessionRepositoryFilter类是在applicationContext.xml中配置的
      		RedisHttpSessionConfiguration类中
      		 -->
      		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
      	</filter>
      	<filter-mapping>
      		<filter-name>springSessionRepositoryFilter</filter-name>
      		<url-pattern>/*</url-pattern>
      	</filter-mapping>
    

    3.在web.xml文件中加载spring配置文件

    • 第一种 监听器启动spring容器(Java)

        <context-param>
        	<param-name>contextConfigLocation</param-name>
        	<param-value>classpath:applicationContext.xml</param-value>
        </context-param>
      
        <listener>
        	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
      
    • 第二种 使用spring mvc的DispatcherServlet启动spring容器

        <servlet>  
               <servlet-name>springmvc</servlet-name>  
               <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
               <load-on-startup>1</load-on-startup>  
           </servlet>  
         
           <servlet-mapping>  
               <servlet-name>springmvc</servlet-name>  
               <url-pattern>/</url-pattern>  
           </servlet-mapping>
      

    4.Spring配置文件(applicationContext.xml)配置一个RedisHttpSessionConfiguration类(在session的配置文件中配置即可)

    		<!--  
    		spring注解、bean的处理器 
    	    注解的配置    识别注解
    		-->
    		<context:annotation-config/>
    
    
    		<!--  Spring session的配置类  -->
    		<bean class:"org.springframework.session.data.redis.config.annotation.web.RedisHttpSessionConfiguration">
    			<!--指定session策略-->
        		<!--<property name="httpSessionStrategy" ref="httpSessionStrategy"/>-->
        		<!--
        		指定过期时间
        		单位  秒
        		-->
        		<property name="maxInactiveIntervalInSeconds" value="1800" />
    		</bean>
    		<bean id="httpSessionStrategy" class="org.springframework.session.web.http.CookieHttpSessionStrategy">
            <!--httpsession策略-->
            <property name="httpSessionStrategy" ref="httpSessionStrategy"/>
    		</bean>
    		<!-- 采用cookie策略 -->
    	    <bean id="httpSessionStrategy" class="org.springframework.session.web.http.CookieHttpSessionStrategy">
    	    	<property name="cookieSerializer"  ref="cookieSerializer" />
        	</bean>
        	<bean id="cookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer" />
    	        <!--指定cookie的域名及路径-->
    	        <property name="cookiePath" value="/"/>
    	        <property name="domainName" value="web.com"/>
    	    </bean>
    

    5.Spring配置文件配置Spring-data-redis

    		<!-- 配置jedis连接工厂,用于连接redis -->
    		<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    		    <property name="hostName" value="${redis.hostName}"/>
    		    <property name="port" value="${redis.port}"/>
    		    <property name="password" value="${redis.password}"/>
    		    <!-- 是否使用连接池 -->
    		    <property name="usePool" value="${redis.usePool}"/>
    		    <!-- 超时时间 -->
    		    <property name="timeout" value="${redis.timeout}"/>
    		</bean>
    		<!-- 读取redis.properties属性配置文件 -->
    		<context:property-placeholder location="classpath:redis.properties"/>
    

    配置redis配置文件

    redis.hostName=127.0.0.1
    redis.port=6379
    redis.password=123456
    redis.usePool=true
    redis.timeout=10000
    
  • springBoot配置
    1.maven配置依赖

     <!--redis 依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--sessions 依赖-->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
    

    2.配置redis.properties文件

    在applications.properties文件中加上:

       #同时引用redies.properties文件相当于mvc中<import resource="xxxxx.xml" />
       spring.profiles.include=redis 
    
     spring.redis.host=localhost
     spring.redis.port=6379
     # spring session使用存储类型,spirngboot默认就是使用redis方式,如果不想用可以填none。
     spring.session.store-type=redis
     #连接超时时间(毫秒)
     spring.redis.timeout=1800000
     #指定cookie的路径
     server.servlet.session.cookie.path="/"
     #指定cookie的域名
     server.servlet.session.cookie.domain="web.com"
    

    3.在启动类中加入@EnableRedisHttpSession 注解
    4.在需要操作Redis的类中注入redisTemplate,它是由spring自动配置好的

    @Autowride
    private RedisTemplate<String,String> redisTemplate;
    
    //写代码时最好将key的序列化设置成可读性比较强的
    redisTemplate.setKeySerializer(new StringSerializer());
    

    或者

    @Autowride
    private RedisTemplate<Object,Object> redisTemplate;
    

    泛型里只能写<String,String>、<Object,Object>

实际应用

  • 同域名下相同项目实现session共享
    在同一个域名下,比如:www.myweb.com,同一个项目部署了多台tomcat,此为典型的集群方式

  • 同域名下不同项目实现session共享
    在同一个域名下有多个不同的项目,如:www.web,com/jiekuan;www.web.com/touzi;
    在这里插入图片描述
    注意:设置Cookie路径为根/上下文
    在applicationContext.xml文件的RedisHttpSessionConfiguration类的bean中设置session策略

       		<!--  Spring session的配置类  -->
       		<bean class:"org.springframework.session.data.redis.config.annotation.web.RedisHttpSessionConfiguration">
       			<!--指定session策略-->
           		<!--<property name="httpSessionStrategy" ref="httpSessionStrategy"/>-->
           		<!--
           		指定过期时间
           		单位  秒
           		-->
           		<property name="maxInactiveIntervalInSeconds" value="1800" />
       		</bean>
       		<bean id="httpSessionStrategy" class="org.springframework.session.web.http.CookieHttpSessionStrategy">
               <!--httpsession策略-->
               <property name="httpSessionStrategy" ref="httpSessionStrategy"/>
       		</bean>
    			<!-- 采用cookie策略 -->
       	    <bean id="httpSessionStrategy" class="org.springframework.session.web.http.CookieHttpSessionStrategy">
       	    	<!-- cookie的存放方式 -->
       	    	<property name="cookieSerializer"  ref="cookieSerializer" />
           	</bean>
           	<bean id="cookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer" />
           		<!-- 不设置的时候默认的是项目工程下的 -->
       	        <!--指定cookie的路径  存放在根路径下-->
       	        <property name="cookiePath" value="/"/>
       	    </bean>
    
  • 同域名不同二级子域名下的项目实现session共享
    同一个根域名但是二级域名不同,如:www.web.com、beijing.web.com、nanjing.web.com
    在这里插入图片描述
    * 设置Cookie路径为根/上下文
    同上
    * 设置cookie域名根域名web.com

     <bean id="cookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer" />
         <!--指定cookie的路径-->
         <property name="cookiePath" value="/"/>
         <!--指定cookie的域名-->
         <property name="domainName" value="web.com"/>
     </bean>
    
  • 不同根域名下的项目实现session共享
    根域名不同 如:www.baidu.com、www.webo.com,要实现一处登录,处处登录,Spring Session不支持,需要采用其它方式。
    如:单点登录(Single Sign On,SSO),在多个应用系统中,用户只需要登录一次就可访问所有相互信任的应用系统。
    比如阿里的多个业务线之间的登录模式

集群环境下session共享示例
在这里插入图片描述

发布了9 篇原创文章 · 获赞 11 · 访问量 406

猜你喜欢

转载自blog.csdn.net/qq_41681399/article/details/105278282