`
fan
  • 浏览: 142481 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

struts2的validate错误跳转与chain配合使用的要点

阅读更多
本文基于struts2.1.8.1
        按照struts2的官方文档,chain类型默认的目标Action跳转方法是execute(),摘录xwork的doc: method - used to specify another method on target action to be invoked. * If null, this defaults to execute method * * 在一般情况下,这没有问题。在使用validate拦截器拦截到错误,希望转到目标Action的特定方法时,却发现根本不执行。
        为了描述方便清晰,先定义以上使用场景: FooAction有触发validate拦截器的相关验证代码,验证不通过触发workflow的跳转功能,默认转入FooAction的input结果指定的去向,即BarAction的某个方法,定义为someMethod()。网上有一则相关文章提到:如果在定向到input视图前有错误(如action的hasError方法返回true)和异常发生,且返回的input视图的type为"chain"(即返回到另一个action)时,这个action的方法必须为input,否则这个方法不会执行,而是会直接定位到物理视图。按照这个做法,的确可以进入指定input方法并且执行,可是并没有官方文档有类似说明,这是为什么呢?经过对validate、workflow拦截器的调试分析,终于揭秘了真相。
        FooAction的validate拦截器执行相关的验证方法并得到了errors,通过workflow再chain到BarAction时,会过一遍BarAction的拦截器栈,也就是说,workflow拦截器会再次被执行,只不过此次是针对BarAction。看workflow的代码:
@Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();

        if (action instanceof ValidationAware) {
            ValidationAware validationAwareAction = (ValidationAware) action;

            if (validationAwareAction.hasErrors()) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Errors on action " + validationAwareAction + ", returning result name 'input'");
                }

                String resultName = inputResultName;

                if (action instanceof ValidationWorkflowAware) {
                    resultName = ((ValidationWorkflowAware) action).getInputResultName();
                }

                InputConfig annotation = action.getClass().getMethod(invocation.getProxy().getMethod(), new Class[0]).getAnnotation(InputConfig.class);
                if (annotation != null) {
                    if (!annotation.methodName().equals("")) {
                        Method method = action.getClass().getMethod(annotation.methodName());
                        resultName = (String) method.invoke(action);
                    } else {
                        resultName = annotation.resultName();
                    }
                }


                return resultName;
            }
        }

        return invocation.invoke();
    }

        在本场景中,由于FooAction验证的结果会通过chain传过来,validationAwareAction.hasErrors()的结果就是true,最终会走return resultName;也就是直接走了return "input",而不会进入action的someMethod方法。那为什么方法更名为input就可以了呢?原来,我们的配置文件里,对validate及workflow配置了
<param name="excludeMethods">input,back,cancel,browse</param>

input恰好就名列其中。也就是说,转向BarAction的input时,workflow是不进行拦截的,所以能进入BarAction的input方法。实际上,按照struts2的设计思想,input等方法就是用于错误处理的,不直接对前端提供服务,所以应该排除在validate和workflow之外。
        这样,解决问题的方法就是:
1,利用struts2现有的机制,更改someMethod方法名为excludeMethods中现有的,最好是input,同时,chain的配置里,明确指定method参数为input,而不是默认的executed
2,把someMethod加入到validate和workflow的excludeMethods配置中
推荐第一种方法,不破坏struts2的设计思想。
分享到:
评论
5 楼 fan 2012-02-29  
虽然是很久以前的帖子了 ,但我还是要更正您的解决方法, 我认为不是很恰当。


很久没上来了。这个解决方案看起来很不错,没有试用。关键是要明白问题的原因。感谢你的回复。
4 楼 chenchangqun11 2011-11-23  
虽然是很久以前的帖子了 ,但我还是要更正您的解决方法, 我认为不是很恰当。

出现这中情况是因为在 chain 之前,fieldError!=null  chain后  actionContext 中仍有 fielidError ,执行目标action前 还会 执行验证  validationAwareAction.hasErrors() 此时
为 true 当然返回input
我提供的解决方法

在目标action中在全局验证方法 validate( ) 如下

@Override
	public void validate()
	{
		this.clearErrorsAndMessages();//一定要写在该方法第一行
		 
	}
3 楼 thinkingmysky 2011-09-04  
博主,我有个问题哦,在目标action上加入一个input方法,然后再配置里面加入method="input" 也根本不起作用啊?、

代码如下:
<action name="login" class="login_LoginAction">
<result name="success" type="chain">logon</result>
<result name="input" type="dispatcher">
<param name="location">/login.jsp</param>
</result>
</action>


<action name="logon" class="com.samilpower.action.base.DispatcherAction" method="input">
<result name="input" type="dispatcher">
<param name="location">/view/index.jsp</param>
</result>
</action>
2 楼 psjay 2010-10-11  
多谢博主,这个问题终于解决了
1 楼 angelgreen 2010-08-09  
嗯 大神  小弟今天也遇到这问题 

不错

相关推荐

Global site tag (gtag.js) - Google Analytics