我们在开发中经常用到标签,特别是struts的标签库都那么强大。
那在我们平时的开发总偶尔也会用到一些特定的标签可以用来简化工作。
首先我们新建一个类继承SimpleTagSupport或实现SimpleTag接口。在jsp2.0后是这样,之前可以继承TagSupport类。这里主要说的jsp2.0后的定义方法。
在类中我们主要是要重写doTag()方法。这个方法中就是你定义的标签主要要做的事情。
然后定义标签要用到的属性,这个定义就像javabean定义样,jsp引擎会自动把标签定义的属性设置进来。
最后就在WEB-INF 文件下新建一个 .tld 的文件,该文件主要是对该标签及其属性的定义和描述。可以在struts包和JSTL包中找到定义模板。
下边是自己学习写的几个标签:
1、数字格式化标签代码
public class NumberForm extends SimpleTagSupport{
private boolean fill;//不够是否填充
private int decimal;//小数位数 这里有int的原因是及时不输入默认的也是0 而Integer默认是null
private double var;//要格式化的数 这里也一样不用封装类型,而用基本类型
public void setFill(boolean fill) {
this.fill = fill;
}
public void setDecimal(int decimal) {
this.decimal = decimal;
}
public void setVar(double var) {
this.var = var;
}
@Override
public void doTag() throws JspException, IOException {
String ff=fill?"0":"#";//0不够位的用0补齐
StringBuilder sb=new StringBuilder("");
for(int i=0;i<decimal;i++){
sb.append(ff);
}
if(sb.length()>0){
sb.insert(0, ".");
}else{
sb.append("0");
}
DecimalFormat df = new DecimalFormat(sb.toString());
getJspContext().getOut().print(df.format(var));
}
}
2、if条件判断标签代码
public class MyIf extends SimpleTagSupport {
private boolean test;
private String var;
public void setTest(boolean test) {
this.test = test;
}
public void setVar(String var) {
this.var = var;
}
@Override
public void doTag() throws JspException, IOException {
if(var!=null&&!"".equals(var)){
getJspContext().setAttribute(var, this.test);
}
if(test){
getJspBody().invoke(getJspContext().getOut());
}
}
}
3、 for 循环标签代码
public class ForEach extends SimpleTagSupport {
private Integer begin;
private Integer end;
private Integer step;
private String var;
private String varStarus;
private Object items;
public void setBegin(Integer begin) {
this.begin = begin;
}
public void setEnd(Integer end) {
this.end = end;
}
public void setStep(Integer step) {
this.step = step;
}
public void setVar(String var) {
this.var = var;
}
public void setVarStarus(String varStarus) {
this.varStarus = varStarus;
}
public void setItems(Object items) {
this.items = items;
}
public void doTag() throws JspException, IOException {
if(items==null){
numEach();
}else{
setItem();
}
}
//数字的循环
private void numEach() throws JspException, IOException{
if(this.begin!=null&&this.end!=null){
this.step=this.step==null?1:this.step;
ForEachElement element=new ForEachElement();
int n=0;
for(int i=this.begin;i<this.end;i=i+this.step){
element.setIndex(n++);
if(var!=null&&!"".equals(var)){
//获取jspcontext对象 jsp页面中本来就有这个对象
getJspContext().setAttribute(var,i);
}
if(varStarus!=null&&!"".equals(varStarus)){
getJspContext().setAttribute(varStarus, element);
}
//获取标签体中的内容并执行(写入到一个流中)
getJspBody().invoke(getJspContext().getOut());
}
}
}
//item对象循环
@SuppressWarnings("unchecked")
private void setItem() throws JspException, IOException{
if(this.items instanceof Collection){
ForEachElement element=new ForEachElement();
Collection<Object> coll=(Collection<Object>)this.items;
Iterator<Object> it=coll.iterator();
for(int i=0;i<coll.size()&&it.hasNext();i++){
element.setIndex(i);
if(var!=null&&!"".equals(var)){
getJspContext().setAttribute(var, it.next());
}
if(varStarus!=null&&!"".equals(varStarus)){
getJspContext().setAttribute(varStarus, element);
}
getJspBody().invoke(getJspContext().getOut());
}
}else if(this.items instanceof Map){
ForEachElement element=new ForEachElement();
ForEachMap eachMap=new ForEachMap();
Map<String, Object> map=(Map<String, Object>)this.items;
element.setCount(map.size());
int i=0;
for (Map.Entry<String, Object> set : map.entrySet()) {
element.setIndex(i++);
eachMap.setKey(set.getKey());
eachMap.setValue(set.getValue());
if(var!=null&&!"".equals(var)){
getJspContext().setAttribute(var, eachMap);
}
if(varStarus!=null&&!"".equals(varStarus)){
getJspContext().setAttribute(varStarus, element);
}
getJspBody().invoke(getJspContext().getOut());
}
}
}
}
//循环标签中应该有的基本属性
public class ForEachElement {
private int index;
private int count;
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
//当传入的item是map对象时 应对有的属性
public class ForEachMap {
private String key;
private Object value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
@Override
public String toString() {
return this.value==null?"":this.value.toString();
}
}
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>自定义标签</description>
<display-name>MY TAG</display-name>
<tlib-version>1.0</tlib-version>
<short-name>mytag</short-name>
<uri>http://cd.zhonghua.cn/mytag</uri>
<tag>
<description>
数值格式化标签
</description>
<name>numForm</name>
<!-- 标签对应处理的类 -->
<tag-class>cd.zhonghua.mytag.NumberForm</tag-class>
<body-content>empty</body-content>
<!--
empty 此标签式空标签 类似于html中的input的标签 直接在标签后用/ 结束 没有标签体
scriptless 标签体重的内容是支持EL表达式
tagdependent 标签体重的内容不支持EL表达式
标签体中不支持<%%>
-->
<attribute>
<description>
要格式化的数字
</description>
<name>var</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>double</type>
</attribute>
<attribute>
<description>
小数位数不够指定位数时是否用0填充,值为true或false
</description>
<name>fill</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>boolean</type>
</attribute>
<attribute>
<description>
指定小数位数
</description>
<name>decimal</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>int</type>
</attribute>
</tag>
<tag>
<description>
循环标签 如果items有值则以items为基准
</description>
<name>forEach</name>
<tag-class>cd.zhonghua.mytag.ForEach</tag-class>
<body-content>scriptless</body-content>
<attribute>
<description>
每次循环存入变量的名称
</description>
<name>var</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<description>
当前数的属性 第几个 总共多少个数
</description>
<name>varStarus</name>
<required>false</required>
<!-- 此属性是否支持表达式 -->
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<description>
循环数据源列表 Collection Map
</description>
<name>items</name>
<required>false</required>
<!-- 此属性是否支持表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<description>
循环开始数
</description>
<name>begin</name>
<required>false</required>
<!-- 此属性是否支持表达式 -->
<rtexprvalue>true</rtexprvalue>
<type>int</type>
</attribute>
<attribute>
<description>
循环结束数
</description>
<name>end</name>
<required>false</required>
<!-- 此属性是否支持表达式 -->
<rtexprvalue>true</rtexprvalue>
<type>int</type>
</attribute>
<attribute>
<description>
循环步长 默认值为1
</description>
<name>step</name>
<required>false</required>
<!-- 此属性是否支持表达式 -->
<rtexprvalue>true</rtexprvalue>
<type>int</type>
</attribute>
</tag>
<tag>
<description>
判断表达式
</description>
<name>if</name>
<tag-class>cd.zhonghua.mytag.MyIf</tag-class>
<body-content>scriptless</body-content>
<attribute>
<description>
条件表达式的值 true/false
</description>
<name>var</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<description>
条件表达式/[true|false]
</description>
<name>test</name>
<required>true</required>
<!-- 此属性是否支持表达式 -->
<rtexprvalue>true</rtexprvalue>
<type>boolean</type>
</attribute>
</tag>
</taglib>
个人理解还望多多指点