Web应用程序中一个常见的用法是,先对请求进行处理而后将请求重定向到另一个控制器、servlet或其余对象。这种作法自己没什么问题,可是当请求被重定向时它会建立一个崭新的request,并将本来保存在request属性中的数据全都清除掉,所以重定向的目标操做就没法再得到这些数据。当咱们使用struts2的actionmessage的时候,遇到重定向,这些消息全都over了。 java
有些开发者为了不上述状况的发生而将这些信息保存在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.java
这个实现很好理解,无非内部定义了两个Map,将保存在里面的数据,在两个Map里来回的转移,这样就保证在下一次重定向请求时,咱们只须要将其中一个Map的数据转移到另一个Map中,而清楚掉一个Map。这样就保证在重定向时,该做用域下依然保存数据。而在第二次的请求时,若是没有新的数据加进来,原来的数据将会被清空。经过这种方式,Flash的做用域的数据只能保持在下一次的重定向请求中。
第三步也是很关键的一步,若是咱们不去清理该做用域下的数据,那么这个做用域就没法达到应有的效果。这就须要咱们在每次重定向的时候要执行做用域的next()方法,来清理数据。
咱们编写的是Struts2的实现,咱们就须要在Struts2的过滤器中植入对Flash Scope处理的操做。看OecpStruts2FilterDispatcher.java
Java代码
- 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);
- }
- } finally {
- prepare.cleanupRequest(request);
- }
- }
- }
- }
该类继承了Struts2原有的过滤器,在web.xml中,将Struts2的配置换成该过滤器。在该过滤器中,咱们对每次新的请求都调用了FlashScope的next()方法,对数据进行清理。
若是咱们为了使用方便,咱们能够设计一个Action的顶级类,好比BaseAction.java,在该类中,咱们定义flash的属性。
Java代码
- protected FlashScope flash;
- public FlashScope getFlash(){
- this.flash=new StrutsFlashScope();
- return this.flash;
- }
咱们在action就能够flash.put(“message”,”我是struts2的flash做用域”);在页面上咱们只须要经过<s:property value=”%{flash.message}”/>来显示。这样,咱们删除一篇文章后重定向到文章列表,咱们就能够把“删除成功”这样的信息,显示在重定向的文章列表上。而再次刷新文章列表,该消息就消失了。 web
附件下载请移到:http://www.oecp.cn/hi/yongtree/blog/937 session