struts2提供了annotation来代替配置文件,并且说:"It is great start."。我试用了Annoation风格的Action配置,感觉并不是很好用,尤其在比较复杂的Action中,反而不如XML直观明了。甚至,我不喜欢使用带有{}的简化配置,还是传统的方式更加一目了然。尤其是配置配置Action的时候需要在web.xml中注明packages,简直是...
今天终于找到了Struts2 Annotation的用途——验证。
下面代码是在一个Action中使用CRUD、ModelDriven的情况下利用Annotation验证的方式,Action使用了springside风格,父类提供了基本的CRUD能力:
这是子类的代码:
这是Struts的配置文件
说明一下:
1.不必在web.xml的添加任何代码,struts会自动根据Annotation进行验证。
2.在[b]不[/b]需要验证的方法前加@SkipValidation,如果你采用了SpringSide风格的Action,那么在父类的方法前加@SkipValidation即可。但是如果子类覆盖了父类的方法,子类方法前也需要用@SkipValidation标注。感觉Struts2好像弄反了,实际应用中,需要验证的方法要少于不需要验证的方法,如果缺省的方法都不验证,只有标注了@Validations的方法验证就更好了。
3.一直感觉struts2 的XML验证方式比较难以维护,Annotation的使用解决了这个问题。
今天终于找到了Struts2 Annotation的用途——验证。
下面代码是在一个Action中使用CRUD、ModelDriven的情况下利用Annotation验证的方式,Action使用了springside风格,父类提供了基本的CRUD能力:
//这是父类代码
@SuppressWarnings( { "serial", "unchecked" })
public abstract class AbstractCrudAction<T, M extends Manager>
extends BaseAction implements Preparable, ModelDriven {
/**
* 定义显示单个实体的页面
*/
public static final String VIEW = "view";
/**
* 定义显示实体列表的页面
*/
public static final String INDEX = "index";
/**
* Action所使用的Manager类
*/
private M manager;
/**
* Action所管理的Entity
*/
private T model;
/**
* Action所管理的实体的类型
*/
private Class entityClass;
/**
* 用于保存查询结果。
*/
protected Collection<T> items;
/**
* 用于对应页面上CheckBox,List等组件的选择值.
*/
protected Serializable[] selectedItems;
/**
* 用于保存分页查询结果
*/
private Page page;
/**
* 创建一个新的实体,如果成功,返回index页面,如果失败,返回输入页面.
*/
public String create() {
//代码略
}
/**
* <B>创建或更新</B>一个实体,如果成功,返回index页面,如果失败,返回输入页面.
* <code>save()</code>相当于调用{@link create()}和{@link update()},
* 为了简化jsp编码,可以将新建和编辑页面合二为一,此时,<code>save()</code>方法.
*
*/
public String save() {
//代码略
}
/**
* @see {@link #save()}
*/
public String update() {
return SUCCESS;
}
/**
* 列出实体
*/
@SkipValidation
public String index() {
//代码略
}
/**
* 根据<code>Id</code>查询单个<code>model</code>并定向到显示它的页面.
*/
@SkipValidation
public String view() {
return VIEW;
}
/**
* 重定向到编辑页面。为了简化页面编程,将新建和编辑和为一个页面。
*/
@SkipValidation
public String edit() {
return INPUT;
}
/**
* 重定向到新建页面。为了简化页面编程,将新建和编辑和为一个页面。
*/
@SkipValidation
public String editNew() {
return INPUT;
}
/**
* 如果<code>id != null</code>,则删除ID所代表的Entity, 否则,如果<code>selectedItems.length > 0</code>则删除
* <code>selectedItems</code>所代表的所有Entities.
* @return
*/
@SkipValidation
public String remove() {
//代码略
}
// Method from Preparable
/**
* @see com.opensymphony.xwork2.Preparable#prepare()
*/
public void prepare() {
if (model == null || extractId(model) == null) {
model = (T) ReflectUtil.newInstance(getEntityClass());
} else {
model = (T) manager.get(extractId(model));
}
}
/**
* 从{@link #model}中取得ID
* @param model 给定Model
* @return 实体对象的ID值
*/
protected abstract Serializable extractId(T model);
/**
* 将{@link #id}转换为实际的类型,子类必须根据持久化标识的类型实现,例如:<br>
* <pre>
* protected Serializable convertId(Serializable id) {
* return (id == nul) ? null : Integer.valueOf(id.toString());
* }
* </pre>
*/
protected abstract Serializable convertId(Serializable id);
// Protected methods
protected Class getEntityClass() {
if (entityClass == null) {
entityClass = GenericsUtil.getGenericClass(getClass(), 0);
}
return entityClass;
}
//Method from ModelDriven
/**
* @see com.opensymphony.xwork2.ModelDriven#getModel()
*/
public T getModel() {
if(model == null) {
model = (T) ReflectUtil.newInstance(getEntityClass());
}
return model;
}
// Getters and setters.
public void setModel(T model) {
this.model = model;
}
public void setManager(M manager) {
this.manager = manager;
}
protected M getManager() {
return manager;
}
public Collection<T> getItems() {
return items;
}
public Serializable[] getSelectedItems() {
return selectedItems;
}
public void setSelectedItems(Serializable[] selectedItems) {
this.selectedItems = selectedItems;
}
public Page getPage() {
return page;
}
}
这是子类的代码:
//少了中间的DefaultCrudAction
@Validation
public class DeptAction extends DefaultCrudAction<Dept, DeptManager> {
/**
* 当前上级部门ID
*/
private Integer parentId;
/**
* 部门序列号管理器
*/
private DeptSerialNoManager serialNoManager;
/**
* 用于查询的部门名称
*/
private String deptName = StringUtils.EMPTY;
@Override
@SkipValidation
public String index() {
return INDEX;
}
@Override
@Validations(requiredStrings = { @RequiredStringValidator(type = ValidatorType.SIMPLE, fieldName = "model.name", message = "部门名称是必须的.")})
public String save() {
}
/**
* 处理parentDept为null的情况
*/
@Override
@SkipValidation
public String edit() {
}
/**
* 重置所有部门编号
*/
@SkipValidation
public String updateSerialNo() {
serialNoManager.updateAllSerialNo();
return SUCCESS;
}
public DeptSerialNoManager getSerialNoManager() {
return serialNoManager;
}
public void setSerialNoManager(DeptSerialNoManager serialNoManager) {
this.serialNoManager = serialNoManager;
}
}
这是Struts的配置文件
<package name="admin.dept" extends="struts-default" namespace="/admin/dept">
<action name="index" class="deptAction" method="index">
<result name="index" type="dispatcher">/pages/admin/dept/index.jsp</result>
</action>
<action name="editNew" class="deptAction" method="editNew">
<result name="input">/pages/admin/dept/edit.jsp</result>
</action>
<action name="edit" class="deptAction" method="edit">
<result name="input">/pages/admin/dept/edit.jsp</result>
</action>
<action name="remove" class="deptAction" method="remove">
<result name="success" type="redirect">index.do</result>
</action>
<action name="save" class="deptAction" method="save">
<result name="success" type="redirect">index.do</result>
<result name="input">/pages/admin/dept/edit.jsp</result>
</action>
<action name="updateDeptSerialNo" class="deptAction" method="updateSerialNo">
<result name="success" type="redirect">index.do</result>
</action>
</package>
<!--如果使用{},这个配置文件会更简单一些.-->
说明一下:
1.不必在web.xml的添加任何代码,struts会自动根据Annotation进行验证。
2.在[b]不[/b]需要验证的方法前加@SkipValidation,如果你采用了SpringSide风格的Action,那么在父类的方法前加@SkipValidation即可。但是如果子类覆盖了父类的方法,子类方法前也需要用@SkipValidation标注。感觉Struts2好像弄反了,实际应用中,需要验证的方法要少于不需要验证的方法,如果缺省的方法都不验证,只有标注了@Validations的方法验证就更好了。
3.一直感觉struts2 的XML验证方式比较难以维护,Annotation的使用解决了这个问题。