Struts 解决 HTTP Status 404 - No result defined for action XxxAction and result yyy 错误的方案

Java EE 中 SpringFramework AOP 代理 Struts 2 的 Action 的方法后所遭遇的问题及其解决方案

bachue posted @ 2011年8月08日 17:12 in Java with tags Action AOP class controller deltamaster java JSP proxy spring struts View EE J2EE SpringFrameWork cglib around super applicationContext advice , 5139 阅读

我们夏季学期的作业,JavaEE的项目正在进行。在我的反复诱导下,Deltamaster 同学终于动用了AOP,不过很快就出了问题。他用AOP对所有Action类的execute方法进行增强(“advice”),但问题是,增强之后,View中的错误信息就无法输出了。

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<s:property value="errorMessage" />

由于AOP是我怂恿的,所以问题还是要由我来解决。Deltamaster如果有什么问题,那我肯定不会先去Google,因为我用Google就是他教的。所以首先,我仔细对比了启用AOP与不启用AOP两种情况下Action的表现,发现完全一致,确定Action没有问题。

由于AOP中我们用的是级别最高的around,有拦截并修改函数返回值的能力。我多次测试了around函数中proceed()函数的返回值在函数中各个点的位置,也没有发现问题。也就是说,around本身的代码也没有错误,但不排除是SpringFramework AOP的Bug使得Controller无法获取到action的返回值。不过,我暂时不会往Bug这块地方想。

如果Controller确实没有获取到action的返回值,也就是,jsp文件没有被调用。我随后在jsp后面加了一句输出语句,然后运行。输出成功了!这就表示该jsp文件确实被调用了,同时也证明了Controller确实获取到了action的返回值,前面AOP有Bug的推论不成立。总之从action到view,中间所有过程均正常。

那么就是errorMessage没有被获得了,在jsp中写errorMessage,实质将调用action类的getErrorMessage方法,我在这个方法中加了句输出语句。测试时这句话并没有输出,也就是说,getErrorMessage没有被调用。但为什么不被调用呢?我在action类中自己写了点get方法,测试发现都没有输出。(此处省略1000+字,关于我是如何验证是否是AOP的Bug造成getErrorMessage失效,以及是否是传回对象的类型无法匹配等等各种怀疑)最后,索性直接写

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<s:property value="class" />

输出了,而且发现是个proxy类,我随即将class改成了class.superclass.name,也就是输出本类的父类的名字,结果是,java.lang.reflect.Proxy,原因终于被发现了,作为一个Java的动态代理类,怎么可能有getErrorMessage方法。我们知道,SpringFramework AOP实现的核心方法是Java动态代理(基于接口的代理)或CGLIB(基于类的代理),这里似乎用的是前者。Proxy类对象代替Action类调用了View,结果当View要求调用者的getErrorMessage方法时,Proxy类没有这样的方法,所以导致出错!

随后我仔细查看了Proxy类的文档,全是类方法,没有任何能获得被代理对象的实例方法。无奈下,直接Google了,很快就找到了解答,很幸运,是中文解答:http://jeooo-li.iteye.com/blog/436931。“只要在Spring的配置文件applicationContext中的<aop:aspectj-autoproxy/>改为<aop:aspectj-autoproxy proxy-target-class="true"/>就可以了。”,经过测试,这个解答是正确的,问题解决。

经过初步测试,发现proxy-target-class="true" 一旦加上后,SpringFramework AOP将使用CGLIB方法而不是动态代理,生成Action类的子类,这样即可以满足AOP增强处理的要求,又完美继承了Action类的所有方法,因此才能解决问题。

Avatar_small
deltamaster 说:
2011年8月13日 08:25

对的,其实我一开始就告诉你没有调用到getErrorMessage方法了。

DDO Request 说:
2022年8月05日 22:04

Drawing and Disbursing Officer is a major and important role in today’s developing India. As every organization has come forward with an official online human resource and development system software. The salaries, payslip, and other important details of an employee taken care of by the Drawing and Disbursing Officer. They play an important role in the organization. DDO Request They reduce the manual work and with their individual effort, the department employees salaries may disbursed. The payment against working days and the leaves taken along with many other criteria observed by a DDO officer. Even an employee who wants to enjoy the services of fficial website will need to reach out to DDO officers. It is all to raise a request for their employee registration.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter