0

0

JSP Tag 文件中实现完全求值 Body 内容的方法

碧海醫心

碧海醫心

发布时间:2025-07-10 18:56:15

|

875人浏览过

|

来源于php中文网

原创

jsp tag 文件中实现完全求值 body 内容的方法

本文探讨了在 JSP Tag 文件中实现完全求值 Body 内容的方法,类似于 Java 类中 BodyTag 接口的 EVAL_BODY_INCLUDE 功能。由于 JSP Tag 文件本身的限制,直接支持完整的 JSP 代码(包括 Scriptlet 和表达式)是不可能的。本文将解释这一限制,并提供替代方案。

JSP Tag 文件提供了一种方便的方式来封装和重用 JSP 代码片段。然而,它们在处理 Body 内容时存在一些限制。一个常见的问题是如何让 Tag 文件支持其 Body 中包含完整的 JSP 代码,包括 Scriptlet (<% ... %>) 和表达式 (<%= ... %>)。

Tag 文件 Body 内容的限制

在 Tag 文件中,body-content 属性用于指定 Body 内容的类型。常用的值包括:

  • empty: Tag 没有 Body 内容。
  • scriptless: Tag 的 Body 内容可以包含 EL 表达式和 JSTL 标签,但不能包含 Scriptlet。
  • tagdependent: Tag 的 Body 内容由 Tag 自身处理,JSP 引擎不会对其进行解释。

遗憾的是,没有一个 body-content 的值允许在 Tag 文件的 Body 中使用完整的 JSP 代码。尝试这样做会导致类似于 "Scripting elements are disallowed here" 的错误。

示例:无法在 Tag 文件中使用 Scriptlet

考虑以下 Tag 文件 dialog.tag:

<%@tag pageEncoding="UTF-8" body-content="scriptless" %>

<div class="dialog">
    <jsp:doBody />
</div>

以及使用它的 Tag 文件 use-dialog.tag:

<%@tag pageEncoding="UTF-8" %>
<%@attribute name="someAttribute" type="java.lang.String" required="false" %>
<%@taglib prefix="mytaglib" uri="/WEB-INF/tlds/mytaglib" %>

<mytaglib:dialog>
    <%-- 使用变量 --%>
    Hello <%= someAttribute %>

    <%-- 使用其他标签 --%>
    <mytaglib:some-other-tag someParameter="5" />
</mytaglib:dialog>

这段代码会抛出异常,因为 dialog.tag 的 Body 中包含了 Scriptlet 表达式 (<%= someAttribute %>)。

使用 Java 类实现 BodyTag

知我AI
知我AI

一款多端AI知识助理,通过一键生成播客/视频/文档/网页文章摘要、思维导图,提高个人知识获取效率;自动存储知识,通过与知识库聊天,提高知识利用效率。

下载

解决这个限制的唯一方法是使用 Java 类来实现 BodyTag 接口。BodyTag 允许你完全控制 Body 内容的处理方式。

以下是一个 Dialog.java 的示例:

import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyTag;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.JspException;
import java.io.IOException;

public class Dialog implements BodyTag {

    private PageContext pageContext;
    private Tag parent;
    private BodyContent bodyContent;

    @Override
    public void setPageContext(PageContext pageContext) {
        this.pageContext = pageContext;
    }

    @Override
    public void setParent(Tag parent) {
        this.parent = parent;
    }

    @Override
    public Tag getParent() {
        return parent;
    }

    @Override
    public void setBodyContent(BodyContent bodyContent) {
        this.bodyContent = bodyContent;
    }

    @Override
    public void doInitBody() throws JspException {
        // 可选:在 Body 内容求值之前执行一些初始化操作
    }

    @Override
    public int doStartTag() throws JspException {
        try {
            JspWriter out = pageContext.getOut();
            out.print("<div class=\"dialog\">");
        } catch (IOException e) {
            throw new JspException(e);
        }
        return EVAL_BODY_BUFFERED; //  EVAL_BODY_INCLUDE 已经过时,推荐使用 EVAL_BODY_BUFFERED
    }

