几个错误的解决关键
几个错误的解决关键
分类: 经验技巧之Hibernate 2007-12-10 13:47 1951人阅读 评论(0) 收藏 举报
导读:
1、
org.springframework.orm.ObjectRetrievalFailureException: Object of class [com.xindeco.myregister.pojo.MyRegisterInfo] with identifier [14]: not found
MyRegisterInfo在数据库没有identifier [14]对象。
2、
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Initialization of bean failed; nested exception is org.hibernate.MappingException: Repeated column in mapping for entity: com.xindeco.myregister.pojo.MyRegisterInfo column: password (should be mapped with insert="false" update="false")
出错原因:password 和repassword同时对应数据库表中的password一列,同时update和insert都设为true。
xml文件如下:
type="java.lang.String"
update="true"
insert="true"
access="property"
column="password"
length = "32"
/> type="java.lang.String"
update="true"
insert="true"
access="property"
column="password"
length = "32"
/>
type="java.lang.String"
update="false"
insert="false"
access="property"
column="password"
length = "32"
/> type="java.lang.String"
update="false"
insert="false"
access="property"
column="password"
length = "32"
/>
解决的方法:
将repassword的insert和update设为false。
3、
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Initialization of bean failed;
nested exception is org.hibernate.PropertyNotFoundException: Could not find a getter for ID in class
错误原因:hibernate的映射文件中ID是大写的,而pojo的类中id是小写的
注意事项:每个pojo的类都要继承abstractEntity,其中abstractEntity类有个ID的属性要重写
public abstract class AbstractEntity
implements Entity, BaseDTO {
abstract public long getID();
abstract public void setID(long id);
public int hashCode() {
return (int)this.getID();
}
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Entity) {
return this.getID() == ( (Entity) obj).getID();
}
return false;
}
}
4、
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition
错误原因:
在application.xml文件中deleteRegister方法以delete开头,并没有被设定为可更改的,应如下设置:
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
加上一行
PROPAGATION_REQUIRED
5、
ERROR org.apache.struts.util.RequestUtils - Error creating form bean of class com.xindeco.business.web.form.GraAppInfoForm
public class GraAppInfoForm
extends ActionForm 错误写成
public abstratic class GraAppInfoForm
extends ActionForm
6、
2006-04-25 08:56:38,495 ERROR com.xindeco.business.web.action.GraAppAction - com.xindeco.business.web.action.GraAppAction@8e2fb5
java.lang.ClassCastException: $Proxy0
at com.xindeco.business.web.action.GraAppAction.newone(GraAppAction.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:274)
at com.xindeco.core.web.action.BaseAction.dispatchMethod(BaseAction.java:153)
at org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:194)
actioin类中的newone方法如下:
public class GraAppAction
extends BaseAction {
public ActionForward newone(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
GraAppService graservice = (GraAppService) this.getBean("GraAppService");
}
applicationcontext中的GraAppService的配置如下:
因此this.getBean("GraAppService");是为了得到GraAppServicImpl类的实现。GraAppService是interface
public class GraAppServiceImpl extends BaseServiceImpl
implements GraAppService{
}
7、org.hibernate.hql.ast.QuerySyntaxException: Demand is not mapped. [from Demand where unitid = ? and needNum >usedNeedNum]
hibernate.cfg.xml没有配置Demand.hbm.xml文件的目录
8、org.springframework.jdbc.BadSqlGrammarException: Bad SQL grammar [] in task 'Hibernate operation'; nested exception is java.sql.SQLException: 列名 'id' 无效。
java.sql.SQLException: 列名 'name' 无效。
因为hibernate声明的id,name的columnid属性没有与数据库的字段对应,所以id,name无效。
9、java.lang.NumberFormatException: null
at java.lang.Integer.parseInt(Integer.java:415)
at java.lang.Integer.parseInt(Integer.java:497)
at com.xindeco.business.service.impl.DemandServiceImpl.findDemandListByUnitId(DemandServiceImpl.java:33)
错误语句为
needNum = Integer.parseInt(demand.getNeedNum());
usedNeedNum = Integer.parseInt(demand.getUsedNeedNum());
因为demand.getUsedNeedNum()==null,无法转化为string 类型,
10、rg.apache.jasper.JasperException: /GraAppInfo/GraAppInfoNew.jsp(343,29) According to TLD, tag bean:write must be empty, but is not
错误的原因:
就因为少了/>
以后懂得通过查找字数,来检查错误
11、2006-04-26 13:27:54,812 ERROR com.xindeco.core.util.BeanUtils - bean property [Nation] copy failed
com.xindeco.core.exception.ConvertException: org.springframework.orm.hibernate3.HibernateSystemException: Unknown entity: java.lang.String; nested exception is org.hibernate.MappingException: Unknown entity: java.lang.String
beanUtil.beanCopy(grapojo,form,BizConstants.CONVERTER);
要求:
1、pojo类的属性只有与form属性名字相同,才能beancopy成功
2、pojo中属性是实体,在form中一定要用int,long表示
出现这错误的原因是pojo中的属性不是实体,而错误写成:
string
private String nation;应改成 private Syscode nation;
12、
2006-04-26 14:38:37,843 ERROR com.xindeco.business.web.action.GraAppAction - com.xindeco.business.web.action.GraAppAction@fa1b2d
java.lang.NullPointerException
at com.xindeco.business.web.action.GraAppAction.newone(GraAppAction.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
hibernate配置文件没改,程序找不到相应的类
name="FSUnit"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="fSUnit"
/> name="FSUnit"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="fSUnit"
/>
其实FSUnit对应的类应该是FSUnit
name="FSUnit"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="fSUnit"
/> name="FSUnit"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="fSUnit"
/>
13、
org.hibernate.MappingException: An association from the table GraAppInfo refers to an unmapped class: com.xindeco.business.pojo.FSUnit
错误原因:hibernate.cfg.xml没有配置fsunit.hbm.xml文件的位置
14、
java.lang.ClassCastException: com.xindeco.business.dao.impl.GraAppDAOImpl
at com.xindeco.business.service.impl.GraAppServiceImpl.addGraduateApp(GraAppServiceImpl.java:16)
GraAppServiceImpl.java:16
第16行: GraAppDAO dao = (GraAppDAO) this.getBaseDAO();//其实得到的是GraAppDAOImpl
错误的原因是
public class GraAppDAOImpl
extends BaseDAOImpl {
}
没有实现GraAppDAO接口,正确的做法是
public class GraAppDAOImpl
extends BaseDAOImpl implements GraAppDAO {
}
先继承后实现
15、2006-04-27 08:38:54,078 ERROR com.xindeco.business.web.action.GraAppAction - com.xindeco.business.web.action.GraAppAction@1d6399b
java.lang.ClassCastException: com.xindeco.business.pojo.SysCode
at org.hibernate.type.StringType.set(StringType.java:26)
at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:63)
at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:40)
一般是因为hibernate声明类型和pojo类声明的类型不一样,并且前面已经出现了Hibernate: insert into TGraAppInfo (name, whereFrom, degree, college, speciality, studentRelTel, remark, higherEduLength, highSchool, studyResume, normalOrNot, proxyUnit, workPost, workPlace, studentAddress, studentPostNumber, nation, appStatus) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
的操作提示,查出错误的原因有:
name="demand"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="demandID"
/> name="demand"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="demandID"
/>
name="appStatus"
type="int"
update="true"
insert="true"
access="property"
column="appStatus"
length="10"
/> name="appStatus"
type="int"
update="true"
insert="true"
access="property"
column="appStatus"
length="10"
/>
应改为
name="demand"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="demandID"
/> name="demand"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="demandID"
/>
name="nation"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="nation"
/> name="nation"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="nation"
/>
16、
org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance - save the transient instance before flushing: com.xindeco.business.pojo.SysCode
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:626)
at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:570)
at
org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:482)
pojo类为:
public class GraAppInfo{
private College college;
}
action 类为
public class GraAppAction
extends BaseAction {
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
graInfo.setCollege(new College());//必须从数据库找到college这个对象,而不能新生成
graInfo.getCollege().setID(graForm.getCollegeID());
graInfo.setAppStatus(Integer.parseInt("0"));
service.addGraduateApp(graInfo);
}
public class GraAppServiceImpl extends BaseServiceImpl
implements GraAppService{
public boolean addGraduateApp(GraAppInfo info)
{
this.getBaseDAO().save(info);
return true;
}
}
dao类save方法为
getHibernateTemplate().save(obj);
当cascade="all",插入new college 除了id和原来的记录一样,其他的字段全部都被更新,为null
当cascase=“insert”,插入new college 只会把它的id插入grainfo表中,其他字段不变。
17、java.sql.SQLException: Unable to convert between java.lang.Integer and BLOB.
因为
name="province"
type="com.xindeco.business.pojo.SysCode"//不能用复杂类,
update="true"
insert="true"
access="property"
column="provinceId"
/> name="province"
type="com.xindeco.business.pojo.SysCode"//不能用复杂类,
update="true"
insert="true"
access="property"
column="provinceId"
/>
应该改为
name="province"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="provinceId"
/> name="province"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="provinceId"
/>
18、javax.servlet.jsp.JspException: Cannot create iterator for this collection
at org.apache.struts.taglib.logic.IterateTag.doStartTag(IterateTag.java:265)
jsp文件如下:
graduateList是一个类,而logic:iterator要求必须是ArrayList,HashSet....这样的集合类,而graduateList中一个属性是ArrayList或HashSet的
应改为:
19、2006-05-11 17:13:37,468 ERROR com.xindeco.business.web.action.GraAppAction - com.xindeco.business.web.action.GraAppAction@bc22eb
org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed
SysUser user= (SysUser) request.getSession().getAttribute(WebConstants.SESSION_USER);
System.out.println(user.getRole().getRoleName());
当hibernate session取出数据放到http session时,
由于sysuser中role的lazy=“true”,所以没有将RoleName放到http session中,当System.out.println(user.getRole().getRoleName());
时,虽然http session还开着, hibernat seesion已经关闭
name="role"
lazy="false"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="roleID"
/> name="role"
lazy="false"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="roleID"
/>
20、Association references unmapped class: com.xindeco.workflow.WFNode
因为application.xml文件中没有配置
系统找不到WFNode
name = "nodes "
table = "WF_ROLENODES "
lazy = "true "
inverse = "false "
cascade = "none "
sort = "unsorted "
> name = "nodes "
table = "WF_ROLENODES "
lazy = "true "
inverse = "false "
cascade = "none "
sort = "unsorted "
>
column = "roleID "
> column = "roleID "
>
class = "com.xindeco.workflow.WFNode "
column = "nodeId "
outer - join = "auto "
/> class = "com.xindeco.workflow.WFNode "
column = "nodeId "
outer - join = "auto "
/>
12:45 | 永久链接 | 浏览 (184) | 评论 (0) | struts |
logic:Iterator标签(以下简称“该标签”)是Struts里非常常用的一个标签,其作用在于循环显示给定容器对象中的值。
如此常用的标签,其源代码当然需要拿出来研究一下,以下列举几条研究成果:
1、该标签内部使用Collection来表示给定的容器,所有的给定容器对象(如ArrayList,Map等)都会被其转化成为Collection,Collection实际就是Map和List的父类。
2、该标签自己维护循环索引,不用程序员管理索引
3、该标签常见的几个属性如下:name、property、scope、id
对应Struts给出的Api说明如下:
name:包括要遍历Collection的Jsp页面的bean的名字(如果property没有被定义),或者是那些通过getter方法获得属性的Jsp中的Bean的名字,这些getter方法返回的是Collection(如果property定义了)。
property:在name命名的Jsp bean中定义的属性的名字,通过getter方法返回一个Collection
scope:指示到哪里去寻找name为名字的bean,如果没有定义缺省为"any scope"
id:如果Collection非空的话,在每次遍历时候Collection中每个元素的名字。
其中除了id每个元素均为Rt expr,这儿的rt expr的意思就是Run Time Expression。明确的说就是,如果你对一个Attribute的指定为true,你就可以在这样的属性中使用<%=%>之类的东东。这个配置文件在tld中。
只有id是必须要说明的。
关于Api说明的说明:
id只是一个临时标识,在下面的
举例说明
以下代码生成一个阶梯状表格
系统 资源 操作
soft3
res3
opt3
soft12
res12
opt1211
soft11
res11
opt1111
在此之前传来一个request.getAttribute("userPurview"),所以有在第一个logic中的userPurview,就是在这个request里面寻找userPurview
返回的是一个list
>
//这个id可以随便起名,但是要注意下文使用的一致性
系统资源操作
//此处name和上面id保持一致,property就是第一个list里面的元素
结论:
多级迭代和单层差不多,唯一注意的就是id和 12:44 | 永久链接 | 浏览 (37) | 评论 (0) | struts |
html:form注意事项
在使用html:form时需指定action属性,特别是在使用
html标签时指定的action应在xml中找得到并且页面显示的ActionForm
应于action中使用的.do引擎相匹配,否则JSP会出错
Struts中JSP基本操作
文件头部需增加的代码
<%@ page contentType="text/html;charset=gb2312" %>
<%request.setCharacterEncoding("GB2312");%>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-template.tld" prefix="template" %>
一般信息输出
下拉框输出
注:所有html标签(即需在form中显示的),在使用时都需在容器内部
name="[Xml中Form-bean段的name属性]"
property="[将ActionForm的一个属性作为Option的value,该属性为Collection,]"
labelProperty="[将ActionForm的一个属性作为Option的text,该属性为Collection,]"
/> name="[Xml中Form-bean段的name属性]"
property="[将ActionForm的一个属性作为Option的value,该属性为Collection,]"
labelProperty="[将ActionForm的一个属性作为Option的text,该属性为Collection,]"
/>
逻辑叠代器使用
id="[自定义的代表封装单条记录标识,该标识应与bean:write中name属性相同]RecoreId"
name="[Xml中Form-bean段的name属性]"
property="[Action中具为Collection属性名称]"
offset="[显示的偏移量]"
length="[显示记录数]"
> id="[自定义的代表封装单条记录标识,该标识应与bean:write中name属性相同]RecoreId"
name="[Xml中Form-bean段的name属性]"
property="[Action中具为Collection属性名称]"
offset="[显示的偏移量]"
length="[显示记录数]"
>
name="[自定义的代表封装单条记录标识,该标识应与bean:write中name属性相同]RecoreId" property="[单条记录所映射的ActionForm的属性]recordname"/> name="[自定义的代表封装单条记录标识,该标识应与bean:write中name属性相同]RecoreId" property="[单条记录所映射的ActionForm的属性]recordname"/>
12:44 | 永久链接 | 浏览 (28) | 评论 (0) | struts |
Struts Html标签和标准的HTML标签功能相同,这里提倡在Struts应用中使用Struts标签,这是因为这些标签可以和Struts框架的其他组件紧密的联系起来,如比标签用来定义HTML表单,Struts能够把这个表单中的数据自动映射到对应的ActionForm中.下面对具体的标签进行深度研究.首先研讨一些基本的东东,我个人认为不是很常用的,生成基本HTML元素的标签,这些标签和HTML元素对应,主要包括:
1)生成元素,这个标签有一个lang属性,用于显示用户使用的语言,设置卫true的时候,标签将先根据存储当前HttpSession中的Locale对象来输出网页数用的语言,如果没有HttpSession或者里面没有Locale对象,就根据HTTP请求头的属性来输出语言,如果HTTP请求头中没有,就根据默认的Locale来输出语言.
2)生成元素,这个用于生成当前网页的绝对URL路径.如果使用了这个标签,当该网页引用同一个应用的其他网页的时候,只需要给出相对于当前网页的相对URL路径即可.
3)生成Anchor元素,这个是超连接标签,感觉有一些好处可言,比如允许在RUL中以多种方法包含请求参数.当用户浏览器关闭Cookie的时候,会自动重写URL,把SessionID作为请求参数包含在URL中,用于跟踪用户的Session状态.它的主要属性有三种,分别是forward指定全局转发连接.href指定完整的URL连接.page指定相对于当前网页的RUL.
4)生成用户请求URI,用于输出超连接中的URL部分,但它并不生成HTML
元素.URI指的是URL中的协议,主机和端口以后的内容.
5)生成HTML元素,用于在HTML页中嵌入图片.page属性指定当前的URI.
根据我个人的一些看法,感觉Struts确实很好,但是在好的东西也有一些不实用的地方,JAVA也是如此,以上方法我比较推荐标签,感觉这个标签有十分不错的功效,下面阐述一下具体的使用方法:
1) 创建全局转发连接:首先在Struts配置文件中配置
在JSP页面中引用:index
2) 创建完整URL的连接,也就是说可以连接到其他的站点
Action
3) 从一个网页连接到同一个应用的另外一个网页
Action
4) 在URL或者RUI中包含请求参数的方法
Action
5) 在URL或者URI中包含单个请求变量的方法
pagemProperty>Action
paramId属性指定请求参数名,paramName属性指定变量名称,paramProperty指定变量卫JavaBean的属性.
研讨完了StrutsHtml标签库的基本标签,下面开始研究一个重要的东东,Struts的表单标签以及它的子标签,单选按钮,复选框,下拉列表等等,下面是详细介绍:
1)表单标签的action属性来指定当用户提交表单后,处理用户请求的组件,就是说在form里action属性比如设置了一个in.do的,那么在配置文件中action元素的path属性如果是/in,这就说明是这个action来接收form提交过来的数据.这个感觉挺简单,此外还需要知道name是设置表单名字,method是来设置请求方法,比如Get或Post.
2)文本标签的property属性指定字段的名字,它和ActionForm中的一个属性匹配,这个属于表单标签的一个子标签,可以把用户填写的值提交到具体的ActionForm中
3)标签在表单中生成取消按钮,当用户按下取消按钮的时候,产生一个取消事件,这个时间由Action来捕获,至于如何处理在Action类中的execute()方法编程实现,主要用途是在用户按了提交按钮,请求没发送过去又不想提交的时候,起到一个反悔作用.
4)标签用来生成复位按钮,类似以上的取消按钮这些实现复位,取代了HTML代码.
5)标签生成提交按钮.使用方法和取消,复位一样都是这样写代码的:
提交.
6)标签在表单上生成隐藏字段,用于在表单上存放不希望让用户看到或者不允许修改的信息,它的属性类似文本标签,property和ActionForm中的具体属性对应.如果想要在表单想显示某个值,而且不希望用户修改,可以用这个方法.
7)标签在表单上生成标准的HTML检查框,比如ActionForm中的属性是boolean类型只能有2个值,就可以在表单中使用这个标签来表示.主要通过property属性来设置对应的ActionForm属性,还有一个value属性,用来设置用户选中检查框的值,默认值是true,就是说当用value=false的时候如果用户没选择这个检查框,就把ActionForm的属性设置卫true,为了检查框能够正常工作,必须在ActionForm的reset()方法中对其复位,在value属性为true的时候,必须在reset()方法中把对应的属性设置为false.
8)标签和差不多,区别就在于它可以生成复选框.它的性能比更加灵活,可以动态的决定被选中复选框的数目,只要property属性相同,而value属性不一样,就可以和ActionBean的同一个数组对应.此外checkbox只能和blooean类型的属性对应,而multibox则没有限制.
9)标签表示单选按钮,多个标签可以组合使用.
10)标签生成下拉列表或多选列表,重要的属性是size属性指定每次网页上显示的可选的项目数量.multiple属性指定是否支持多项选择,如果设置为true表示多选列表,默认为false.property属性于ActionForm中的某个属性对应,这个属性用来存储用户在列表上选中的值.在单选的情况下,ActionForm的对应属性定义为简单类型,不能是数组.在多选的情况下类型是数组.
以上是对StrutsHtml标签库的Form系列标签以及子标签的简单阐述,这些标签不一定都常用,所以了解即可,能掌握常用的几个标签就OK了.下面研究一下文件上传,是指通过用户浏览把用户本地的文件传到Web服务器标签提供了从Html表单中上传文件的功能.这个标签也是Form标签的子标签所以必须嵌套在中,而且的method属性必须设置为Post.enctype编码属性必须设置为multipart/form-data.而且它的property属性必须设置和ActionForm中的Flie类型的属性对应.如果property=”file”则ActionForm中必须要设置private File file;属性,而且提供相应的get/set方法.然后通过Action来完成接收上传文件的功能,首先创建一个读取用户上传文件的InputStream流对象,然后创建一个把上传数据写到目标文件中的OutputStream对象,接下来通过一个驯化把数据从源文件写到目标文件中,上传就实现了.
标签用于输出错误消息,在request和session范围寻找ActionMessages或者其子类ActionErrors集合对象.在从ActionMessages集合对象中读取ActionMessage对象,把ActionMessage对象包含的错误消息文本显示在网页上.至于具体的错误文本消息存放在ResourceBundle中,而且标签能识别错误文本中的HTML元素,例如等等.标签可以存放在网页的任何地方,也可以在表单内.因为它输出错误和它在网页的位置无关.它的具体属性是.1)name:指定ActionMessages对象的属性key,标签处理类根据这个key来家查request或session范围的ActionMessages集合对象.2)property:指定消息属性,如果不设置会显示ActionMessages集合对象中所有的消息对象ActionMessage.3)bundle:指定ResourceBundle如果这个没设置,将从应用中默认的ResourceBundle中获取消息.
标签和标签有些类似,也能够在网页中输出消息,具体的属性是:1)name:指定ActionMessages对象的属性key,标签处理根据这个key来检索request或者session范围内的ActionMessages对象.2)message:指定消息的来源,如果是true则从request或者session范围内检索出属性key为Globals.MESSAGE_KEY的具体的ActionMessages对象.3)id:用来命名从消息集合中检索出每个ActionMessages对象,它和标签的name属性匹配.
Struts的标签库固然很好,但是有些是需要用的,有些也是不用也罢的,所以可以根据实际情况进行研究,不过感觉还是都了解一下的好,不一定都要会用,但是起码都能看懂就OK了呵呵^_^ (网友们的支持,是我继续写技术文章的动力!)
12:43 | 永久链接 | 浏览 (51) | 评论 (0) | struts |
Struts标签
solo L
发布日期:2005年06月01日,更新日期:2005年06月01日
您使用过旅游指南吗?它总是能让我们快速的找到目的地。我对此有深刻的印象,希望这篇指南也能使您快速的完成Struts标签相关的任务。我深入细致的总结了日常使用Struts的一些经验,感觉Struts标签的用途非常广泛并且功能强大,但是学起来还是比较费时间的。我认为学习Struts标签最好的方式就是参考良好的示例,幸运的是这些示例您可以在下面找到。
Struts是Apache Jakarta的一个著名的开源项目,目标是为构建基于Java的web应用程序提供一个框架。
Struts提供了非常多的标签,依据功能和使用习惯的不同被分到了五个标签库中:
Bean Tags:该标签库包含的标签可以用来创建bean、访问bean和访问bean的属性。同时提供了依据cookies、headers和parameters的值创建相关bean的能力。
HTML Tags:该标签库包含的标签可以用来创建Struts输入表单。
Logic Tags:该标签库包含的标签可以用来进行逻辑判断、集合迭代和流程控制。
Nested Tags:该标签库建立在前三个标签库的基础上,具有前三个标签库的所有功能,只是允许标签间的嵌套。
Tiles Tags:该标签库包含的标签可以用来创建tiles样式的页面。
这篇指南主要介绍前三个标签库中的标签。如果您对后两类标签也感兴趣可以查阅参考资料中的Struts的用户指南。
回页首
bean:cookie
cookie最早是由Netscape公司提出来的,用来存储客户的少量状态信息。如果您对cookie的具体细节感兴趣可以查阅参考资料中的cookie spec。
bean:cookie标签取回请求中名称为name的cookie的值。如果没有指定multiple属性则依据刚取回的值创建一个Cookie类型的bean。如果指定了multiple属性则依据刚取回的值创建一个Cookie[]类型的数组。然后用id属性值将Cookie或Cookie[]绑定到page作用域中(这种绑定是为了其它标签能够使用该值),并创建对应的scripting变量(这种变量是为了JSP脚本能够使用该值)。
下面的代码片段示例了如何使用bean:cookie标签读取名为JSESSIONID的cookie的值,并且使用了两种方式进行了输出:
这个cookie的名称是,值为。
<%
String name = jSession.getName();
String value = jSession.getValue();
out.println("这个cookie的名称是"+name+",值为"+value+"。< String name = jSession.getName();
String value = jSession.getValue();
out.println("这个cookie的名称是"+name+",值为"+value+"。
");
%>
回页首
bean:define
bean:define标签在toScope(如果没有指定值就使用page作用域)指定的作用域中创建一个新属性,同时创建一个scripting变量。我们可以通过id值使用它们。新创建的属性可以由其它标签使用,而新创建的scripting变量可以由JSP脚本使用。
我们可以使用三种方式为新创建的属性和scripting变量赋值:
通过该标签的name、property和scope取回值,并且保持类型的一致性,除非取回的值为Java的原始类型,这时会使用适合的包装器类对这些值进行包装。
通过该标签的value指定值,这时新创建的属性和scripting变量的类型为java.lang.String。
通过在该标签的体中嵌入值,这时新创建的属性和scripting变量的类型为java.lang.String。
下面的代码片段示例了如何使用bean:define标签创建新属性values和新scripting变量values,它将listForm中persons的值取出来赋给values:
下面给出ListForm的代码片段以帮助您更好的理解,其中Person是一个只有id和name两个属性的简单bean:
public class ListForm extends ActionForm {
private List persons = null;
public List getPersons() {
return persons;
}
public void setPersons(List persons) {
this.persons = persons;
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
persons = null;
}
}
下面的代码片段示例了logic:iterate标签如何使用bean:define标签创建的新属性values:
下面的代码片段示例了JSP脚本如何使用bean:define标签创建的新scripting变量values:
<%
Person p = new Person();
for(int i=0;i< Person p = new Person();
for(int i=0;i
p = (Person)values.get(i);
out.println(p.getId());
out.println("
");
}
%>
回页首
bean:header
bean:header标签取回请求中名称为name的header的值。如果没有指定multiple属性则依据刚取回的值创建一个String类型的bean。如果指定了multiple属性则依据刚取回的值创建一个String[]类型的数组。然后用id属性值将String或String[]绑定到page作用域中(这种绑定是为了其它标签能够使用该值),并创建对应的scripting变量(这种变量是为了JSP脚本能够使用该值)。
下面是我的浏览器发送的header的内容,这些内容和浏览器有关,因此您的浏览器发送的内容可能和下面列出的不同。不过这没有关系,因为要理解bean:header标签您只要对这些内容有一个大概的认识就足够了。
accept: */*
accept-language: zh-cn
accept-encoding: gzip, deflate
user-agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
host: localhost:8080
connection: Keep-Alive
下面的代码片段示例了如何使用bean:header标签读取名为User-Agent的header的值,并且使用了两种方式进行了输出:
您的浏览器是
。
<%
out.println("您的浏览器是"+userAgent+"。< out.println("您的浏览器是"+userAgent+"。
");
%>
回页首
bean:include
bean:include标签对指定url(由forward、href或page确定)处的资源做一个请求,将响应数据作为一个String类型的bean绑定到page作用域,同时创建一个scripting变量。我们可以通过id值访问它们。
下面的代码片段示例了bean:include标签的用法,其中include.txt文件包含要include的内容,然后将这些内容输出:
<%
out.println(value);
%> out.println(value);
%>
回页首
bean:message
bean:message标签用来从指定的locale中取回国际化的消息并输出,在这个过程中我们还可以传递五个以内的参数。message key可以通过key直接指定,也可以通过name和property间接的指定。
bean:message标签有两种指定message key的方式,一是通过key属性直接指定;二是通过name和property属性间接的指定,其中message key是在message resources文件中定义的。
我们可以在struts-config.xml文件中使用来设置message resources文件。
为了介绍该标签我使用了三个message resources文件,三个文件的名字分别为Resources.properties、Resources_en.properties和Resources_zh.properties。在struts-config.xml文件中的设置(这里不用设置三个,struts会依据locale自动找到对应的文件)如下:
三个message resources文件中定义的message key为:
resource=Resources.properties.
from=Resources.properties.
from=Resources_en.properties.
因为文件的编码被限制为ISO8859所以要有汉字必须用jdk的native2ascii提前转换
-->
from=Resources_zh.properties.
下面的代码片段示例了bean:message标签的用法:
English
Chinese
上面的代码中含有改变locale的两个html:link标签,要使它们工作您的struts-config.xml文件中必须含有下面定义的form和action:
在不同的locale下我们得到了如下的两个结果:
在locale为zh时的结果:
Resources_zh.properties.
Resources.properties.
在locale为en时的结果:
Resources_en.properties.
Resources.properties.
让我们来看一下在locale为zh时如何得到的是上面的结果。因为locale为zh所以
先找Resources_zh.properties这个文件从中得到form键的值。而
也会先找Resources_zh.properties这个文件但这次没有找到resource键,这时Struts会到Resources.properties这个文件中找,很幸运这里找到了。如果还没有找到,或message resource文件不存在就会抛出异常。当locale为en时类似,您可以自己试试。
回页首
bean:page
bean:page标签将页上下文中的application、config、request、response 或 session取出,然后用id属性值将它们绑定到page作用域中(这种绑定是为了其它标签能够使用该值),并创建对应的scripting变量(这种变量是为了JSP脚本能够使用该值)。
下面的代码片段示例了bean:page标签取出response,然后使用bean:write标签将response的characterEncoding和contentType属性输出:
<%
String characterEncoding = res.getCharacterEncoding();
String contentType = res.getContentType();
out.println(characterEncoding+"< String characterEncoding = res.getCharacterEncoding();
String contentType = res.getContentType();
out.println(characterEncoding+"
");
out.println(contentType+"
");
%>
您可以用和上面类似的代码访问application、config、request 或 session中的任何一个对象。
回页首
bean:parameter
bean:parameter标签取回请求中的参数值。如果没有指定multiple属性则依据刚取回的值创建一个String类型的bean。如果指定了multiple属性则依据刚取回的值创建一个String[]类型的数组。然后用id属性值将String或String[]绑定到page作用域中(这种绑定是为了其它标签能够使用该值),并创建对应的scripting变量(这种变量是为了JSP脚本能够使用该值)。
下面的两个代码片段使用相同的url传递参数,url的形式为http://127.0.0.1:8080/struts-demo/parameter.jsp?param=1?m=2?m=3。前面的代码片段中没有指定multiple属性,因此p是String类型而且仅仅读取了参数的第一个值。后面的代码片段中指定了multiple属性的值,因此ps是String[]类型的包含所有参数的值。
回页首
bean:resource
bean:resource标签取回指定的web应用程序的资源,以InputStream或String的形式保存到page作用域中并且创建scripting变量。采用什么形式取决于标签的input属性,如果指定input则以InputStream的形式保存,如果没有指定input则以String的形式保存。
下面的两个代码片段示例了bean:resource标签,其中resource.txt是要使用的资源文件。前面的代码片段中没有指定input属性,因此以String的形式处理资源文件,bean:write标签输出资源文件的内容。后面的代码片段中指定了input属性的值,因此以InputStream的形式使用资源文件,两个bean:write标签分别输出InputStream对象的实例名(如java.io.ByteArrayInputStream@16dadf9)和类名(如class java.io.ByteArrayInputStream)。
<%
out.println(str+"< out.println(str+"
");
%>
<%
out.println(is+"< out.println(is+"
");
out.println(is.getClass()+"
");
%>
回页首
bean:size
bean:size标签创建一个java.lang.Integer类型的bean,这个bean的值为该标签指定的Collection或Map中所含元素的个数。 这可以和logic:iterate标签配合使用,因为logic:iterate标签不能得到所叠代的集合的元素的个数,这有时候很不方便。
下面的代码片段示例了bean:size标签取出persons中还有元素的个数,其中listForm和persons的定义参见bean:define标签部分:
回页首
bean:struts
bean:struts标签取回Struts的内部对象formBean、forward或mapping的值,然后用id绑定到page作用域中(这种绑定是为了其它标签能够使用该值),并创建对应的scripting变量(这种变量是为了JSP脚本能够使用该值)。
下面的代码片段示例了bean:struts标签取出listForm对象,让我们先来看一下listForm的定义在读代码:
private boolean one = false;
private boolean two = false;
private boolean three = false;
One
Two
Three
如果选中后被提交则相应的属性的值为true。
回页首
html:radio
html:radio标签生成一个radio。主要的用法有两种,下面我们通过代码来示例。
下面的代码示例了html:radio标签的一般用法,如果被提交则选中的radio的value值将被提交到radioForm中的id中。
One
Two
下面的代码示例了html:radio标签的典型用法,其中的persons和bean:define标签中的一致,您可以参考bean:define标签。我只介绍这个,idName指定html:radio要使用的bean(这里为person),value="id"表示person的id属性将作为radio元素的value值而property="id"表示提交时选中的radio的值将被提交给radioForm中的id属性。
回页首
html:multibox
html:multibox标签生成多个checkbox。当您要使用大量的checkbox时使用这个标签非常方便,可以使您避免在ActionForm中声明大量的boolean类型的变量,带之以一个数组就行了。
注意:为了正确的处理没有选中的checkbox您必须在reset()中设置数组的长度为0。
下面的代码示例了html:multibox标签的一般用法,如果被提交则选中的所有checkbox的value值将被提交到multiboxForm中的selectedItems中,这是一个String[]数组。
下面的代码示例了html:multibox标签的典型用法:
回页首
html:link
html:link标签生成一个锚点()元素。我从html:link标签如何构造基本url和如何构造query参数两个方面来介绍这个标签。
构造基本url是依据该标签的如下四个属性进行的,这四个属性一次只能出现一个。让我们看看它们:
forward,指定一个全局ActionForward的名称。另外如果forward是module相关的则该forward必须指向一个action而不能是一个页面。
action,指定一个Action的名称。
href,struts会直接使用这个值而不会对其进行任何处理。
page,指定一个页面的路径,必须以/开始。
构造query参数,下面列举了可能的形式,其中baseurl只是一个占位符:
baseurl?p=00001(单参单值)
baseurl?p1=00001&p2=00002&p3=00003(多参单值)
baseurl?p=00001&p=00002&p=00003(单参多值)
baseurl?p1=00001&p2=00002&p=00001&p=00002&p=00003(混合)
下面我们以代码示例来说明每一种html:link的用法,首先让我们花点时间看看相关action中的代码:
public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) {
DataForm dataForm = (DataForm) form;
dataForm.setParam("00001");
HashMap paramSingleMap = new HashMap();
paramSingleMap.put("p1","00001");
paramSingleMap.put("p2","00002");
paramSingleMap.put("p3","00003");
dataForm.setParamSingleMap(paramSingleMap);
HashMap paramMultiMap = new HashMap();
paramMultiMap.put("p",new String[]{"00001","00002","00003"});
dataForm.setParamMultiMap(paramMultiMap);
HashMap paramSMMap = new HashMap();
paramSMMap.put("p1","00001");
paramSMMap.put("p2","00002");
paramSMMap.put("p",new String[]{"00001","00002","00003"});
dataForm.setParamSMMap(paramSMMap);
List persons = new ArrayList();
Person person1 = new Person();
person1.setId("00001");
person1.setName("赵辰");
Person person2 = new Person();
person2.setId("00002");
person2.setName("李为芳");
Person person3 = new Person();
person3.setId("00003");
person3.setName("王微");
persons.add(person1);
persons.add(person2);
persons.add(person3);
dataForm.setPersons(persons);
return mapping.findForward("success");
}
Go Top
单参单值
多参单值
单参多值
混合
下面的代码示例了html:link标签的indexed属性和indexId属性的用法,这两个属性只有html:link标签嵌套在logic:iterate标签中时才可用。
person
html:rewrite标签和html:link标签类似只是不生成锚点(),而是简单的输出字符串。
回页首
html:errors
html:errors标签和html:messages标签的功能相似,所以我们放到一起来介绍。
html:errors标签将由name属性指定的ActionMessages、ActionErrors、String和String[]直接输出到页面中。
html:messages标签将用由name属性(注意message属性值对它的影响)指定的ActionMessages、ActionErrors、String和String[]创建一个新的属性和scripting变量,使用id属性值作为名称。
html:errors标签和html:messages标签的property属性是用来为errors和messages分类的。我们可以给这两个标签指定property属性,以便只显示某一类的错误或消息。
在资源文件增加了如下的内容:
# -- standard errors --
errors.header=
errors.prefix=
errors.suffix=
errors.footer=
error=error with none value .
error1=error1 with one value is {0} .
error2=error2 with two values are {0} , {1} .
error3=error3 with three values are {0} , {1} , {2} .
error4=error4 with four values are {0} , {1} , {2} ,{3} .
下面的代码示例了actionErrors的构造:
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors actionErrors = new ActionErrors();
actionErrors.add("property1",
new ActionMessage("error"));
actionErrors.add("property2",
new ActionMessage("error1","value0"));
actionErrors.add("property2",new ActionMessage("error2","value0","value1"));
actionErrors.add("property3",new ActionMessage("error3","value0","value1","value2"));
actionErrors.add("property3",new ActionMessage("error4","value0","value1","value2","value3"));
actionErrors.add("property4", new ActionMessage("error1",new Object[]{"value0"}));
actionErrors.add("property4", new ActionMessage("error2",new Object[]{"value0","value1"}));
actionErrors.add("property4", new ActionMessage("error3",new Object[]{"value0","value1", "value2"}));
actionErrors.add("property5",new ActionMessage("error4",new Object[]{"value0","value1", "value2","value3"}));
actionErrors.add("notBundle",new ActionMessage("not a bundle key",false));
return actionErrors;
}
errors标签代码示例:
messages标签代码示例:
图示 2. 上面的两段代码示例运行结果相同,如下所示:
回页首
html:javascript
html:javascript标签生成用于校验的javascript脚本代码。
下面的代码片段示例了html:javascript标签的基本用法,其中formName属性的值是在validation.xml文件的中定义的form的名称。有一点值得注意的是在确定时要使用合适的language属性值。
回页首
html:xhtml
html:xhtml标签在页面中一出现就是告诉该页的所有其它的Struts html标签以XHTML1.0兼容的形式输出。这和将html:html标签的xhtml属性值指定为true有些类似。如果上述情况都没有出现,Struts html标签将以html4.01兼容的形式输出。
回页首
logic:iterate
logic:iterate标签用来迭代集合,您可以使用如下方式来为这个标签指定其要叠代的集合:
使用一个运行时表达式,这个表达式的值是一个集合。
用name属性引用一个JSP Bean,这个JSP Bean本身就是一个集合。
用name属性引用一个JSP Bean,这个JSP Bean的一个属性是一个集合,这时可以联合使用property来指定这个集合。
上面所提到的集合可以是:
对象类型或原子类型的数组(Array)。
java.util.Collection的实现,包括ArrayList,Vector。
java.util.Enumeration的实现。
java.util.Iterator的实现。
java.util.Map的实现,包括HashMap,Hashtable和TreeMap。
如果您叠代的集合中含有null的值,这时需要采取一定的措施,因为这时logic:iterate不会在page作用域中创建对象。一般是使用标签或标签来判断一下。
下面是logic:iterate叠代ArrayList的示例的对象引用关系和部分代码:
图示 3. logic:iterate中对象的引用关系
图中的persons列表是在ListAction中填充的,在这里只是简单的加入了三个Person对象,在实际的应用中这些数据应该取自数据库。具体的代码如下:
public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request, HttpServletResponse response) {
ListForm listForm = (ListForm) form;
List persons = new ArrayList();
Person person1 = new Person();
person1.setId("00001");
person1.setName("赵辰");
Person person2 = new Person();
person2.setId("00002");
person2.setName("李为芳");
Person person3 = new Person();
person3.setId("00003");
person3.setName("王微");
persons.add(person1);
persons.add(person2);
persons.add(person3);
listForm.setPersons(persons);
return mapping.findForward("success");
}
标签输出的结果为:
00001-->赵辰
00002-->李为芳
00003-->王微
回页首
logic:present
如果指定的值出现该标签就会创建其标签体内的内容。该标签用于以下情况:
检查具有指定名称的cookie是否出现。
检查具有指定名称的header是否出现。
检查具有指定名称的JSP Bean是否出现 或 检查具有指定名称的JSP Bean中的property属性是否出现。
检查request中指定名称的参数是否出现。
检查当前的认证用户是否与指定的安全角色相关联。
检查当前认证的主体是否具有指定的名字。
下面的代码示例了logic:present标签检查具有指定名称User-Agent的header是否出现:
您的浏览器是 。
logic:notPresent标签的应用正好和logic:present标签相反。
回页首
logic:messagesPresent
logic:messagesPresent标签用于以下情况:
在request作用域中存在一个ActionMessages对象,标签的property属性和ActionMessages中的property对应。
在request作用域中存在一个ActionErrors对象,标签的property属性和ActionErrors中的property对应。
存在一个String对象,将其转换(构造)成ActionMessage然后在添加到ActionMessages中。
存在一个String Array对象,将数组中的每一个String转换成一个ActionMessage,在将其添加到ActionMessages中。
标签的message属性值为true时将以Globals.MESSAGE_KEY为key在request作用域中查找Message,其它情况下,将name的值作为key查找,如果name 没有出现,默认值为Globals.ERROR_KEY。
下面的代码示例了logic:messagesPresent标签的典型用法:
标签logic:messagesNotPresent的应用正好和logic:messagesPresent的应用相反。
回页首
logic:empty
logic:empty标签是用来判断是否为空的。如果为空,该标签体中嵌入的内容就会被处理。该标签用于以下情况:
当Java对象为null时
当String对象为""时
当java.util.Collection对象中的isEmpty()返回true时
当java.util.Map对象中的isEmpty()返回true时
下面的代码示例了logic:empty标签判断集合persons是否为空:
集合persons为空!
logic:notEmpty标签的应用正好和logic:empty标签相反。
回页首
logic:match
logic:match标签用来处理子串匹配问题。
如果指定的值匹配该标签就会创建其标签体内的内容。该标签用于以下情况:
检查具有指定名称的cookie是否与该标签的value匹配。
检查具有指定名称的header是否与该标签的value匹配。
检查具有指定名称的JSP Bean是否与该标签的value匹配 或 检查具有指定名称的JSP Bean中的property属性值是否与该标签的value匹配。
检查request中指定名称的参数值是否与该标签的value匹配。
下面的代码示例了logic:match标签的典型用法:
MS IE 6.0
logic:notMatch标签的应用正好和logic:match标签相反。
回页首
logic:equal
这里要介绍的不只是logic:equal(=)标签,而是要介绍一类标签,这类标签完成比较运算,包括:
logic:equal(=)
logic:notEqual(!=)
logic:greaterEqual(>=)
logic:lessEqual(<=)
logic:graterThan(>)
logic:lessThan(<)
该类标签的用法类似,我们只介绍logic:equal标签,其它的留给您自己去完成。
logic:equal是用来判断是否相等的。如果相等,该标签体中嵌入的内容就会被处理。该标签用于以下情况:
比较由该标签的cookie属性指定的cookie的值是否与该标签的value属性值相等。
比较由该标签的header属性指定的header的值是否与该标签的value属性值相等。
比较由该标签的name属性指定的JSP Bean是否与该标签的value属性值相等(property属性不出现)或比较由该标签的name属性指定的JSP Bean中的property属性值是否与该标签的value属性值相等。
比较由该标签的parameter属性指定的参数值(request中)是否与该标签的value属性值相等。
回页首
logic:forward
我觉得将forward和redirect这两个动作放到一起对比着介绍更加有利于理解,基于此原因也就将logic:forward和logic:redirect这两个标签也拿到这里一起介绍了。
让我们看看这两个动作的区别:
forward是在servlet内部执行,浏览器完全不会感知到这个动作,原始的url也不会改变,浏览器重新装载的话也只是对原始的请求进行简单的重复。
redirect则分成两个步骤:第一步是web应用程序告诉浏览器第二个url,然后浏览器向第二个url发送请求。
redirect比forward慢,因为浏览器要做二次请求。还有就是要注意,在第一次的请求作用域(request作用域)内的bean对于第二次请求是不可见的。
理解了上面描述的区别也就知道了什么时候该选用logic:forward标签什么时候该选用logic:redirect标签了。logic:forward标签完成PageContext.forward()或HttpServletResponse.sendRedirect(),如何选择由控制器决定。logic:redirect标签完成HttpServletResponse.sendRedirect()。
在使用logic:redirect标签时我们可以向使用html:link一样构造baseurl和query参数。如果您感兴趣可以参考html:link标签。
回页首
总结
这篇指南的背景是Struts-1.2.9,其中的所有的代码示例也都是在这个版本下调试通过的。目前Struts仍然在快速的发展中,但是从开发者应用的角度来讲还是比较稳定的。因此我有理由相信其中的代码示例也可以很好的运行在其它的版本之上。最后希望这篇指南能够让您心情愉快!
参考资料
图解 Tomcat 体系结构
使用Log4j进行日志记录
Struts的官方文档
Struts的用户指南
cookie spec,这是关于Cookie最的全面的说明。
HTML元素
关于作者
solo L 一位有些理想主义的软件工程师,创建了solol.org。他常常在这里发表一些对技术的见解。
Copyright ? SoloL.org
12:43 | 永久链接 | 浏览 (37) | 评论 (0) | struts |
本篇文章包含了在用Struts开发web应用时经常碰到的一些异常和错误,根据异常或错误信息本身,经常可以找到潜在的错误发生原因。
下面列出了一些Struts的常见错误和异常,并给出了一些可能发生此类错误或异常的原因。有的后面有相关连接,你可以通过它找到更多的信息。
Cannot retrieve mapping for action
异常
javax.servlet.jsp.JspException: Cannot retrieve mapping for action /Login (/Login是你的action名字)
可能原因
action没有再struts-config.xml 中定义,或没有找到匹配的action,例如在JSP文件中使用 Cannot retrieve definition for form bean null
异常
org.apache.jasper.JasperException: Cannot retrieve definition for form bean null
可能原因
这个异常是因为Struts根据struts-config.xml中的mapping没有找到action期望的form bean。大部分的情况可能是因为在form-bean中设置的name属性和action中设置的name属性不匹配所致。换句话说,action和form都应该各自有一个name属性,并且要精确匹配,包括大小写。这个错误当没有name属性和action关联时也会发生,如果没有在action中指定name属性,那么就没有name属性和action相关联。当然当action制作某些控制时,譬如根据参数值跳转到相应的jsp页面,而不是处理表单数据,这是就不用name属性,这也是action的使用方法之一。
No action instance for path /xxxx could be created
异常
No action instance for path /xxxx could be created
可能原因
特别提示:因为有很多中情况会导致这个错误的发生,所以推荐大家调高你的web服务器的日志/调试级别,这样可以从更多的信息中看到潜在的、在试图创建action类时发生的错误,这个action类你已经在struts-config.xml中设置了关联(即添加了 在struts-config.xml中通过action标签的class属性指定的action类不能被找到有很多种原因,例如:
定位编译后的.class文件失败。Failure to place compiled .class file for the action in the classpath (在web开发中,class的的位置在r WEB-INF/classes,所以你的action class必须要在这个目录下。例如你的action类位于WEB-INF/classes/action/Login.class,那么在struts-config.xml中设置action的属性type时就是action.Login).
拼写错误,这个也时有发生,并且不易找到,特别注意第一个字母的大小写和包的名称。
在struts-config.xml中指定的action类没有继承自Stuts的Action类,或者你自定义的Action类没有继承自Struts提供的Action类。
你的action类必须继承自Struts提供的Action类。
你的classpath的问题。例如web server没有发现你的资源文件,资源文件必须在WEB-INF/classes/目录下。
Problem in struts-config.xml file with action mapping.
Problem with data-sources.xml file.
相关链接
http://www.mail-archive.com/struts-user@jakarta.apache.org/msg65874.html
Action Mapping mistake in struts-config.xml:
http://www.manning.com/ao/readforum.html?forum=siaao&readthread=177
data-sources.xml file?:
http://www.caucho.com/quercus/faq/section.xtp?section_id=30
No getter method for property XXXX of bean org.apache.struts.taglib.html.BEAN
异常
javax.servlet.jsp.JspException: No getter method for property username of bean org.apache.struts.taglib.html.BEAN
可能原因
没有位form bean中的某个变量定义getter 方法
这个错误主要发生在表单提交的FormBean中,用struts标记时,在FormBean中必须有一个getUsername()方法。注意字母“U”。
Related Links
Case can trip up the matching between get method's name and name specified in Struts tag
http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=58&t=000163
java.lang.NoClassDefFoundError: org/apache/struts/action/ActionForm
错误
java.lang.NoClassDefFoundError: org/apache/struts/action/ActionForm
可能原因
这个错误主要发生在在classpath中找不到相应的Java .class文件。如果这个错误发生在web应用程序的运行时,主要是因为指定的class文件不在web server的classpath中(/WEB-INF/classes 和 /WEB-INF/lib)。
在上面的错误中,原因是找不到ActionForm类。
This error is sometimes seen when one or more ActionForm.class instances are actually in the classpath. This most often occurs when ActionForm.class is made available correctly by placing struts.jar in the /WEB-INF/lib directory. When this library has been correctly placed and it is verified that ActionForm.class actually is present in the struts.jar file, the problem is either that more than one copy of ActionForm.class is in the classpath or (more likely) that duplicate versions of class files other than ActionForm are in the same classpath, causing confusion. This is especially true if a class that extends ActionForm is made available twice, such as in an .ear file that encompasses a .war file as well as in the .war file's own classpath (/WEB-INF/classes). This problem can be resolved by guaranteeing that there are no redundant classes, especially those related to Struts (directly from Struts or extensions of Struts), in the web application's view.
相关连接
EJB and Web Shared Links:
http://forum.java.sun.com/thread.jsp?forum=26&thread=413060&tstart=0&trange=15
Keep Action and ActionForm (and their children) as non-overlapping unit(s) of an application
http://www.mail-archive.com/struts-user@jakarta.apache.org/msg47466.html
http://www.mail-archive.com/struts-user@jakarta.apache.org/msg47467.html
Exception creating bean of class org.apache.struts.action.ActionForm: {1}
异常
javax.servlet.jsp.JspException: Exception creating bean of class org.apache.struts.action.ActionForm: {1}
可能原因
Instantiating Struts-provided ActionForm class directly instead of instantiating a class derived off ActionForm. This might occur implicitly if you specify that a form-bean is this Struts ActionForm class rather than specifying a child of this class for the form-bean.
Not associating an ActionForm-descended class with an action can also lead to this error.
Related Links
Cannot find ActionMappings or ActionFormBeans collection
Exception
javax.servlet.jsp.JspException: Cannot find ActionMappings or ActionFormBeans collection
可能原因
不是标识Struts actionServlet的标记就是映射.do扩展名的标记或者两者都没有在web.xml中声明。
在struts-config.xml中的打字或者拼写错误也可导致这个异常的发生。例如缺少一个标记的关闭符号/>。最好使用struts console工具检查一下。
另外,load-on-startup必须在web.xml中声明,这要么是一个空标记,要么指定一个数值,这个数值用来表servlet运行的优先级,数值越大优先级越低。
还有一个和使用load-on-startup有关的是使用Struts预编译JSP文件时也可能导致这个异常。
相关链接
Explicitly Define
http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=50&t=001055
http://threebit.net/tutorials/ejb/general/
NullPointerException at ... RequestUtils.forwardURL
异常
java.lang.NullPointerException at org.apache.struts.util.RequestUtils.forwardURL(RequestUtils.java:1223)
可能原因
在struts-config.xml中的forward元素缺少path属性。例如应该是如下形式:
Cannot find bean org.apache.struts.taglib.html.BEAN in any scope
Exception
javax.servlet.jsp.JspException: Cannot find bean org.apache.struts.taglib.html.BEAN in any scope
Probable Causes
试图在Struts的form标记外使用form的子元素。这常常发生在你在后面使用Struts的html标记。
另外要注意可能你不经意使用的无主体的标记,如,这样web 服务器解析时就当作一个无主体的标记,随后使用的所有标记都被认为是在这个标记之外的,如又使用了
还有就是在使用taglib引入HTML标记库时,你使用的prefix的值不是html。
相关连接
Using form subelements outside of a form tag
http://forum.java.sun.com/thread.jsp?thread=337537&forum=4&message=1384153
Missing message for key xx.xx.xx
Exception
javax.servlet.jsp.JspException: Missing message for key xx.xx.xx
Probable Causes
这个key的值对没有在资源文件ApplicationResources.properties中定义。如果你使用eclipse时经常碰到这样的情况,当项目重新编译时,eclipse会自动将classes目录下的资源文件删除。
资源文件ApplicationResources.properties 不在classpath中 应将资源文件放到 WEB-INF/classes 目录下,当然要在struts-config.xml中定义)
Cannot find message resources under key org.apache.struts.action.MESSAGE
异常
Cannot find message resources under key org.apache.struts.action.MESSAGE
可能原因
很显然,这个错误是发生在使用资源文件时,而Struts没有找到资源文件。
Implicitly trying to use message resources that are not available (such as using empty html:options tag instead of specifying the options in its body -- this assumes options are specified in ApplicationResources.properties file)
XML parser issues -- too many, too few, incorrect/incompatible versions
Related Links
Provide Struts with Resource Bundle
http://threebit.net/tutorials/ejb/general/
XML Parser Issues
http://www.mail-archive.com/struts-user@jakarta.apache.org/msg15779.html
No input attribute for mapping path /loginAction
错误
No input attribute for mapping path /xxxxAction
可能原因e
No input attribute in action mapping in struts-config.xml file for the action with the name specified in the error message. An input attribute is not required if form validation is not performed (either because the validate attribute is set to false or because the validation method in the relevant form class is not implemented. The input attribute specifies the page leading to this action because that page is used to display error messages from the form validation.
Related Links
Strange Output Characters
错误
Strange and seemingly random characters in HTML and on screen, but not in original JSP or servlet.
可能原因
混和使用Struts的html:form标记和标准的HTML标记不正确。
使用的编码样式在本页中不支持。
"Document contained no data" or no data rendered on page
错误
"Document contained no data" in Netscape
No data rendered (completely empty) page in Microsoft Internet Explorer
可能原因
使用一个Action的派生类而没有实现perform()方法或execute()方法。在Struts1.0中实现的是perform()方法,在Struts1.1中实现的是execute()方法,但Struts1.1向后兼容perform()方法。
但你使用Struts1.1创建一个Action的派生类,并且实现了execute()方法,而你在Struts1.0中运行的话,就会得到"Document contained no data" error message in Netscape or a completely empty (no HTML whatsoever) page rendered in Microsoft Internet Explorer.”的错误信息。
12:42 | 永久链接 | 浏览 (88) | 评论 (0) | struts |
Struts提供了五个标签库,即:HTML、Bean、Logic、Template和Nested。
标签库
说明
HTML 标签 用来创建能够和Struts 框架和其他相应的HTML 标签交互的HTML 输入表单
Bean 标签 在访问JavaBeans 及其属性,以及定义一个新的bean 时使用
Logic 标签 管理条件产生的输出和对象集产生的循环
Template 标签 随着Tiles框架包的出现,此标记已开始减少使用
Nested 标签 增强对其他的Struts 标签的嵌套使用的能力
标签的公共特征
使用固定属性名称的Struts 标签:
属性
说明
id 命名自定义标签创建时的脚本变量名。
name 指出关键字值,在该关键字下可以找到一个存在的bean 。如果给出了scope属性,则仅仅在scope中查找。否则,根据标准的顺序在各种scope中查找:(page, request, session, or application)。
property 指出bean 中的某个属性,可以在其中检索值。如果没有标明,则使用对象本身的值。
scope 定义了Bean在哪个范围(page, request, session, or application)中被查找。如果没有标明按顺序查找。脚本变量(见id)将在相同的范围中创建。
Struts 标签也支持嵌套引用,例如:
Property="foo.bar.baz"
这相当于进行下面的调用:
getFoo().getBar().getBaz();
或者做为setter:
getFoo().getBar().setBaz(value);
虽然Struts 标签的设计原意是为了避免使用scriptlet,scriptlet的表达式还能够提供给所有的Struts 标签使用。但请确保使用完整的表达式:
错误:
/index.jsp>'>
正确:
'> // 表达式必须提供整个属性值
Html 标签库
标签
它有两个属性:locale和xhtml,两者都不是必需的。
此行代码解析后:
说明:生成的结果取决于Struts应用程序所位于的服务器的locale。如果你将应用程序部署到一个不同locale的服务器,你不需要改变代码,Locale会自动调整。
标签:表示所包含页面的绝对位置。这个标签只有内嵌在head标签中才有效。
此行代码解析后:
标签
最重要的属性page:图象文件的路径,前面必须带有一个斜线。
其它属性:heignt、width、alt。
标签
Click demo
此行代码解析后:
Click demo
标签:通过一个简单的标签,你就可以在一个JSP页面上显示完全自定义的错误信息。功能超强大!!
说明:这个标签在Request对象的属性集合中查找reserved key。如果它找到一个reserved key,它就假设这个key是一个String、或是一个String数组
(它包含在模块的MessageResources中查找的message keys)、或是类型为org.apache.struts.action.ActionErrors的一个对象。
如果在应用程序资源中存在相应的信息,那么就可以用下面这些可选的message keys:
· errors.header or errors.prefix:相应的信息在错误信息的单独列表前显示。
· errors.footer or errors.suffix:相应的信息在错误信息的单独列表后显示。
标签系列
使用标签时必须遵循一些规则:
标签中必须包含一个action属性,它是这个标签中唯一必需的属性。如果不具备该属性则JSP页面会抛出一个异常。之后你必须给这个action属性指定一个有效值。一个有效值是指应用程序的Struts配置文件中元素里的任何一个子元素的访问路径。而且相应的元素中必须有一个name属性,它的值是form bean的名称。
如果你有上述一个标签 ,那么你的Struts配置文件的元素中必须有一个如下显示为粗体的元素:
type=/"com.javapro.struts.LoginAction/"
name=/"loginForm/"
scope=/"request/"
input=/"/login.jsp/"> type=/"com.javapro.struts.LoginAction/"
name=/"loginForm/"
scope=/"request/"
input=/"/login.jsp/">
.
.
.
// 这就是说一个form标签是和form bean相关联的。
任何包含在中用来接收用户输入的标签(、、、
我的异常网推荐解决方案:org.hibernate.MappingException: Association references unmapped class,http://www.myexception.cn/j2ee/326371.html