打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
spring session入门
userphoto

2015.06.28

关注
参考资料:
http://projects.spring.io/spring-session/#quick-start
http://docs.spring.io/spring-session/docs/current-SNAPSHOT/reference/html5/guides/httpsession.html#httpsession-sample

spring session提供以下功能:
1.API and implementations for managing a user's session
2.HttpSession - allows replacing the HttpSession in an application container (i.e. Tomcat) neutral way
2.1.Clustered Sessions - Spring Session makes it trivial to support clustered sessions without being tied to an application container specific solution.
2.2.Multiple Browser Sessions - Spring Session supports managing multiple users' sessions in a single browser instance (i.e. multiple authenticated accounts similar to Google).
2.3.RESTful APIs - Spring Session allows providing session ids in headers to work with RESTful APIs
3.WebSocket - provides the ability to keep the HttpSession alive when receiving WebSocket messages

仅是集群session功能,都是振奋人心的.spring session是通过filter嵌入去实现的(spring security也是使用这种方式),下面是个例子.

1.主要依赖

  1. <dependency>  
  2.     <groupId>org.slf4j</groupId>  
  3.     <artifactId>jcl-over-slf4j</artifactId>  
  4.     <version>${slf4j.version}</version>  
  5. </dependency>  
  6. <dependency>  
  7.     <groupId>org.slf4j</groupId>  
  8.     <artifactId>slf4j-log4j12</artifactId>  
  9.     <version>${slf4j.version}</version>  
  10. </dependency>  
  11. <dependency>  
  12.     <groupId>org.springframework</groupId>  
  13.     <artifactId>spring-webmvc</artifactId>  
  14.     <version>${spring.version}</version>  
  15.     <exclusions>  
  16.         <exclusion>  
  17.             <groupId>commons-logging</groupId>  
  18.             <artifactId>commons-logging</artifactId>  
  19.         </exclusion>  
  20.     </exclusions>  
  21. </dependency>  
  22. <dependency>  
  23.     <groupId>org.springframework</groupId>  
  24.     <artifactId>spring-tx</artifactId>  
  25.     <version>${spring.version}</version>  
  26. </dependency>  
  27. <dependency>  
  28.     <groupId>org.springframework</groupId>  
  29.     <artifactId>spring-aop</artifactId>  
  30.     <version>${spring.version}</version>  
  31. </dependency>  
  32. <dependency>  
  33.     <groupId>org.springframework</groupId>  
  34.     <artifactId>spring-context-support</artifactId>  
  35.     <version>${spring.version}</version>  
  36. </dependency>  
  37. <dependency>  
  38.     <groupId>org.springframework.data</groupId>  
  39.     <artifactId>spring-data-redis</artifactId>  
  40.     <version>1.4.1.RELEASE</version>  
  41. </dependency>  
  42. <dependency>  
  43.     <groupId>redis.clients</groupId>  
  44.     <artifactId>jedis</artifactId>  
  45.     <version>2.5.2</version>  
  46. </dependency>  
  47. <dependency>  
  48.     <groupId>org.springframework.session</groupId>  
  49.     <artifactId>spring-session</artifactId>  
  50.     <version>${spring.session.version}</version>  
  51. </dependency>  
2.写一个configuration来启用RedisHttpSession,在这个配置注册一个redis客户端的连接工厂Bean,供Spring Session用于与redis服务端交互.
  1. package org.exam.config;  
  2. import org.springframework.context.annotation.Bean;  
  3. import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;  
  4. import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;  
  5. /** 
  6.  * Created by xin on 15/1/20. 
  7.  */  
  8. @EnableRedisHttpSession  
  9. public class SessionConfig {  
  10.     @Bean  
  11.     public JedisConnectionFactory connectionFactory() {  
  12.         return new JedisConnectionFactory();  
  13.     }  
  14. }  
3.写一个Initializer,主要用于向应用容器添加springSessionRepositoryFilter.
  1. package org.exam.config;  
  2. import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;  
  3. /** 
  4.  * Created by xin on 15/1/20. 
  5.  */  
  6. public class SessionApplicationInitializer extends AbstractHttpSessionApplicationInitializer {  
  7. }  
4.将SessionConfig加入到org.exam.config.DispatcherServletInitializer#getRootConfigClasses
  1. @Override  
  2. protected Class<?>[] getRootConfigClasses() {  
  3.     return new Class<?>[] {AppConfig.class,SessionConfig.class};  
  4. }  
