JSP自定义标签
自定义标签是用户定义的JSP语言元素。当JSP页面包含一个自定义标签时将被转化为servlet,标签转化为对被 称为tag handler的对象的操作,即当servlet执行时Web container调用那些操作。JSP标签扩展可以让你创建新的标签并且可以直接插入到一个JSP页面。
JSP1.0规范中可以继承TagSupport类并重写的doStartTag()方法来开发自定义标签;JSP2.0规范也可以继承SimpleTagSupport类并重写的doTag()方法来开发自定义标签。建议使用继承SimpleTagSupport的方式开发自定义标签。
tld文件中attribute属性
属性 | 描述 |
---|---|
name | 定义属性的名称。每个标签的是属性名称必须是唯一的。 |
required | 指定属性是否是必须的或者可选的,如果设置为false为可选。 |
rtexprvalue | 声明在运行表达式时,标签属性是否有效。 |
type | 定义该属性的Java类类型 。默认指定为 String |
description | 描述信息 |
fragment | 如果声明了该属性,属性值将被视为一个 JspFragment。 |
继承TagSupport的方式
开发步骤:
1、继承TagSupport,重写doStartTag方法。
/**
* 自定义日期标签
*/
public class DateTag extends TagSupport {
private static final long serialVersionUID = 1L;
@Override
public int doStartTag() throws JspException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateFormat = sdf.format(new Date());
try {
pageContext.getOut().write(dateFormat);
} catch (IOException e) {
e.printStackTrace();
}
return super.doStartTag();
}
}
2、编写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>TagLibrary</short-name>
<uri>/aric-Tag</uri>
<tag>
<name>date</name>
<tag-class>cn.aric.tag.DateTag</tag-class>
<!-- 空的标签体 -->
<body-content>empty</body-content>
</tag>
</taglib>
3、编写jsp文件,在jsp页面中使用自定义标签
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 引入自定义标签库 -->
<%@ taglib uri="/aric-Tag" prefix="a" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登陆页面</title>
</head>
<body>
欢迎登陆系统!当前时间:<a:date/>
</body>
</html>
标签中静态常量:
EVAL_BODY_INCLUDE:告诉服务器正文的内容,并把这些内容送入输出流
SKIP_BODY:告诉服务器不要处理正文内容
EVAL_PAGE:让服务器继续执行页面
SKIP_PAGE:让服务器不要处理剩余的页面
EVAL_BODY_AGAIN:让服务器继续处理正文内容,只有doAfterBody方法可以返回
EVAL_BODY_BUFFERED:BodyTag接口的字段,在doStartTag()返回
EVAL_BODY_INCLUDE、SKIP_BODY一般由doStartTag()返回,而EVAL_PAPGE、SKIP_PAGE由doEndTag()返回。
BodyTagSupport
BodyTagSupport类几个方法:doStartTag(), setBodyContent(), doInitBody(), doAfterBody(), doEndTag();他们执行顺序:
doStartTag()→doInitBody()→setBodyContent()→doAfterBody()→doEndTag()
doStartTag()方法可返回EVAL_BODY_INCLUDE或SKIP_BODY,如果返回EVAL_BODY_INCLUDE则继续执行;如果返回SKIP_BODY则接下来的doInitBody(),setBodyContent(), doAfterBody()三个方法不会被执行,而直接执行doEndTag()方法。
setBodyContent()方法用于设置标签体内容,如果在此之前要作一些初始化工作,则在doInitBody()方法中完成。标签体内容执行完后,会调用doAfterBody()方法,此方法可返回EVAL_BODY_TAG, SKIP_BODY, EVAL_PAGE或SKIP_PAGE。
如果返回EVAL_BODY_TAG则会再次设置标签体内容,直到返回SKIP_BODY;如果返回EVAL_PAGE则标签体执行完后会继续执行JSP页面中接下来的部分;如果返回SKIP_PAGE,则JSP页面的后续内容将不再执行。
1、Java代码:
/**
* 继承BodyTagSupport,实现修改页面内容
*/
public class BodyTag extends BodyTagSupport{
private BodyContent bodyContent;
@Override
public void setBodyContent(BodyContent b) {
this.bodyContent = b;
}
@Override
public int doEndTag() throws JspException {
String content = bodyContent.getString();
System.out.println(content);
//修改页面内容
String newStr = "www.abc.com";
JspWriter jspWriter = bodyContent.getEnclosingWriter();
try {
jspWriter.write(newStr);
} catch (IOException e) {
e.printStackTrace();
}
//服务器继续执行该页面
return EVAL_PAGE;
}
}
2、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>TagLibrary</short-name>
<uri>/aric-Tag</uri>
<tag>
<name>date</name>
<tag-class>cn.aric.tag.DateTag</tag-class>
<!-- 空的标签体 -->
<body-content>empty</body-content>
</tag>
<tag>
<name>body</name>
<tag-class>cn.aric.tag.BodyTag</tag-class>
<body-content>scriptless</body-content>
</tag>
</taglib>
3、编写jsp页面,使用自定义标签
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/aric-Tag" prefix="a" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
<a:body>
欢迎访问网站!
</a:body>
</body>
</html>
继承SimpleTagSupport的方式
开发步骤:
1、继承SimpleTagSupport,重写doTag方法。
/**
* 自定义日期标签
*/
public class DateSimpleTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException, IOException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateFormat = sdf.format(new Date());
//获取jsp输出流
JspWriter jspWriter = getJspContext().getOut();
jspWriter.write(dateFormat);
}
}
2、新建aricTag.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>SimpleTagLibrary</short-name>
<uri>/aric-SimpleTag</uri>
<tag>
<name>date</name>
<tag-class>cn.aric.simpleTag.DateSimpleTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
3、在jsp页面中使用自定义标签
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 引入自定义标签库 -->
<%@ taglib uri="/aric-SimpleTag" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
欢迎登陆网站!当前时间:<s:date/>
</body>
</html>
修改标签内容
Java代码:
/**
* 修改页面内容
*/
public class BodySimpleTag extends SimpleTagSupport{
@Override
public void doTag() throws JspException, IOException {
StringWriter stringWriter = new StringWriter();
JspFragment jspFragment = getJspBody();
jspFragment.invoke(stringWriter);
String content = stringWriter.toString();
System.out.println(content);
content = "www.shuai.com";
PageContext pageContext = (PageContext) getJspContext();
pageContext.getOut().write(content);
}
}
在aricTag.tld文件中加自定义标签:
<tag>
<name>body</name>
<tag-class>cn.aric.simpleTag.BodySimpleTag</tag-class>
<body-content>scriptless</body-content>
</tag>
url访问权限
Java代码:
/**
* 根据链接来源判断是否有权限访问
*/
public class LinkSimpleTag extends SimpleTagSupport {
@Override
public void doTag() throws JspException {
PageContext pageContext = (PageContext) getJspContext();
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
//http协议中头文件属性,告诉服务器是从哪个页面链接过来的
String referer = request.getHeader("referer");
if (referer == null) {
//如果不是链接过来的抛出异常
throw new SkipPageException();
}
}
}
在aricTag.tld文件中加自定义标签:
<tag>
<name>link</name>
<tag-class>cn.aric.simpleTag.LinkSimpleTag</tag-class>
<body-content>empty</body-content>
</tag>
新建link.jsp页面,访问不到页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/aric-SimpleTag" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
<s:link/>
<h3>我是测试超链接的网页!</h3>
</body>
</html>
新建access.jsp页面,添加a标签链接到link.jsp页面,能访问到
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
<a href="http://localhost:8008/tag/simplePage/link.jsp">超链接访问</a>
</body>
</html>
循环遍历
Java代码:
/**
* 循环表达式,用来遍历集合
*/
@SuppressWarnings("unused")
public class LoopSimpleTag extends SimpleTagSupport{
//自定义属性,并添加setter方法
private String var;
private String[] items;
public void setVar(String var) {
this.var = var;
}
public void setItems(String[] items) {
this.items = items;
}
@Override
public void doTag() throws JspException, IOException {
if (items != null && items.length > 0) {
PageContext pageContext = (PageContext) getJspContext();
for (int i = 0; i < items.length; i++) {
pageContext.setAttribute("name", items[0]);
getJspBody().invoke(null);
}
}
}
}
在aricTag.tld文件中加自定义标签:
<tag>
<name>loop</name>
<tag-class>cn.aric.simpleTag.LoopSimpleTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>var</name>
<required>true</required>
</attribute>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
新建loop.jsp页面,在页面中使用自定义标签
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/aric-SimpleTag" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
<!-- 实际是从后台传输数据,以下的java代码只是为了简单演示循环效果 -->
<%
String[] persons = {"张三","李四","王五"};
pageContext.setAttribute("persons", persons);
%>
<s:loop items="${persons }" var="name">
${name }
</s:loop>
</body>
</html>
参数表达式
Java代码:
/**
* 根据参数来确定是否显示标签体中内容
*/
public class ParamSimpleTag extends SimpleTagSupport{
@Override
public void doTag() throws JspException, IOException {
PageContext pageContext = (PageContext) getJspContext();
String name = pageContext.getRequest().getParameter("name");
//如果页面传过来的参数是aric,显示标签体中内容
if (name != null && "aric".equals(name)) {
getJspBody().invoke(null);
}
super.doTag();
}
}
在aricTag.tld文件中加自定义标签:
<tag>
<name>param</name>
<tag-class>cn.aric.simpleTag.ParamSimpleTag</tag-class>
<body-content>scriptless</body-content>
</tag>
新建param.jsp页面,在页面中使用自定义标签
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/aric-SimpleTag" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
<s:param>
<h3>测试params</h3>
</s:param>
</body>
</html>
条件表达式
Java代码:
/**
* 条件表达式
*/
public class IfSimpleTag extends SimpleTagSupport{
//条件属性
private boolean flag;
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void doTag() throws JspException, IOException {
if (flag) {
getJspBody().invoke(null);
}
}
}
在aricTag.tld文件中加自定义标签:
<tag>
<name>if</name>
<tag-class>cn.aric.simpleTag.IfSimpleTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>flag</name>
<!-- 必要的 -->
<required>true</required>
<!-- 允许使用EL表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/aric-SimpleTag" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
<!-- 实际是从后台传输数据,以下的java代码只是为了简单演示循环效果 -->
<%
String name ="aric";
pageContext.setAttribute("name", name);
%>
<s:if flag="${name == 'aric' }">
欢迎访问网站!
</s:if>
<s:if flag="${name != 'aric' }">
请您先注册!
</s:if>
</body>
</html>
复合标签
Java标签:
/**
* 复合标签中父标签
*/
public class ChooseSimpleTag extends SimpleTagSupport{
//条件标记
private boolean flag;
public void setFlag(boolean flag) {
this.flag = flag;
}
public boolean isFlag() {
return flag;
}
@Override
public void doTag() throws JspException, IOException {
getJspBody().invoke(null);
}
}
/**
* 复合表达式,符合条件情况的表达式
*/
public class WhenSimpleTag extends SimpleTagSupport{
//测试是否符合条件的标记
private boolean test;
public void setTest(boolean test) {
this.test = test;
}
@Override
public void doTag() throws JspException, IOException {
//符合test条件
if (test) {
getJspBody().invoke(null);
ChooseSimpleTag choose = (ChooseSimpleTag) getParent();
//设置父标签的标记为true
choose.setFlag(true);
}
}
}
/**
* 复合表达式,其他不符合when情况的表达式
*/
public class OtherSimpleTag extends SimpleTagSupport{
@Override
public void doTag() throws JspException, IOException {
ChooseSimpleTag choose = (ChooseSimpleTag) getParent();
//不符合条件
if (!choose.isFlag()) {
getJspBody().invoke(null);
}
}
}
在aricTag.tld文件中加自定义标签:
<tag>
<name>choose</name>
<tag-class>cn.aric.simpleTag.ChooseSimpleTag</tag-class>
<body-content>scriptless</body-content>
</tag>
<tag>
<name>when</name>
<tag-class>cn.aric.simpleTag.WhenSimpleTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<name>other</name>
<tag-class>cn.aric.simpleTag.OtherSimpleTag</tag-class>
<body-content>scriptless</body-content>
</tag>
jsp页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/aric-SimpleTag" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
<%
pageContext.setAttribute("name", "java");
%>
<s:choose>
<s:when test="${name eq 'java'}">我是Java程序员</s:when>
<s:other>我不是Java程序员</s:other>
</s:choose>
</body>
</html>