学科分类
目录
Java Web

简单标签的属性

在上一小节中,实现了一个具有防盗链功能的<itcast:antiHotLinking/>标签,当请求消息头中referer请求头字段的值不符合判断条件时,标签会将用户的访问请求重定向到index.html页面。如果多个JSP页面都需要这样的防盗链功能,则需要重定向到不同的页面。这时,<itcast:antiHotLinking/>标签很难满足需求。为了提高标签的灵活性和复用性,在JSP页面使用自定义标签时,可以通过设置属性为标签处理器传递参数信息。例如,可以为<itcast:antiHotLinking />标签增加一个url属性,通过该属性指定重定向的页面,具体示例如下:

<itcast:antiHotLinking url = "/chapter09/index.html" />

要想为自定义标签设置属性,通常需要完成两件任务,具体如下:

1、在标签处理器类中,为每一个属性定义对应的成员变量并定义setter()方法

自定义标签每个属性都必须按照JavaBean的属性定义方式,例如标签中有一个属性名为url,在标签处理器类中就必须定义一个与之对应的方法setUrl()。当JSP容器调用标签处理器对象的doTag()方法之前,将依次调用每个属性对应的setter()方法,将各个属性值传递给标签处理器类。

默认情况下,自定义标签的属性值为静态文本,当setter()方法的参数为String类型时,JSP容器会直接将属性值作为一个字符串传递给该方法。如果setter()方法中的参数类型为基本数据类型,JSP容器在调用setter()方法之前会先将属性值进行转换。例如在JSP页面中使用了如下所示的标签:

<itcast:test attr = "123" />

而标签处理器类中定义的setter方法如下所示:

public void setAttr(int attr)

当JSP容器在处理attr属性时,会先调用Integer. value("123")方法将字符串“123”转换为整数123,之后再作为参数传递给标签处理器类的setAttr()方法。

2、在TLD文件中声明每个标签的属性信息

在TLD文件中,<tag>标签有一个子元素<attribute>用于描述自定义标签的属性,自定义标签的每个属性都必须要有一个对应的<attribute>元素。在<attribute>元素中还包含了一些子元素,表1列举了<attribute>的一些子元素,具体如下:

表1 <attribute>的子元素

元素名 功能描述
description 用于描述属性的描述信息
name 用于指定属性的名称,属性名大小写敏感,且不能以jsp、_jsp、java、和sun开头
required 用于指定在JSP页面调用自定义标签时是否必须设置这个属性。其取值包括true和false,true表示必须设置,false表示设不设置均可。默认值为false
rtexprvalue rtexprvalue是runtime expression value(运行时表达式)的简称,用于指定属性的值为静态还是动态。其取值包括true和false,true表示属性值可以为一个动态元素,比如一个脚本表达式<%=value%>,false表示属性值只能为静态文本值,比如“abc”。默认值为false
type 用于指定属性值的类型

​ 在表1列举的5个元素中,<name>子元素用于指定属性的名称,其值必须进行设置,而且属性名称一定要和jsp页面中自定义标签属性名一致,其它的子元素则可以设置也可以不用设置。

接下来,对上一小节的<itcast:antiHotLinking/>标签进行修改,为其增加一个url属性,具体实现步骤如下所示:

​ (1)修改例1中定义的标签处理器类AntiHotLinking.java,为其增加一个成员变量url和一个成员方法setUrl(String url),如例1所示。

例1 AntiHotLinking.java

 1  package cn.itcast.chapter09.simpletag;

 2  import java.io.IOException;

 3  import javax.servlet.http.*;

 4  import javax.servlet.jsp.JspException;

 5  import javax.servlet.jsp.PageContext;

 6  import javax.servlet.jsp.tagext.*;

 7  public class AntiHotLinking extends SimpleTagSupport {

 8    private String url;

 9    public void setUrl(String url) {

 10     this.url = url;

 11   }

 12   public void doTag() throws JspException, IOException {

 13     // 获得JSP页面的pageContext对象

 14     PageContext pageContext = (PageContext) this.getJspContext();

 15     // 获得request对象

 16     HttpServletRequest request = (HttpServletRequest) pageContext

 17         .getRequest();

 18     // 获得请求的超链接所网页的URL

 19     String referer = request.getHeader("referer");

 20     // 拼写本机的请求消息头

 21     String serverName = "http://" + request.getServerName();

 22     // 输出访问页面的URL

 23     System.out.println(referer);

 24     // 判断请求消息头的值不为空且请求头与本机头字段信息相同

 25     if (referer != null && referer.startsWith(serverName)) {

 26     // 执行JSP页面内容

 27     } else {

 28       try {

 29         // 获取响应对象

 30           HttpServletResponse resp = 

 31              (HttpServletResponse)pageContext.getResponse();

 32         // 将请求重定向到本地资源index.html页面

 33         resp.sendRedirect(url);

 34       } catch (Exception e) {

 35         e.printStackTrace();

 36       }

 37     }

 38   }

 39 }

在例1中,当JSP容器解析到标签的url属性时,会调用setUrl()方法将属性值传递给成员变量url,这样在程序的第33行就可以根据调用者指定的url属性值来决定要重定向到哪个页面。

(2)为描述<itcast:antiHotLinking />标签的<tag>标签增加子元素<attribute>,如下所示:

<tag>

  <name>antiHotLinking</name>

    <tag-class>

   cn.itcast.chapter09.classisctag.AntiHotLinking

  </tag-class>

  <body-content>scriptless</body-content>

  <attribute>

    <name>url</name>

    <required>true</required>

  </attribute>

