JSP第七篇【自定义标签就是如此简单】(修订版)(一)

简介: 为了简化标签开发的复杂度,在JSP 2.0中定义了一个更为简单、便于编写和调用的SimpleTag接口来实现标签的功能。。一般来说,实现了SimpeTag接口的标签称之为简单标签


SimpleTag接口


  • 首先我们来看一下它的源码吧
public interface SimpleTag extends JspTag {
    void doTag() throws JspException, IOException;
    void setParent(JspTag var1);
    JspTag getParent();
    void setJspContext(JspContext var1);
    void setJspBody(JspFragment var1);
}
  • setParent()和getParent()方法就不多说了,我们来看一下剩下的3个方法
void doTag() throws JspException, IOException;
void setJspContext(JspContext var1);
void setJspBody(JspFragment var1);
  • 明显地:
  • doTag()就是我们要写代码处理逻辑地方
  • setJspContext(JspContext var1)是将PageContext对象传递给标签处理器类(PageContext是JspContext的子类)
  • setJspBody(JspFragment var1)把代表标签体的JspFragment对象传递给标签处理器对象


快速入门


  • 一般地,我们做开发都是继承SimpleTagSupport类(该类实现了SimpleTag)来编写自定义标签
  • 下面我们就来个快速入门吧
  • 目标:传入字符串格式就可以显示想要的格式日期,对比之前传统标签的,看有什么不同之处
  • 标签处理器类:
public class Demo1 extends SimpleTagSupport {
    String format = null;
    @Override
    public void doTag() throws JspException, IOException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        this.getJspContext().getOut().write(simpleDateFormat.format(new Date()));
    }
    public String getFormat() {
        return format;
    }
    public void setFormat(String format) {
        this.format = format;
    }
}
  • tld文件:
<tag>
    <name>formatDate</name>
    <tag-class>tag.Demo1</tag-class>
    <body-content>tagdependent</body-content>
    <attribute>
        <name>format</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
</tag>
  • 效果:

1.png2.png

  • 简单标签的好处就是不用去理会doStartTag、doEndTag、SKIP_BODY以及一系列的方法和属性!
  • 简单标签一个doTag()方法走天下!


SimpleTagSupport类的执行顺序:


  • ①WEB容器调用标签处理器对象的setJspContext方法,将代表JSP页面的pageContext对象传递给标签处理器对象
  • ②WEB容器调用标签处理器对象的setParent方法,将父标签处理器对象传递给这个标签处理器对象。【注意,只有在标签存在父标签的情况下,WEB容器才会调用这个方法】
  • ③如果调用标签时设置了属性,容器将调用每个属性对应的setter方法把属性值传递给标签处理器对象。如果标签的属性值是EL表达式或脚本表达式,则WEB容器首先计算表达式的值,然后把值传递给标签处理器对象。
  • ④如果简单标签有标签体,容器将调用setJspBody方法把代表标签体的JspFragment对象传递进来
  • ⑤执行标签时:容器调用标签处理器的doTag()方法,开发人员在方法体内通过操作JspFragment对象,就可以实现是否执行、迭代、修改标签体的目的。

3.png


深入简单标签


在我们讲解传统标签的时候,配合着SKIP_BODY、SKIP_PAGE等变量可以实现如下的功能:

  1. 控制jsp页面某一部分内容(标签体)是否执行
  2. 控制整个jsp页面是否执行
  3. 控制jsp页面内容重复执行
  4. 修改jsp页面内容输出

  • 简单标签可没有这些变量呀,那它怎么才能实现上面那些功能呢?
  • 在doTag方法中可以抛出javax.servlet.jsp.SkipPageException异常,用于通知WEB容器不再执行JSP页面中位于结束标记后面的内容,这等效于在传统标签的doEndTag方法中返回Tag.SKIP_PAGE常量的情况,我们来测试一下,在上面例子的代码中添加
throw new SkipPageException();
  • 效果:

4.png

  • 至于其他的功能下面会讲到


带标签体的简单标签


  • SimpleTagSupport也可以带标签体,但是处理方法和传统标签完全不同
  • 传统标签是这样子的:将标签体的内容通过setBodyContent()注入到BodyContent对象中。
  • 简单标签是这样子的:通过JspFragment对象实现!
  • 我们来看一下JspFragment对象的源码吧
public abstract class JspFragment {
    public JspFragment() {
    }
    public abstract void invoke(Writer var1) throws JspException, IOException;
    public abstract JspContext getJspContext();
}

