创建一个扩展Spring标记库的自定义标记库

时间:2012-10-27 06:16:27

标签: java spring jsp spring-mvc taglib

我想创建一个自定义标记库,它应该扩展现有的Spring MVC 3.0标记库。我想这样做是因为我希望我的JSP代码独立于任何框架。

这意味着,如果我想从Spring更改为Struts,那么我无需更改JSP页面中的任何内容。我只是更改了我的自定义标记库,它将扩展Struts标记库,所有工作正常。

4 个答案:

答案 0 :(得分:16)

您无法扩展整个库,但您可以扩展库中的所有标记并为它们创建新的描述符,然后使用您自己的标记而不是Spring标记。

例如,转到名为spring-form.tld的文件。您将看到标记描述符,其中包含属性描述和标记类名称。

要拥有自己的标记库,您必须创建:

  1. my-lib.tld(指定[uri for a library])
  2. 扩展您需要的所有标签
  3. 将描述符放入my-lib.tld
  4. 在my-lib.tld而不是Spring中使用URI
  5. 只需在Google上搜索“jsp自定义标记”即可。或者看看JSP custom tags

    例如,从Struts和Spring:

    获取[form]标签的两个类
    • org.apache.struts.taglib.html.FormTag
    • org.springframework.web.servlet.tags.form.FormTag。

    您必须创建以下内容:

    package org.my.example.tags;
    
    import javax.servlet.jsp.JspException;
    
    import org.springframework.web.servlet.tags.form.FormTag;
    import org.springframework.web.servlet.tags.form.TagWriter;
    
    /**
     */
    public class SpringFormTag extends FormTag {
        private static final String FOCUS_ATTRIBUTE = "focus";
        private String focus;
    
        public void setFocus(String focus) {
            this.focus = focus;
        }
    
        public String getFocus() {
            return focus;
        }
    
        @Override
        protected void writeDefaultAttributes(TagWriter tagWriter) throws JspException {
            writeOptionalAttribute(tagWriter, FOCUS_ATTRIBUTE, getFocus());
            super.writeDefaultAttributes(tagWriter);
        }
    }
    

    我只发布了spring的表单标记代码。

    文件my-lib.tld:

    <?xml version="1.0" encoding="UTF-8"?>
    <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
            version="2.0">
        <description>My tag library</description>
        <tlib-version>3.0</tlib-version>
        <short-name>html</short-name>
        <uri>http://test.com/test.tld</uri>
        <tag>
            <name>form</name>
            <tag-class>org.my.example.tags.SpringFormTag</tag-class>
            <body-content>JSP</body-content>
            <attribute>
                <name>action</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>acceptCharset</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>dir</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>disabled</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
                <type>boolean</type>
            </attribute>
            <attribute>
                <name>enctype</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>focus</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>focusIndex</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>lang</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>method</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>onreset</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>onsubmit</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>readonly</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
                <type>boolean</type>
            </attribute>
            <attribute>
                <name>scriptLanguage</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
                <type>boolean</type>
            </attribute>
            <attribute>
                <name>style</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>styleClass</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>styleId</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
            <attribute>
                <name>target</name>
                <required>false</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
        </tag>
    </taglib>
    

    您还必须将.tld文件放入JAR文件的META-INF目录中。带有此taglibrary的JAR文件必须只是WAR文件中包含的JAR文件,否则将无法检测到taglibraries。

    然后将您的taglib包含在JSP文件中:

    <%@ taglib prefix="html" uri="http://test.com/test.tld" %>
    

    并使用它:

    <html:form action="asd" focus="1">
        <div><input type="text"></div>
        <div><input type="submit"></div>
    </html:form>
    

    如果你想在它们之间切换,你还必须为Struts创建这样的库。

    在执行此操作时,您唯一需要记住的是Spring和Struts有一些不同的标记定义,因此Struts具有“焦点”而Spring则没有。我认为可能会有更多的差异。

    如果你真的想从一个转换到另一个,你必须让你的标签拥有Spring和Struts的所有属性。但我并不认为这是值得的。

