JSP Tag File 实战:打造 Layui 后台管理布局模板
前言
在 Java Web 开发中,我们经常遇到一个问题:后台管理系统的头部、侧边栏、底部是固定的,每个页面都要重复写一遍这些 HTML 结构,不仅代码臃肿,维护起来也非常痛苦。
传统的做法是用<%@ include %>静态包含,但这种方式不够灵活——每个页面还是得手动引入多个文件。本文将介绍一种更优雅的解决方案:利用 JSP Tag File 创建布局模板,配合 Layui 前端框架,打造一个干净、可复用的后台管理布局。
先来看最终效果:我们创建一个Layout.tag标签文件,在任何 JSP 页面中只需几行代码就能生成完整的后台管理页面。
一、什么是 JSP Tag File
Tag File 是 JSP 2.0 引入的一种技术,它允许开发者用 JSP 语法来创建自定义标签,而不需要编写 Java 类。
简单来说,Tag File 就是一个扩展名为.tag的文本文件,结构和 JSP 文件非常相似。它被放置在WEB-INF/tags/目录下,可以被任何 JSP 页面像使用普通标签一样调用。
Tag File 最大的优势是:不懂 Java 的人也能编写,只需要掌握 JSP 语法即可。
二、项目结构与准备工作
2.1 目录结构
前端项目结构
你的Web项目/ ├── WEB-INF/ │ |── jsp/ | | └── views/ │ | └── user/ │ └── index.jsp ← 视图界面 │ ├── tags/ ← 存放所有 tag 文件 │ │ └── layout/ │ │ └── Layout.tag ← 我们的布局模板 │ └── components/ │ ├── app.jsp ← 公共资源引入(CSS/JS) │ └── layout/ │ ├── Header.jsp ← 头部组件 │ └── Side.jsp ← 侧边栏组件 ├── res/ │ └── layui/ ← Layui 前端框架 └── 项目结构2.2 引入 Layui
Layui 是一款轻量级、模块化的前端 UI 框架,提供了完善的后台布局方案。你需要将 Layui 的资源文件放入res/layui/目录下。
三、Layout.tag 标签文件详解
公共资源的app.jsp代码:
<meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="<%= request.getContextPath() %>/res/layui/css/layui.css" rel="stylesheet" /> <script src="<%= request.getContextPath() %>/res/twcss/browser@4.js"></script> <script src="<%= request.getContextPath() %>/res/jquery/jquery-3.5.1.min.js"></script> <script type="text/javascript" src="<%= request.getContextPath() %>/res/jquery/jquery_Extend.js"></script> <script src="<%= request.getContextPath() %>/res/layui/layui.js"></script>下面是完整的Header.jsp代码:
<div class="layui-header"> <div class="layui-logo layui-hide-xs layui-bg-black">layout demo</div> <!-- 头部区域(可配合layui 已有的水平导航) --> <ul class="layui-nav layui-layout-left"> <!-- 移动端显示 --> <li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-header-event="menuLeft"> <i class="layui-icon layui-icon-spread-left"></i> </li> <li class="layui-nav-item layui-hide-xs"><a href="javascript:;">nav 1</a></li> <li class="layui-nav-item layui-hide-xs"><a href="javascript:;">nav 2</a></li> <li class="layui-nav-item layui-hide-xs"><a href="javascript:;">nav 3</a></li> <li class="layui-nav-item"> <a href="javascript:;">nav groups</a> <dl class="layui-nav-child"> <dd><a href="javascript:;">menu 11</a></dd> <dd><a href="javascript:;">menu 22</a></dd> <dd><a href="javascript:;">menu 33</a></dd> </dl> </li> </ul> <ul class="layui-nav layui-layout-right"> <li class="layui-nav-item layui-hide layui-show-sm-inline-block"> <a href="javascript:;"> <img src="//unpkg.com/outeres@0.0.10/img/layui/icon-v2.png" class="layui-nav-img"> tester </a> <dl class="layui-nav-child"> <dd><a href="javascript:;">Your Profile</a></dd> <dd><a href="javascript:;">Settings</a></dd> <dd><a href="javascript:;">Sign out</a></dd> </dl> </li> <%--<li class="layui-nav-item" lay-header-event="menuRight" lay-unselect> <a href="javascript:;"> <i class="layui-icon layui-icon-more-vertical"></i> </a> </li>--%> </ul> </div>下面是完整的Side.jsp代码:
<div class="layui-side layui-bg-black"> <div class="layui-side-scroll"> <ul class="layui-nav layui-nav-tree" lay-filter="menuInfo"> <li class="layui-nav-item layui-nav-itemed"> <a class="" href="javascript:;">menu group 1</a> <dl class="layui-nav-child"> <dd><a href="javascript:;" url="user/index">menu 1</a></dd> <dd><a href="javascript:;" url="park/index">menu 2</a></dd> <dd><a href="javascript:;" url="menu3">menu 3</a></dd> <dd><a href="javascript:;" url="menu4">the links</a></dd> </dl> </li> </ul> </div> </div>下面是完整的Layout.tag代码:
<%@ tag body-content="scriptless" pageEncoding="UTF-8" %> <%@ attribute name="title" required="false" %> <!DOCTYPE html> <html> <head> <jsp:include page="/WEB-INF/components/app.jsp" /> <title>${title}</title> <style>.layui-body { padding: 16px; }</style> </head> <body> <script src="<%= request.getContextPath() %>/res/layui/layui.js"></script> <div class="layui-layout layui-layout-admin"> <jsp:include page="/WEB-INF/components/layout/Header.jsp" /> <jsp:include page="/WEB-INF/components/layout/Side.jsp" /> <div class="layui-body"> <jsp:doBody /> </div> <div class="layui-footer">底部固定区域</div> </div> <script></script> </body> </html>3.1 第一行:tag 指令
<%@ tag body-content="scriptless" pageEncoding="UTF-8" %>
这是 Tag File 的核心指令:
body-content="scriptless":表示标签体内容不能包含 JSP 脚本片段(即<% ... %>这种写法),只能使用 EL 表达式(${...})和 HTML。这是 JSP 2.0 推崇的"无脚本"开发方式。pageEncoding="UTF-8":指定文件编码为 UTF-8。
3.2 attribute 指令:定义标签属性
<%@ attribute name="title" required="false" %>
attribute指令用于定义标签的属性:
name="title":属性名,使用标签时通过这个名称传值。required="false":该属性不是必填的。如果设为true,使用标签时必须提供该属性。
在标签体中,我们可以通过${title}来获取这个属性的值。
3.3 公共资源引入
<jsp:include page="/WEB-INF/components/app.jsp" />
通过request.getContextPath()动态获取项目根路径,确保资源路径在任何部署环境下都能正确访问。
四、如何使用布局模板
4.1 在 JSP 页面中引入标签库
jsp
<%@ taglib tagdir="/WEB-INF/tags/layout" prefix="layout" %>
tagdir:指定 Tag File 所在的目录。prefix:给这个标签库起一个前缀,使用时通过前缀:标签名的方式调用。
4.2 使用布局标签
对应的控制器:
@RequestMapping(value = "/user/index",method = RequestMethod.GET) public ModelAndView user() { ModelAndView view = new ModelAndView(); view.setViewName("/views/user/index"); view.addObject("msg","sssss"); return view; }<%@ taglib tagdir="/WEB-INF/tags/layout" prefix="t" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <t:layout title="用户管理"> <div>用户管理</div> </t:layout>效果:
浏览器标题显示"用户管理"(通过
title属性传入)。自动引入头部、侧边栏、底部。
标签中间的内容(用户列表表格)被渲染到
layui-body区域。
五、核心概念总结
5.1 body-content="scriptless" 的意义
这个设置强制标签体内容不能包含 JSP 脚本片段(<% ... %>),只能使用 EL 表达式和 JSTL 标签。
✅ 允许的写法:
<layout:Layout title="${pageTitle}"> <c:forEach items="${userList}" var="user"> <tr><td>${user.name}</td></tr> </c:forEach> </layout:Layout>❌ 禁止的写法:
<layout:Layout title="<%= request.getParameter("title") %>"> <% String name = "test"; %> </layout:Layout>这样做的好处是强制实现了表现层与业务逻辑的分离,让 JSP 页面更加干净、易于维护。
5.2 Tag File vs JSP Include
| 对比项 | Tag File | JSP Include |
|---|---|---|
| 复用方式 | 作为自定义标签使用 | 静态/动态包含 |
| 传参能力 | 支持 attribute 传参 | 有限(可通过 request 传参) |
| 标签体 | 支持jsp:doBody插槽 | 不支持 |
| 灵活性 | 高,可像普通标签一样使用 | 较低,只是单纯包含 |
| 学习成本 | 稍高 | 低 |
Tag File 本质上提供了一种比 JSP Include 更强大的页面模板化方法。
5.3 Tag File 的存放位置
Tag File 必须存放在WEB-INF/tags/目录或其子目录下。这是因为:
WEB-INF目录下的文件对客户端不可见,保证了安全性。Tomcat 服务器会在这个指定目录中查找 Tag File。
六、总结
本文通过一个完整的 Layui 后台管理布局示例,介绍了 JSP Tag File 的核心用法:
Tag File 是什么:用 JSP 语法创建自定义标签的技术。
如何创建:在
WEB-INF/tags/下创建.tag文件,使用tag指令和attribute指令。核心机制:
jsp:doBody作为内容插槽,body-content="scriptless"保证代码规范。如何使用:通过
taglib指令引入,像普通标签一样调用。
通过这种方案,你可以将后台管理系统的公共布局抽取为一个标签文件,所有页面共用一套头部、侧边栏和底部,只需关注各自的主体内容。这不仅减少了大量重复代码,也让页面维护变得异常简单——修改一次布局,所有页面同步更新。
希望这篇教程对你有所帮助!如果有任何问题,欢迎在评论区交流讨论。
