【问题标题】:Create a custom tag library which extends the Spring tag library创建一个扩展 Spring 标签库的自定义标签库
【发布时间】:2012-10-27 06:16:26
【问题描述】:

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

这意味着,如果我想从 Spring 更改为 Struts,那么我不需要更改 JSP 页面中的任何内容。我只是更改了我的自定义标签库,它将扩展 Struts 标签库并且一切正常。

【问题讨论】:

  • 我的问题是我只想把spring的标签库扩展成我的自定义标签库。

标签: java spring jsp spring-mvc taglib


【解决方案1】:

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

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

所以要拥有自己的标签库,你必须创建:

  1. my-lib.tld(指定[库的uri])
  2. 扩展您需要的所有标签
  3. 将描述符放入 my-lib.tld
  4. 在 my-lib.tld 中使用 URI 而不是 Spring 的

只需在 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 目录中。带有此标签库的 JAR 文件必须只是包含在您的 WAR 文件中的 JAR 文件,否则将无法检测到标签库。

然后将你的 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 的所有属性。但我真的不认为值得付出努力。

【讨论】:

  • 你能给我举个同样的例子吗?
  • 您能否提供相同的工作示例。我没有得到你想说的。但根据您的解释,这似乎是正确的方式。
  • 感谢您的解决方案,将我的 100 赏金奖励给您,并继续提供帮助。
【解决方案2】:

我实际上已经做了与您所要求的类似的事情。我们有许多项目必须具有相同的设计、可用性和易于维护性。 因为我们使用 Spring MVC,所以我的一些标签是 spring 表单标签的包装器。例如输入标签:

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 和其他标签。 在一个非常大的项目中,我认为值得投资,因为它易于维护。

【讨论】:

  • 如果要扩展整个spring标签库怎么办?
  • 这也可以。在这种情况下,您不再依赖于 spring 的标签,并且可以轻松地将标签的实现更改为依赖于其他一些 taglib。我基本上为几乎所有的弹簧标签制作了包装器。我的想法是让复合标签比 Spring 的工作多一点。例如,我的输入标签制作了一个标签并打印了错误代码,并将工作委托给了 spring 的输入标签。
  • 你能提供你的示例项目吗?如果可能的话
  • 好的,我怎么发给你?我应该给你发电子邮件吗?
  • 是的,您可以通过 bhavik.ambani@yahoo.in 给我发邮件。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

    • 但正如我所说,我想为我的自定义标签库继承该标签库。我该怎么做?
    猜你喜欢
    • 2012-01-24
    • 1970-01-01
    • 2011-04-19
    • 2011-02-01
    • 1970-01-01
    • 2016-11-26
    • 2014-05-11
    • 1970-01-01
    • 2011-07-08
    相关资源
    最近更新 更多