自定义标签库

18 篇文章 0 订阅

客户化JSP标签

  1. 客户化JSP标签技术是在JSP 1.1版本中才出现的,它支持用户在JSP文件中自定义标签,这样可以使JSP代码更加简洁。
  2. 这些可重用的标签能处理复杂的逻辑运算和事务,或者定义JSP网页的输出内容和格式。

创建客户化JSP标签的步骤

• (1)创建标签的处理类
• (2)创建标签库描述文件,标签库描述文件的额后缀名是:.tld
• (3)在JSP文件中引入标签库,然后插入标签,例如:mm:hello/

JSP Tag API

  1. Servlet容器编译JSP网页时,如果遇到自定义标签,就会调用这个标签的处理类。
  2. 标签处理类必须扩展以下两个类之一:
    – javax.servlet.jsp. tagext .TagSupport
    – javax.servlet.jsp. tagext . BodyTagSupport

TagSupport类的主要方法

  1. doStartTag
    Servlet容器遇到自定义标签的起始标志时调用该方法
  2. doEndTag
    Servlet容器遇到自定义标签的结束标志时调用该方法
  3. setValue(String k,Object o)
    在标签处理类中设置key/value
  4. getValue(String k)
    在标签处理类中根据参数key返回匹配的value
  5. removeValue(String k)
    在标签处理类中删除key/value
  6. setPageContext(PageContext pc)
    设置PageContext对象,该方法由Servlet容器在调用doStartTag或doEndTag方法前调用
  7. setParent(Tag t)
    设置嵌套了当前标签的上层标签的处理类,该方法由Servlet容器在调用doStartTag或doEndTag方法前调用
  8. getParent()
    返回嵌套了当前标签的上层标签的处理类

TagSupport类的两个重要属性

• parent:代表嵌套了当前标签的上层标签的处理类
• pageContext : 代 表 Web 应 用 中 的javax.servlet.jsp.PageContext对象
• JSP容器在调用doStartTag或doEndTag方法前 , 会 先 调 用 setPageContext 和setParent 方 法 , 设 置 pageContext 和parent。
• 在doStartTag或doEndTag方法中可以通过getParent方法获取上层标签的处理类;在TagSupport类中定义了protected类型的pageContext成员变量,因此在标签处理类中可以直接访问pageContext变量。

PageContext类

PageContext类提供了保存和访问Web应用的共享数据的方法:
– public void setAttribute(String name, Object value, intscope)
– public Object getAttribute(String name, int scope)
• 其中,scope参数用来指定属性存在的范围,它的可选值包括:
– PageContext.PAGE_SCOPE
– PageContext.REQUEST_SCOPE
– PageContext.SESSION_SCOPE
– PageContext.APPLICATION_SCOPE
• 例如:
pageContext.setAttribute(“username”,”zhangsan”,PageContext.SESSION_SCOPE);

TagSupport类的处理标签的方法

• public int doStartTag() throws JspException
• public int doEndTag() throws JspException

doStartTag()方法

• 当Servlet容器遇到自定义标签的起始标志,就会调用doStartTag()方法。
• doStartTag()方法返回一个整数值,用来决定程序的后续流程。它有两个可选值:
– Tag.SKIP_BODY
– Tag.EVAL_BODY_INCLUDE
• Tag.SKIP_BODY表示标签之间的内容被忽略。
• Tag.EVAL_BODY_INCLUDE表示标签之间的内容被正常执行。例如
对于以下代码:
<prefix: Mytag>
Hello
……
……
</prefix:Mytag>
假若的doStartTag()方法返回Tag.SKIP_BODY,”Hello”字符串不会显示在网页上;若返回Tag.EVAL_BODY_INCLUDE,“Hello” 字符串将显示在网页上。

doEndTag()方法

当Servlet容器遇到自定义标签的结束标志,就会调用doEndTag()方法。
• doEndTag()方法也返回一个整数值,用来决定程序后续流程。它有两个可选值:
– Tag.SKIP_PAGE
– Tag.EVAL_PAGE
• Tag.SKIP_PAGE表示立刻停止执行JSP网页,网页上未处理的静态内容和JSP程序均被忽略,任何已有的输出内容立刻返回到客户的浏览器上。
• Tag.EVAL_PAGE表示按正常的流程继续执行JSP网页。

用户自定义的标签属性

在标签中还能包含自定义的属性,例如:
<prefix:mytag username=“zhangsan">
……
……
</prefix:mytag>
在标签处理类中应该将这个属性作为成员变量,并且分别提供设置和读取属性的方法,假定以上username为String类型,可以定义如下方法:

private String username;
public void setUsername(String value){
this.username=value;
}
public String getUsername(){
return username;
}

范例1:创建hello标签

定义一个名为mytaglib的标签库,它包含一个简单的hello标签,这个标签能够将JSP页面中所有的mm:hello/解析为字符串“hello”。

hello标签的处理类HelloTag

package learn.tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

public class MyTag extends TagSupport {

