JavaWeb学习之JSTL自定义标签库的使用、JSTL自定义函数库(7)
一、自定义标签,步骤
* 确定需求
* <my:date /> 输出当前系统的时间 yyyy-MM-dd hh:mm:ss:SSS
* 编写Java类
新建包名:com.yxl.tag,新建类MyDateTag,实现SimpleTag接口
* 只要与此接口有关的实现类,javax.servlet.jsp.tagext.JspTag
* 需要实现具体的接口
* javax.servlet.jsp.tagext.SimpleTag,简单标签,JSP2.0**,选择这个
* javax.servlet.jsp.tagext.Tag,经典标签
package com.yxl.tag;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;
public class MyDateTag implements SimpleTag {
public MyDateTag(){
System.out.println("默认构造");
}
private PageContext pageContext;
/**
* 1、被调用的方法,tomcat调用
*/
public void setJspContext(JspContext pc) {
// System.out.println(pc);
// System.out.println("setJspContext");
this.pageContext = (PageContext) pc;
}
/**
* 2、tomcat调用
* 建议,在doTage方法中完成整个tag的功能
* 需要再doTage方法之前,完成准备工作
*/
public void doTag() throws JspException, IOException {
// System.out.println("doTag");
//输出当前系统的时间 yyyy-MM-dd hh:mm:ss:SSS
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS");
String date = format.format(new Date());
//将获得的时间输出到浏览器
this.pageContext.getOut().print(date);
}
@Override
public JspTag getParent() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setJspBody(JspFragment arg0) {
// TODO Auto-generated method stub
}
@Override
public void setParent(JspTag arg0) {
// TODO Auto-generated method stub
}
}
* 编写tld文件
在WEB-INF下新建文件夹tld,在tld文件夹下新建mytag.tld
* tld文件是xml文档
* 扩展名为*.tld
* 位置:必须放置到WEB-INF目录下
* 内容:
<taglib 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-jsptaglibrary_2_1.xsd"
version="2.1">
<!-- 确定当前标签库的版本 -->
<tlib-version>1.0</tlib-version>
<!-- 建议引入当前便签库是,使用的简写 @taglib prefix="my" -->
<short-name>my</short-name>
<!-- 为当前标签库配置文件,起一个名称
* 内容:自定义,全球唯一
-->
<uri>http://www.yxl.cn/jsp/mytag</uri>
<!-- <my:date / > 注册标签 -->
<tag>
<!-- 确定标签名称 -->
<name>date</name>
<!-- 确定实现类 -->
<tag-class>com.yxl.tag.MyDateTag</tag-class>
<!-- 格式化当前标签的body内容
* empty:当前标签没有标签体
-->
<body-content>empty</body-content>
</tag>
</taglib>
* 在JSP页面引入
* <%@ taglib uri="http://www.yxl.cn/jsp/mytag" prefix="my"%>
* 测试
* <my:date />
二、案例
* 需求:<my:maxVal num1="12" num2="13" />
package com.yxl.tag;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;
public class MyMaxValueTag implements SimpleTag {
public MyMaxValueTag() {
System.out.println("默认构造");
}
private PageContext pageContext;
private Integer num1;
private Integer num2;
// num1
public void setNum1(Integer num) {
this.num1 = num;
}
public void setNum2(Integer num) {
this.num2 = num;
}
/**
* 1、被调用的方法,tomcat调用
*/
public void setJspContext(JspContext pc) {
// System.out.println(pc);
// System.out.println("setJspContext");
this.pageContext = (PageContext) pc;
}
/**
* 2、tomcat调用 建议,在doTage方法中完成整个tag的功能 需要再doTage方法之前,完成准备工作
*/
public void doTag() throws JspException, IOException {
System.out.println(this.num1);
System.out.println(this.num2);
// 判断两个数据的大小,然后输出
if (this.num1 > this.num2) {
this.pageContext.getOut().print(num1 + "大于" + num2);
} else if (this.num1 < this.num2){
this.pageContext.getOut().print(num1 + "小于" + num2);
}
else{
this.pageContext.getOut().print(num1 + "等于" + num2);
}
}
@Override
public JspTag getParent() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setJspBody(JspFragment arg0) {
// TODO Auto-generated method stub
}
@Override
public void setParent(JspTag arg0) {
// TODO Auto-generated method stub
}
}
<taglib 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-jsptaglibrary_2_1.xsd"
version="2.1">
<!-- 确定当前标签库的版本 -->
<tlib-version>1.0</tlib-version>
<!-- 建议引入当前便签库是,使用的简写 @taglib prefix="my" -->
<short-name>my</short-name>
<!-- 为当前标签库配置文件,起一个名称 * 内容:自定义,全球唯一 -->
<uri>http://www.yxl.cn/jsp/mytag</uri>
<!-- <my:date / > 注册标签 -->
<tag>
<!-- 确定标签名称 -->
<name>date</name>
<!-- 确定实现类 -->
<tag-class>com.yxl.tag.MyDateTag</tag-class>
<!-- 格式化当前标签的body内容 * empty:当前标签没有标签体 -->
<body-content>empty</body-content>
</tag>
<!-- <my:maxValue / > 注册标签 -->
<tag>
<!-- 确定标签名称 -->
<name>maxValue</name>
<!-- 确定实现类 -->
<tag-class>com.yxl.tag.MyMaxValueTag</tag-class>
<!-- 格式化当前标签的body内容 * empty:当前标签没有标签体 -->
<body-content>empty</body-content>
<!-- 确定当前标签使用了哪些属性 -->
<attribute>
<!-- 设置属性名称 -->
<name>num1</name>
<!-- 设置属性是否必须 * true/false * yes/no -->
<required>true</required>
<!-- rtexprvalue 运行时表达式的值 * runtime expression value -->
<rtexprvalue>true</rtexprvalue>
<!-- 确定标签类型 -->
<type>java.lang.Integer</type>
</attribute>
<attribute>
<!-- 设置属性名称 -->
<name>num2</name>
<!-- 设置属性是否必须 * true/false * yes/no -->
<required>true</required>
<!-- rtexprvalue 运行时表达式的值 * runtime expression value -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
* 需求:<my:toUpperCase>xxYYdfsdDFwerd</my:toUpperCase>
标签体
package com.yxl.tag;
import java.io.IOException;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.JspTag;
import javax.servlet.jsp.tagext.SimpleTag;
public class MyToUpperCaseTag implements SimpleTag {
public MyToUpperCaseTag() {
System.out.println("默认构造");
}
private PageContext pageContext;
private JspFragment jspBody;
/**
* 1、被调用的方法,tomcat调用
*/
public void setJspContext(JspContext pc) {
this.pageContext = (PageContext) pc;
}
public void setJspBody(JspFragment jspBody){
this.jspBody = jspBody;
}
/**
* 2、tomcat调用 建议,在doTage方法中完成整个tag的功能 需要再doTage方法之前,完成准备工作
*/
public void doTag() throws JspException, IOException {
StringWriter stringWriter = new StringWriter();
this.jspBody.invoke(stringWriter);
String data = stringWriter.toString();
this.pageContext.getOut().print(data.toUpperCase());
}
@Override
public JspTag getParent() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setParent(JspTag arg0) {
// TODO Auto-generated method stub
}
}
<!-- <my:toUpperCase / > 转换为大写 -->
<tag>
<!-- 确定标签名称 -->
<name>toUpperCase</name>
<!-- 确定实现类 -->
<tag-class>com.yxl.tag.MyToUpperCaseTag</tag-class>
<!-- 格式化当前标签的body内容 * empty:当前标签没有标签体 -->
<!-- JSP:支持JSP所有的语法,在Tag中使用
scriptless:对于JSP页面的脚本不支持
tagdependent:标签体不做处理,原样输出 -->
<body-content>scriptless</body-content>
</tag>
<my:toUpperCase>abcd</my:toUpperCase>
* 需求:循环
使用extends SimpleTagSupport这种方式实现标签类,SimpleTagSupport已经实现了SimpleTag接口
三种循环遍历
<taglib 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-jsptaglibrary_2_1.xsd"
version="2.1">
<!-- 确定当前标签库的版本 -->
<tlib-version>1.0</tlib-version>
<!-- 建议引入当前便签库是,使用的简写 @taglib prefix="my" -->
<short-name>my</short-name>
<!-- 为当前标签库配置文件,起一个名称 * 内容:自定义,全球唯一 -->
<uri>http://www.yxl.cn/jsp/mytag</uri>
<!--
<my:myeach start="0" end="9" step="1" var="ss">
${ss} ** <br/>
</my:myeach>
-->
<tag>
<name>myeach</name>
<tag-class>com.yxl.tag.MyEachTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>start</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>end</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>step</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<!--
<my:myList items="${listObj}" var="yyyyy">
${yyyyy} ## <br/>
</my:myList>
-->
<tag>
<name>myList</name>
<tag-class>com.yxl.tag.MyListTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<name>forEach</name>
<tag-class>com.yxl.tag.ForEachTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
package com.yxl.tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class MyEachTag extends SimpleTagSupport{
/*
* <my:myeach start="0" end="9" step="1" var="ss">
${ss} ** <br/>
</my:myeach>
*/
private Integer start;
private Integer end;
private Integer step;
private String var;
public void setStart(Integer start) {
this.start = start;
}
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 doTag() throws JspException, IOException {
//完成功能:将获得的变量信息,输出到浏览器
for(int i = start ; i <= end ; i +=step){
//从父类中,获得pagecontext对象
this.getJspContext().setAttribute(var, i);
//将el表达式的结果发送到浏览器
// * el表达式的位置
// * 如何发送
this.getJspBody().invoke(null);
//this.getJspBody().invoke(this.getJspContext().getOut());
}
}
}
package com.yxl.tag;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class MyListTag extends SimpleTagSupport {
/*
<my:myList items="${listObj}" var="yyyyy">
${yyyyy} ## <br/>
</my:myList>
*/
private List items;
private String var;
public void setItems(List items) {
this.items = items;
}
public void setVar(String var) {
this.var = var;
}
@Override
public void doTag() throws JspException, IOException {
//完成功能:将获得的list信息遍历输出到浏览器
Iterator it = items.iterator();
while(it.hasNext()){
Object str = it.next();
//将结果放置到作用域
this.getJspContext().setAttribute(var, str);
//将el表达式的结果数据到浏览器
this.getJspBody().invoke(null);
}
}
}
package com.yxl.tag;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class ForEachTag extends SimpleTagSupport {
/*
<my:myList items="${listObj}" var="yyyyy">
${yyyyy} ## <br/>
</my:myList>
*/
private Iterator<Object> items;
private String var;
public void setItems(Object items) {
//list
if(items instanceof List){
this.items = ((List)items).iterator();
}
//map
if(items instanceof Map){
this.items = ((Map)items).entrySet().iterator();
}
//object[]
if(items instanceof Object[]){
this.items = Arrays.asList((Object[])items).iterator();
}
}
public void setVar(String var) {
this.var = var;
}
@Override
public void doTag() throws JspException, IOException {
//完成功能:将获得的list信息遍历输出到浏览器
while(items.hasNext()){
Object str = items.next();
//将结果放置到作用域
this.getJspContext().setAttribute(var, str);
//将el表达式的结果数据到浏览器
this.getJspBody().invoke(null);
}
}
}
<my:myeach start="0" end="9" step="1" var="eeee">
${eeee} ** <br/>
</my:myeach>
<%
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("123");
list.add("wasd");
pageContext.setAttribute("listObj",list);
%>
myList<br/>
<my:myList items="${listObj}" var="yyyyy">
${yyyyy} ## <br/>
</my:myList>
<my:forEach items="${listObj}" var="mm">
${mm} <br/>
</my:forEach>
<hr/>
<%
Map<String,String> map = new HashMap<String,String>();
map.put("11111","11111");
map.put("22222","222222");
map.put("33333","33333");
pageContext.setAttribute("mapObj",map);
%>
遍历Map<br/>
<my:forEach items="${mapObj}" var="map">
${map.key} ---- ${map.value} <br/>
</my:forEach>
三、自定义函数
* 创建类,但方法必须是静态的
package com.yxl.domain;
public class Calculator {
private String firstNum;
private String operator;
private String secondNum;
private String result;
public String getFirstNum() {
return firstNum;
}
public void setFirstNum(String firstNum) {
this.firstNum = firstNum;
}
public String getOperator() {
return operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
public String getSecondNum() {
return secondNum;
}
public void setSecondNum(String secondNum) {
this.secondNum = secondNum;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public Calculator() {
}
//计算方法
public static void calculator(Calculator cal){
//通过运算符,将firstNum和secondNum处理的结果,存放到result
double first = Double.valueOf(cal.firstNum);
double second = Double.valueOf(cal.secondNum);
char ope = cal.operator.charAt(0);
switch (ope) {
case '+':
cal.result = String.valueOf(first + second);
break;
case '-':
cal.result = String.valueOf(first - second);
break;
case '*':
cal.result = String.valueOf(first * second);
break;
case '/':
cal.result = String.valueOf(first / second);
break;
default:
throw new RuntimeException("非法操作符");
}
}
}
* 书写配置文件tld
新建myFun.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.0</tlib-version>
<short-name>myfn</short-name>
<uri>http://www.yxl.cn/mytag/functions</uri>
<!-- 确定当前函数 myfn:calculator(cal) -->
<function>
<name>calculator</name>
<function-class>com.yxl.domain.Calculator</function-class>
<!-- 当前使用函数的声明 public static void calculator(Calculator cal) -->
<function-signature>void calculator(com.yxl.domain.Calculator)</function-signature>
</function>
</taglib>
* 引用
* <%@ taglib uri="http://www.yxl.cn/mytag/functions" prefix="myFn" %>
* 测试
<jsp:useBean id="cal" class="com.yxl.domain.Calculator"></jsp:useBean>
<jsp:setProperty property="firstNum" value="1" name="cal"/>
<jsp:setProperty property="operator" value="+" name="cal"/>
<jsp:setProperty property="secondNum" value="4" name="cal"/>
${myFn:calculator(cal)}
${cal.result}
四、总结
* 共同点:
* 需要引入
* <%@ taglib uri="http://www.yxl.cn/mytag/myeach" prefix="my" %>
* 都需要配置tld文件
* 区别:
* 自定义标签
* 创建一个类,完成一个功能或一组功能。
* 可以选择el表达式
* 自定义函数
* 创建一个静态方法,完成一个操作。
* 必须与EL表达式结合使用
${fn:xxxx}