DDR爱好者之家 Design By 杰米

JSP 自定义标签实现数据字典的实例

 1.关于JSP标签的好处就不再罗嗦

数据字典就是使用的下拉框,只要定义使用那个字典就会将这个字典可用的内容显示出来

显示字典时只要定义那个字典和属性值就可以显示出字典的显示值 

2.首先在web.xml中定义自定义标签加载的引用,两个属性分别是引用的URI和加载路径 



<"1.0" encoding="UTF-8""2.5" xmlns="http://java.sun.com/xml/ns/javaee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 
  <welcome-file-list> 
    <welcome-file>index.jsp</welcome-file> 
  </welcome-file-list> 
  <jsp-config> 
    <taglib> 
      <taglib-uri>/tld/web-html</taglib-uri> 
      <taglib-location> 
        /WEB-INF/tlds/web-html.tld 
      </taglib-location> 
    </taglib> 
  </jsp-config> 
</web-app> 

 3.在web-html.tld中定义自己的标签,数据字典应用的话我们需要一个标签库,三个标签。分别是,select标签,options标签,和现实数据字典的标签,每个标签都对应不同的实现类

<"1.0" encoding="UTF-8""-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"  
  "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> 
<taglib> 
  <tlib-version>1.0</tlib-version><!-- 标签库版本 --> 
  <jsp-version>1.2</jsp-version> <!-- 标签库要求的JSP规范版本 --> 
  <short-name>html</short-name>  <!-- JSP页面编写工具可以用来创建助记名的可选名字 --> 
  <tag> 
    <name>select</name> 
    <tag-class>com.SelectTag</tag-class> 
    <body-content>JSP</body-content> 
    <attribute> 
      <name>name</name> 
      <rtexprvalue>true</rtexprvalue> 
    </attribute> 
    <attribute> 
      <name>style</name> 
      <rtexprvalue>true</rtexprvalue> 
    </attribute> 
  </tag> 
  <tag> 
    <name>options</name> 
    <tag-class>com.OptionsTag</tag-class> 
    <body-content>JSP</body-content> 
    <attribute> 
      <name>collection</name> 
      <rtexprvalue>true</rtexprvalue> 
    </attribute> 
  </tag> 
  <tag> 
    <name>selectDisplay</name> 
    <tag-class>com.SelectDisplay</tag-class> 
    <body-content>JSP</body-content> 
    <attribute> 
      <name>collection</name> 
      <rtexprvalue>true</rtexprvalue> 
    </attribute> 
    <attribute> 
      <name>name</name> 
      <rtexprvalue>true</rtexprvalue> 
    </attribute> 
    <attribute> 
      <name>value</name> 
      <rtexprvalue>true</rtexprvalue> 
    </attribute> 
  </tag> 
</taglib> 
 
 
 

 4.实现类

实现类的作用就是在后台拼接所需HTML标签内容,然后由JSP进行输出

实现类最主要的两个方法,一个遇到这个标签开始时输出,一个是结束时输出

如果需要定义属性,可以参考实现类定义属性,并在TLD中定义,在JSP中使用标签时快捷键就可以出来这个属性

首先是select标签的代码:

package com; 
import java.io.IOException; 
import javax.servlet.jsp.JspException; 
import javax.servlet.jsp.JspTagException; 
import javax.servlet.jsp.tagext.BodyTagSupport; 
/** 
 * TagSupport与BodyTagSupport的区别: 
 * 主要看标签处理类是否要读取标签体的内容和改变标签体返回的内容,如果不需要就用TagSupport,否则就用BodyTagSupport 
 * 用TagSupport实现的标签,都可以用BodyTagSupport来实现,因为BodyTagSupport继承了TagSupport 
 */ 
