以下所说的struts-config.xml和ApplicationResources.properties{文件名是缺省时使用的,如果你用了多模块,或指定了不同的资源文件名Uͼq些名字要做相应的修攏V?/p>
1?#8220;No bean found under attribute key XXX”
在struts-config.xml里定义了一个ActionFormQ但type属性指定的cM存在Qtype属性的值应该是Formcȝ全名。或者是Q在Action的定义中Qname或attribute属性指定的ActionForm不存在?br>
2?#8220;Cannot find bean XXX in any scope”
在Action
里一般会request.setAttribute()一些对象,然后在{向的jsp文g里(用tag或request.getAttribute()?
法)得到q些对象q显C出来。这个异常是说jsp要得C个对象,但前面的Action里ƈ没有对象设|到requestQ也可以是session?
servletContextQ里?br>可能是名字错了,h查jsp里的tag的一般是name属性,或getAttribute()Ҏ(gu)的参数|或者是Action逻辑有问题没有执行setAttribute()Ҏ(gu)先转向了?br>q?
有另外一个可能,Ua是jsp文g的问题,例如<logic:iterate>会指定一个id|然后在@环里<bean:
write>使用q个g为name的|如果q两个g同,也会出现此异常。(都是一个道理,request里没有对应的对象。)
3?#8220;Missing message for key "XXX"”
~少所需的资源,查ApplicationResources.properties文g里是否有jsp文g里需要的资源Q例如:
q? 行代码会找msg.name.prompt资源Q如果AppliationResources.properties里没有这个资源就会出现本异常。在? 用多模块Ӟ要注意在模块的struts-config-xxx.xml里指定要使用的资源文件名Uͼ否则当然什么资源也找不刎ͼq也是一个很Ҏ(gu)犯的? 误?/p>
4?#8220;No getter method for property XXX of bean teacher”
q条异常信息说得很明白,jsp里要取一个bean的属性出来,但这个beanq没有这个属性。你应该查jsp中某个标{property属性的倹{例如下面代码中的cade应该改ؓcode才对Q?/p>
5?#8220;Cannot find ActionMappings or ActionFormBeans collection”
一般是因ؓstruts-config.xml里面?lt;action写错了。xml用手工写很容易出?#8230;…
6?#8220;Cannot retrieve mapping for action XXX”
?jsp?lt;form>标签里指定action='/XXX'Q但q个Actionq未在struts-config.xml里设|过?/p>
7、HTTP Status 404 - /xxx/xxx.jsp
Forward的path属性指向的jsp面不存在,h查\径和模块Q对于同一模块中的Action转向Qpath中不应包含模块名Q模块间转向Q记住用contextRelative="true"?/p>
8、没有Q何异怿息,昄I白面
可能是Action里用的forward与struts-config.xml里定义的forward名称不匹配?br>
9?#8220;The element type "XXX" must be terminated by the matching end-tag "XXX".”
q个是struts-config.xml文g的格式错误,仔细查它是否是良构的xml文gQ关于xml文g的格式这里就不赘qC?/p>
10?#8220;Servlet.init() for servlet action threw exception”
一般出现这U异常在后面会显CZ个关于ActionServlet的异常堆栈信息,其中指出了异常具体出现在代码的哪一行。我曄遇到的一ơ提C如下:
决问题,先下载struts的源码包Q然后在ActionServlet.java的第1003行插入断点,q对各变量进行监视。很丢hQ我竟然把struts-config.xml文g弄丢了,因此出现了上面的异常Q应该是和CVS同步时不心删除的?/p>
11?#8220;Resources not defined for Validator”
q个是利用Validator插g做验证时可能出现的异常,q时你要查validation.xml文gQ看里面使用的资源是否确实有定义Qform的名U是否正,{等?/p>
上面q些是我在用Struts做项目时遇到q的问题Q其中一些曾困绕我不时_其实大部分都是自׃l心造成的。希望这文章能对你的开发有所帮助QƈƢ迎l箋补充?/p>
工具?/b>: "default.properties"是配|选项定义文g。通过在classpath中包含一个叫"struts.properties"的文Ӟq设|不同的属性|你可以覆盖这个默认的配置Q实现自q配置?/blockquote>对于Struts, servlet配置提供了初始化tag的参数和使用的文Ӟ而Struts2没有q样的配|参敎ͼ取而代之的是在classpath下的默认配置文g"struts.xml"?br />工具?提示: Struts actions(扩展?.do")QStruts2 actions(扩展?.action"),所以Struts和Struts2可以在一个系l中共存。所以最好是保持原先的系l,在新功能的开发上用Struts2, 如果旉和资源允许的情况下再逐步q移。另一U方法是只是把Struts2的扩展名改ؓ".do",可重用JSPs.分析Actions
在上面介l的hq作程中,我们谈及了一些Struts和Struts2的不同点。现在我们将较深入地探讨q两个框架中actionl构的具体差别?br />让我们来回顾一?Struts ?action l构, 主要的Ş式如下:CODE:public class MyAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
// do the work
return (mapping.findForward("success"));
}
}
当实C个Struts action? 你需要注意一下问题:相比较之下, Struts2的action 提供了很多简单的实现。下面就是个例子
- 所有的action 都必ȝ承于base Action c?
- 所有的action都必LU程安全?因ؓaction是单例的,singleton?
- 因ؓ所有的action都必LU程安全?所以所有的对象都不能是cd? 都必MҎ(gu)参数的Ş式传倹{?
- 调用action的方法必d名ؓ "execute" ( 在Struts中的 DispatchAction cd像可以用其它Ҏ(gu)L行同一个action Q但实际上在框架中调用的仍然?"execute" Ҏ(gu)?.
- ActionForward 的结果是通过ActionMapping cM的方法来产生?通常?findForward"Ҏ(gu).
CODE:public class MyAction {
public String execute() throws Exception {
// do the work
return "success";
}
}
首先你会注意到的是,Struts2中的action不再l承于Q何类或需要实CQ何接口。实际上Q它q远不只q些。按照惯例,只有"execute"Ҏ(gu)能调用action, 但在Struts2中ƈ非必要,M声明为public String methodName() Ҏ(gu)都能通过配置来调用action.
另外Q你会注意到q回g再是"ActionForward ",而是String, 如果你需喜欢String的Ş式,那在Action接口里有个帮助方法可以提供简单的l果帔RQ如"success", "none", "error", "input" ?"login"?br />最后,和Struts最大的革命性的不同? 调用action不再是带参数的。那你如何在获得你所需要的值呢Q答案是"inversion of control" ?"dependency injection", 反{控制(想了解更多可以看Martin Fowler的文?http://www.martinfowler.com/articles/injection.html)?br />Z更好C解反转控Ӟ让我们来看看一个例子,如何在action处理q程中可以访问到HttpServerRequest 。在我们的例子中Q我们用ServletRequestAware 接口Q这个接口包含了相应属性的setter,如下CODE:public interface ServletRequestAware {
public void setServletRequest(HttpServletRequest request);
}
当我们承这个接口时Q我们需要通过setter为我们的HttpServerRequest 属性变量赋|CODE:public class MyAction implements ServletRequestAware {
private HttpServletRequest request;
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public String execute() throws Exception {
// do the work using the request
return Action.SUCCESS;
}
}
看v来现在这些属性是cȝ别的Qƈ不是U程安全的,但是在Struts2里ƈ没有问题Q因为每个请求过来的时候都会生一个新的action对象实例Q它q没有和其他h׃n一个对象,所以不需要考虑U程安全问题?br />
现在我们q有最后一步,是把action兌?b>ServletConfigInterceptor 拦截器。这个拦截器l承?b>ServletRequestAware 接口Qƈ提供了把HttpServletRequest 注入到action中的功能。但是你现在不用担心如何配置q些Q我们将在下一文章中具体讲述。最重要的是我们明白了拦截器和接口共同ؓaction提供了反转控制的功能?br />q个设计的好处是能让action完全和框架解耦。action仅仅是一个被框架使用的简单的POJO。这对于单元试但来极大的好处, 你能方便的ؓStruts action实现 StrutsTestCase 或 MockStrutsTestCase 单元试?br />
ȝ
By到现在ؓ止,你应该已l了解了Struts2的整个请求流E,q有高层的框架概念, 你也应该能自己动手配|Struts2的actionQ和讲出Struts和Struts2的差别了?br />在下文章中Q我们将会介l一个详l的Struts应用向Struts2q移的例子,同时我们也会介绍q移中相关的知识Q会讲述如何l合使用JSTL, JSP ?Struts2Q进一步讲qStruts和Struts2的action的差别,Struts2的配|和其他框架元素Q和谈到更多的其他相x架的特征?br />(?a target="_blank">http://www.infoq.com/, cac 译)
]]>
package com.sharp.struts.action;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.Globals;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
import com.sharp.struts.form.OwnerForm;
/**
* OwnerAction.java created by EasyStruts - XsltGen.
* http://easystruts.sf.net
* created on 10-09-2004
*
* XDoclet definition:
* @struts:action path="/owner" name="ownerForm" input="/owner.jsp" validate="true"
* @struts:action-forward name="/success.jsp" path="/success.jsp"
*/
public class OwnerAction extends DispatchAction {
public ActionForward changeLanguage(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
String language = request.getParameter("language");
if (language.equals("en")) {
request.getSession().setAttribute(Globals.LOCALE_KEY, Locale.ENGLISH);
} else {
request.getSession().setAttribute(Globals.LOCALE_KEY, Locale.CHINESE);
}
return mapping.findForward("owner");
}
}
q里需要注意一下,千万不要弄错Q我在这里就p了一个多时Q因为把文g名写错了
Locale.ENGLISH是一个Locale对象QgetLanguage()Ҏ(gu)q回enQ跟资源文g(ApplicationResources_en.properties)的后~相同
Locale.CHINESE是一个Locale对象QgetLanguage()Ҏ(gu)q回zhQ跟资源文g(ApplicationResources_zh_CN.properties)的后~相同
另外q用C个ownerForm.java文gQ内容如下:
// Created by Xslt generator for Eclipse.
// XSL : not found (java.io.FileNotFoundException: (Bad file descriptor))
// Default XSL used : easystruts.jar$org.easystruts.xslgen.JavaClass.xsl
package com.sharp.struts.form;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
/**
* OwnerForm.java created by EasyStruts - XsltGen.
* http://easystruts.sf.net
* created on 10-09-2004
*
* XDoclet definition:
* @struts:form name="ownerForm"
*/
public class OwnerForm extends ActionForm {
// --------------------------------------------------------- Instance Variables
/** Email property */
private String email;
/** Greet property */
private String greet = "Mr.";
/** Address property */
private String address;
/** Tel property */
private int tel = 0;
/** Name property */
private String name;
// --------------------------------------------------------- Methods
......
//getter,setter mothodQ这里不赘列?BR>
}
5、ȝ
q样一个国际化的小例子可以运行了Q不q上面写得比较粗略,需要对java和struts有一定了解?BR>|上对国际化也有其他的做法,也可以参考?BR>如果上述有所偏颇Q敬h正?BR>