JspFragment对象十分简单,重要的只有invoke(Writer var1)方法(获取JspContext对象并不重要,在标签描述器上就可以获取到了)

public abstract void invoke(java.io.Writer out) :

  • 用于执行JspFragment对象所代表的JSP代码片段
  • 参数out用于指定将JspFragment对象的执行结果写入到哪个输出流对象中,如果传递给参数out的值为null,则将执行结果写入到JspContext.getOut()方法返回的输出流对象中。(简而言之,可以理解为写给浏览器)

  • 下面是标签处理器类的代码
public class Demo1 extends SimpleTagSupport {
    @Override
    public void doTag() throws JspException, IOException {
        //得到代表标签体的对象
        JspFragment jspFragment = getJspBody();
        //invoke方法接收的是一个Writer,如果为null,就代表着JspWriter(),将标签体的数据写给浏览器!
        jspFragment.invoke(null);
    }
}
  • 效果:

5.png

  • 既然标签体的内容是通过JspFragment对象的invoke()方法写给浏览器的,那么那么那么,我只要控制好invoke()方法,我想干什么就干什么!
  • 也就是说:
  • 不调用invoke()方法,标签体内容就不会输出到浏览器上
  • 重复调用invoke()方法,标签体内容就会被重复执行
  • 若想在标签处理器中修改标签体内容,只需在调用invoke方法时指定一个可取出结果数据的输出流对象(例如StringWriter),让标签体的执行结果输出到该输出流对象中,然后从该输出流对象中取出数据进行修改后再输出到目标设备,即可达到修改标签体的目的
  • 来来来,我们来试验一下:
  • 不调用invoke()方法
public void doTag() throws JspException, IOException {
    //得到代表标签体的对象
    JspFragment jspFragment = getJspBody();
    //jspFragment.invoke(null);
}
  • 标签体的内容没有输出
    6.png
  • 调用两次invoke()方法
public void doTag() throws JspException, IOException {
    //得到代表标签体的对象
    JspFragment jspFragment = getJspBody();
    jspFragment.invoke(null);
    jspFragment.invoke(null);
}
  • 标签体的内容被输出了两次
    7.png
  • invoke()方法指定别的输出流(StringWriter),将标签体的内容写到流对象中,再通过流对象把数据取出来,达到修改的目的。
//得到代表标签体的对象
JspFragment jspFragment = getJspBody();
//创建可以存储字符串的Writer对象
StringWriter stringWriter = new StringWriter();
//invoke()方法把标签体的数据都写给流对象中
jspFragment.invoke(stringWriter);
//把流对象的数据取出来,流对象的数据就是标签体的内容
String value = stringWriter.toString();
//将数据改成是大写的,写到浏览器中
getJspContext().getOut().write(value.toUpperCase());
  • 标签体的内容被改成了大写!

8.png

我们可以发现,传统标签能完成的功能,简单标签都可以完成,并且更为简单!



自定义标签的应用


既然我们学了简单标签,我们就用简单标签来做开发吧!

防盗链

在讲解request对象的时候,我们讲解过怎么实现防盗链的功能。现在我们使用标签来进行防盗链

模拟下场景:1.jsp页面是海贼王资源,2.jsp页面提示非法盗链,index1.jsp是我的首页。别人想要看我的海贼王资源,就必须通过我的首页点进去看,否则就是非法盗链!

  • 标签处理器的代码
@Override
public void doTag() throws JspException, IOException {
    //如果想要做成更加灵活的,就把站点设置和资源设置成标签属性传递进来!
    //等会我们要获取得到request对象,需要使用到JspContext的子类PageContext
    PageContext pageContext = (PageContext) this.getJspContext();
    //获取request对象
    HttpServletRequest httpServletRequest = (HttpServletRequest) pageContext.getRequest();
    //获取到referer
    String referer = httpServletRequest.getHeader("Referer");
    //获取到response对象,等会如果是非法盗链,就重定向别的页面上
    HttpServletResponse httpServletResponse = (HttpServletResponse) pageContext.getResponse();
    //非法盗链!
    if (referer == null || !referer.startsWith("http://localhost:8080/zhongfucheng")) {
        //2.jsp提示了非法盗链!
        httpServletResponse.sendRedirect("/zhongfucheng/2.jsp");
        //不执行页面下面的内容了,保护页面
        throw new SkipPageException();
    }
}
  • 1.jsp代码:
<zhongfucheng:Referer/>
<html>
<head>
    <title></title>
</head>
<body>
海贼王最新资源
</body>
</html>
  • index1.jsp代码
<h1>这是首页!</h1>
<a href="${pageContext.request.contextPath}/1.jsp"> 海贼王最新资源</a>
  • 2.jsp代码
<body>
你是非法盗链的!!!!!!
</body>
  • 第一次我是直接访问1.jsp,Referer是为空的,所以是非法盗链。第二次我是通过从首页点进去看的,所以可以访问1.jsp。效果图:

9.gif


if标签


在JSTL中,我们已经使用过了<c:if/>标签了,现在我们学习了自定义标签,可以开发类似于JSTL的if标签了!

既然是if标签,那么就需要编写带属性和带标签体的标签(需要判断是true还是false呀!,通过判断是否为真值来决定是否执行标签体的内容)

  • 标签处理器代码
public class Demo1 extends SimpleTagSupport {
    //定义一个Boolean类型的变量
    boolean test ;
    @Override
    public void doTag() throws JspException, IOException {
        //获取到代表标签体内容的对象
        JspFragment jspFragment = this.getJspBody();
        //如果为真值才执行标签体的内容
        if (test == true) {
            jspFragment.invoke(null);
        }
    }
    public boolean isTest() {
        return test;
    }
    public void setTest(boolean test) {
        this.test = test;
    }
}
  • tld文件的代码
<tag>
    <name>if</name>
    <tag-class> tag.Demo1</tag-class>
    <body-content>scriptless</body-content>
    <attribute>
        <name>test</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
</tag>
  • 本来就没有user这个域对象属性,所以user就是为null

10.png

  • 将user改成不为null,浏览器就没有输出了

11.png

目录
相关文章
|
Java
JSP自定义标签【下】
JSP自定义标签【下】
65 0
|
Java
jsp自定义标签
jsp自定义标签
75 1
|
5月前
|
Java 容器
JSP 教程 之 JSP 自定义标签 3
JSP自定义标签允许开发人员创建可重用的组件,简化页面逻辑。在JSP 2.0及以上版本,可通过继承`SimpleTagSupport`并覆写`doTag()`方法来创建自定义标签,如`HelloTag`,它有一个`message`属性。属性值通过setter方法`setMessage()`设置。在TLD文件中定义该属性后,可在JSP页面使用`&lt;ex:Hello message=&quot;This is custom tag&quot;/&gt;`来调用,输出定制的文本。
26 0
|
5月前
|
Java 容器
JSP 教程 之 JSP 自定义标签 4
**JSP自定义标签允许创建用户定义的语言元素。它们转换为Servlet中的tag handler,在执行时由Web容器调用。使用SimpleTagSupport继承并重写doTag()方法可创建简单标签。标签可设置属性,如message,通过setter方法访问。TLD文件定义属性元数据,JSP页面则通过prefix和uri引用。例如,&lt;ex:Hello message=&quot;...&quot;/&gt; 显示定制消息。属性可配置为必需、类型、描述及是否为JspFragment。**
29 0
|
5月前
|
搜索推荐 Java 容器
JSP 教程 之 JSP 自定义标签 2
**JSP自定义标签允许用户创建个性化标签,简化页面逻辑。在JSP 2.0中,通过继承`SimpleTagSupport`并重写`doTag()`可创建简单标签处理器。示例展示了一个名为`Hello`的自定义标签,它接收并显示标签体内容。TLD文件配置了标签元数据,JSP页面引用该标签并展示“这是消息主体”。**
24 0
|
5月前
|
Java 容器
JSP 教程 之 JSP 自定义标签 1
**JSP自定义标签简介**:扩展JSP功能,创建用户定义标签,通过Servlet容器调用Tag Handler。在JSP 2.0中,使用SimpleTagHandlers简化定制。以&quot;Hello&quot;标签为例,创建`HelloTag`类继承`SimpleTagSupport`,重写`doTag()`打印消息。编译后,在`custom.tld`定义标签库,JSP页面引用后即可使用。例如 `&lt;ex:Hello/&gt;` 显示 &quot;Hello Custom Tag!&quot;。
28 0
|
前端开发 Java
通用分页进阶之jsp之自定义标签
通用分页进阶之jsp之自定义标签
35 1
|
6月前
|
Java 数据安全/隐私保护
Jsp自定义标签(foreach,dept,select)
Jsp自定义标签(foreach,dept,select)
48 0
|
6月前
|
XML Java 数据格式
JSP自定义标签
JSP自定义标签
69 0
|
存储 Java 开发者
JSP自定义标签(下)
JSP自定义标签(下)
57 0