`
squall140
  • 浏览: 146301 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

spring3.X mvc 应用Session属性的策略

 
阅读更多

喜好读书,就便是把生活生计中寂寞的辰光换成重大享受的时刻。本文项目组内容参考至:http://anffvf.blog.163.com/blog/static/314754201101342148699/

士兵不要思惟,有魁首替他们思惟。?

WEB 应用凡是会引入 Session,用来在办事端和客户端之间保存一系列动作/消息的状况,比如网上购物保护 user 登录信息直到 user 退出。在 user 登录后,Session 周期里有很多 action 都须要从 Session 中获得 user,再验证身份权限,或者进行其他的操纵。这此中就会涉及到法度去接见 Session属性的题目。在java中,Servlet 规范供给了 HttpSession对象来满足这种需求。开辟人员可以从 HttpServletRquest对象获得 HttpSession,再从HttpSession中获得状况信息。

还是回到购物车的例子,假设在 controller 某个办法(本文简称为action)中我们要从HttpSession中取到user对象。若是基于Servlet,标准的代码会是如许的:

public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
User user = (User)req.getSession().getAttribute("currentUser");
//
}

如许的代码在传统的Servlet法度中是很常见的:因为应用了 Servlet API,从而对 Servlet API产生依附。如许若是我们要测试 action,我们就必须针对 HttpServletRequest、HttpServletResponse 和 HttpSession类供给 mock 或者 stub 实现。当然如今已经有很多开源的 Servlet 测试框架帮助我们减轻这个疾苦,包含 Spring 就自带了对了这些类的 stub 实现,但那还是太冗繁琐碎了。那有没有斗劲好的办法来让我们的 controller 更 POJO,让我们的 action 离开 Servlet API 依附,更有益于测试和复用呢?我们来看看在 Spring2.5 中接见 Session 属性的几种策略,并将在本博的后续文章持续商量解决规划选择后面的深层含义。

(一)经由过程办法参数传入HttpServletRequest对象或者HttpSession对象

Spring对annotationed的 action 的参数供给主动绑定支撑的参数类型包含 Servlet API 里面的 Request/Response/HttpSession(包含Request、Response在Servlet API 中声明的具体子类)。于是开辟人员可以经由过程在 action 参数中声明 Request 对象或者 HttpSession 对象,来让容器注入响应的对象。

action 的代码如下:

@RequestMapping
public void hello(HttpSession session){
User user = (User)session.getAttribute("currentUser");
//
}

长处:

1. 法度中直接获得底层的 Request/HttpSession 对象,直接应用 Servlet API 规范中定义的办法操纵这些对象中的属性,直接而简单。
2. action 须要接见哪些具体的 Session 属性,是由本身把握的,真正正确到 Session 中的每个特定属性。

不足:

1. 法度对 Servlet API 产生依附。固然 controller 类已经不须要从 HttpServlet 持续,但仍须要 Servlet API 才干完成编译运行,甚至测试。
2. 露出了底层 Servlet API,露出了很多并不须要的底层办法和类,开辟人员轻易滥用这些 API。

(二)经由过程定制阻碍器(Interceptor)在controller类级别注入须要的User对象

Interceptor 是 Spring 供给的扩大点之一,SpringMVC 会在 handle 某个 request 前后调用在设备中定义的 Interceptor 完成一些切面的工作,比如验证用户权限、处理惩罚分发等,类似于 AOP。那么,我们可以提取如许一个“横切点”,在 SpringMVC 调用 action 前,在 Interceptor 的 preHandle 办法中给 controller 注入 User 成员变量,使之具有当前登录的 User 对象。

此外还须要给这些特定 controller 声明一类 interface,比如 IUserAware。如许开辟人员就可以只针对这些须要注入 User 对象的 controller 进行注入加强。

IUserAware 的代码:

public interface IUserAware {
public void setUser();
}

?
controller 的代码:

@Controller
public GreetingController implements IUserAware {
private User user;
public void setUser(User user){
this.user = user;
}

@RequestMapping
public void hello(){
//user.sayHello();
}
//
}

?

Interceptor 的代码:

public class UserInjectInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
if (handler.isAssignableFrom(IUserAware)){
User user = (User)httpServletRequest.getSession().getAttribute("currentUser");
IUserAware userAware = (IUserAware) handler;
userAware.setUser(user);
}
return super.preHandle(httpServletRequest, httpServletResponse, handler);
}
//
}

?

为了让 SpringMVC 能调用我们定义的 Interceptor,我们还须要在 SpringMVC 设备文件中声明该 Interceptor,比如:

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="userInjectInterceptor"/><!-- userInjectInterceptor bean 的声明省略-->
</list>
</property>
</bean>

?

长处:

1. 对 Servlet API 的接见被移到了自 SpringMVC API 扩大的 Interceptor,controller 不须要关怀 User 如何获得。
2. 开辟人员可以经由过程随时添加或移除 Interceptor 来完成对不合参数在某一类型 controller 上的注入。
3. controller 的 User 对象经由过程外界注入,测试时开辟人员可以很轻易地注入本身想要的 User 对象。
4. controller 类去掉了对 Servlet API 的依附,更 POJO 和通用。
5. controller 类是经由过程对 interface 的声明来帮助完成注入的,并不存在任何持续依附

不足:

1. SpringMVC 对 controller 默认是遵守单例(singleton)处理惩罚的,在 controller 类中添加一个成员变量,可能会引起多线程的安然题目。
2. 因为 User 对象是定义为 controller 的成员变量,并且是经由过程 setter 注入进来,在测试时须要很警惕地包管对controller 注入了 User 对象,不然有可能我们拿到的就不必然是一个“好公民”(Good Citizen)。


其实,一言而蔽之,这些不足之所以呈现,是因为我们把某个 action 级别须要的 User 对象上提到 controller 级别,破损了 the convention of stateless for controller classes,而 setter 体式格式的注入又带来了一些隐含的繁琐和不足。当然,我们可以经由过程把 controller 声明为“prototype”来绕过 stateless 的商定,也可以包管每次 new 一个 controller 的同时给其注入一个 User 对象。然则我们有没有更简单更 OO 的体式格式来实现呢?答案是有的。

(三)经由过程办法参数处理惩罚类(MethodArgumentResolver)在办法级别注入User对象

正如前面所看到的,SpringMVC 供给了不少扩大点给开辟人员扩大,让开辟人员可以按需索取,plugin 上自定义的类或 handler。那么,在 controller 类的层次上,SpringMVC 供给了 Interceptor 扩大,在 action 上有没有供给响应的 handler 呢?若是我们可以或许对 action 实现注入,呈现的各种不足了。

经由过程查阅 SpringMVC API 文档,SpringMVC 其实也为 action 级别供给了办法参数注入的 Resolver 扩大,容许开辟人员给 HandlerMapper 类 set 自定义的 MethodArgumentResolver。

action 的代码如下:

@RequestMapping
public void hello(User user){
//user.sayHello()
}

?

Resolver 的代码如下:

public class UserArgumentResolver implements WebArgumentResolver {

public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception {
if (methodParameter.getParameterType().equals(User.class)) {
return webRequest.getAttribute("currentUser", RequestAttributes.SCOPE_SESSION);
}
return UNRESOLVED;
}
}

?
设备文件的相干设备如下:

<bean class="org.springframework.web.servlet.mvc.annotation.OwnAnnotationMethodHandlerAdapter">
<property name="customArgumentResolver">
<ref bean="userArgumentResolver"/><!-- userArgumentResolver bean 的定义省略 -->
</property>
</bean>

?

长处:

1. 具备第二种规划的所有长处

2. 真正做到了按需分派,只在真正须要对象的地位注入具体的对象,削减其他处所对该对象的依附。
3. 其他人能很轻易地从 action 的参数列表得知 action 所须要的依附,API 更清楚易懂。
4. 对于很多 action 须要的某一类参数,可以在独一的设置点用很便利一致的体式格式进行注入。

不足:

1. 对象依附注入是针对所有 action, 注入粒度还是较粗。不克不及做到具体 action 接见具体的 Session 属性

(四)经由过程 SpringMVC 的 SessionAttributes Annotation 接洽关系 User 属性

SpringMVC 文档提到了 @SessionAttributes annotation,和 @ModelAttribute 共同应用可以往 Session 中存或者从 Session 中取指定属性名的具体对象。文档里说;

The type-level @SessionAttributes annotation declares session attributes used by a specific handler. This will typically list the names of model attributes which should be transparently stored in the session or some conversational storage, serving as form-backing beans between subsequent requests.

很明显,@SessionAttributes 是用来在 controller 内部共享 model 属性的。从文档自带的例子来看,标注成 @SessionAttributes 属性的对象,会一向保存在 Session 或者其他会话存储中,直到 SessionStatus 被显式 setComplete()。那这个 annotation 对我们有什么帮助呢?

答案就是我们可以在须要接见 Session 属性的 controller 上加上 @SessionAttributes,然后在 action 须要的 User 参数上加上 @ModelAttribute,并包管两者的属性名称一致。SpringMVC 就会主动将 @SessionAttributes 定义的属性注入到 ModelMap 对象,在 setup action 的参数列表时,去 ModelMap 中取到如许的对象,再添加到参数列表。只要我们不去调用 SessionStatus 的 setComplete() 办法,这个对象就会一向保存在 Session 中,从而实现 Session 信息的共享。

controller的代码如下:

@Controller
@SessionAttributes("currentUser")
public class GreetingController{
@RequestMapping
public void hello(@ModelAttribute("currentUser") User user){
//user.sayHello()
}
//
}

?
应用这种规划,还须要在 SpringMVC 设备文件的 ViewResolver 定义处,加上 p:allowSessionOverride="true",如许若是你对 User 对象做了批改,SpringMVC 就会在衬着 View 的同时覆写 Session 中的相干属性。

长处:

1. 具备第二种规划的所有长处

2. 应用 Annotation 声明对 Session 特定属性的存取,每个 action 只须要声明本身想要的 Session 属性。
3. 其他人能很轻易地从 action 的参数列表得知 action 所须要的依附,API 更清楚易懂。

不足:

1. 对于雷同属性的 Session 对象,须要在每个 action 上定义。
2. 这种规划并不是 SpringMVC 的初志,是以有可能会引起一些争议。


纵观这四类办法,我们可以看出我们对 Session 属性的接见把握设置,是从所有 Servlet,到某一类型的 controller 的成员变量,到所有 action 的某一类型参数,再到具体 action 的具体对象。每种规划都有各自的长处和不足:第一种规划固然正确,但可惜引入了对 Servlet API 的依附,晦气于 controller 的测试和逻辑复用。第二、三种规划固然解决了对 Servlet API 的依附,也分别在 controller 和 action 级别上供给了对 Session 属性的接见,但注入粒度在必然程度上还是不敷细,要想对具体属性进行接见可能会斗劲繁琐。不过,这在另一方面也供给了简便而同一的办法来对一系列雷同类型的参数进行注入。第四种规划经由过程应用 Annotation,不仅摆脱了 Servlet API 的依附,并且在 action 级别上供给了对 Session 具体属性的接见把握。然则这种接见有可能会粒度详尽,须要在很多不合 action 上声明雷同的 annotation。并且,毕竟成果这种用法并不是 SpringMVC 的初志和推荐的,可能会带来一些争议。

本文演示了 Spring2.5 接见 Session 属性的几种不合解决规划,并解析了各自的长处和不足。本文并不筹算对这些解决规划评出对错,只是试图列出在选择规划时的思维过程以及选择标准。每种规划都 能满足某一类高低文的需求,在特定的开辟景象和团队中都可能会是最优的选择。然则笔者还是发明,全部过程中,一些通俗轻易忽视的 OOP 的准则或者原则在阐扬着效应,鉴于本文篇幅已经较长,就留到后续文章中持续商量解决规划选择背后的深层含义,敬请等待。

?

分享到:
评论

相关推荐

    springmvc, spring5.x , hibernate5.x 整合

    在IT行业中,Spring框架是Java领域最广泛应用的轻量级框架之一,而Spring MVC是它的一个模块,专门用于处理Web应用程序的模型-视图-控制器(MVC)架构。Spring 5.x带来了许多性能改进和新特性,如Reactor支持以实现...

    spring_MVC源码

    弃用了struts,用spring mvc框架做了几个项目,感觉都不错,而且使用了注解方式,可以省掉一大堆配置文件。本文主要介绍使用注解方式配置的spring mvc,之前写的spring3.0 mvc和rest小例子没有介绍到数据层的内容,...

    spring mvc spring4.x hibernate4.注解方式注入

    在IT行业中,Spring MVC、Spring 4.x和Hibernate 4是三个非常重要的框架,它们各自在Web应用开发中承担着核心角色。Spring MVC是用于构建Web应用程序的模型-视图-控制器(MVC)框架,Spring 4.x是Spring框架的一个...

    Spring4.x++企业应用开发实战

    《Spring4.x++企业应用开发实战》这本书是针对Spring框架的深入学习与实践指南,尤其关注Spring 4.x版本的应用。Spring作为Java企业级开发的重要框架,提供了丰富的功能,包括依赖注入、AOP(面向切面编程)、数据...

    org.springframework.web的jar包.zip

    这个包主要包含了Spring MVC(Model-View-Controller)框架的基础组件,如`DispatcherServlet`,它是Spring MVC的前端控制器,负责接收HTTP请求并分发到相应的处理器。此外,还有`HttpServletRequest`和`...

    Struts2.X+Hibernate3.X+Spring2.5 整合

    标题"Struts2.X+Hibernate3.X+Spring2.5 整合"指的是将这三个框架的特定版本(Struts2.X,Hibernate3.X,Spring2.5)集成到同一个项目中,实现高效的企业级应用开发。这种整合能够充分利用各个框架的优势,使开发者...

    spring Spring MVC Hibernate 4.x 整合案例

    在IT领域,Spring、Spring MVC和Hibernate是三个非常重要的开源框架,它们分别在不同层面上为Java应用程序提供了强大的支持。本整合案例将详细介绍如何将这三个框架整合在一起,以实现一个完整的Web应用程序,涵盖...

    Spring MVC Locale 的使用 中文 英文 等语言 切换

    在Spring MVC框架中,`Locale`是用来处理应用程序中的多语言支持的关键组件。它定义了用户的语言和地区设置,例如中文(zh_CN)或英文(en_US)。这篇博客文章将深入探讨如何在Spring MVC应用中实现语言切换功能,以...

    struts1.x+spring 2.x+hibernate3.x jar包 组合

    Struts1.x、Spring 2.x 和 Hibernate3.x 是经典的Java Web开发框架组合,被称为SSH(Struts-Spring-Hibernate)集成。这个jar包集合包含了这三个框架的核心库和其他相关依赖,便于开发者快速搭建一个基于MVC模式的...

    《精通Spring 2.x-企业应用开发详解》chapter17

    3. **Spring与Hibernate集成**:Spring 2.x强化了与ORM框架如Hibernate的整合,包括事务同步、Hibernate Session管理以及DAO层的抽象。学习如何在Spring环境中配置Hibernate,使用HibernateTemplate或JPA进行数据...

    Struts1.3+Spring4.x+Hibernate4.x框架整合实现对书籍的增删改查(含分页)

    Spring4.x则是一个全面的轻量级应用框架,它提供了依赖注入(DI)和面向切面编程(AOP)等核心特性。在这个项目中,Spring作为整个应用的容器,管理着所有的Bean,包括Struts的动作类和服务类。通过Spring的DI,我们...

    基于eclipse的struts2.x+hibernate3.x+spring3.x整合文档及实例源码

    综上所述,"基于eclipse的struts2.x+hibernate3.x+spring3.x整合文档及实例源码"提供了一个完整的SSH整合教程,通过下载的源码和文档,开发者可以学习并实践SSH的集成,了解每个框架在实际项目中的作用和它们协同...

    Spring中自定义session管理,SpringSession的使用

    spring.session.store-type=redis ``` 3. 配置Session过期时间:可以在配置类中定义全局的Session过期时间,或者通过`HttpSession`的`setMaxInactiveInterval()`方法为每个Session设置单独的过期时间。 四、集成...

    spring MVC No Session found for current thread

    在IT行业中,Spring MVC是一个广泛使用的轻量级Web框架,用于构建基于Java的企业级应用程序。当我们遇到“Spring MVC No Session found for current thread”的错误时,这通常意味着在尝试访问HttpSession对象时,...

    Spring MVC3构建Web应用详解

    在这个教程中,我们将探讨如何使用Spring MVC 3来创建一个简单的Web应用。首先,我们需要建立一个新的Web项目。 1. 创建Web项目: 在Eclipse或MyEclipse环境中,通过File &gt; New &gt; Web Project来创建一个新的项目,...

    《精通Spring2.x-企业应用开发详解》源代码

    《精通Spring2.x-企业应用开发详解》这本书深入剖析了Spring框架的核心特性和在实际企业应用中的使用方式。源代码涵盖了第二至第六章的内容,这五个章节分别涉及了Spring的基础、依赖注入、AOP(面向切面编程)、...

    spring.mvc.hibernate231security-CRUD

    标题 "spring.mvc.hibernate231security-CRUD" 暗示了这是一个关于Spring MVC、Hibernate和Spring Security的项目,其中包含了创建、读取、更新和删除(CRUD)操作的实现。在这个项目中,我们将深入探讨这三大核心...

    Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)所有实验及实验报告.zip

    Spring MVC是Spring框架的一部分,专门用于构建Web应用程序的Model-View-Controller(MVC)架构。它提供了一个灵活的模型绑定机制,可以将HTTP请求参数与Java对象字段对应起来,同时支持多种视图技术,如JSP、...

    spring session redis分布式session

    spring.session.store-type=redis ``` 然后,通过配置类或者@EnableRedisHttpSession注解启用Spring Session,并配置相应的Redis连接工厂: ```java @Configuration @EnableRedisHttpSession public class ...

    spring applicationContext.xml详细配置

    综上,`applicationContext.xml`是Spring应用的核心配置文件,它定义了bean的生命周期、依赖关系、数据访问和事务处理策略,同时结合Hibernate实现了ORM(对象关系映射),并利用AOP和拦截器提供了面向切面的编程...

Global site tag (gtag.js) - Google Analytics