</tag>

​ 在上面的<attribute>元素中,通过<name>子元素指定标签的属性为url,由于标签处理器类需要根据url属性的值决定重定向的页面,因此将<required>子元素的值设置为true,即在JSP页面调用标签时,必须指定url属性。

(3)修改antiHotLinking.jsp页面,为其中的<itcast:antiHotLinking />标签增加url属性,如下所示:

 <itcast:antiHotLinking url = "/chapter09/index.html" />

(4)启动Tomcat服务器,在浏览器中输入URL地址http://localhost:8080/chapter09/antiHotLinking.jsp访问antiHotLinking.jsp页面,由于referer头字段为空,因此标签根据url属性的值将请求重定向到指定的index.html页面,如图1所示。

图1 访问antiHotLinking.jsp页面

从图1可以看出,我们已经成功的为<itcast:antiHotLinking/>标签增加了一个url属性。

:动手体验:为标签属性设置JSP动态元素

在TLD文件中,如果将<rtexprvalue>元素的值设置为true,则标签的属性值可以被设置为一个JSP动态元素,这是一个非常有用的功能,它使得标签的属性值不再局限于静态文本,而可以根据程序的需求动态地进行设置。例如标签中有一个名为user的属性,这个属性接收cn.itcast.chapter09.domain.User类型的值,而在页面的session域中以“user”为键保存了一个User类型的对象,那么在JSP页面中可以使用EL表达式来设置标签的user属性值,如下所示:

<itcast:showtime user = "${user }" />

需要注意的是,当自定义标签的属性值为JSP动态元素时,JSP容器在处理标签属性时不会对属性的值进行转换,而是直接将其传递给标签处理器类,所以在这种情况下,JSP动态元素的结果类型必须与处理器类中属性的类型相同,否则会出现编译错误。

接下来就根据上面的需求设计一个自定义标签<itcast: showtime user = "" />,在标签中定义一个user属性接收cn.itcast.chapter09.domian.User类型的值。

(1)在chapter09工程下,创建一个cn.itcast.chapter09.domain包,并在该包中定义一个User类,在类中定义一个name属性,如例2所示。

例2 User.java

 1  package cn.itcast.chapter09.domain;

 2  public class User {

 3    //定义name字段

 4    private String name;

 5    //提供set和get方法

 6    public String getName() {

 7      return name;

 8    }

 9    public void setName(String name) {

 10     this.name = name;

 11   }

 12 }

(2)在chapter09工程下的cn.itcast.chapter09.classisctag包中编写标签处理器类Showtime.java,在类中定义一个User类型的成员变量user以及一个setUser(User user)方法,如例3所示。

例3 Showtime.java

 1  package cn.itcast.chapter09.simpletag;

 2  import java.io.IOException;

 3  import javax.servlet.jsp.JspException;

 4  import javax.servlet.jsp.JspWriter;

 5  import javax.servlet.jsp.PageContext;

 6  import javax.servlet.jsp.tagext.SimpleTagSupport;

 7  import cn.itcast.chapter09.domain.User;

 8  public class Showtime extends SimpleTagSupport {

 9    //定义user属性

 10   private User user;

 11   //提供setter方法

 12   public void setUser(User user) {

 13     this.user = user;

 14   }

 15   public void doTag() throws JspException {

 16      //获取pageContext对象

 17     PageContext pageContext = (PageContext) this.getJspContext();

 18      //获取out对象

 19     JspWriter out = pageContext.getOut();

 20     try {//输出用户名

 21       out.write("当前用户的名字:" + user.getName());

 22     } catch (IOException e) {

 23       e.printStackTrace();

 24     }

 25   }

 26 }

(3)在simpletag.tld文件中增加一个Tag元素,对标签处理器类Showtime进行注册,注册信息如下所示:

<tag>

  <name>showtime</name>

  <tag-class>cn.itcast.chapter09.simpletag.Showtime</tag-class>

  <body-content>scriptless</body-content>

  <attribute>

     <name>user</name>

     <required>true</required>

     <rtexprvalue>true</rtexprvalue>

  </attribute>

</tag>

由于标签<itcast: showtime user = "" />中的user属性接收一个JSP动态元素,因此在<attribute>元素中设置子元素<rtexprvalue>的值为true。

(4)编写JSP页面showtime.jsp,在页面中首先使用脚本片段在session域中存入一个User对象,并设置User对象的name属性值,然后使用<itcast:showtime user = "${user }" />标签,在标签中使用EL表达式将session域中的User对象传给user属性。showtime.jsp页面如例4所示。

例4 showtime.jsp

 1  <%@ page language="java" pageEncoding="GBK"

 2  import="cn.itcast.chapter09.domain.User"%>

 3  <%@taglib uri="/simpleTag" prefix="itcast"%>

 4  <html>

 5  <head>

 6  <title>showtime Tag</title>

 7  </head>

 8  <body>

 9  <%--向User对象中存值--%>

 10   <%

 11     User user = new User();

 12     user.setName("Conca");

 13     session.setAttribute("user", user);

 14   %>

 15   <itcast:showtime user="${user }" />

 16 </body>

 17 </html>

(5)启动Tomcat服务器,在浏览器地址栏输入URL地址http://localhost:8080/chapter09/showtime.jsp访问showtime.jsp页面,可以看到浏览器中显示出session域中User对象的name属性值,如图2所示。

图2 访问antiHotLinking.jsp页面

点击此处
隐藏目录