自定义标签

来源:互联网 发布:米卡有软件 编辑:程序博客网 时间:2024/06/14 05:08
一、概述
我们在进行javaweb开发时,jsp页面上经常会用到jstl标签和structs标签,但是有时候这些标签并不能满足我们的要求,这个时候就需要或者可以通过自定义标签的方式来满足我们要实现的功能。

二、自定义标签的组成
自定义标签一般由三部分组成,准确的说是两部分,第三部分是我们在jsp页面中引用我们自定义的标签,然后使用。
  1. 标签的处理程序(Java类)
  2. tld文件:标签的描述符文件(.tld文件要放在和web.xml同一级目录下)
  3. 引用标签,使用taglib引入到jsp中

三、自定义标签的作用
  1. 使我们的Java代码和JSP页面彻底分离
  2. 还可以使我们的代码更安全(页面中没有算法、商业业务逻辑等)
  3. 提供了可重用的功能组件

四、标签处理程序的编写


标签处理程序必须实现接口或者继承类,实现Tag和BodyTag接口可以自定义带有标签体和属性的标签,实现SimpleTag接口只能自定义最简单的标签(没有标签体,也没有属性)。而TagSupport、BodyTagSupport、SimpleTagSupport类正好是Tag、BodyTag、SimpleTag接口的实现类。


五、几个简单的例子
示例1:没有标签体,也没有属性
//标签处理程序
packagecom.wangyi.tag;
importjava.io.IOException;
importjavax.servlet.jsp.JspContext;
importjavax.servlet.jsp.JspException;
importjavax.servlet.jsp.JspWriter;
importjavax.servlet.jsp.PageContext;
importjavax.servlet.jsp.tagext.SimpleTagSupport;
/**
 * 自定义标签1:没有标签体,也没有属性
 */
publicclassWelcomeTag extends SimpleTagSupport {
      /*
       * 当jsp页面执行该标签处理程序所指定的标签的时候,执行该方法
       */
      @Override
   publicvoid doTag() throws JspException, IOException {
            //获得当前jsp页面的上下文对象
            JspContextjc= this.getJspContext();
            //获得该jsp页面上下文对象的输出流
            JspWriterout= jc.getOut();
            //获得session中的user属性
            Objectobj= jc.getAttribute("user",PageContext.SESSION_SCOPE);
            if(obj!=null){//如果session中存在user属性
                  out.println("成功!");
            }else{//如果不存在
                  out.println("<a href=''>登录</a>");
            }     
    }
      
}

//标签的描述符文件文件(.tld文件)
<?xmlversion="1.0"encoding="UTF-8"?>
<taglibxmlns="http://java.sun.com/xml/ns/j2ee";
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2eehttp://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd";
 version="2.0">
   
 <description>welcomeTag</description>
 <display-name>welcomeTag</display-name>
 <tlib-version>1.0</tlib-version>
 <!-- 指定标签库默认的前缀名(prefix) -->
 <short-name>wt</short-name>
 <!-- 在jsp页面中引入该标签的url-->
 <uri>http://www.wangyi.com/welcome</uri>
  <!-- 一个.tld中可以定义多个tag,一个tag代表一个标签 -->
 <tag>
      <!-- 标签的名称 -->
      <name>welcomeTag</name>
      <!-- 标签处理程序类 -->
      <tag-class>com.wangyi.tag.WelcomeTag</tag-class>
      <!-- 设定标签间的主体(body)内容形式
            只有三种值:
               jsp:表示标签间可有主体内容
                empty:表示标签间不能有主体内容
               Tagdependent:表示标签间主体内容由标签自行处理
       -->
      <body-content>empty</body-content>
 </tag>
</taglib>

示例2:有标签体,但是没有属性
//标签处理程序
packagecom.wangyi.tag;
importjava.io.IOException;
importjavax.servlet.jsp.JspException;
importjavax.servlet.jsp.JspWriter;
importjavax.servlet.jsp.tagext.BodyContent;
importjavax.servlet.jsp.tagext.BodyTagSupport;
/**
 * 自定义标签2:有标签体,但没有属性
 */
publicclassTestTag extends BodyTagSupport {
      /**
       * 当jsp页面执行到某个标签结束的时候,执行该方法处理标签体的内容
       */
      @Override
      publicintdoAfterBody() throws JspException {
            //获得该标签的标签体
            BodyContentbc= this.getBodyContent();
            //获得该标签的标签体的输出流
            JspWriterout= bc.getEnclosingWriter();
            //获得标签体的内容
            Stringcontent= bc.getString();
            try{
                  out.println(content.toUpperCase());
            }catch(IOException e) {
                  e.printStackTrace();
            }
            returnthis.EVAL_PAGE;//该返回值告诉jsp页面,这个标签执行完毕,可以去执行页面中的其他标签了
      }
      
      
}

//标签的描述符文件文件(.tld文件)
 <tag>
      <name>testTag</name>
      <tag-class>com.wangyi.tag.TestTag</tag-class>
      <body-content>JSP</body-content>
 </tag>

//页面:
<%@pagelanguage="java"contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!-- 引入自定义标签 -->
<%@tagliburi="http://www.wangyi.com/welcome";prefix="wt"%>
<!DOCTYPEhtmlPUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd";>
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
<title>自定义标签1</title>
</head>
<body>
      自定义标签1:<wt:welcomeTag/>
      <br>
      自定义标签2:<wt:testTag>this is second custom tag.</wt:testTag>