    @Override
    public int doEndTag() throws JspException {
        try {
            JspWriter out = pageContext.getOut();
            if (bodyContent != null) {
                out.print(bodyContent.getString()); // 输出 Body 内容
            }
            out.print("</div>");
        } catch (IOException e) {
            throw new JspException(e);
        } finally {
            if (bodyContent != null) {
                try {
                    bodyContent.clear(); // 清理 BodyContent
                } catch (IOException e) {
                    // ignore
                }
            }
        }
        return EVAL_PAGE; // 继续评估 JSP 页面
    }

    @Override
    public void release() {
        pageContext = null;
        parent = null;
        bodyContent = null;
    }
}

关键点:

  • setPageContext(PageContext pageContext): 设置 PageContext 对象,允许访问 JSP 页面上下文。
  • doStartTag(): 在 Tag 开始标签处执行,输出 <div class="dialog">。EVAL_BODY_BUFFERED 指示容器评估 Tag 的 Body 并将其存储在 BodyContent 对象中。
  • doEndTag(): 在 Tag 结束标签处执行,输出 </div>。在此方法中,我们从 bodyContent 获取 Body 内容并将其输出。
  • release(): 释放资源,这是一个好习惯。

使用 Java Tag

为了使用 Java Tag,需要在 TLD 文件中声明它。例如,如果你的 TLD 文件是 mytaglib.tld,你可以添加以下内容:

<tag>
    <name>dialog</name>
    <tag-class>com.example.Dialog</tag-class>
    <body-content>JSP</body-content>
</tag>

然后,你可以像这样在 JSP 页面中使用它:

<%@taglib prefix="mytaglib" uri="/WEB-INF/tlds/mytaglib.tld" %>

<mytaglib:dialog>
    <%-- 使用变量 --%>
    Hello <%= request.getParameter("name") %>

    <%-- 使用其他标签 --%>
    <mytaglib:some-other-tag someParameter="5" />
</mytaglib:dialog>

总结

虽然 JSP Tag 文件提供了一种便捷的方式来创建可重用的组件,但它们在处理包含完整 JSP 代码的 Body 内容时存在限制。要实现完全求值的 Body 内容,你需要使用 Java 类来实现 BodyTag 接口。这种方法允许你完全控制 Body 内容的处理方式,并支持 Scriptlet 和表达式。这种方式虽然稍微复杂,但提供了更大的灵活性和控制力。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

2008

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

681

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2440

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

49

2026.01.19

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

931

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

32

2025.12.06

jsp分页功能如何实现
jsp分页功能如何实现

当数据有几万、几十万甚至上百万时,户必须要拖动页面才能浏览更多的数据,很大程度的影响了户体验。这时可以使用分页来显示数据,能够使数据更加清晰直观,环受数量的限制。php中文网为大家带来了jsp分页功能相关教程、以及相关文章等内容,供大家免费下载使用。

103

2023.06.21

jsp怎么打开
jsp怎么打开

打开jsp的步骤是安装Java开发环境、配置Web服务器、创建JSP文件、部署到Web服务器、启动Web服务器、在浏览器中访问JSP页面。本专题为大家提供jsp相关的文章、下载、课程内容,供大家免费下载体验。

132

2023.10.08

chatgpt使用指南
chatgpt使用指南

本专题整合了chatgpt使用教程、新手使用说明等等相关内容,阅读专题下面的文章了解更多详细内容。

0

2026.03.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
誉天教育RHCE视频教程
誉天教育RHCE视频教程

共9课时 | 1.5万人学习

尚观Linux RHCE视频教程(二)
尚观Linux RHCE视频教程(二)

共34课时 | 6.1万人学习

尚观RHCE视频教程(一)
尚观RHCE视频教程(一)

共28课时 | 4.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号