用spring对struts2的Action加AOP时,不要让Action继承于ActionSupport

sulong 于 2007-12-17 说两句 »

用spring做为struts2的ObjectFactory,用spring来生成action,并对action的方法加上aop时,不要使Action继承于ActionSupport,否则会出现类似于以下的异常:

 java.lang.NoSuchMethodException: $Proxy84.executeList()
at java.lang.Class.getMethod(Class.java:1581)
at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.getActionMethod(AnnotationValidationInterceptor.java:55)

我的Action类继承于ActionSupport类,没有直接实现什么接口。我用AOP把事务加在了Action里的execute打头的方法前,结果,运行时就出现了上面的找不到方法的异常,如果不让Action继承于ActionSupport类就没有了这样的问题。在调试的时候,发现spring生成的代理类里面只有一个execute方法。看来spring在生成代理类时,如果找不到被代理类直接实现的接口,就会到它的超类中去找。在这个例子中,spring就找到了ActionSupport实现的Action接口。

我又试过在struts.xml里定义让struts2以接口的方式去取Action,Action实现一个自己接口,结果struts2又报另外一个错误。看来在这种情况下,只好不要让Action继承于struts2的ActionSupport类了。

  • Share/Bookmark
Advertisement

10 comments

  1. henry says:

    路过~^_^

    接下来我也要好好研究下这几个流行的开源框架,有什么疑问还要向你请教,不要吝啬哦!

  2. sulong says:

    大家一起分享了。这些都是一些做到时才会发现的小问题,没什么高深的。唉,不过这也说明了这些开源框架之间结合起来还是不太好呀! 用了一段时间struts2了,觉得不是特别好用。我看,这java的web开发出路只有jruby grail等脚本了。

  3. goddie says:

    不继承ActionSupport怎么加入addActionMessage信息?有更好的解决办法吗。有的话请来mail告知,先谢。

  4. sulong says:

    goddie2046,
    你好,首先谢谢你在我的博客上的留言。
    查找struts2和xwork2的API可以看到,addActionMessage方法是因为ActionSupport实现了 ValidationAware实引入的,所以如果你自定义的Action类也想要这个功能,那么也像ActionSupport那样实现那个接口,就可以了。参照ActionSupport的源代码,大致如下:
    public class MyAction implements ValidationAware {
    private final ValidationAwareSupport validationAware = new ValidationAwareSupport();

    public void addActionMessage(String aMessage) {
    validationAware.addActionMessage(aMessage);
    }

    ….
    }

    不过我想这样还是不够完美,因为我们还是强迫Action类实现了某个接口。在一个Action类是一个POJO,不实现任何特定接口,不实现任何特定类的时候,struts2也能够通过反射来使用这个Action类,我想 struts2很可能是动态地生成了一些代理类,然后让这些代理类去通过反射调用我们所写的Action类的指定方法来完成业务。而那些被生成的代理类,如果需要的话,很可能就实现了ValidationAware接口,因此,只要能在运行时,在我们的Action类的业务方法里取得那些代理类的 ValidationAware类型的引用,就可以通过这个引用调用addActionMessage方法了。不过,我暂时没有找到方法。

    希望我的想法对你能有些帮助。

  5. sulong says:

    通过调用
    ServletActionContext.getRequest()
    方法,可以取到HttpServletRequest。ServletActionContext是ActionContext的一个子类,在 Servelet环境下会使用这个子类。这个类是一个ThreadLocal的变量,struts2框架会在给客户端分配处理线程时,在这个线程里设置上这个变量,因此只要在struts2的环境中,就可以直接调用这个静态方法取得变量了。ServletActionContext中还包含很多其它的方法,通过它们你可以揭开struts2的面纱,看到servlet的相关信息。

  6. Marshall says:

    和博主遇到了同样的问题,找到了解决方案:

    http://forum.springframework.org/showthread.php?t=51758

  7. Marshall says:

    回复不让显示xml,就是给aop:config加上
    proxy-target-class=”true”
    属性

  8. sulong says:

    谢谢!!

  9. Anonymous says:

    路过路过路过路过

  10. jolphin says:

    非常非常! 感谢!

说两句