答案 1 :(得分:3)

我实际上做了类似你问的事情。我们有许多项目必须具有相同的设计,可用性和易维护性。 由于我们使用Spring MVC,因此我的一些标签是围绕spring form标签的包装器。例如输入标记:

import org.apache.commons.lang.StringUtils;
import org.springframework.web.servlet.tags.form.InputTag;

public class InputText extends AbstractInputTag {

    private String maxlength;

    @Override
    public void initInput() throws Exception {
        InputTag input = new InputTag();
        if ( StringUtils.isNotEmpty( maxlength ) ) {
            input.setMaxlength( maxlength );
        }
        setInput( input );
    }

    public void setMaxlength( String maxlength ) {
        this.maxlength = maxlength;
    }
}  

它从一个将标签添加到输入的抽象标记扩展,并且还处理错误代码:

import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.servlet.tags.form.AbstractHtmlInputElementTag;
import org.springframework.web.servlet.tags.form.ErrorsTag;

public abstract class AbstractInputTag extends AbstractTag {

    private String path;
    private String code;
    private String labelWidth = "35%";
    private String valueWidth = "";
    private AbstractHtmlInputElementTag input;

    @Override
    public int doStart() throws Exception {
        TaglibUtils.assertHasAncestorOfType( this, Form.class );
        initInput();

        TaglibUtils.doLabel( pageContext, getId(), code, labelWidth );

        setParent( input );
        input.setPageContext( pageContext );
        input.setCssErrorClass( "zsa-validationerror-input" );
        input.setPath( path );
        input.setId( getId() );

        if( !StringUtils.isEmpty( valueWidth ) ) {
            input.setCssStyle( "width: " + valueWidth );
        }
        pageContext.getOut().print( "<div>" );
        input.doStartTag();
        return EVAL_BODY_INCLUDE;
    }

    @Override
    public int doEnd() throws Exception {
        input.doEndTag();
        input.release();
        pageContext.getOut().print( "</div>" );

        ErrorsTag errorsTag = new ErrorsTag();
        errorsTag.setParent( this );
        errorsTag.setPageContext( pageContext );
        errorsTag.setPath( path );
        errorsTag.doStartTag();
        JspWriter out = pageContext.pushBody();
        out.print( "<span class=\"zsa-validationerror-flag\"></span>" );
        errorsTag.setBodyContent( ( BodyContent )out );
        errorsTag.doInitBody();
        errorsTag.doAfterBody();
        errorsTag.doEndTag();
        out = pageContext.popBody();
        errorsTag.release();
        return EVAL_PAGE;
    }

    public abstract void initInput() throws Exception;
}

在我的表单看起来像这样之前:

 <portlet:actionURL var="coreSearch" portletMode="view" windowState="NORMAL"></portlet:actionURL>
   <form:form commandName="searchContext" id="searchComplex" action="${coreSearch}" method="POST">
    <div class="rightDivPart" style="width: 50%; padding-left: 50px">
        <label class="label" for="tin">TIN: </label>
        <form:input cssErrorClass="inputErrorClass" path="tin" cssClass="medium"/>
     ...       

制作包装标签后,它们现在看起来像这样:

<ics:form id="searchComplex" commandName="searchContext" action="searchComplex" type="action">
    <ics:panel id="searchComplex">
      <ics:inputText id="mrn" path="mrnCriteria.mrn"/>
    </ics:panel>        
</ics:form>  

现在我的JSP-s几乎没有JavaScript,Css,JQuery和其他标签。 在一个非常大的项目中,我认为由于易于维护而值得进行投资。

答案 2 :(得分:1)

您可以将行为封装到tag files中。如果应用于spring标记库或任何其他标记库,这将是某种组合。

答案 3 :(得分:0)

使用JSTL标签。 JSTL意味着您的JSP将更通用,可供任何使用JSP的Java Web MVC技术使用。