目录
标签与自定义标签:
什么是标签?
标记语言,是一种注释文本的语言,以便于计算机可以操作。很多与“ML”结尾的语言都是标记语言,比如:HTML,XML,XHTML,VML等等。
标记语言与其他语言一样,也需要运行它们的环境,比如HTML的运行环境时浏览器,XML也要自己的解析和运行的环境。
标签基本结构:
<开始标签>标签体<结束标签>
<name>out</name>
空标签:
<开始标签 属性名="属性值"/></结束标签>
<br/><br/>
<开始标签 属性名="属性值"/>
<action path="/studentAction" type="org.lisen.mvc.action.StudentAction"></action>
<forward name="students" path="/students/studentList.jsp" redirect="false"/>
jsp标签库是什么?
是一个JSP标签集合,它封装了JSP应用的通用核心功能, 基于JSP标签我们可以理解为,是JSP应该通用功能的一种封装方式。
标签的生命周期图:
SKIP_BODY:跳过主体( 不会打印“awa”)
EVAL_BODY_INCLUDE:计算标签主体内容并[输出](会打印“awa”)
EVAL_PAGE:计算页面的后续部分
SKIP_PAGE:跳过页面的后续部分(不建议用,直接跳过后面全部类容包括body)
EVAL_BODY_AGAIN:再计算主体一次
实例(完整的流程图):
EVAL_BODY_INCLUDE SKIP_BODY
实例化标签助手类->doStartTag()------------->doAfterBody---------------->doEndTag()...
EVAL_BODY_AGAIN
/**
* 在标签体之后在结束标签之前执行的动作
* 返回值两种:
* 1.跳过主题,执行doEndTag的方法SKIP_BOOY
* 2.再计算主题一次 EVAL_BODY_AGAIN
*/
@Override
public int doAfterBody() throws JspException {
//获取count值
int count = (int)pageContext.getAttribute("count");
if(count<3) {
count++;
pageContext.setAttribute("count", count);
return EVAL_BODY_AGAIN;
}else {
return SKIP_BODY;
}
}
@Override
public int doEndTag() throws JspException {
return super.doEndTag();
}
/**
* 默认为跳过标签体
*/
@Override
public int doStartTag() throws JspException {
pageContext.setAttribute("count", 1);
String str="";
for (Object string : item) {
str+=string;
}
pageContext.setAttribute(var, str);
return EVAL_BODY_INCLUDE;
}
自定义标签的创作流程:
1.创建一个标签助手类(继承BodyTagSupport)
①out标签
像这个out标签就是一个简单的流程:
SKIP_BODY
实例化标签助手类->doStartTag()------------->doEndTag()
package com.ljq.mymvc.tag;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import com.mysql.jdbc.StringUtils;
/**
* 自定义out标签
*
* @author 一麟
*
*/
public class OutTag extends BodyTagSupport {
private String val;// 传入的值
private String defaultVal;// 默认值
/**
* @param val
*/
public void setVal(String val) {
this.val = val;
}
public void setDefaultVal(String defaultVal) {
this.defaultVal = defaultVal;
}
/**
* 处理标签的数值(执行开始标签)
*/
@Override
public int doStartTag() {
JspWriter out = this.pageContext.getOut();
try {
if (StringUtils.isNullOrEmpty(val)) {
out.println(this.defaultVal);
} else {
out.println(this.val);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return SKIP_BODY;
}
}
②if标签
package com.ljq.mymvc.tag;
import javax.servlet.jsp.tagext.BodyTagSupport;
/**
* if自定义标签
*
* @author 一麟
*
*/
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() {
if(this.isTest()) {
return EVAL_BODY_INCLUDE;
}
return SKIP_BODY;
}
}
③select标签
package com.ljq.mymvc.tag;
import java.util.List;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import org.apache.commons.beanutils.BeanUtils;
import com.mysql.jdbc.StringUtils;
/**
* 下拉框标签助手类
*
* @author 一麟
*
*/
@SuppressWarnings("all")
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() {
JspWriter out = this.pageContext.getOut();
try {
String html = getSelectHtml();
out.print(html);
} catch (Exception e) {
e.printStackTrace();
}
return SKIP_BODY;
}
// 构造select标签(通过传入的参数)
private String getSelectHtml() throws Exception {
StringBuilder sb = new StringBuilder();
// 元素需求判断(需要的元素就构造)
sb.append("<select id='" + id + "' name='" + name + "'");
if (!StringUtils.isNullOrEmpty(this.cssClass)) {
sb.append(" class='" + this.cssClass + "'");
}
if (!StringUtils.isNullOrEmpty(this.cssStyle)) {
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();
}
}
④foreach标签
package com.ljq.mymvc.tag;
import java.util.List;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import org.apache.commons.beanutils.BeanUtils;
import com.mysql.jdbc.StringUtils;
/**
* 下拉框标签助手类
*
* @author 一麟
*
*/
@SuppressWarnings("all")
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() {
JspWriter out = this.pageContext.getOut();
try {
String html = getSelectHtml();
out.print(html);
} catch (Exception e) {
e.printStackTrace();
}
return SKIP_BODY;
}
// 构造select标签(通过传入的参数)
private String getSelectHtml() throws Exception {
StringBuilder sb = new StringBuilder();
// 元素需求判断(需要的元素就构造)
sb.append("<select id='" + id + "' name='" + name + "'");
if (!StringUtils.isNullOrEmpty(this.cssClass)) {
sb.append(" class='" + this.cssClass + "'");
}
if (!StringUtils.isNullOrEmpty(this.cssStyle)) {
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文件就是标签库描述文件(Tag Library Descrptor File)
tag.tld
<!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>/yilinyyds</uri>
<tag>
<name>out</name>
<tag-class>com.ljq.mymvc.tag.OutTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>val</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>out标签,val属性是传入的值</description>
</attribute>
<attribute>
<name>defaultVal</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>用户定义默认值</description>
</attribute>
</tag>
<tag>
<name>if</name>
<tag-class>com.ljq.mymvc.tag.IfTag</tag-class>
<body-content>jsp</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<description>if标签判断,若为true则执行标签中的代码</description>
</attribute>
</tag>
<tag>
<name>foreach</name>
<tag-class>com.ljq.mymvc.tag.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>
<tag>
<name>select</name>
<tag-class>com.ljq.mymvc.tag.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>
</taglib>
注意:tld文件一定要放在WEB-INF目录下或者子目录。
- <taglib>:描述信息
- <description>与<display-name>:可选,用于在IDE中的XML工具显示,和真正的TLD内容没什么关系,可有多个,用于不同语言的显示
- <tlib-version>:必选,taglib的版本
- <jsp-version>:必选,jsp的版本
- <short-name>:必选,给出推荐和缺省的tag前缀。
- <uri>:可选,建议给出,若不提供则需要在web.xml中配置<jsp-config>描述tag
library,uri可以随意配置,不需要真实存在。 - <tag>:用来装载单个标签的信息
- <name>:必选,标签名称。
- <tag-class>:标签处理类(指的是自定义标签类的权限类名)
- <tei-class>:可选,javax.servlet.jsp.tagext.TagExtraInfo的继承类,用于校验tag的属性,确保使用的正确,<c:import><c:forEach>就有定义。
- <body-content>:必选,有四个选项empty、scriptless、JSP、tagdependent,之后篇章介绍。
- <variable>:可选,可定义多个,JSTL TLD中都没有使用,它是用来提供tag的结果的各种变量信息。什么是variable?我们通过pageContext.setAttribute/getAttribute设置或获取某个值,这就是变量。不通过variable,我们也可以通过EL来获取。如果提供了variable,我们除了EL外,还可以在java代码中使用这些变量。但现在都是采用MVC模式,JSP页面中java代码基本上也不会被使用。子参数依次包括:
- <description>:标签的描述,建议有,方便项目的维护
- <name> 变量的名字 。
- <required>:是否必填
- <rtexprvalue:可选,rtexprvalue是runtime expression value:true表示允许EL这类运行时计算值,false则不允许,缺省为false。
- <type>:可选,属性类型,缺省为Object
3.页面显示
接下来我们创建一个jsp文件显示页面查看结果。
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/yilinyyds" prefix="y"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试</title>
</head>
<body>
<center>
<%
request.setAttribute("name", "");
request.setAttribute("name02", "小明");
%>
<!-- out 标签 -->
<y:out val="${name}" defaultVal="name为空" />
<br>
<y:out val="${name02}" defaultVal="name02为空" />
<br>
<y:if test="${100 == 100}">
hello world!
</y:if>
<y:if test="${100 == 200}">
no happy!
</y:if>
</center>
</body>
</html>
下面这行代码就是引入自定义标签 uri就是在tld描述文件中定义的,而prefix就是你自己定义的前缀,字母即可。
<%@ taglib uri="/yilinyyds" prefix="y"%>
页面输出结果: