首页 > 代码库 > 【struts2】值栈(后篇)

【struts2】值栈(后篇)

  在值栈(前篇)我们学习了值栈的基本知识,接下来,来看看在程序中具体如何使用值栈。

  ActionContext的基本使用

  1.1 如何获取?

  要获取ActionContext有两个基本的方法,如果在不能获取到ActionInvocation的地方,可以直接使用ActionContext一个静态的getContext方法,就可以访问到当前的ActionContext了,示例如下:

ActionContext ctx = ActionContext.getContext();  

  如果在能获取到ActionInvocation的地方,比如在拦截器里面、自定义的Result里面等,可以通过ActionInvocation来获取到ActionContext,示例如下:

ActionContext ctx = actionInvocation.getInvocationContext();  

  1.2 获取过后,如何使用?

   ActionContext主要的功能是用来存放数据的,典型的方法如下:

  • get(String key):根据key从ActionContext当前的存储空间里面获取相应的值
  • put(String key, Object value):把值存储在ActionContext的存储空间里面
  • Map<String,Object> getApplication():返回ServletContext中存储的值
  • Map<String,Object> getSession():返回HttpSession中存储的值
  • Map<String,Object> getContextMap():返回当前context存储的值
  • Map<String,Object> getParameters():返回HttpServletRequest对象里面存储的,客户端提交的参数
  • ValueStack getValueStack():获取OGNL的值栈

  对于getXXX的方法,都有对应的setXXX方法,这里就不去赘述了,具体的请参看Struts2的API文档。

  1.3 应用示例

  在《自定义更强大的logger拦截器》《自定义登陆验证拦截器》中,两个拦截器都使用了ActionContext对象,详细请查看这两篇文章。

  2 ValueStack的基本使用

  在值栈(前篇)中,我们看到了ValueStack被包含在ActionContext中,ValueStack也是用来存储对象的,但是它主要是通过OGNL表达式来访问,也就是说,在Struts2里面主要是通过标签来访问的。ValueStack有一个特点,如果访问的值栈里有多个对象,且相同的属性在多个对象中同时出现,则值栈会按照从栈顶到栈底的顺序,寻找第一个匹配的对象。

  2.1 如何获取?

  直接由ActionContext对象的getValueStack()方法即可获取

  2.2 如何使用?

  ValueStack主要的功能也是用来存放数据的,典型的方法如下:

  • Object findValue(String expr):根据表达式在value stack中,按照缺省的访问顺序去获取表达式对应的值
  • void setValue(String expr, Object value):根据表达式,按照缺省的访问顺序,向value stack中设置值
  • Object peek():获取value stack中的顶层对象,不修改value stack对象
  • Object pop():获取value stack中的顶层对象,并把这个对象从value stack中移走
  • void push(Object o):把对象加入到value stack对象中,并设置成为顶层对象

  2.3 应用示例

  前面的示例中,欢迎页面显示的帐号,是从登录页面填写并传递到后台的数据,假如现在想要修改在欢迎页面显示的帐号数据,但是前面从登录页面填写并传递到后台的数据不需要变化,那么该怎么实现呢?先来分析一下,要想修改result页面显示的值,肯定需要在Result处理之前修改这个值,否则等Result处理完成过后再改就没有意义了。因此,可以选用PreResultListener的技术,在里面把值修改好,然后再进行Result处理。另外一点,在欢迎页面是通过标签来获取帐号的数据并展示的,也就是说值的来源是value stack,因此,在PreResultListener里面要修改的就是value stack里面的值。好了,清楚该干什么过后,来具体看看示例。

  1)先来实现PreResultListener,在里面修改value stack里面的值,示例如下:

public class MyPreResult implements PreResultListener{  
    public void beforeResult(ActionInvocation actionInvocation, String result) {  
        System.out.println("现在处理Result执行前的功能,result="+result);  
        actionInvocation.getInvocationContext().getValueStack().setValue("account", "被修改了");  
    }  
}  

  2)实现了PreResultListener,还需要在运行之前注册,这里选择在Action里面来注册这个监听器,示例如下:

public class HelloWorldAction extends ActionSupport {  
    private String account;  
    private String password;  
    private String submitFlag;  
    public String execute() throws Exception {  
        this.businessExecute();  
        ActionContext c = ActionContext.getContext();  
        MyPreResult pr = new MyPreResult();  
        c.getActionInvocation().addPreResultListener(pr);  
        return "toWelcome";  
    }  
    /** 
     * 示例方法,表示可以执行业务逻辑处理的方法, 
     */  
    public void businessExecute(){  
        System.out.println("用户输入的参数为==="+"account="+account+",password="+password+",submitFlag="+submitFlag);  
    }  
    //属性对应的getter/setter方法,省略了  
}  

  3)struts.xml、登陆界面和欢迎界面都不变。欢迎界面中的<s:property value="http://www.mamicode.com/account"/>就可以获得MyPreResult类中修改的account值了。

  由于通常情况下,向value stack里面压入值都是由Struts2去完成,而访问value stack多是通过标签中的OGNL表达式,因而直接使用ValueStack的机会并不是很多。

  参考资料:http://www.iteye.com/topic/1124526