	@Override
	public int doStartTag() throws JspException {

		try {
			//向页面输出文本字符串
			this.pageContext.getOut().print("hello world ");
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return EVAL_BODY_INCLUDE;
	}
	
	@Override
	public int doEndTag() throws JspException {
		try {
			//向页面输出文本字符串
			this.pageContext.getOut().print("welcome");
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return EVAL_PAGE;
	}
}

创建hello标签的标签库的描述文件

创建Tag Library的描述文件mytaglib.tld文件,在这个文件中定义mytaglib标签库和hello标签。这个文件存放位置为/WEB-INF/mytaglib.tld。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

<taglib>

	<tlib-version>1.0</tlib-version>
	<jsp-version>1.1</jsp-version>
	<short-name>myTag</short-name>
	<uri>/myTag</uri>

	<tag>
		<name>firstTag</name>
		<tag-class>learn.tag.MyTag</tag-class>
		<body-content>empty</body-content>
	</tag>
</taglib>

在JSP中加入hello标签

在 hellowithtag1.jsp 中 加 入 引 用mytaglib的taglib指令:<%@ taglib uri="/mytaglib" prefix=“mm” %>以上taglib指令中,prefix属性用来指定引用mytaglib标签库时的前缀。
在 hellowithtag1.jsp 文件中插入hello标签:mm:hello/ :

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="/myTag" prefix="hello"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<p><font color="blue"><hello:firstTag/></font></p>

</body>
</html>

结果是:
在这里插入图片描述
查看页面源代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="http://localhost:8080/JavaWeb/">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<p><font color="blue">hello world welcome</font></p>

</body>
</html>

范例2:创建message标签

创建一个能替换test应用中JSP网页的静态文本的标签,这个标签名为message,它放在mytaglib标签库中。

创建包含JSP网页静态文本的文件

首先将创建包含JSP网页静态文本的文件,这些文本以key/value的形式存放,这个文件名为message.properties:

title=hello world
body=welcome

在Web应用启动时装在静态文本

尽管装载静态文本的任务可以直接由标签处理类来完成,但是把初始化的操作安排在Web应用启动时完成,这更符合Web编程的规范。
在本例中,由DispatcherServlet类的init方法负责从静态文本文件中读取静态文本,然后把它们装载到Properties对象中,最后再把这个Properties对象作为属性保存到ServletContext中。
在这里插入图片描述

DispatcherServlet类的init方法

package learn.servlet;

import java.io.InputStream;
import java.util.Properties;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;


public class InitServlet2 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	@Override
	public void init(ServletConfig config) throws ServletException {
		Properties ps = new Properties();
		
		try {
			ServletContext context = config.getServletContext();
			
			InputStream inputStream = context.getResourceAsStream("/WEB-INF/message.properties");
			
			ps.load(inputStream);
			
			inputStream.close();
			//将properties对象放置到application范围内供其他组件使用
			context.setAttribute("ps", ps);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}

为 了 保 证 在 Web 应 用 启 动 时 就 加 载DispatcherServlet,应该在web.xml中配置这个Servlet时设置load-on-startup属性:

<servlet>
		<display-name>InitServlet2</display-name>
		<servlet-name>InitServlet2</servlet-name>
		<servlet-class>learn.servlet.InitServlet2</servlet-class>
		<load-on-startup>10</load-on-startup>
	</servlet>

创建MessageTag标签处理类

MessageTag包含一个成员变量key,它与message标签的属性key对应。在MessageTag中定义了getKey和setKey方法在MessageTag的doEndTag方法中,首先从pageContext中读取包含静态文本的Properties对象然后从Properties对象中读取key对应的静态文本,最后输出该文本

package learn.tag;

import java.util.Properties;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagSupport;

public class MyTag2 extends TagSupport {

	private String key;
	
	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	@Override
	public int doEndTag() throws JspException {
		try {
			
			Properties properties = (Properties)this.pageContext.getAttribute("ps", PageContext.APPLICATION_SCOPE);
			
			String message = properties.getProperty(key);
			
			this.pageContext.getOut().println(message);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return EVAL_PAGE;
	}
}

在mytaglib库中定义message标签

	<tag>
		<name>message</name>
		<tag-class>learn.tag.MyTag2</tag-class>
		<body-content>empty</body-content>
		<attribute>
			<name>key</name>
			<required>true</required>
		</attribute>
	</tag>

最后jsp页面输出:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="/myTag" prefix="hello" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<hello:message key="title"/>
<hello:message key="body"/>

</body>
</html>

在这里插入图片描述

练习

  1. 问题:在标签处理类中,如何访问session范围内的共享数据?
    • 选项:
    (A) 在 TagSupport 类 中 定 义 了 session 成 员 变 量 , 直 接 调 用 它 的getAttribute()方法即可。
    **(B)**在标签处理类TagSupport类中定义了pageContext成员变量,先通过它的 getSession() 方 法 获 得 当 前 的HttpSession 对 象 , 再调用HttpSession对象的getAttribute()方法。
    © pageContext.getAttribute(“attributename”,PageContext.SESSION_SCOPE)

  2. 问 题 : 在 下 面 的 选 项 中 , 哪 些 是TagSupport类的doStartTag()方法的有效返回值?
    • 选项:
    (A) Tag.SKIP_BODY
    (B) Tag.SKIY_PAGE
    © Tag.EVAL_BODY_INCLUDE
    (D) Tag.EVAL_PAGE

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值