</body>
</html>

示例3:通用的分页标签

//标签处理程序
packagecom.wangyi.tag;
importjava.io.IOException;
importjava.text.MessageFormat;
importjavax.servlet.jsp.JspException;
importjavax.servlet.jsp.JspWriter;
importjavax.servlet.jsp.tagext.TagSupport;
/**
 * 自定义分页标签
 */
publicclassPageTag extends TagSupport {
      
      privateintnowPage = 1; //当前页
      privateintpageSize = 4; //分页大小
      privateintcount = 0;  //总记录数
      privateStringurl;     //访问url
      
      publicintgetNowPage() {
            returnnowPage;
      }
      publicvoidsetNowPage(intnowPage) {
            this.nowPage=nowPage;
      }
      publicintgetPageSize() {
            returnpageSize;
      }
      publicvoidsetPageSize(intpageSize) {
            this.pageSize=pageSize;
      }
      publicintgetCount() {
            returncount;
      }
      publicvoidsetCount(intcount) {
            this.count=count;
      }
      publicString getUrl() {
            returnurl;
      }
      publicvoidsetUrl(String url) {
            this.url=url;
      }
      
      /**
       * 当jsp页面遇到了分页标签的时候执行该方法。
       * 这个标签一定是有属性的,这些属性就是给我们这个类的属性赋值(通过反射调用setter方法)
       */
      @Override
      publicintdoStartTag() throws JspException {
            //总页数的计算
            intallPage= count%pageSize== 0 ? count/pageSize:count/pageSize+ 1;
            
            //特殊当前页处理
            if(nowPage<= 1){
                  nowPage= 1;
            }
            
            if(nowPage>=allPage){
                  nowPage=allPage;
            }
            
            //超链接的模板,第一个占位{0}:访问url,第二个占位{1}:当前页,第三个占位{2}:该链接的显示文字
            Stringlink= "<a href=''{0}?page={1}''>{2}</a>";
            
            //MessageFormat.format()方法:第一个参数是字符串模板,其他参数均为字符串模板中需要填充的占位
            //首页
            Stringfirst= MessageFormat.format(link,url,"1","首页");
            //上一页
            Stringup= "上一页";
            if(nowPage>  1){
                  up= MessageFormat.format(link,url,nowPage-1+"","上一页");
            }
            
            //下一页
            Stringnext= "下一页";
            if(nowPage<allPage){
                  next= MessageFormat.format(link,url,nowPage+1+"","下一页");
            }
            
            //尾页
            Stringlast= MessageFormat.format(link,url,allPage+"","尾页");
            
            //htmlString:在jsp页面上显示的分页块元素
            StringhtmlString= "{0} {1} {2} {3}&nbsp;&nbsp;&nbsp;&nbsp;共{4}页,第{5}页,分页单位:{6},共{7}条";
            htmlString= MessageFormat.format(htmlString,first,up,next,last,allPage+"",nowPage+"",pageSize+"",count);
            
            //将htmlString输出到页面中
            JspWriterout= this.pageContext.getOut();
            try{
                  out.println(htmlString);
            }catch(IOException e) {
                  e.printStackTrace();
            }
            
            returnthis.EVAL_PAGE;////该返回值告诉jsp页面,这个标签执行完毕,可以去执行页面中的其他标签了
      }
}

//标签的描述符文件文件(.tld文件)
<?xmlversion="1.0"encoding="UTF-8"?>
<taglibxmlns="http://java.sun.com/xml/ns/j2ee";
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2eehttp://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd";
 version="2.0">
   
 <description>welcomeTag</description>
 <display-name>welcomeTag</display-name>
 <tlib-version>1.0</tlib-version>
 <!-- 指定标签库默认的前缀名(prefix) -->
 <short-name>wt</short-name>
 <!-- 在jsp页面中引入该标签的url,也可以不写该元素,然后通过引入该tld文件的方式来引入该tld里面的标签 -->
 <!--<uri>http://www.wangyi.com/page</uri>; -->
 <tag>
      <name>page</name>
      <tag-class>com.wangyi.tag.PageTag</tag-class>
      <body-content>empty</body-content>
      
      <!-- 定义标签体的属性 -->
      <attribute>
            <name>nowPage</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
      </attribute>
      <attribute>
            <name>pageSize</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
      </attribute>
      <attribute>
            <name>count</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
      </attribute>
      <attribute>
            <name>url</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
      </attribute>
 </tag>
</taglib>

//页面:
<%@pagelanguage="java"contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@tagliburi="http://java.sun.com/jstl/core_rt";prefix="c"%>
<!-- 引入自定义标签,采用tld文件中url的方式 -->
<%@tagliburi="http://www.wangyi.com/welcome";prefix="wt"%>
<!-- 引入自定义标签,采用直接引入标签描述符文件(.tld文件)的方式 -->
<%@tagliburi="/WEB-INF/pageTag.tld" prefix="p"%>
<!DOCTYPEhtmlPUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd";>
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
<title>自定义标签1</title>
</head>
<body>
      自定义标签1:<wt:welcomeTag/>
      <br>
      自定义标签2:<wt:testTag>this is second custom tag.</wt:testTag>
      <br>
      自定义标签3:<p:pagepageSize="5"url="UserServlet"count="16"nowPage="1"/>
</body>
</html>

示例1、示例2、示例3结果: