用 Reflection 将 beann 属性提取为值 |
<nobr>第 2 页(共3 页)</nobr> |
开发人员通常使用 Java Reflection 改进自定义标签代码。 在这一小节中,我们将用 Reflection 改写 MapEntryTag
,使它可以使用所有范围内的所有 bean 属性定义 map 中的项。 例如,假设有像这样的一个 bean:
public class Test { String test="Jenny"; public String getTest() { return test; } public void setTest(String string) { test = string; } }
改写后的标签可以将 bean 属性作为 map 中的项使用,像下面这样:
<jsp:usebean id="bean" class="trivera.tags.map.Test"></jsp:usebean> <map:mapdefine id="employee2"> <map:mapentry property="test" name="bean" id="firstName"></map:mapentry> <map:mapentry value="33" type="java.lang.Integer" id="age"></map:mapentry> <map:mapentry value="22.22" type="java.lang.Float" id="salary"></map:mapentry> <map:mapentry name="properties" id="properties"></map:mapentry> </map:mapdefine>
注意 firstName
项现在是用 bean 的 test 属性定义的。
为了做到这一点,我们需要在自定义标签中加入 Relection,像这样(参看代码中的注释以了解改变的过程):
public class MapEntryTag extends TagSupport {... /* All of these have corresponding getters and setter method */ String type = "java.lang.String"; //Holder for the type attribute String id; //Holder for the id attribute String value; //Holder for value attribute String name; //Holder for name attribute String property; //Holder for property attribute String scope; //Holder for scope attribute public int doEndTag() throws JspException { MapDefineTag mapDef = (MapDefineTag) this.getParent(); Object objectValue = null; /* Check to see if the value property is set, if it is then this is a simple entry */ if (value !=null){ if (type.equals("java.lang.String")) { objectValue = value; } else if (type.equals("java.lang.Integer")) { Integer intValue = Integer.valueOf(value); objectValue = intValue; } else if (type.equals("java.lang.Float")) { Float floatValue = Float.valueOf(value); objectValue = floatValue; } /* If it is not a simple entry, then use reflection to get the property from the bean */ }else { Object bean =null; if (scope == null){ bean = pageContext.findAttribute(name); }else if("page".equalsIgnoreCase(scope)){ bean = pageContext.getAttribute(name); }else if("request".equalsIgnoreCase(scope)){ bean = pageContext.getRequest().getAttribute(name); }else if("session".equalsIgnoreCase(scope)){ bean = pageContext.getSession().getAttribute(name); }else if("application".equalsIgnoreCase(scope)){ bean = pageContext.getServletContext().getAttribute(name); } /* If the property attribute is null, then just use the bean as the entry*/ if (property==null){ objectValue = bean; mapDef.getMap().put(id,bean); /* If the property attribute is set, then use reflection to read the property */ }else { try{ String propertyMethod = "get" + property.substring(0,1).toUpperCase() + property.substring(1, property.length()); Method prop = bean.getClass() .getMethod(propertyMethod,new Class[]{}); objectValue = prop.invoke(bean, new Object[]{}); }catch(Exception e){ throw new RuntimeException(e); } } } mapDef.getMap().put(id,objectValue); return EVAL_PAGE; }
看起来仅仅是为了实现一些很多标签都要有的功能就需要做大量的工作。幸运的是,有一个库使这种开发变得容易了。在下一小节分析这个库 —— Struts —— 是如何发挥作用的。
用 Struts 简化自定义标签开发 |
<nobr>第 3 页(共3 页)</nobr> |
对 Struts 的深入讨论超出了本教程的范围(有关这个框架的更多信息请参阅 参考资料)。不过,如果熟悉这个框架,那么这些知识会对开发自定义标签有帮助。
也可以不使用 Reflection,而使用 Struts 的 RequestUtils
实现在上一小节看到的结果,如下所示:
public class MapEntryTag extends TagSupport {... private String type = "java.lang.String"; ... public int doEndTag() throws JspException { MapDefineTag mapDef = (MapDefineTag) this.getParent(); Object objectValue = null; if (value !=null){ if (type.equals("java.lang.String")) { objectValue = value; } else if (type.equals("java.lang.Integer")) { Integer intValue = Integer.valueOf(value); objectValue = intValue; } else if (type.equals("java.lang.Float")) { Float floatValue = Float.valueOf(value); objectValue = floatValue; } }else { /** THIS USED TO BE 30 LINES OF CODE */ objectValue = RequestUtils.lookup(pageContext, name, property, scope); } mapDef.getMap().put(id,objectValue); return EVAL_PAGE; }
可以看到,objectValue = RequestUtils.lookup(pageContext, name, property, scope);
这一行代替了使用 Reflection 的代码中的 30 行! Struts 自带了许多实用程序,使自定义标签的开发更容易了。
介绍 |
<nobr>第 1 页(共3 页)</nobr> |
可以编写标签处理程序对其 正文内容 进行操作。记住,标签的正文内容是 JSP 页中出现在自定义标签的开始和结束标签之间的数据。操纵其正文的标签称为 正文标签。编写正文标签处理程序比简单标签处理程序要复杂。
注意: 记住,简单标签也可以有正文。惟一的不同是简单标签不能读取或者操纵其正文。
要编写正文标签处理程序,必须实现 BodyTag
接口。BodyTag
实现了 Tag
实现的所有方法 (详见 第 1 步:创建一个实现了 Tag 接口的标签处理程序 ),而且还实现了另外两个处理正文内容的方法:
方法
目的
void setBodyContent(BodyContent b) |
bodyContent 属性的 Setter 方法。 |
void doInitBody() |
准备对正文进行判断。每次调用标签时,在获得新的 BodyContent 并通过 setBodyContent() 对其进行设置之后调用一次。 如果没有请求正文内容就不调用,因为 doStartTag() 返回 EVAL_BODY_BUFFERED 。 |
就像 Tag
接口有 TagSupport 类一样,BodyTag
接口有 BodyTagSupport
类。 因此,正文标签处理程序只需要覆盖它们要使用的方法。BodyTagSupport
类继承了 TagSupport 并实现了 BodyTag
接口。这使得编写正文标签处理程序更容易了。BodyTagSupport
定义了 get
/setBodyContent()
和一个 protected bodyContent
实例变量。
BodyTagSupport
类重新定义了 doStartTag()
生存周期方法以返回 EVAL_BODY_BUFFERED
。 通过返回 EVAL_BODY_BUFFERED
,doStartTag()
请求创建一个新的缓冲区 —— 即一个 BodyContent
。
BodyContent
是一个包含运行时正文判断结果的缓冲区。 BodyContent
继承了 JspWriter
并作为标签正文的隐式 out
。因此,JSP 容器创建 BodyContent
的一个实例,并且在处理标签的正文内容时,它写入这个实例而不是根 JspWriter
中。 因此,在标签中使用隐式对象 out
时,实际上使用的是 BodyContent
对象而非 JspWriter
(JspWriter
是页的隐式 out
)。
可以从 BodyContent
得到判断后的正文,它是一个 String
。BodyContent
是在运行时由容器调用页的 pageContext
的 pushBody()
和 popBody()
方法创建的 (只有在 doStartTag()
返回 EVAL_BODY_BUFFERED
时才调用pushBody()
)。 因此,BodyContent
是在 JspWriter
和 BodyContent
的一个嵌套结构中的。 (外面的 out
可以是另一个 BodyContent
对象,因为 BodyContent
是一个 JspWriter
。) 通过 setBodyContent()
方法将 BodyContent
提供给正文标签处理程序。 向正文标签处理程序传递一个 BodyContent
实例 (通过 setBodyContent()
) 并可以决定如何处理它。 可以对它做进行一步处理、放弃它、将它发送给浏览器等。
已经介绍了足够的背景知识了,该分析代码了!在下面几小节中我们将分析一个简单正文标签的例子。
例子:map 标签 |
<nobr>第 2 页(共3 页)</nobr> |
自定义标签的开发人员可以决定如何处理标签的正文。 例如,可以编写一个执行 SQL 语句的标签,标签的正文是要执行的 SQL 语句。
回到 hashmap 主题,我们将编写一个像下面这样解析字符串的标签:
{ firstName=Jennifer, lastName=Wirth, age=25 }
实际上,这个标签将读取这种字符串并将它转换为一个 Map
(java.util.Map
)。我们将调用新标签 map
。下面是使用新标签的例子:
<%@taglib uri="map" prefix="map"%> <map:map id="employee"> { firstName=Jennifer, lastName=Jones, age=25 } </map:map>
The employee map is <%=employee%>
上面的代码创建一个名为 employee
的 map
,它有三项:firstName
、lastName
和 age
。
实现标签处理程序
MapParseTag
是一个 map
标签的标签处理程序。它根据传递给正文的字符串定义一个 map。在 doAfterBody()
方法中,MapParseTag
用 body.getString()
将正文内容抓取为字符串。然后用 body.clearBody()
清除正文内容。
public class MapParseTag extends BodyTagSupport { private String id; private Map map; public int doStartTag() throws JspException { map=new FastTreeMap(); return EVAL_BODY_BUFFERED; } public int doAfterBody() throws JspException { /* Grab the body content */ BodyContent body = this.getBodyContent(); /* Get the body content as a String */ String content = body.getString(); /* Clear the body */ body.clearBody(); /* Parse the map */ int start = content.indexOf("{"); int end = content.lastIndexOf("}"); content = content.substring(start+1, end); /* Parse the entries in the map */ StringTokenizer token = new StringTokenizer(content,"=;, \t\r\n"); while(token.hasMoreTokens()){ String key = token.nextToken(); String value = token.nextToken(); map.put(key,value); } this.pageContext.setAttribute(id,map); return SKIP_BODY; }
多简单!我们已经讨论了对其正文进行处理的标签,现在要详细讨论实现了执行流程的标签了。
分享到:
相关推荐
本实例将深入探讨如何实现一个简单的JSP自定义标签。 首先,自定义标签的实现主要依赖于两个核心概念:Tag接口和TagSupport类。`Tag`接口定义了自定义标签必须实现的方法,如`doStartTag()`和`doEndTag()`,它们...
本篇学习笔记将深入探讨JSP自定义标签的相关概念、创建方法以及实际应用。 一、概述 1.1 使用简单标签机制 JSP自定义标签提供了类似HTML标签的语法结构,通过自定义标签,开发者可以封装复杂的Java代码,使得页面...
jsp自定义标签jsp自定义标签jsp自定义标签jsp自定义标签
本教程将深入探讨JSP自定义标签的使用,同时结合实例介绍分页和下拉框绑定值的封装。 一、JSP自定义标签基础 1. **定义标签库(Tag Library)**:自定义标签首先需要定义一个TLD(Tag Library Descriptor)文件,它...
使用jsp自定义标签的功能实现权限的控制。(如果用户没有某个模块的删除权限,就不现实这个删除按钮) 在整个项目中所有的页面都可以引入自定义的标签去做到权限的控制。 自定义标签文件 删除 可以控制页面中的每...
在JSP自定义标签的例子中,我们可以看到这个压缩包文件可能包含了一个完整的示例项目,可以在Apache Tomcat这样的Servlet容器下直接运行。Apache Tomcat是一款开源的Servlet容器,广泛用于部署和运行Java Web应用...
本文将详细讲解如何利用JSP自定义标签库实现数据列表的显示,以及涉及到的相关技术。 首先,`UserListTag.java` 是自定义标签的核心类,它继承了`javax.servlet.jsp.tagext.TagSupport` 或 `javax.servlet.jsp....
在使用JSP自定义标签时,开发者可能会遇到一些报错问题,这通常涉及到项目结构、类路径设置或自定义标签的编译与打包方式。在本文中,我们将深入探讨这些问题,以及如何解决“JspException”这个特定异常。 首先,...
首先,我们要理解JSP自定义标签的概念。自定义标签是JSP的一种扩展机制,它允许开发者创建自己的标签库,以更加清晰和可维护的方式编写页面。自定义标签的实现通常涉及三个主要部分:标签库描述符(TLD)、标签处理...
本教程将深入探讨JSP自定义标签的实例与详细讲解。 一、JSP自定义标签概述 JSP自定义标签是类似于HTML标签的自定义组件,但它们提供了更强大的功能,可以封装Java代码,提供复杂的业务逻辑。自定义标签通过TLD(Tag...
本篇将深入探讨“JSP自定义标签之日期显示”,以及如何通过自定义标签来优雅地处理日期格式化和展示。 首先,我们要理解JSP自定义标签的基本概念。自定义标签是JSP的一种扩展,它不是Java内置的标签,而是由开发者...
本教程将深入探讨如何利用JSP自定义标签来编写一个灵活、可扩展的分页系统,该系统不依赖于特定的数据库,具有很高的通用性。 首先,理解JSP自定义标签的工作原理至关重要。自定义标签由三部分组成:标签库描述符...
在Java Server Pages (JSP) 2.0版本中,自定义标签和自定义标签函数极大地扩展了JSP开发的灵活性和可重用性。这些特性允许开发者创建可复用的组件,使代码更加清晰,易于维护。本文将深入探讨JSP 2.0中的自定义标签...
【jsp自定义标签库注意事项】 在Java服务器页面(JSP)开发中,自定义标签库是一种强大的工具,它能够帮助开发者创建可重用的代码片段,提高代码的可读性和可维护性。以下是对JSP自定义标签库的详细解释和使用注意...
综上所述,“权威实用jsp自定义标签demo,checkbox,radio>”教程旨在帮助开发者掌握如何创建和使用与选择器相关的自定义标签,从而提升JSP开发的效率和质量。通过学习这个教程,你可以了解到自定义标签的核心概念、...
一、JSP自定义标签基础 JSP自定义标签是JSP技术的一部分,它允许开发者创建自己的标签,以扩展HTML或XML文档。这些自定义标签可以封装复杂的Java代码,使JSP页面更加清晰,易于理解和维护。自定义标签由两部分组成:...
本资源“jsp自定义标签大全.rar”提供了一套全面的JSP自定义标签的实例和指南,旨在帮助开发者深入理解和应用这一特性。 **JSP自定义标签的基本概念** JSP自定义标签不同于标准动作标签(如<jsp:include>或<jsp:...
java jsp自定义标签非常好用大家下载学习java jsp自定义标签非常好用大家下载学习java jsp自定义标签非常好用大家下载学习java jsp自定义标签非常好用大家下载学习java jsp自定义标签非常好用大家下载学习java jsp...
首先,我们需要理解JSP自定义标签的基本结构。自定义标签通常由两部分组成:标签库描述符(TLD)和标签处理类。TLD文件定义了标签的名称、属性、行为等元数据,而标签处理类则实现了这些行为,处理由JSP页面传递过来的...
总结起来,"JSP自定义Table标签demo"是一个教育性的示例,它演示了如何利用JSP自定义标签的灵活性和强大功能,来创建复杂且可复用的组件,如动态表格。通过学习和理解这个demo,开发者可以提升自己的JSP开发能力,...