jsp

位置:IT落伍者 >> jsp >> 浏览文章

JSP自定义标签开发入门


发布日期:2019年06月26日
 
JSP自定义标签开发入门

一般情况下开发jsp自定义标签需要引用以下两个包

import javaxservletjsp*;

import javaxservletjsptagext*;

首先我们需要大致了解开发自定义标签所涉及到的接口与类的层次结构(其中SimpleTag接口与SimpleTagSupport类是JSP中新引入的)

目标:自定义一个用表格显示用户信息的简单标签

效果图

在jsp页面使用此自定义标签

假设我们有一个UserInfo的javabean那么在JSP页面使用此标签只需调用此标签即可

  1. <!创建需要展现UserInfo的实例(用于测试数据)>
  2. <%
  3. UserInfouser=newUserInfo();
  4. usersetUserName("Xuwei");
  5. usersetAge();
  6. usersetEmail("test@testtest");
  7. pageContextsetAttribute("userinfo"user);
  8. %>
  9. <!给标签设置user属性绑定要展现的UserInfo对象>
  10. <cc:showUserInfouser="${pageScopeuserinfo}"/>

开发步骤

简单标签的开发我们只要实现Tag接口即可为了简单起见可以直接继承实现了此接口的TagSupport类

创建自定义标签类

  1. publicclassUserInfoTagextendsTagSupport{
  2. privateUserInfouser;
  3. @Override
  4. publicintdoStartTag()throwsJspException{
  5. try{
  6. JspWriterout=thispageContextgetOut();
  7. if(user==null){
  8. outprintln("NoUserInfoFound");
  9. &


nbsp;returnSKIP_BODY;

  • }
  • outprintln("<tablewidth=pxborder=align=center>");
  • outprintln("<tr>");
  • outprintln("<tdwidth=%>Username:</td>");
  • outprintln("<td>"+usergetUserName()+"</td>");
  • outprintln("</tr>");
  • outprintln("<tr>");
  • outprintln("<td>Age:</td>");
  • outprintln("<td>"+usergetAge()+"</td>");
  • outprintln("</tr>");
  • outprintln("<tr>");
  • outprintln("<td>Email:</td>");
  • outprintln("<td>"+usergetEmail()+"</td>");
  • outprintln("</tr>");
  • outprintln("</table>");
  • }catch(Exceptione){
  • thrownewJspException(egetMessage());
  • }
  • returnSKIP_BODY;
  • }
  • @Override
  • publicintdoEndTag()throwsJspException{
  • &nbs


p;returnEVAL_PAGE;

  • }
  • @Override
  • publicvoidrelease(){
  • superrelease();
  • thisuser=null;
  • }
  • //getterandsetters
  • publicUserInfogetUser(){
  • returnuser;
  • }
  • publicvoidsetUser(UserInfouser){
  • thisuser=user;
  • }
  • }

在WebInf创建标签库描述文件tdl(Tag Library Description)

  1. <?xmlversion=""encoding="UTF"?>
  2. <taglibversion=""xmlns="
  3. xmlns:xsi="
  4. xsi:schemaLocation="
  5. <tlibversion></tlibversion>
  6. <jspversion></jspversion>
  7. <shortname>cc</shortname>
  8. <uri>/mytaglib</uri>
  9. <tag>
  10. <name>showUserInfo</name>
  11. <tagclass>commytagsUserInfoTag</tagclass>
  12. <bodycontent>empty</bodycontent>
  13. <attribute>
  14. <name>user</name>
  15. <required>false</required>
  16. <rtexprvalue>true</rtexprvalue>
  17. </attribute>
  18. </tag>
  19. </taglib>

配置webxml

  1. <jspconfig>
  2. <taglib>
  3. <tagliburi>/mytaglib</tagliburi>&n


bsp;

  • <tagliblocation>/WEBINF/mytaglibtld</tagliblocation>
  • </taglib>
  • </jspconfig>

在需要使用此标签的jsp页面头部引入

  1. <%@tagliburi="/mytaglib"prefix="cc"%>

使用(参照上面的使用步骤)

此致一个简单的JSP标签开发完成

标签类说明

我们创建的UserInfoTag类继承了TagSupport类而它又实现了Tag接口Tag接口的生命周期由其所在的容器控制如下图

setPageContext() 将所在jsp页面的pageContext注入进来目的是为了在后面的方法中可以访问到jsp页面对象的pageContext属性

setParent() 设置此标签的父标签

setAttribute() 将标签中的属性注入到此class的属性不需要自己实现但要提供属性的get与set方法

doStartTag() 在开始标签属性设置后调用如果返回SKIP_BODY则忽略标签之中的内容如果返回EVAL_BODY_INCLUDE则将标签体的内容进行输出

doEndTag() 在结束标签之前调用返回SKIP_PAGE跳过整个jsp页面后面的输出返回EVAL_PAGE执行页面余下部分

release() 生命周期结束时调用

特别说明在tomcat之后的版本中默认开启了标签缓沖池(websphere和weblogic并不会这么做)所以执行完标签后并不会执行release()方法(_jspDestroy()时才释放)也就是说同一个jsp页面自定义标签不管使用多少次只会存在一个实例但也并不是每一个标签都会为其创建一个缓沖池要根据参数来判断例如

  1. <cc:UserInfoTaguser=”…”/>
  2. <cc:UserInfoTag/>

上面例子中由于参数不同就会创建两个标签缓沖池

这个问题可以通过设定tomcat的配置文件加以解决

在%tomcat%\conf\webxml加入enablePooling参数并设置为false(不缓存自定义标签)

  1. <initparam>
  2. <paramname>enablePooling</paramname>
  3. <paramvalue>false</paramvalue>
  4. </initparam>

清空%tomcat%\conf\目录

TagSupport类已经为我们实现并扩展了一些方法(比如在上述方法中我们可以直接使用pageContext对象调用父标签getParent()等)所以一般情况下我们只需重写doStartTag()doEndTag() 即可

TLD文件说明

<!版本号>
<tlibversion></tlibversion>
<jspversion></jspversion>
<shortname>cc</shortname>
<tag>
<!—指定标签名 >
<name>showUserInfo</name>
<!—指定标签类文件的全路径 >
<tagclass>commytagsUserInfoTag</tagclass>
<!如果不需要标签体则设置empty反之设定jsp >
<bodycontent>empty</bodycontent>
<!—设定属性(如果有的话) >
<attribute>
<!—指定标签名 >
<name>user</name>
<!—是否是必须如果非必须没设置则为空 >
<required>false</required>
<rtexprvalue>true</rtexprvalue><!—是否可在属性中使用表达式 >
</attribute>
</tag>

Webxml文件说明

<jspconfig>
<taglib>
<!

标签库的uri路径
即jsp头文件中声明<%@ taglib uri="/mytaglib" prefix="cc"%>
的uri
>
<tagliburi>/mytaglib</tagliburi>
<!—tld文件所在的位置>
<tagliblocation>/WEBINF/mytaglibtld</tagliblocation>
</taglib>
</jspconfig>

目标:自定义一个类似于AspNet中的Reapter控件的标签

效果图

在jsp页面使用此自定义标签

  1. <!创建需要展现javabean(UserInfo)集合的实例(用于测试数据)>
  2. <%
  3. List<UserInfo>users=newArrayList<UserInfo>();
  4. usersadd(newUserInfo("Zhangsan""Zhangsan@com"));
  5. usersadd(newUserInfo("Lisi""Lisi@sinacom"));
  6. usersadd(newUserInfo("Wangwu""Wangwu@qqcom"));
  7. pageContextsetAttribute("users"users);
  8. %>
  9. <!给标签绑定数据源>
  10. <tablewidth=pxborder=align=center>
  11. <tr>
  12. <tdwidth=%>UserName</td>
  13. <tdwidth=%>Age</td>
  14. <td>Email</td>
  15. </tr>
  16. <cc:repeatervar="item"items="${pageScopeusers}">
  17. <tr>
  18. <td>${itemuserName}</td>
  19. <td>${itemage}</td>
  20. <td>${itememail}</td>
  21. </tr>
  22. </cc:repeater>
  23. </table>


;

开发步骤

要完成此控件我们需要实现一个迭代接口即IterationTag由于TagSupport同样实现了此接口所以我们继承此类

创建自定义标签类

  1. publicclassRepeaterextendsTagSupport{
  2. privateCollectionitems;
  3. privateIteratorit;
  4. privateStringvar;
  5. @Override
  6. publicintdoStartTag()throwsJspException{
  7. if(items==null||itemssize()==)returnSKIP_BODY;
  8. it=itemsiterator();
  9. if(ithasNext()){
  10. pageContextsetAttribute(varitnext());
  11. }
  12. returnEVAL_BODY_INCLUDE;
  13. }
  14. @Override
  15. publicintdoAfterBody()throwsJspException{
  16. if(ithasNext()){
  17. pageContextsetAttribute(varitnext());
  18. returnEVAL_BODY_AGAIN;
  19. }
  20. returnSKIP_BODY;
  21. }
  22. @Override
  23. publicintdoEndTag()throwsJspException{
  24. returnEVAL_PAGE;
  25. }
  26. publicvoidsetItems(Collectionitems){
  27. thisitems=items;
  28. }
  29. publicvoidsetVar(Stringvar){
  30. &


nbsp;thisvar=var;

  • }
  • }

在WebInf创建标签库描述文件tdl(Tag Library Description)由于目标种已经创建了此文件我们只需增加此标签的配置即可

  1. <tag>
  2. <name>repeater</name>
  3. <tagclass>commytagsRepeater</tagclass>
  4. <bodycontent>jsp</bodycontent>
  5. <attribute>
  6. <name>items</name>
  7. <required>false</required>
  8. <rtexprvalue>true</rtexprvalue>
  9. </attribute>
  10. <attribute>
  11. <name>var</name>
  12. <required>true</required>
  13. <rtexprvalue>true</rtexprvalue>
  14. </attribute>
  15. </tag>

配置webxml (目标中已完成无需修改)



在需要使用此标签的jsp页面头部引入

  1. <%@tagliburi="/mytaglib"prefix="cc"%>

使用(参照上面的使用步骤)

标签类说明

我们用到了迭代接口以下是容器处理此接口的流程

作为目标中的补充 在doAfterBody()如果返回值是EVAL_BODY_AGAIN那么将重新执行此方法

目标:使用BodyTagSupport

此目标并不会使用实际例子进行显示主要是说明为什么什么情况下需要使用到BodyTag接口或者BodyTagSupport类?

如果我们需要在 之间的标签体的头部和尾部加上一些标记或者是其他处理一般的处理方法是在doStartTag和doEndTag方法中进行 但是如果是个迭代标签标签体的每段内容在循环输出时每次都需要在头部和尾部加上一些标记我们使用BodyTagSupport就很方便了

此接口在doStartTag()方法返回值多了一个EVAL_BODY_BUFFERED它将对主体进行计算并输出到缓沖区(注此处是缓沖区并非直接输出到客户端需要我们手动(thisbodyContentgetEnclosingWriter()write(thisbodyContentgetString());)进行输出客户端的调用否则主体内容不会进行显示)

标签类说明

关于BodyTagSupport接口的说明

目标:自定义的函数库
>

创建函数库类

  1. publicclassMyFunctions{
  2. publicstaticStringformatMyName(Stringname){
  3. return"yournameis"+name;
  4. }
  5. publicstaticintadd(intaintb){
  6. returna+b;
  7. }
  8. }

在TLD文件中配置 (引用于目标中的tld文件)

  1. <function>
  2. <name>formatMyName</name>
  3. <functionclass>comtaglibMyFunctions</functionclass>
  4. <functionsignature>javalangStringformatMyName(javalangString)</functionsignature>
  5. </function>
  6. <function>
  7. <name>add</name>
  8. <functionclass>comtaglibMyFunctions</functionclass>
  9. <functionsignature>javalangStringadd(intint)</functionsignature>
  10. </function>

JSP中调用

  1. ${cc:formatMyName("wangfei")}
  2. ${cc:add()}

上一篇:用JSP编写通用信息发布程序

下一篇:如何学习JSP