@SuppressWarnings("serial") 
public class SelectTag extends BodyTagSupport { 
  @Override 
  public int doStartTag() throws JspException { 
    try { 
      StringBuffer results = new StringBuffer("<select"); 
      if(name != null){ 
        results.append(" name=\""); 
        results.append(name); 
        results.append("\""); 
      } 
      if(style != null){ 
        results.append(" style=\""); 
        results.append(style); 
        results.append("\""); 
      } 
      results.append(">"); 
      pageContext.getOut().write(results.toString()); 
    } catch (IOException ex) { 
      throw new JspTagException("错误"); 
    } 
    return EVAL_BODY_INCLUDE; 
  } 
  @Override 
  public int doEndTag() throws JspException { 
    try { 
      StringBuffer results = new StringBuffer(""); 
      // 因为下拉中包含下拉内容,所以只能在遇到结束标签时才能写select结束 
      results.append("</select>");      
      pageContext.getOut().write(results.toString()); 
    } catch (IOException ex) { 
      throw new JspTagException("错误"); 
    } 
    return EVAL_PAGE; 
  } 
  // 样式 
  protected String style; 
  // 名字 
  protected String name; 
  public String getStyle() { 
    return style; 
  } 
  public void setStyle(String style) { 
    this.style = style; 
  } 
  public String getName() { 
    return name; 
  } 
  public void setName(String name) { 
    this.name = name; 
  }   
  /** 
  doStartTag()方法是遇到标签开始时会呼叫的方法,其合法的返回值是EVAL_BODY_INCLUDE与SKIP_BODY,前者表示将显示标签间的文字,后者表示不显示标签间的文字 
  doEndTag()方法是在遇到标签结束时呼叫的方法,其合法的返回值是EVAL_PAGE与SKIP_PAGE,前者表示处理完标签后继续执行以下的JSP网页,后者是表示不处理接下来的JSP网页 
  doAfterBody(),这个方法是在显示完标签间文字之后呼叫的,其返回值有EVAL_BODY_AGAIN与SKIP_BODY,前者会再显示一次标签间的文字,后者则继续执行标签处理的下一步 
  EVAL_BODY_INCLUDE:把Body读入存在的输出流中,doStartTag()函数可用 
  EVAL_PAGE:继续处理页面,doEndTag()函数可用 
  SKIP_BODY:忽略对Body的处理,doStartTag()和doAfterBody()函数可用 
  SKIP_PAGE:忽略对余下页面的处理,doEndTag()函数可用 
  EVAL_BODY_BUFFERED:申请缓冲区,由setBodyContent()函数得到的BodyContent对象来处理tag的body,如果类实现了BodyTag,那么doStartTag()可用,否则非法 
  EVAL_BODY_AGAIN:请求继续处理body,返回自doAfterBody(),这个返回值在你制作循环tag的时候是很有用的  
  预定的处理顺序是:doStartTag()返回SKIP_BODY,doAfterBodyTag()返回SKIP_BODY,doEndTag()返回EVAL_PAGE 
  如果继承了TagSupport之后,如果没有改写任何的方法,标签处理的执行顺序是:doStartTag() ->不显示文字 ->doEndTag()->执行接下来的网页 
  如果您改写了doStartTag(),则必须指定返回值, 
  如果指定了EVAL_BODY_INCLUDE,则执行顺序是:doStartTag()->显示文字->doAfterBodyTag()->doEndTag()->执行下面的网页 
   */ 
} 

关于返回参数,返回具体数字也可以,不用过于纠结

然后是下拉内容实现类

package com; 
import java.io.IOException; 
import javax.servlet.jsp.JspException; 
import javax.servlet.jsp.JspTagException; 
import javax.servlet.jsp.tagext.BodyTagSupport; 
@SuppressWarnings("serial") 
public class OptionsTag extends BodyTagSupport { 
  @Override 
  public int doStartTag() throws JspException { 
    return EVAL_BODY_INCLUDE; 
  } 
  @Override 
  public int doEndTag() throws JspException { 
    try { 
      StringBuffer results = new StringBuffer(""); 
      if ("SEX".equals(collection)) { 
        results.append("<option value=\"0\" selected=\"selected\">请选择</option>"); 
        results.append("<option value=\"1\">男</option>"); 
        results.append("<option value=\"2\">女</option>"); 
      } 
      pageContext.getOut().write(results.toString()); 
    } catch (IOException ex) { 
      throw new JspTagException("错误"); 
    } 
    return EVAL_PAGE; 
  } 
  // collection只是传递一个标识,具体下拉值内容是从数据库取还是从请求中得到为不同具体实现 
  protected String collection; 
  public String getCollection() { 
    return collection; 
  } 
  public void setCollection(String collection) { 
    this.collection = collection; 
  } 
} 

 具体你的字典数据从数据库中如何存储如何查询,可以自定义实现

