实现自定义select标签

  我们经常会遇到这种场景:

    假设项目中有一个分类对象,类似数据字典,一个code对应一个name。这个在页面作为一个过滤条件:选择分类。一般做法是在jsp页面直接写select标签,用option在页面

做判断。比如:

<label>选择分类:
                    <select id="levelClassSelect" name="classCode"
                            class="form-control  input-small  input-sm input-inline"
                            >
                        <option value="-1" <c:if test="${searchParam.classCode==-1}"> selected="selected" </c:if>>全部
                        </option>
                        <c:forEach items="${levelClassDtoList}" var="v_levelClass">
                            <option value="${v_levelClass.code}"
                                    <c:if test="${v_levelClass.id==searchParam.classCode}">selected="selected" </c:if>>${v_levelClass.name}</option>
                        </c:forEach>
                    </select>
                </label>
这样操作我们需要在后台Controller中查询放置levelClassDtoList对象,页面写这样一个select标签。如果这个标签是在多个页面使用,那么我们每个页面都需要复制一份,每个页面对应的后台Controller中也要查询放置一份levelClassDtoList对象。这样就重复做事情,而且一旦有变动,需要改很多地方,费时,还容易出错。所有我们就想到可不可把这个自定义成一个标签,多处使用?方便我们使用和后期维护。可以的。结合自己的项目,需要以下4个步骤:

  1. 定义java的tag类:LevelCodeTag

    采用继承org.springframework.web.servlet.tags.RequestContextAwareTag

    RequestContextAwareTag类是一个abstract修饰的抽象类,有一个protected级别的抽象方法,子类需要实现这个方法,将自己需要的数据放入pageContext对象中即可。
    public abstract class RequestContextAwareTag extends TagSupport implements TryCatchFinally {
    ...//省略部分代码
    	/**
    	 * Called by doStartTag to perform the actual work.
    	 * @return same as TagSupport.doStartTag
    	 * @throws Exception any exception, any checked one other than
    	 * a JspException gets wrapped in a JspException by doStartTag
    	 * @see javax.servlet.jsp.tagext.TagSupport#doStartTag
    	 */
    	protected abstract int doStartTagInternal() throws Exception;
    ...//省略部分代码
    }
    
    
    
    LevelCodeTag:
    public class LevelCodeTag extends RequestContextAwareTag {
        @Override
        protected int doStartTagInternal() throws Exception {
           //通过注入spring的levelClassService.findAll()方法得到数据库的所有levelCode对象,并放置在pageContext对象中。
            ILevelClassService levelClassService=getBean("levelClassService");
            pageContext.setAttribute("levelCodeList", levelClassService.findAll());
            return 0;
        }
    private WebApplicationContext wac;
    
        /**
         * 从web应用上下文中,根据注册的beanName获取对象
         * @param beanName spring 管理的beanName
         * @param <T>
         * @return
         */
        @SuppressWarnings("unchecked")
        protected <T> T getBean(String beanName) {
            if (wac == null) {
                wac = getRequestContext().getWebApplicationContext();
            }
            return (T) wac.getBean(beanName);
        }
    }


  2. 定义tld文件
    这个文件是放置在WEB-INF目录下yq_fn.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">
    
    
        <tlib-version>1.1</tlib-version><!--版本号-->
        <short-name>yq_fn</short-name><!--后面引用的短名称-->
        <uri>http://www.wangan.com/media/tag</uri><!--定义uri,便于后面引用定位-->
        <tag>
            <name>listLevelCode</name><!--名字-->
            <tag-class>com.wangan.media.tag.LevelCodeTag</tag-class><!--指向步骤1中定义的java的tag类-->
            <body-content>empty</body-content><!--使用empty即可-->
        </tag>
        
    </taglib>
  3. 定义tag标签文件
    定义了tld文件,我们就可以通过tld文件得到javatag中的levelCodeList对象,定义levelCode.tag文件,这个文件和步骤2中的yq_fn.tld文件在同一目录下。
    <%@tag pageEncoding="utf-8" %><!--定义编码,防止乱码 -->
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><!--引入c标签-->
    <%@taglib prefix="yq" uri="http://www.wangan.com/media/tag" %><!--  引入步骤2中我们自定义的tld文件,定义前缀为yq(这个可以根据自己项目任意定义),uri值是tld文件中的uri值-->
    <!-- 下面定义这个select标签需要的属性字段-->
    <%@attribute name="levelName" required="true" type="java.lang.String"  rtexprvalue="true"%><!--name:属性的名字,required:使用这个标签时候,本属性是否必须的;type:这个属性值的类型;rtexprvalue:这个标签是否支持el表达式,我们设置为true,支持表达式,这样就可以在引用时候动态设置值-->
    <%@attribute name="levelCode" required="true"   rtexprvalue="true"%>
    <%@attribute name="selectId" required="true" rtexprvalue="true" %>
    <yq:listLevelCode/><!--引入文件2中订阅的listLevelCode,就相当于引入了步骤一中的java代码,这样我们就能访问步骤一中定义的levelCodeList对象。yq就是第三行定义的前缀,liestLevelCode就是步骤2中定义的name值-->
    
    <!--下面就是动态定义我们的select标签了,class值是我项目中使用到的,请忽略-->
    <select class="form-control input-small input-sm input-inline"  id="${selectId}" name="${levelName}">
        <option value="0" <c:if test="${levelCode ==0}"> selected="selected" </c:if>>全部</option>
        <c:forEach items="${levelCodeList}" var="v_level" >
            <option value="${v_level.code}"
                    <c:if test="${v_level.code== levelCode}"> selected="selected" </c:if>>${v_level.name}</option>
        </c:forEach>
    </select>


  4. web.xml中配置tld文件
    将步骤2中定义的tld文件交给项目管理
     <jsp-config>
            <taglib>
                <taglib-uri>http://www.wangan.com/media/tag</taglib-uri><!--这个地址就是步骤2中的uri值-->
                <taglib-location>/WEB-INF/tags/yq_fn.tld</taglib-location><!--这个值就是步骤2中定义的tld文件的路径-->
            </taglib>
        </jsp-config>

  5. jsp使用自定义标签
    <%@ taglib prefix="yq" tagdir="/WEB-INF/tags" %><!--引入步骤3中自定义的标签-->
    <label>选择分类:
                <yq:levelCode selectId="levelClassCode" levelName="levelClassCode" levelCode="${levelClassCode}"/>
    <!--yq就是引入的时定义的前缀,levelCode就是引入是tagdir目录下的*.tag文件的名字。我们要引入步骤3中定义的levelCode.tag标签。levelCode属性是页面用el表达式动态获取-->
    </label>

  6. 页面效果

    总结:几个简单步骤后,我们就实现了一次定义,随意使用的效果。以后每次使用就按照步骤5引用就可以了。这样我们关于levelCode对象的值都没有在页面写死,以后需要修改这个对象数据,我们直接修改库的字典就可。最开始,由于项目时间要求,本人是直接在页面对select标签写死value和name的,后面项目需要扩展,增加分类,此时就需要修改多出页面和数据库,由于后面也有多余的时间,则抽取出来成标签,以后再需要修改,就直接修改数据库字典即可。


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值