终于发现struts2 Annotation的用处了——验证
struts2提供了annotation来代替配置文件,并且说:"It is great start."。我试用了Annoation风格的Action配置,感觉并不是很好用,尤其在比较复杂的Action中,反而不如XML直观明了。甚至,我不喜欢使用带有{}的简化配置,还是传统的方式更加一目了然。尤其是配置配置Action的时候需要在web.xml中注明packages,简直是...
今天终于找到了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@Validationpublic 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; }}
<package name="admin.dept" extends="struts-default" namespace="/admin/dept"> <action name="index" method="index"> <result name="index" type="dispatcher">/pages/admin/dept/index.jsp</result> </action> <action name="editNew" method="editNew"> <result name="input">/pages/admin/dept/edit.jsp</result> </action> <action name="edit" method="edit"> <result name="input">/pages/admin/dept/edit.jsp</result> </action> <action name="remove" method="remove"> <result name="success" type="redirect">index.do</result> </action> <action name="save" method="save"> <result name="success" type="redirect">index.do</result> <result name="input">/pages/admin/dept/edit.jsp</result> </action> <action name="updateDeptSerialNo" method="updateSerialNo"> <result name="success" type="redirect">index.do</result> </action></package><!--如果使用{},这个配置文件会更简单一些.-->