显示的标签实现,为了将来可以在页面取到标签内容值,我们定义隐藏域来保存属性值,然后在显示显示内容


package com; 
import java.io.IOException; 
import javax.servlet.jsp.JspException; 
import javax.servlet.jsp.JspTagException; 
import javax.servlet.jsp.tagext.BodyTagSupport; 
@SuppressWarnings("serial") 
public class SelectDisplay extends BodyTagSupport { 
  @Override 
  public int doStartTag() throws JspException { 
    try { 
      StringBuffer results = new StringBuffer(""); 
      pageContext.getOut().write(results.toString()); 
    } catch (IOException ex) { 
      throw new JspTagException("错误"); 
    } 
    return EVAL_BODY_INCLUDE; 
  } 
  @Override 
  public int doEndTag() throws JspException { 
    try { 
      StringBuffer results = new StringBuffer(""); 
      if ("SEX".equals(collection)) { 
        results.append("<span>"); 
        results.append("<input type=\""); 
        results.append("hidden\" name=\""); 
        results.append(getName()); 
        results.append("\""); 
        results.append(" value=\""); 
        results.append(getValue()); 
        results.append("\">");         
        if ("1".equals(getValue())) { 
          results.append("男"); 
        } else if ("2".equals(getValue())) { 
          results.append("女"); 
        } else { 
          results.append("请选择"); 
        } 
        results.append("</span>"); 
      } 
      pageContext.getOut().write(results.toString()); 
    } catch (IOException ex) { 
      throw new JspTagException("错误"); 
    } 
    return EVAL_PAGE; 
  } 
  // collection只是传递一个标识,具体下拉值内容是从数据库取还是从请求中得到为不同具体实现 
  protected String collection; 
  // 传递的值 
  protected String value; 
  // 该属性的名称 
  protected String name; 
  public String getCollection() { 
    return collection; 
  } 
  public void setCollection(String collection) { 
    this.collection = collection; 
  } 
  public String getName() { 
    return name; 
  } 
  public void setName(String name) { 
    this.name = name; 
  } 
  public String getValue() { 
    return value; 
  } 
  public void setValue(String value) { 
    this.value = value; 
  } 
} 
 
 
 

5.JSP中引用,直接在index.jsp中引用

需要引入相应的标签内容,引入的方式在JSP头部引用

标签的属性可以设置也可以不设置,标签的使用和HTML标签的使用是一样的,定义属性即可

<%@ page language="java" pageEncoding="UTF-8"%> 
<%@ taglib uri="/tld/web-html" prefix="html"%> 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html> 
  <head> 
    <title>JSP 自定义标签的实现</title> 
  </head> 
  <body> 
    请选择: 
    <html:select name="sex" style="width:100px"> 
      <html:options collection="SEX"></html:options> 
    </html:select> 
    显示性别: 
    <html:selectDisplay collection="SEX" value="1" name="sex"></html:selectDisplay>    
  </body> 
</html> 
 

 6.后话

访问项目就可以看到效果,附件是这个项目的源代码,导入到MyEclipse中可以查看

如果想要自己设计一个大的标签库,可以设计一个父类,包含一些主要的属性,例如name,id,style等属性。然后在子类中定义自己的特有属性

这个实现只是学习一下JSP自定义标签使用的HelloWorld程序,然后包含了字典应用的实际例子,程序简单,仅供参考

 如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

DDR爱好者之家 Design By 杰米
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
DDR爱好者之家 Design By 杰米

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。