spring 组件@Scope(request,session)示例
2017-11-30 22:27
351 查看
上回说到, spring组件的注解Scope大约有singleton、prototype、request、session、global session 这么几种常用的场景。这里需要特别说明一下,根据源代码显示 Scope注解分为ConfigurableBeanFactory和WebApplicationContext两个大类,ConfigurableBeanFactory包含(singleton、prototype)两种Scope,WebApplicationContext下面有(ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,request,session,application,servletContext,contextParameters,contextAttributes)这么几种Scope。今天的示例重点是对request,session两个场景进行一次测试。
那在谈到具体的示例前,我先分享下对这两种场景的使用心得,以便与各位看官进行思想上的神交! 我们都知道B/S站点运行起来后,是一个多线程的运行环境。每个客户端登录都会产生一个session会话,它的生命周期 从登录系统到 session过期,期间session上存储的信息都是有效可用的,我习惯于叫它会话级的缓存,像用户登录的身份信息我们一般都会绑定到这个session上。这里我们要讲的@Scope("session"),就是spring提供出来的一个会话级bean方案,在这种模式下,用spring的DI功能来获取组件,可以做到在会话的生命周期中这个组件只有一个实例。接下来再说请求(request),http协议的处理模型,从客户端发起request请求,到服务端的处理,最后response给客户端,我们称为一次完整的请求。在这样的一次请求过程中,我们的服务站可能要串行调用funcA->funcB->funcC·... 这样的一串函数,假如我们的系统需要做细致的权限校验(用户权限,数据权限),更可怕的是funcA,funcB,funcC是3个人分别实现的,而且都要做权限校验。那么极有可能会出现3个人各连接了一次数据库,读取了同一批权限数据。这里想象一下,假如一个数据读取要花2秒,那么3个方法就要花费6秒的处理时间。但实际上这些数据只用在这个请求过程中读取一次,缓存在request上下文环境中,我习惯称之为线程级缓存。关于线程级缓存java有ThreadLocal方案,像Hibernate的事务就是用这种方案维持一次执行过程中数据库连接的唯一。当然,今天要讲的@Scope("request")也可以做到这种线程级别的缓存。下面我们看看具体的测试示例
实现测试步骤说明:
1、创建一个@Scope("session")标注的Bean组件。关于proxyMode这个参数,是为了解决依存的会话或者请求上下文环境还没有时,自动装载组件报错,这里交给JDK代理,可以保证环境准备就绪时再执行组件装载。
2、创建一个@Scope("request")标注的Bean组件
3、添加一个多例的组件自动组装服务类,方便获取session、request组件。
4、添加测试代码
5、先发起一次登录请求,再发起一次登录后的检查请求。从打印的测试结果可以看到两次请求 拿到的session组件,其对应的ID都是相同的,所以在同一个会话中,session组件是唯一的。而request组件,在同一个request请求过程中,调用两次都得到同一个组件ID,而在第二次请求中request组件的ID改变了。因此正如上面所说,@Scope("request")模式在同一请求过程中,spring返回的组件也是唯一的,我们可以用这个方案来做线程级别的数据缓存。
参考资料
https://www.cnblogs.com/waytofall/p/3460533.html
https://www.cnblogs.com/lonecloud/p/5937513.html
那在谈到具体的示例前,我先分享下对这两种场景的使用心得,以便与各位看官进行思想上的神交! 我们都知道B/S站点运行起来后,是一个多线程的运行环境。每个客户端登录都会产生一个session会话,它的生命周期 从登录系统到 session过期,期间session上存储的信息都是有效可用的,我习惯于叫它会话级的缓存,像用户登录的身份信息我们一般都会绑定到这个session上。这里我们要讲的@Scope("session"),就是spring提供出来的一个会话级bean方案,在这种模式下,用spring的DI功能来获取组件,可以做到在会话的生命周期中这个组件只有一个实例。接下来再说请求(request),http协议的处理模型,从客户端发起request请求,到服务端的处理,最后response给客户端,我们称为一次完整的请求。在这样的一次请求过程中,我们的服务站可能要串行调用funcA->funcB->funcC·... 这样的一串函数,假如我们的系统需要做细致的权限校验(用户权限,数据权限),更可怕的是funcA,funcB,funcC是3个人分别实现的,而且都要做权限校验。那么极有可能会出现3个人各连接了一次数据库,读取了同一批权限数据。这里想象一下,假如一个数据读取要花2秒,那么3个方法就要花费6秒的处理时间。但实际上这些数据只用在这个请求过程中读取一次,缓存在request上下文环境中,我习惯称之为线程级缓存。关于线程级缓存java有ThreadLocal方案,像Hibernate的事务就是用这种方案维持一次执行过程中数据库连接的唯一。当然,今天要讲的@Scope("request")也可以做到这种线程级别的缓存。下面我们看看具体的测试示例
实现测试步骤说明:
1、创建一个@Scope("session")标注的Bean组件。关于proxyMode这个参数,是为了解决依存的会话或者请求上下文环境还没有时,自动装载组件报错,这里交给JDK代理,可以保证环境准备就绪时再执行组件装载。
@Component //@Scope(value=WebApplicationContext.SCOPE_SESSION) @Scope(value=WebApplicationContext.SCOPE_SESSION,proxyMode=ScopedProxyMode.INTERFACES) public class SessionBean implements ISessionBean { private UUID uuid; public SessionBean(){ uuid = UUID.randomUUID(); } public void printId(){ System.out.println("SessionBean:"+uuid); } }
2、创建一个@Scope("request")标注的Bean组件
@Component @Scope(value = WebApplicationContext.SCOPE_REQUEST,proxyMode= ScopedProxyMode.INTERFACES) public class RequestBean implements IRequestBean { private UUID uuid; public RequestBean() { uuid = UUID.randomUUID(); } public void printId() { System.out.println("RequestBean:" + uuid); } }
3、添加一个多例的组件自动组装服务类,方便获取session、request组件。
@Service @Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class BeanInstance { @Autowired private IRequestBean requestBean; @Autowired private ISessionBean sessionBean; public IRequestBean getRequestBean() { return requestBean; } public ISessionBean getSessionBean() { return sessionBean; } }
4、添加测试代码
@Controller @RequestMapping("/user") // 添加session信息的注解,可以实现 session信息与map的映射 赋值 @SessionAttributes("user") public class UserController { @Autowired private BeanInstance beanInstance1; @Autowired private BeanInstance beanInstance2; @RequestMapping(value = "/login", method = RequestMethod.GET) public String login(String name, Model model, HttpServletRequest request, HttpSession session) { model.addAttribute("user", name); System.out.println("SessionBean-1"); beanInstance1.getSessionBean().printId(); System.out.println("SessionBean-2"); beanInstance2.getSessionBean().printId(); System.out.println("RequestBean-1"); beanInstance1.getRequestBean().printId(); System.out.println("RequestBean-2"); beanInstance2.getRequestBean().printId(); return "user/check"; } /** * 检查自动装载的信息 * @param model * @param request * @param session * @return */ @RequestMapping(value = "/check", method = RequestMethod.GET) public String check(Model model, HttpServletRequest request, HttpSession session) { System.out.println("SessionBean-1"); beanInstance1.getSessionBean().printId(); System.out.println("SessionBean-2"); beanInstance2.getSessionBean().printId(); System.out.println("RequestBean-1"); beanInstance1.getRequestBean().printId(); System.out.println("RequestBean-2"); beanInstance2.getRequestBean().printId(); return "user/check"; } }
5、先发起一次登录请求,再发起一次登录后的检查请求。从打印的测试结果可以看到两次请求 拿到的session组件,其对应的ID都是相同的,所以在同一个会话中,session组件是唯一的。而request组件,在同一个request请求过程中,调用两次都得到同一个组件ID,而在第二次请求中request组件的ID改变了。因此正如上面所说,@Scope("request")模式在同一请求过程中,spring返回的组件也是唯一的,我们可以用这个方案来做线程级别的数据缓存。
参考资料
https://www.cnblogs.com/waytofall/p/3460533.html
https://www.cnblogs.com/lonecloud/p/5937513.html
相关文章推荐
- spring 学习1-Request, session, and global session scopes|(Initial web configuration)
- spring 组件自动装载示例(@ComponentScan,@Component,@Scope)
- Spring4.04中实现bean的scope(范围)设置为session或者request
- 【Spring】Spring IOC原理及源码解析之scope=request、session
- 【Spring】Spring IOC原理及源码解析之scope=request、session
- 浅谈Spring学习之request,session与globalSession作用域
- spring的普通类中如何取session和request对像
- scope="session"和scope="request"--抛出异常非常的bug+垃圾
- JSP中page、request、session和application的scope
- spring scope="prototype", scope="session"
- ContextLoaderListener、RequestContextListener等web项目的监听器,用于实例化spring容器中的组件
- Spring获取Session和request
- 利用Spring随时随地获得Request和Session
- Freemarker SpringMVC 前台无法使用session;request等对象问题
- Thymeleaf+SpringMVC,从模板中获取数据session、request参数
- spring创建SqlSession的scope="request"问题
- spring如何获取request response session
- 【转载】spring的普通类中如何取session和request对像
- Spring 的作用域 Singleton,Prototype, Session ,Request
- spring在普通类中获取session和request,springsession