首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

总算发现struts2 Annotation的用处了——验证

2012-11-18 
终于发现struts2 Annotation的用处了——验证struts2提供了annotation来代替配置文件,并且说:It is great s

终于发现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;  }}

这是Struts的配置文件
<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><!--如果使用{},这个配置文件会更简单一些.-->

说明一下:
1.不必在web.xml的添加任何代码,struts会自动根据Annotation进行验证。
2.在需要验证的方法前加@SkipValidation,如果你采用了SpringSide风格的Action,那么在父类的方法前加@SkipValidation即可。但是如果子类覆盖了父类的方法,子类方法前也需要用@SkipValidation标注。感觉Struts2好像弄反了,实际应用中,需要验证的方法要少于不需要验证的方法,如果缺省的方法都不验证,只有标注了@Validations的方法验证就更好了。
3.一直感觉struts2 的XML验证方式比较难以维护,Annotation的使用解决了这个问题。
1 楼 Fly_m 2008-03-18   你这个例子不够全面,你只验证了一个方法.我刚也试了下你的方法,发现其中有一个问题是值得注意的,就是一个类中出现两个方法都需要验证,且两个验证都是不同的验证,如A方法验证a,B方法验证b.当同时出现两个方法验证不同的东西时,错误就出现了.
B方法在验证b的同时,会同时尝试去验证a(即会叠加另一个方法的验证),这样,本来不需要验证a方法的B方法,就已经出现验证错误了.不知道关于这个问题你发现没.如果有相应的解决方法,请与告知. 2 楼 ygxdha 2008-03-18   struts2验证的内核还是common-validator吧。
annotation不过是把需要在common-validator所需要的配置信息转移到java代码中的annotation中去。如果struts2的校验annotion对一些common-validator的支持不够,可以自己添加annotation的实现。只要把common-valitor这个核心搞清楚就ok了 3 楼 Fly_m 2008-03-19   <p>晚上回去搞了半天,还专门下了xwork的源代码来看,结果发现是struts2默认是全局验证了.解决方法就是重写struts2的默认拦截器,在引用validatio拦截器时,加入新的param,如下</p><p>?</p><pre name='code' class='xml'>&lt;interceptor-ref name="validation"&gt;
<br/>&lt;param name="excludeMethods"&gt;input,back,cancel,browse&lt;/param&gt;
<br/>&lt;param name="validateAnnotatedMethodOnly"&gt;true&lt;/param&gt;
<br/>&lt;/interceptor-ref&gt;</pre><p>??这样就可以达到单个方法级别的Annotation验证了.</p><p>以后可要好好看看别人的代码了,本来还以为是xwork没提供这个功能呢,结果是自己小白了.</p><p>不过好像下载xwork2.1的代码好像跟struts2有冲突吧,都无法启动了,最后又换回2.04的了.</p> 4 楼 cats_tiger 2008-03-20   to Fly_m:
哦,原来如此。Ths 5 楼 slaser 2008-04-07   我还是喜欢写代码进行验证。annotation和代码差别也不大了。

热点排行