struts的form标记定义了一个页面的表单,但该struts标记需要根据action 的值来查找module config里的action mapping ,并根据action mapping 的值来初始化action form。因此,在form标记中需要获取一个module config 。在这里,获取哪一个module config成为了form标记能否正常工作的关键,如果module config的获取值不正确,将会造成对应的action mapping 找不到或者找到但却不是正确的action mapping 。从而造成Cannot retrieve mapping for {action name}的错误或者其他意外错误。在form标记的lookup方法中,包含了该查找module的过程,它的查找方法为首先从request中获取当 前的module config,如果没有找到,就从servlet context中获取默认的module config(即module prefix为""的module)。
我们分析ActionServlet的初始化方式,可以发现ActionServlet将初始化好的module config分别保存在servlet context的属性中,其中的属性名为Globals.MODULE_KEY+prefix,但request对象的当前module config是怎么来的呢。它是ActionServlet在获取到一个请求后,根据请求的url与保存在servlet context里的module prefix进行匹配,如果匹配成功,则将属性名为Globals.MODULE_KEY+"匹配成功的prefix"的module config作为当前的module config返回,该过程出现在ActionServlet的process方法中,在select module的时候,将根据以上规则,选择当前的module config,并保存在request的属性Globals.MODULE_KEY。并将实例转给RequestProcessor对象。
我们从上面的分析中可以看出,包含form tag的jsp页面,如果要正确的将自已关联到一个module中,则需要事先将当前module config对象放在request请求中,但存放module config到request请求的动作是在ActionServlet中完成的。因此,页面只有在经过了对一个Acton进行处理后(在处理action 的过程中,会根据action 的 url来匹配当前的module,并将其保存在request中),并通过redirect=false的方式下重定向到一个jsp页面,才能使该jsp 页面正确的关联到module中,否则都将关联到默认的module config中,如直接在地址栏中键入jsp的url这种情况下,所有的jsp文件都关联到默认的module config中。
from:http://www.blogbus.com/blogbus/blog/diary.php?diaryid=139866
今天试着把写的系统登录模块加到我们现有的模块里来,他写的时候因为有些试验的成分,所以没有按照我们项目的配置来写,也没有按照我们的模块来划分配置,加过来以后重新配置了模块信息,结果居然无法正常运行。显示错误:“cannot retrieve action mapping 。废了九牛二虎之力,都无法解决。web.xml、struts-config、模块配置,一切看起来都无比的正常,但就是运行不了。真搞不清楚是哪里出了问题。还以为搞不定,晚上要加班了,谁知道,踏破铁鞋无觅处,柳暗花明又一村,在google上搜索关键字"action mapping 找不到",第一个链接居然就是问题的答案!(还从来没有只点一次就可以找到问题答案的经验,所以兴奋无比^O^)
总的来说,问题的原因就在于,struts是在第一次收到对action 的请求(注意:不包括jsp的请求)时,提取这个请求的url的路径信息,把相应模块的mapping 信息设置到请求中去 。 如果在进入一个模块时,第一次访问的是一个jsp页面,而在这个jsp页面中提交到该模块的一个action ,就会出现找不到action mapping 的情况。这就是因为,在进到这个模块时,访问的是jsp,这个模块的任何一个action 都没有被访问到,所以struts的ActionServlet还没有来得及把这个模块的mapping 设置到请求中,自然找不到该模块的action 。
因此,这就引出一个约定,就是系统中尽量避免对Jsp的直接访问,如果要访问也要通过action 来forward 。 虽然看起来麻烦一点,但是安全性、健壮性都会有所提高。
from:http://dev.csdn.net/article/55/55476.shtm
Struts 1.1支持多模块开发,在myEclipse的Web Application Project里先建立新module (New->Struts 1.1 Module),
再依次加Form Action ActionForward (New -> Struts 1.1 Action , Form & JSP).有时myEclipse会找不到自己刚刚加的Form,手动添加即可,没什么大不了的。myEclipse的web.xml模板不符合标准,需要手动更改。TLD文件好像也不太对,可以用自己曾经做过项目的TLD代替。
下面是两个折腾我很久的问题。
1) 如果在我们security模块里有
<action ></action > path="/UserSecurityCheck"
type="com.scs.presentation.security.UserSecurityCheckAction"
name="UserLoginForm" scope="request"
input="/init.do">
<forward name="loginSucceed" path="/mainmenu.jsp"></forward>
这个例子中,注意mainmenu.jsp前面有个/,ActionServlet会在当前module里寻找这个jsp,也就是说mainmenu.jsp需要放在/%webroot%/security/的目录下面,而不是直接在/%webroot%/下
2) struts的form标记定义了一个页面的表单,但该struts标记需要根据action 的值来查找module config里的action mapping ,并根据action mapping 的值来初始化action form。因此,在form标记中需要获取一个module config。在这里,获取哪一个module config成为了form标记能否正常工作的关键,如果module config的获取值不正确,将会造成Cannot retrieve mapping for {action name}的错误。查找方法为首先从request中获取当前的module config,如果没有找到,就从servlet context中获取默认的module config。
现在struts framework的实现是这样的,只有ActionServlet正确地将module config对象赋值给request的属性Globals.MODULE_KEY后,后来的含form tag的属于该模块的jsp页面才能被struts framework正确与对应此module config挂钩。倘若编程人员/用户试图对某个模块发出的第一个请求是jsp而不是action ,actionServlet 就没有机会做上述的准备工作(因为web container会直接处理jsp请求,不会转发给actionServlet),那么接下来处理jsp中的form tag时,struts framework就会试图从default module config中寻找该actionMapping(因为request里的module specfic config依然为空,所以只好从default里找了),一般上这种寻找是没有结果的,最后framework就会返回Cannot retrieve mapping for ThisAction的错误。
结论是,接入每个module的第一个页面必须是由action 请求(而不是jsp请求),以给actionServlet一个机会装载对应的module config并cache.
<script type="text/javascript"><!-- google_ad_client = "pub-4348265167276910"; /* 468x60, 个人博客 */ google_ad_slot = "2046406163"; google_ad_width = 468; google_ad_height = 60; //--> </script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script><script src="http://pagead2.googlesyndication.com/pagead/expansion_embed.js"></script><script src="http://googleads.g.doubleclick.net/pagead/test_domain.js"></script><script>google_protectAndRun("ads_core.google_render_ad", google_handleError, google_render_ad);</script>
很急 不过看了你的文章 讲的太多了 能不能明了点啊
我也是 首先 访问的.jsp的 类似在 jsp里有个 login的 action
然后就出现 Cannot retrieve mapping for action /addProductType
[email protected] 欢迎加流
谢谢
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <%@ page language="java" contentType="text/html; charset=utf-8" %> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> <html:html xhtml="true" lang="true"> <body> <html:form action="/guestbook.do ?method=save" onsubmit="return validateUserForm(this)"> <html:hidden property="method" value="save" /> username:<html:text property="name" ></html:text> <html:errors property="name" /> <html:submit value="提交"> </html:submit> <html:javascript formName="UserForm" /> </html:form> </body> </html:html>