5.使用例子.
  1. package org.exam.web;  
  2. import org.springframework.stereotype.Controller;  
  3. import org.springframework.ui.Model;  
  4. import org.springframework.web.bind.annotation.RequestMapping;  
  5. import javax.servlet.http.HttpServletRequest;  
  6. import javax.servlet.http.HttpSession;  
  7. /** 
  8.  * Created by xin on 15/1/7. 
  9.  */  
  10. @Controller  
  11. public class DefaultController {  
  12.     @RequestMapping("/")  
  13.     public String index(Model model,HttpServletRequest request,String action,String msg){  
  14.         HttpSession session=request.getSession();  
  15.         if ("set".equals(action)){  
  16.             session.setAttribute("msg", msg);  
  17.         }else if ("get".equals(action)){  
  18.             String message=(String)session.getAttribute("msg");  
  19.             model.addAttribute("msgFromRedis",message);  
  20.         }  
  21.         return "index";  
  22.     }  
  23. }  
得到这个被spring session包装过的session,像平常一样直接使用.
6.测试.先启动redis服务端.
请求:localhost:8080/testweb/?action=set&msg=123   把123通过spring session set到redis去.
请求:localhost:8080/testweb/?action=get  从redis取出刚才存入的值.

从redis删除存入去相关的值,再次请求localhost:8080/testweb/?action=get查看结果


下面顺便跟踪下实现吧:

1.注册springSessionRepositoryFilter位置在:org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer#insertSessionRepositoryFilter,从org.springframework.web.filter.DelegatingFilterProxy#initDelegate可以看出会去找名为springSessionRepositoryFilter Bean的实现作为Filter的具体实现.
2.因为使用了@EnableRedisHttpSession,就会使用org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration,这个配置里注册的springSessionRepositoryFilter Bean就是SessionRepositoryFilter.即springSessionRepositoryFilter的实现为org.springframework.session.web.http.SessionRepositoryFilter
3.Filter每一次的请求都会调用doFilter,即调用SessionRepositoryFilter的父类OncePerRequestFilter的doFilter,此方法会调用SessionRepositoryFilter自身的doFilterInternal.这个方法如下:

  1. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {  
  2.     request.setAttribute(SESSION_REPOSITORY_ATTR, sessionRepository);  
  3.     SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response);  
  4.     SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(wrappedRequest,response);  
  5.     HttpServletRequest strategyRequest = httpSessionStrategy.wrapRequest(wrappedRequest, wrappedResponse);  
  6.     HttpServletResponse strategyResponse = httpSessionStrategy.wrapResponse(wrappedRequest, wrappedResponse);  
  7.     try {  
  8.         filterChain.doFilter(strategyRequest, strategyResponse);  
  9.     } finally {  
  10.         wrappedRequest.commitSession();  
  11.     }  
  12. }  
4.从这里就知request经过了包装,当然里面的getSession方法也重写了.org.springframework.session.web.http.SessionRepositoryFilter.SessionRepositoryRequestWrapper#getSession(boolean)方法如下:
  1. public HttpSession getSession(boolean create) {  
  2.     if(currentSession != null) {  
  3.         return currentSession;  
  4.     }  
  5.     String requestedSessionId = getRequestedSessionId();  
  6.     if(requestedSessionId != null) {  
  7.     S session = sessionRepository.getSession(requestedSessionId);  
  8.         if(session != null) {  
  9.             this.requestedValidSession = true;  
  10.             currentSession = new HttpSessionWrapper(session, getServletContext());  
  11.             currentSession.setNew(false);  
  12.             return currentSession;  
  13.         }  
  14.     }  
  15.     if(!create) {  
  16.         return null;  
  17.     }  
  18.     S session = sessionRepository.createSession();  
  19.     currentSession = new HttpSessionWrapper(session, getServletContext());  
  20.     return currentSession;  
  21. }  
即上面的例子调用getSession会调用此方法来获取Session.而此Session是通过sessionRepository创建的,此处注入的是org.springframework.session.data.redis.RedisOperationsSessionRepository(sessionRepository的注册也是在org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration),而不是应用服务器本身去创建的.






本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
activiti5.22 springboot 流程引擎 实战全过程
利用spring
spring+websocket整合(springMVC+spring+MyBatis即SSM框架和websocket技术的整合)
玩转springboot2.x之搭建Actuator和spring boot admin监控篇
meavn-pom坐标
谈一谈JUnit神奇的报错 java.lang.Exception:No tests found matching
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服