论坛首页 Java企业应用论坛

Struts2 + ECSide解决“查询->更新->回到原查询状态”的问题

浏览 5312 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-12-14  
经常有这样的情况:用户千辛万苦的查询数据,并且翻页呀翻页的找到一条,然后修改它,保存成功以后,查询结果和页数都不见了!下次修改不得不重复上述操作。
使用Struts2的Chain Result可以实现多个Action的连续执行,但是,上述场景中需要跨越两次以上的Requests,很多parameters都无法保留,入下图:
查询=>分页=>编辑(查询参数和分页参数丢失)=>保存=>查询(没有参数的查询)
解决的办法是保留parameters,可以写一个taglib来实现这个目的:
public class ParametersTag extends BodyTagSupport {
  private static Log log = LogFactory.getLog(ParametersTag.class);
  /** 输出为input tag */
  public static final String TYPE_INPUT_TAG = "inputTag";
  /** 输出为query string */
  public static final String TYPE_QUERY_STRING = "queryString";
  
  /**
   * 指定包含的parameters,如果没有指定,则包含全部。可以使用*、?作为通配符。
   */
  private String includes;
  /**
   * @see #TYPE_INPUT_TAG
   * @see #TYPE_QUERY_STRING
   */
  private String type;

  /**
   * @see javax.servlet.jsp.tagext.BodyTagSupport#release()
   */
  @Override
  public void release() {
    includes = null;
    type = null;
    super.release();
  }

  /**
   * @see javax.servlet.jsp.tagext.BodyTagSupport#doEndTag()
   */
  @Override
  public int doEndTag() throws JspException {    
    Enumeration<String> keys = pageContext.getRequest().getParameterNames();
    String str = "";    
    if(StringUtils.isBlank(type) || StringUtils.equals(TYPE_INPUT_TAG, type)) {
      log.debug("Build Input Tags.");
      str = buildInputTags(keys);
    } else {
      log.debug("Build query string.");
      str = buildQueryString(keys);
    }
    try {
      pageContext.getOut().write(str);
    } catch (IOException e) {
      e.printStackTrace();
    }
    return BodyTagSupport.EVAL_PAGE;
  }
  
  /**
   * 根据参数构造queryString
   * @param keys 参数名称
   */
  private String buildQueryString(Enumeration<String> keys) {
    StringBuffer buf = new StringBuffer();
    while(keys.hasMoreElements()) {
      String key = keys.nextElement();
      String value = pageContext.getRequest().getParameter(key);
      if(StringUtils.isBlank(value)) {
        continue;
      }
      buf.append(key)
      .append("=")
      .append(value);
      if(keys.hasMoreElements()) {
        buf.append("&");
      }
    }
    return buf.toString();
  }

  /**
   * 根据参数构造Input
   * @param keys 参数名称
   */
  private String buildInputTags(Enumeration<String> keys) {
    StringBuffer buf = new StringBuffer();
    while(keys.hasMoreElements()) {
      String key = keys.nextElement();
      if(!isInclude(key)) {
        continue;
      }
      String value = pageContext.getRequest().getParameter(key);
      buf.append("<input type='hidden' name='")
      .append(key) 
      .append("' value='")
      .append((value == null) ? StringUtils.EMPTY : value)
      .append("'/>");
    }
    
    return buf.toString();
  }
  
  /**
   * 判断某个参数是否可以包含。
   */
  private boolean isInclude(String target) {
    if(StringUtils.isBlank(includes)) {
      return true;
    }
    PathMatcher matcher = new AntPathMatcher();
    Set<String> incs = StringUtil.parseCommaSplitedString(includes);
    for(String inc : incs) {
      if(matcher.match(inc, target)) {
        return true;
      }
    }
    
    return false;
  }
  
  
  /**
   * @return the includes
   */
  public String getIncludes() {
    return includes;
  }

  /**
   * @param includes the includes to set
   */
  public void setIncludes(String includes) {
    this.includes = includes;
  }

  /**
   * @return the type
   */
  public String getType() {
    return type;
  }

  /**
   * @param type the type to set
   */
  public void setType(String type) {
    this.type = type;
  }
}

jsp页面中这样使用:
<s:form theme="simple" action="create" id="saveForm">
	<jsam:params includes="ec*,query*" type="inputTag"></jsam:params>
</s:form>

或者:
  <a href='edit.do?id=${item.id}&<jsam:params includes="ec*,query*" type="queryString"/>'>edit</a>

在Struts2的配置文件中和chain一起使用:
  <action name="preStorageQuery" class="preStorageAction" method="pageQuery">
	<interceptor-ref name="chain"></interceptor-ref>
        <interceptor-ref name="basicStack"/>
	    <result name="success">list.jsp</result>
  </action>
  <!-- 使用chain,可以回到原来的查询状态 -->
  <action name="save" class="preStorageAction" method="save">		   
	<result name="success" type="chain">		    
	    <param name="actionName">preStorageQuery</param>
	    <param name="method">pageQuery</param>
	    <param name="namespace">/admin/drugstorage/pre</param>
	 </result>		   
	 <result name="input">list.jsp</result>
	 <interceptor-ref name="params" />
	 <interceptor-ref name="model-driven" />
         <interceptor-ref name="validationWorkflowStack" />
  </action>

上面的代码中省略了.tld中的内容,而且taglib只有includes属性,没有excludes属性。
使用taglib应该算是比较丑陋的做法,但是一时也想不到更好的方法,Ajax当然可以解决,可是我这个项目是改造遗留系统,总不能都改成Ajax的。其实这个taglib用起来还算方便,各位如果有更好的办法请多赐教,这篇博文权当抛砖。
   发表时间:2007-12-14  
写的不赖,学习了。
但不知道楼主能否解决一下struts2+ecside的隐藏input表单问题,
在查询、翻页、排序时会发生错误。
0 请登录后投票
   发表时间:2007-12-14  
发生什么错误呀?从来没有遇到过。
0 请登录后投票
   发表时间:2007-12-14  
这里会有一个问题的,查询条件的字段很有可能会和编辑form的字段重复,导致提交form出错。比如查询条件中有合同号字段(ContractNo),在编辑记录的时候恰巧也有合同号信息需要进行修改,这样就会出现异常!
0 请登录后投票
   发表时间:2007-12-21  
我也为这种类型的操作犯愁
0 请登录后投票
   发表时间:2008-09-09  
如果你们用seam中的对话的话,这样的问题相当的简单。
0 请登录后投票
   发表时间:2008-09-09  
GET提交
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics