上篇html标记看法中说到的tag标记实现,现在有了雏形,个人比较喜欢webwork,因此就写了个webwork兼容的tag实现。   只需要在表单中修改form标记为<wwx:form ... ,所有的表单域属性都会自动帮定,无须改动原有html标记,也就是说不需要引入<ww:textfield>等标记,当然webwork的表单域标记中的自动错误输出我没实现,因为我不太喜欢这样的方式输出错误信息,如果想输出可以使用<ww:text>标记,此外这个form标记还可以自动输出webwork中客户端验证的javascript脚本。   当然如果你喜欢在webwork中用jstl的话还得写个JSTLFilter。 package net.libo.web.taglib; import java.io.Writer; import java.util.HashMap; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.BodyContent; import org.apache.velocity.Template; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.context.Context; import com.opensymphony.webwork.ServletActionContext; import com.opensymphony.webwork.config.Configuration; import com.opensymphony.webwork.views.jsp.ParametereizedBodyTagSupport; import com.opensymphony.webwork.views.jsp.TagUtils; import com.opensymphony.webwork.views.util.JavaScriptValidationHolder; import com.opensymphony.webwork.views.util.UrlHelper; import com.opensymphony.webwork.views.velocity.AbstractTagDirective; import com.opensymphony.webwork.views.velocity.VelocityManager; import com.opensymphony.xwork.ActionContext; import com.opensymphony.xwork.ObjectFactory; import com.opensymphony.xwork.config.ConfigurationManager; import com.opensymphony.xwork.config.entities.ActionConfig; import com.opensymphony.xwork.util.OgnlValueStack; import net.libo.web.util.HtmlEncoder; import net.libo.web.util.HtmlUtils; /**  * @author Boyce  *   * Form tag populates a included form with values and  * generates the client-side validation script.  */ public class FormTag extends ParametereizedBodyTagSupport  {     final public static String OPEN_TEMPLATE = "form.vm";     final public static String TEMPLATE = "form-close.vm";     Class actionClass;     String actionName;     JavaScriptValidationHolder javaScriptValidationHolder;     String nameAttr;     String actionAttr;     String targetAttr;     String enctypeAttr;     String methodAttr;     String namespaceAttr;     String validateAttr;            //~ Methods ////////////////////////////////////////////////////////////////     public void setAction(String action) {         this.actionAttr = action;     }     public void setName(String name) {         this.nameAttr = name;     }          public void setTarget(String target) {         this.targetAttr = target;     }     public Class getActionClass() {         return actionClass;     }     public String getActionName() {         return actionName;     }     public void setEnctype(String enctype) {         this.enctypeAttr = enctype;     }     public void setMethod(String method) {         this.methodAttr = method;     }     public void setNamespace(String namespace) {         this.namespaceAttr = namespace;     }     public void setValidate(String validate) {         this.validateAttr = validate;     }     protected String getDefaultTemplate() {         return TEMPLATE;     }     public String getDefaultOpenTemplate() {         return OPEN_TEMPLATE;     }      public int doStartTag() {         try {             evaluateParams(getStack());             mergeTemplate(getDefaultOpenTemplate());         } catch (Exception e) {             return SKIP_PAGE;         }         return EVAL_BODY_AGAIN;     }
     /**      * Performs smart form population.      *      * @return SKIP_BODY      */     public int doAfterBody() {         BodyContent body = getBodyContent();         try  {             JspWriter out = body.getEnclosingWriter();             String bodytext = body.getString();             bodytext = populateForm(bodytext, getStack());             out.print(bodytext);         } catch (Exception ex) {             ex.printStackTrace();         }         return SKIP_BODY;     }      /**      * End of tag.      *      * @return EVAL_PAGE      * @throws JspException       */     public int doEndTag() throws JspException {         try {             try {                 evaluateParams(getStack());                 mergeTemplate(this.getDefaultTemplate());                 return EVAL_PAGE;             } catch (Exception e) {                 throw new JspException("Fatal exception caught in " + this.getClass().getName() + " tag class, doEndTag: " + e.getMessage(), e);             }         } finally {             // clean up after ourselves to allow this tag to be reused             this.reset();         }     }
      protected void mergeTemplate(String templateName) throws Exception {
         // initialize the VelocityEngine         // this may happen more than once, but it's not a big deal         VelocityManager velocityManager = VelocityManager.getInstance();         velocityManager.init(pageContext.getServletContext());         VelocityEngine velocityEngine = velocityManager.getVelocityEngine();         Template t = velocityEngine.getTemplate(templateName);         Context context = velocityManager.createContext(getStack(),                 (HttpServletRequest) pageContext.getRequest(),                 (HttpServletResponse) pageContext.getResponse());         Writer outputWriter = (Writer) ActionContext.getContext().get(AbstractTagDirective.VELOCITY_WRITER);         if (outputWriter == null) {             outputWriter = pageContext.getOut();         }         context.put("tag", this);         context.put("parameters", getParameters());         t.merge(context, outputWriter);          }          public void evaluateParams(OgnlValueStack stack) {         if (actionAttr != null) {             /**              * If called from a JSP, pageContext will not be null.  otherwise, we'll get request and response from the              * ServletActionContext.              *              * todo - determine if there's any reason we can't just always use ServletActionContext              * -> because we want to be able to use the tags if we went directly to the page              */             HttpServletResponse response;             HttpServletRequest request;             if (pageContext != null) {                 response = (HttpServletResponse) pageContext.getResponse();                 request = (HttpServletRequest) pageContext.getRequest();             } else {                 request = ServletActionContext.getRequest();                 response = ServletActionContext.getResponse();             }             final String action = (String) findString(actionAttr);             String namespace;             if (namespaceAttr == null) {                 namespace = TagUtils.buildNamespace(getStack(), (HttpServletRequest) pageContext.getRequest());             } else {                 namespace = findString(namespaceAttr);             }             if (namespace == null) {                 namespace = "";             }             final ActionConfig actionConfig = ConfigurationManager.getConfiguration().getRuntimeConfiguration().getActionConfig(namespace, action);             if (actionConfig != null) {                 try {                     actionClass = ObjectFactory.getObjectFactory().getClassInstance(actionConfig.getClassName());                 } catch (ClassNotFoundException e) {                     // this is ok                 }                 actionName = action;                 String result = UrlHelper.buildUrl(namespace + "/" + action + "." + Configuration.get("webwork.action.extension"), request, response, null);                 addParameter("action", result);                 addParameter("namespace", namespace);                 // if the name isn't specified, use the action name                 if (nameAttr == null) {                     addParameter("name", action);                 }                 // if the id isn't specified, use the action name                 if (id == null) {                     addParameter("id", action);                 }             } else if (action != null) {                 String result = UrlHelper.buildUrl(action, request, response, null);                 addParameter("action", result);                 // namespace: cut out anything between the start and the last /                 int slash = result.lastIndexOf('/');                 if (slash != -1) {                     addParameter("namespace", result.substring(0, slash));                 } else {                     addParameter("namespace", "");                 }                 // name/id: cut out anything between / and . should be the id and name                 if (id == null) {                     slash = result.lastIndexOf('/');                     int dot = result.indexOf('.', slash);                     if (dot != -1) {                         id = result.substring(slash + 1, dot);                     } else {                         id = result.substring(slash + 1);                     }                     addParameter("id", id);                 }             }             // only create the javaScriptValidationHolder if the actionName,and class is known             // and the javaScriptValidationHolder hasn't been created already             // i.e. don'r re-create it on the second call to evaluateExtraParams             if (actionName != null && actionClass != null && javaScriptValidationHolder == null) {                 javaScriptValidationHolder = new JavaScriptValidationHolder(actionName, actionClass, getStack());             }         }                  if (nameAttr != null) {             addParameter("name", findString(nameAttr));         }         if (targetAttr != null) {             addParameter("target", findString(targetAttr));         }         if (enctypeAttr != null) {             addParameter("enctype", findString(enctypeAttr));         }         if (methodAttr != null) {             addParameter("method", findString(methodAttr));         }         if (validateAttr != null) {             addParameter("validate", findValue(validateAttr, Boolean.class));         }         if (javaScriptValidationHolder != null && javaScriptValidationHolder.hasValidators()) {             addParameter("javascriptValidation", javaScriptValidationHolder.toJavaScript());         } else {             addParameter("javascriptValidation", "// cannot find any applicable validators");         }     }  // ---------------------------------------------------------------- populate  private String populateForm(String html, OgnlValueStack valueStack) {   int i = 0, s = 0;   StringBuffer result = new StringBuffer(html.length());   String currentSelectName = null;   while (true) {    // find starting tag    i = html.indexOf('<', s);    if (i == -1) {     result.append(html.substring(s));     break;  // input tag not found    }    result.append(html.substring(s, i)); // tag found, all before tag is stored    s = i;    // find closing tag    i = html.indexOf('>', i);    if (i == -1) {     result.append(html.substring(s));     break;  // closing tag not found    }    i++;    // match tags    String tag = html.substring(s, i);             //System.out.println(tag);    String tagName = HtmlUtils.getTagName(tag);    if (tagName.equalsIgnoreCase("input") == true) {     String tagType = HtmlUtils.getAttribute(tag, "type");     if (tagType != null) {      String name = HtmlUtils.getAttribute(tag, "name");                     HashMap params = new HashMap();                     params.put("name", name);                     javaScriptValidationHolder.registerValidateField((String) name, params);      Object vobj = valueStack.findValue(name);      if (vobj != null) {       String value = vobj.toString();       tagType = tagType.toLowerCase();       if (tagType.equals("text")) {        tag = HtmlUtils.addAttribute(tag, "value", value);       } if (tagType.equals("hidden")) {        tag = HtmlUtils.addAttribute(tag, "value", value);       } if (tagType.equals("image")) {        tag = HtmlUtils.addAttribute(tag, "value", value);       } if (tagType.equals("password")) {        tag = HtmlUtils.addAttribute(tag, "value", value);       } if (tagType.equals("checkbox")) {        String tagValue = HtmlUtils.getAttribute(tag, "value");        if (tagValue == null) {         tagValue = "true";        }        if (tagValue.equals(value)) {         tag = HtmlUtils.addAttribute(tag, "checked");        }       } if (tagType.equals("radio")) {        String tagValue = HtmlUtils.getAttribute(tag, "value");        if (tagValue != null) {         if (tagValue.equals(value)) {          tag = HtmlUtils.addAttribute(tag, "checked");         }        }       }      }     }    } else if (tagName.equalsIgnoreCase("textarea") == true) {     String name = HtmlUtils.getAttribute(tag, "name");     Object value = valueStack.findValue(name);     if (value != null) {      if (value != null) {       tag += HtmlEncoder.encode(value.toString());      }     }    } else if (tagName.equalsIgnoreCase("select") == true) {     currentSelectName = HtmlUtils.getAttribute(tag, "name");    } else if (tagName.equalsIgnoreCase("/select") == true) {     currentSelectName = null;    } else if (tagName.equalsIgnoreCase("option") == true) {     if (currentSelectName != null) {      String tagValue = HtmlUtils.getAttribute(tag, "value");      if (tagValue != null) {       Object vals = valueStack.findValue(currentSelectName);       if (vals != null) {        if (vals.getClass().isArray() == false) {         String value = vals.toString();         if (value.equals(tagValue)) {          tag = HtmlUtils.addAttribute(tag, "selected");         }        } else {         Object[] arr = (Object[])vals;         for (int j=0;j<arr.length;j++) {          arr[j] = arr[j].toString();         }         String vs[] = (String[])arr;         for (int k = 0; k < vs.length; k++) {          String vsk = vs[k];          if (vsk != null) {           if (vsk.equals(tagValue)) {            tag = HtmlUtils.addAttribute(tag, "selected");           }          }         }        }       }      }     }    }    result.append(tag);    s = i;   }   return result.toString();  }      protected void reset() {         this.getParameters().clear();         javaScriptValidationHolder = null;         if (getActionName() != null && getActionClass() != null) {             javaScriptValidationHolder = new JavaScriptValidationHolder(getActionName(), getActionClass(), getStack());         }     }
 }
  还有两个util类就不放到这了,tld说明如下: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"> <taglib>     <tlibversion>1.1</tlibversion>     <jspversion>1.2</jspversion>     <shortname>wwx</shortname>     <uri>wwx</uri>          <tag>         <name>form</name>         <tagclass>net.libo.web.taglib.FormTag</tagclass>         <bodycontent>JSP</bodycontent>         <info>An HTML Component UI widget</info>         <attribute>             <name>name</name>             <required>false</required>             <rtexprvalue>true</rtexprvalue>         </attribute>         <attribute>             <name>action</name>             <required>false</required>             <rtexprvalue>true</rtexprvalue>         </attribute>         <attribute>             <name>target</name>             <required>false</required>             <rtexprvalue>true</rtexprvalue>         </attribute>         <attribute>             <name>namespace</name>             <required>false</required>             <rtexprvalue>true</rtexprvalue>         </attribute>         <attribute>             <name>method</name>             <required>false</required>             <rtexprvalue>true</rtexprvalue>         </attribute>         <attribute>             <name>enctype</name>             <required>false</required>             <rtexprvalue>true</rtexprvalue>         </attribute>         <attribute>             <name>validate</name>             <required>false</required>             <rtexprvalue>true</rtexprvalue>         </attribute>     </tag> </taglib>  
 
  |