将Grails的Flash Scope移栽到Struts2
将Grails的Flash Scope移植到Struts2原文:http://www.po-soft.com/blog/yongtree/937.html??Web应用程序中
将Grails的Flash Scope移植到Struts2
原文:http://www.po-soft.com/blog/yongtree/937.html
??Web应用程序中一个常见的用法是,先对请求进行处理然后将请求重定向到另外一个控制器、servlet或其他对象。这种做法本身没什么问题,但是当请求被重定向时它会创建一个崭新的request,并将原本保存在request属性中的数据全都清除掉,因此重定向的目标操作就无法再获得这些数据。当我们使用struts2的actionmessage的时候,遇到重定向,这些消息全都over了。
有些开发者为了避免上述情况的发生而将这些信息保存在session中。这种做法很好,但开发人员会经常忘记清除临时数据,并且需要开发人员自行维护session的状态。无疑增加了程序的开发的复杂性和无畏的性能浪费。为了解决这个问题,Grails模仿Rails引入了Flash Scope。flash对象只将数据保存在下一次的请求中,在下一次请求之后会自动清除其中的数据。这样不仅减小了开发人员的负担,也使我们能够专注于当前的问题而不用担心其他问题。Flash作用域的确可以很好的解决这个问题,可惜我们常用的SSH框架中,却一直缺少这样一个作用域,不知道Struts2的开发者能不能在以后的版本中增加这样的一个功能。等不了他了,还是我们自己手工创造这样一个对象来解决现有的问题吧。最简单的办法,就是将Grails的实现移植到Struts2中。首先我们下载Grails的源代码包,并找到Flash对象,将其实现按步照班的移植到struts2中。主要修改主要包括两个部分。第一是将Grails的request上下文改成struts2的;第二删掉我们不适用的Grails对错误信息的处理。下面就开始简单的介绍修改后的程序,主要有三个类。第一我们定义一个Flash对象的接口:FlashScope.java???Java代码
- public?interface?FlashScope?extends?Map,?Serializable?{ ??
- ???? ??
- ????/**??
- ?????*?设置一个flash作用域经过新的请求到下个状态。??
- ?????*/??
- ????void?next(); ??
- ? ??
- ????/**??
- ?????*?返回flash对象现有的状态,如果你不希望在下面的请求中使用包含的变量。??
- ?????*???
- ?????*?@return?A?map??
- ?????*/??
- ????Map?getNow(); ??
- } ??
第二开始编写该接口Struts2的实现:StrutsFlashScope.javaJava代码
- public?class?StrutsFlashScope?implements?FlashScope?{ ??
- ? ??
- ????private?Map?current?=?new?ConcurrentHashMap(); ??
- ????private?Map?next?=?new?ConcurrentHashMap(); ??
- ????public?static?final?String?FLASH_SCOPE?=?"com.posoft.web.servlet.FLASH_SCOPE"; ??
- ? ??
- ????public?StrutsFlashScope()?{ ??
- ????} ??
- ? ??
- ????public?void?next()?{ ??
- ???????current.clear(); ??
- ???????current?=?new?ConcurrentHashMap(next); ??
- ???????next.clear(); ??
- ????} ??
- ? ??
- ????public?Map?getNow()?{ ??
- ???????return?current; ??
- ????} ??
- ? ??
- ????public?int?size()?{ ??
- ???????return?current.size()?+?next.size(); ??
- ????} ??
- ? ??
- ????public?void?clear()?{ ??
- ???????current.clear(); ??
- ???????next.clear(); ??
- ????} ??
- ? ??
- ????public?boolean?isEmpty()?{ ??
- ???????return?size()?==?0; ??
- ????} ??
- ? ??
- ????public?boolean?containsKey(Object?key)?{ ??
- ???????return?(current.containsKey(key)?||?next.containsKey(key)); ??
- ????} ??
- ? ??
- ????public?boolean?containsValue(Object?value)?{ ??
- ???????return?(current.containsValue(value)?||?next.containsValue(value)); ??
- ????} ??
- ? ??
- ????public?Collection?values()?{ ??
- ???????Collection?c?=?new?ArrayList(); ??
- ???????c.addAll(current.values()); ??
- ???????c.addAll(next.values()); ??
- ???????return?c; ??
- ????} ??
- ? ??
- ????public?void?putAll(Map?t)?{ ??
- ???????for?(Map.Entry<Object,?Object>?entry?:?((Map<Object,?Object>)?t) ??
- ??????????????.entrySet())?{ ??
- ???????????put(entry.getKey(),?entry.getValue()); ??
- ???????} ??
- ????} ??
- ? ??
- ????public?Set?entrySet()?{ ??
- ???????Set?keySet?=?new?HashSet(); ??
- ???????keySet.addAll(current.entrySet()); ??
- ???????keySet.addAll(next.entrySet()); ??
- ???????return?keySet; ??
- ????} ??
- ? ??
- ????public?Set?keySet()?{ ??
- ???????Set?keySet?=?new?HashSet(); ??
- ???????keySet.addAll(current.keySet()); ??
- ???????keySet.addAll(next.keySet()); ??
- ???????return?keySet; ??
- ????} ??
- ? ??
- ????public?Object?get(Object?key)?{ ??
- ???????if?(next.containsKey(key)) ??
- ???????????return?next.get(key); ??
- ???????return?current.get(key); ??
- ????} ??
- ? ??
- ????public?Object?remove(Object?key)?{ ??
- ???????if?(current.containsKey(key)) ??
- ???????????return?current.remove(key); ??
- ???????else??
- ???????????return?next.remove(key); ??
- ????} ??
- ? ??
- ????public?Object?put(Object?key,?Object?value)?{ ??
- ???????//?create?the?session?if?it?doesn't?exist???
- ???????registerWithSessionIfNecessary(); ??
- ???????if?(current.containsKey(key))?{ ??
- ???????????current.remove(key); ??
- ???????} ??
- ? ??
- ???????if?(value?==?null) ??
- ???????????return?next.remove(key); ??
- ???????else??
- ???????????return?next.put(key,?value); ??
- ????} ??
- ? ??
- ???? ??
- ? ??
- ????private?void?registerWithSessionIfNecessary()?{ ??
- ???????Map<String,?Object>?session?=?ActionContext.getContext().getSession(); ??
- ???????if?(session.get(FLASH_SCOPE)?==?null) ??
- ???????????session.put(FLASH_SCOPE,?this); ??
- ??????? ??
- ????} ??
- ? ??
- } ??
这个实现很好理解,无非内部定义了两个Map,将保存在里面的数据,在两个Map里来回的转移,这样就保证在下一次重定向请求时,我们只需要将其中一个Map的数据转移到另外一个Map中,而清楚掉一个Map。这样就保证在重定向时,该作用域下依然保存数据。而在第二次的请求时,如果没有新的数据加进来,原来的数据将会被清空。通过这种方式,Flash的作用域的数据只能保持在下一次的重定向请求中。第三步也是很关键的一步,如果我们不去清理该作用域下的数据,那么这个作用域就无法达到应有的效果。这就需要我们在每次重定向的时候要执行作用域的next()方法,来清理数据。我们编写的是Struts2的实现,我们就需要在Struts2的过滤器中植入对Flash Scope处理的操作。看OecpStruts2FilterDispatcher.javaJava代码
- public?class?OecpStruts2FilterDispatcher?extends?StrutsPrepareAndExecuteFilter?{ ??
- ????@Override??
- ????public?void?doFilter(ServletRequest?req,?ServletResponse?res, ??
- ???????????FilterChain?chain)?throws?IOException,?ServletException?{ ??
- ???????HttpServletRequest?request?=?(HttpServletRequest)?req; ??
- ???????HttpServletResponse?response?=?(HttpServletResponse)?res; ??
- ???????????try?{ ??
- ??????????????prepare.setEncodingAndLocale(request,?response); ??
- ??????????????prepare.createActionContext(request,?response); ??
- ??????????????prepare.assignDispatcherToThread(); ??
- ??????????????if?(excludedPatterns?!=?null??
- ?????????????????????&&?prepare.isUrlExcluded(request,?excludedPatterns))?{ ??
- ??????????????????chain.doFilter(request,?response); ??
- ??????????????}?else?{ ??
- ??????????????????request?=?prepare.wrapRequest(request); ??
- ??????????????????ActionMapping?mapping?=?prepare.findActionMapping(request, ??
- ?????????????????????????response,?true); ??
- ??????????????????if?(mapping?==?null)?{ ??
- ?????????????????????boolean?handled?=?execute.executeStaticResourceRequest( ??
- ?????????????????????????????request,?response); ??
- ?????????????????????if?(!handled)?{ ??
- ?????????????????????????chain.doFilter(request,?response); ??
- ?????????????????????} ??
- ??????????????????}?else?{ ??
- ?????????????????????/**??
- ??????????????????????*?更新flash作用域??
- ??????????????????????*/??
- ?????????????????????FlashScope?fs?=?(FlashScope)?ActionContext.getContext() ??
- ????????????????????????????.getSession().get(StrutsFlashScope.FLASH_SCOPE); ??
- ?????????????????????if?(fs?!=?null)?{ ??
- ?????????????????????????fs.next(); ??
- ?????????????????????} ??
- ?????????????????????execute.executeAction(request,?response,?mapping); ??
- margin: 0px; padding: 0