一、什么是标签
标记语言,是一种注释文本的语言,以便于计算机可以操作。很多与“ML”结尾的语言都是标记语言,比如:HTML,XML,XHTML,VML等等。标记语言与其他语言一样,也需要运行它们的环境,比如HTML的运行环境时浏览器,XML也要自己的解析和运行的环境。
基本结构:
<开始标签>标签体</结束标签>
<name>out</name>
空标签:
<开始标签 属性名="属性值"/></结束标签>
<action path="/studentAction" type="org.lisen.mvc.action.StudentAction"></action>
<开始标签 属性名="属性值"/>
<forward name="students" path="/students/studentList.jsp" redirect="false"/>
<br/><br/>
二、自定义标签
🔘JSP标签库是什么?
是一个JSP标签集合,它封装了JSP应用的通用核心功能, 基于JSP标签我们可以理解为,是JSP应该通用功能的一种封装方式。
🔘JSP自定义标签生命周期
实例化标签助手类之后就能调用doStartTag这个方法,随后查看这个方法的返回值,若这个返回值是EVAL_BODY_INCLUDE则说明其有标签体需要继续处理重新定义一个方法doAfterBody,查看该方法的返回值是否需要继续处理(返回值为EVAL_BODY_AGAIN再计算主体一次,EVAL PAGE计算页面的后续部分);若返回值是SKIP_BODY跳过主体进入结束标签,最后取消引用助手类。
了解助手类里面常量的意思
- SKIP_BODY:跳过主体
- EVAL_BODY_INCLUDE:计算标签主体内容并[输出]
- EVAL_PAGE:计算页面的后续部分
- SKIP_PAGE:跳过页面的后续部分
- EVAL_BODY_AGAIN:再计算主体一次
🔘如何自定义标签
常见自定义标签主要步骤:
- 编写助手类(继承BodyTagSupport)
- 编写标签库描述文件(tld)
- 在jsp页面上通过taglib指令导入标签库
注意:tld文件必须保存到WEB-INF目录或其子目录
🔘标签类型
- UI标签:输出页面元素 如:Input、table
- 控制标签: 如if标签,foreach标签等
- 数据标签:用于向页面输入数据 如:out标签
- 空标签:如:br、hr
🔘 开发示例
-
out标签
1) 创建助手类
package com.zking.ml;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import com.mysql.jdbc.StringUtils;
public class OutTag extends BodyTagSupport{
private String val;
private String defaultVal;
public String getVal() {
return val;
}
public void setVal(String val) {
this.val = val;
}
public String getDefaultVal() {
return defaultVal;
}
public void setDefaultVal(String defaultVal) {
this.defaultVal = defaultVal;
}
@Override
public int doStartTag() throws JspException {
//pageContext为页面上下文对象,用于和jsp共享数据
JspWriter out = this.pageContext.getOut();
try {
if(StringUtils.isNullOrEmpty(val)) {
out.println(this.defaultVal);
}else {
out.println(this.val);
}
} catch (IOException e) {
e.printStackTrace();
}
return SKIP_BODY;
}
}
2) 编写tld文件,(必须放在WEB-INF目录或其目录下)
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<!-- 标签库描述符 -->
<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>Simple Tags</short-name>
<uri>/zking</uri>
<tag>
<!-- 标签名 -->
<name>out</name>
<!-- 标签助手类 -->
<tag-class>com.zking.ml.OutTag</tag-class>
<!-- 标签的内容类型:empty表示空标签,jsp表示可以为任何合法的JSP元素 -->
<body-content>empty</body-content>
<attribute>
<!-- 属性名, OutTag类中的val属性相匹配 -->
<name>val</name>
<!-- 表示该属性为必要的属性 -->
<required>true</required>
<!-- 该属性可以接受EL表示式的值 -->
<rtexprvalue>true</rtexprvalue>
<!-- 标签描述,用于说明标签的作用 -->
<description>out标签</description>
</attribute>
<attribute>
<!-- 属性名, OutTag类中的val属性相匹配 -->
<name>defaultVal</name>
<!-- 表示该属性为必要的属性 -->
<required>false</required>
<!-- 该属性可以接受EL表示式的值 -->
<rtexprvalue>false</rtexprvalue>
<!-- 标签描述,用于说明标签的作用 -->
<description>out标签</description>
</attribute>
</tag>
</taglib>
3) 在页面上引入使用
若name没有设值则输出来的默认值为十一,下面代码name是设置了值的。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="z" uri="/zking"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
request.setAttribute("name", "苡桉");
%>
<z:out val="${name}" defaultVal="十一"/>
</body>
</html>
效果图如下:
-
if标签
1)编写助手类
package com.zking.ml;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class IfTag extends BodyTagSupport{
private boolean test;
public boolean isTest() {
return test;
}
public void setTest(boolean test) {
this.test = test;
}
@Override
public int doStartTag() throws JspException {
if(this.isTest()) {
return EVAL_BODY_INCLUDE;
}
return SKIP_BODY;
}
}
2) tld文件,在tld中加入if标签的声明
<tag>
<name>if</name>
<tag-class>com.zking.ml.IfTag</tag-class>
<body-content>jsp</body-content>
<description>if标签</description>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
3) 在页面上使用
若两值相等显示下面测试文字,反之则不显示
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="z" uri="/zking"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- if -->
<z:if test="${100 == 100}">
测试if(100 == 100)
</z:if>
<z:if test="${100 == 1}">
测试if(100 == 1)
</z:if>
</body>
</html>
效果图如下:
-
foreach标签
1)编写助手类
package com.zking.ml;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
@SuppressWarnings("serial")
public class ForeachTag extends BodyTagSupport{
private List<?>items;
private String var;
public List<?> getItems() {
return items;
}
public void setItems(List<?> items) {
this.items = items;
}
public String getVar() {
return var;
}
public void setVar(String var) {
this.var = var;
}
@Override
public int doStartTag() throws JspException {
if(Objects.isNull(this.items)||this.items.size()==0) {
return SKIP_BODY;
}
Iterator<?> it = this.items.iterator();
Object next = it.next();
this.pageContext.setAttribute(var, next);
this.pageContext.setAttribute("it",it);
return EVAL_BODY_INCLUDE;
}
@Override
public int doAfterBody() throws JspException {
Iterator<?> it1 = (Iterator<?>)this.pageContext.getAttribute("it");
if(it1.hasNext()) {
this.pageContext.setAttribute(var, it1.next());
return EVAL_BODY_AGAIN;
}
return SKIP_BODY;
}
}
2) tld文件,在tld中加入foreach标签的声明
<tag>
<name>foreach</name>
<tag-class>com.zking.ml.ForeachTag</tag-class>
<body-content>jsp</body-content>
<description>foreach标签</description>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
3) 在页面上使用
<%@page import="com.zking.ml.Book"%>
<%@page import="java.util.List"%>
<%@page import="com.zking.ml.TestData"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="z" uri="/zking"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
//获取测试数据
List<Book>books=TestData.getBooks();
//放入request对象中
request.setAttribute("books", books);
%>
<z:foreach items="${books}" var="b">
${b.id }--${b.name }<br>
</z:foreach>
</body>
</html>
效果图如下
-
select标签
1)编写助手类
package com.zking.ml;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import org.apache.commons.beanutils.BeanUtils;
import com.mysql.jdbc.StringUtils;
@SuppressWarnings("unused")
public class SelectTag extends BodyTagSupport{
private String id;
private String name;
private List<?> items;
private String cssClass;
private String cssStyle;
private String value;
private String text;
private String selectValue;
public void setText(String text) {
this.text = text;
}
public void setValue(String value) {
this.value = value;
}
public void setSelectValue(String selectValue) {
this.selectValue = selectValue;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setItems(List<?> items) {
this.items = items;
}
public void setCssClass(String cssClass) {
this.cssClass = cssClass;
}
public void setCssStyle(String cssStyle) {
this.cssStyle = cssStyle;
}
@Override
public int doStartTag() throws JspException {
try {
JspWriter out = this.pageContext.getOut();
String html = getSelectHtml();
out.print(html);
} catch (Exception e) {
e.printStackTrace();
}
return SKIP_BODY;
}
private String getSelectHtml() throws Exception {
StringBuilder sb = new StringBuilder();
//构造页面需要的select元素
sb.append("<select id="+id+"' name="+name+"'>");
if(StringUtils.isNullOrEmpty(this.cssClass)) {
sb.append("class='"+this.cssClass+"'");
}
if(StringUtils.isNullOrEmpty(this.cssClass)) {
sb.append("style='"+this.cssStyle+"'");
}
sb.append(">");
//循环生成options
for(Object option:this.items) {
String val = BeanUtils.getProperty(option, this.value);
String txt = BeanUtils.getProperty(option, this.text);
if(val.equals(this.selectValue)) {
sb.append("<option value='"+val+"' selected>" + txt + "</option>");
} else {
sb.append("<option value='"+val+"' >" + txt + "</option>");
}
}
sb.append("</select>");
return sb.toString();
}
}
2) tld文件,在tld中加入select标签的声明
<tag>
<name>select</name>
<tag-class>com.zking.ml.SelectTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>id</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>name</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>cssClass</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>cssStyle</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>value</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>text</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>selectValue</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
3) 在页面上使用
<%@page import="com.zking.ml.Book"%>
<%@page import="java.util.List"%>
<%@page import="com.zking.ml.TestData"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="z" uri="/zking"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
//获取测试数据
List<Book>books=TestData.getBooks();
//放入request对象中
request.setAttribute("books", books);
%>
<select id="test" name="test" class="" style="width: 100px">
<option value=0>已付款</option>
<option value= selected>已发货</option>
<option value=2>已签收</option>
</select>
<z:select id="test"
name="test" items="${books}" value="id"
text="name" selectValue="3"/>
</body>
</html>
效果图如下: