JSTL 与 JSON 的优雅邂逅:在 JSP 中轻松处理 JSON 数据**
在 Java Web 开发的早期阶段,JSP(JavaServer Pages)结合 JSTL(JSP Standard Tag Library)是动态页面开发的主流技术,JSTL 提供了一系列标准标签,如 <c:if>, <c:forEach> 等,极大地简化了 JSP 页面中的 Java 代码嵌入,使得页面逻辑更清晰、更易于维护,随着前后端分离架构的兴起和 RESTful API 的普及,JSON (JavaScript Object Notation) 逐渐成为数据交换的事实标准,在传统的 JSP/JSTL 环境下,如何优雅地处理和展示 JSON 数据呢?本文将探讨 JSTL 与 JSON 结合使用的几种方法。
为什么在 JSP/JSTL 中需要处理 JSON?
在前后端分离模式下,JSP 通常只负责渲染视图,数据通过 AJAX 请求从后端 API(通常返回 JSON)获取,但在某些场景下,我们可能仍然需要在服务器端将 Java 对象转换为 JSON,并直接在 JSP 页面中使用 JSTL 进行展示,
- 简单的数据展示页面:对于一些不需要复杂交互的页面,直接在服务器端生成 JSON 并传递给 JSP 可以减少前后端沟通成本。
- 遗留系统集成:在维护或改造旧系统时,可能需要将现有 Java 对象以 JSON 形式展示在 JSP 页面。
- 服务端渲染的部分 JSON 数据:虽然主流是前端渲染,但有时也需要服务端先处理部分数据并以 JSON 形式嵌入。
JSTL 直接处理 JSON 的局限性
需要明确的是,JSTL 本身并不直接提供解析 JSON 数据的标签,JSTL 主要用于处理 XML 形式的数据(如 <sql:query> 返回的 ResultSet 可以转换为 XML)或者简单的 Java 集合/数组,如果我们尝试直接使用 JSTL 标签遍历一个 JSON 字符串,
<c:forEach var="item" items="${jsonString}">
${item.name}
</c:forEach>
这显然是行不通的,因为 ${jsonString} 是一个普通的 Java 字符串,<c:forEach> 无法识别其 JSON 结构并迭代其中的元素。
在 JSP/JSTL 中使用 JSON 的常用方法
既然 JSTL 不能直接处理 JSON,我们需要借助其他技术来桥接这两者,以下是几种常见的实现方式:
使用第三方 JSON 库在 Servlet 中转换,然后存入作用域
这是最常用且推荐的方法,在 Servlet 控制器中,将 Java 对象转换为 JSON 字符串,然后将该字符串存入 request、session 或 application 作用域中,最后在 JSP 页面中使用 JSTL 结合 EL 表达式进行解析和展示,解析 JSON 可以使用专门的 JSTL 扩展标签库或者 JavaScript。
步骤:
- 添加 JSON 处理库依赖:如 Jackson, Gson, or org.json。
- Maven 示例 (Jackson):
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.0</version> <!-- 使用最新稳定版本 --> </dependency>
-
在 Servlet 中转换 Java 对象为 JSON 并存入作用域:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List<User> users = userService.getAllUsers(); // 假设获取到用户列表 // 使用 Jackson 将 List<User> 转换为 JSON 字符串 ObjectMapper objectMapper = new ObjectMapper(); String usersJson = objectMapper.writeValueAsString(users); // 将 JSON 字符串存入 request 作用域 request.setAttribute("usersJson", usersJson); request.getRequestDispatcher("/users.jsp").forward(request, response); } -
在 JSP 页面中使用 JSTL 和 JavaScript 解析 JSON:
-
方案 A:使用 JSTL 的
<c:if>等标签结合 JavaScript 处理<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>用户列表 (JSON + JSTL/JS)</title> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> </head> <body> <h1>用户列表</h1> <ul id="userList"> <!-- JSTL 无法直接遍历 JSON 字符串,这里用 JS 处理 --> </ul> <script> $(document).ready(function() { // 从 JSTL/EL 获取 JSON 字符串 var usersJson = '${usersJson}'; // 注意:直接 ${usersJson} 可能存在 XSS 风险,如果数据不可信,需要转义 // 更安全的做法是使用 JSTL 的 fn:escapeXml 函数,或者确保数据来源可信 try { var usersArray = JSON.parse(usersJson); $.each(usersArray, function(index, user) { $("#userList").append("<li>" + user.name + " - " + user.email + "</li>"); }); } catch (e) { console.error("JSON 解析错误:", e); $("#userList").append("<li>加载数据失败</li>"); } }); </script> </body> </html> -
方案 B:使用 JSTL JSON 标签库 (如 JSTL-Fmt 的扩展或自定义标签) 存在一些专门为 JSTL 设计的 JSON 处理标签库,
jstl-json(非官方,可能需要额外配置或自定义),这些库可能会提供类似<json:parse>的标签来解析 JSON 字符串,并将其转换为 JSTL 可识别的集合对象。 假设有一个自定义的json:parse<%@ taglib prefix="json" uri="http://example.com/tags/jstl-json" %> ... <json:parse var="users" json="${usersJson}"/>
<c:forEach var="user" items="${users}">
<c:out value="${user.name}"/> - <c:out value="${user.email}"/><br/>
</c:forEach>
```
但这种方法需要额外引入特定库,并且不如方案 A 灵活通用。
在 JSP 中直接使用 Java 代码片段 (不推荐)
虽然不推荐在 JSP 中嵌入大量 Java 代码,但对于简单的 JSON 解析,可以使用脚本片段(<% %>)结合 JSON 库:
<%@ page import="com.fasterxml.jackson.databind.ObjectMapper" %>
<%@ page import="java.util.List" %>
<%@ page import="com.example.User" %>
<%
List<User> users = (List<User>) request.getAttribute("users"); // 假设直接传了对象
ObjectMapper mapper = new ObjectMapper();
String usersJson = mapper.writeValueAsString(users);
request.setAttribute("usersJson", usersJson); // 再存回
%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
...
<script>
var users = JSON.parse('${usersJson}'); // 同样注意 XSS
// 遍历 users...
</script>
这种方法违背了 JSP 的设计初衷(视图与逻辑分离),应尽量避免。
使用 JSP 作为数据接口返回纯 JSON (不涉及 JSTL 展示)
如果目标仅仅是让 JSP 返回 JSON 数据,那么可以在 JSP 中设置响应头,并直接输出 JSON 字符串,不使用 JSTL 进行页面渲染:
<%@ page contentType="application/json;charset=UTF-8" language="java" %>
<%@ page import="com.fasterxml.jackson.databind.ObjectMapper" %>
<%@ page import="java.util.List" %>
<%@ page import="com.example.User" %>
<%
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
List<User> users = userService.getAllUsers(); // 获取数据
ObjectMapper mapper = new ObjectMapper();
String usersJson = mapper.writeValueAsString(users);
out.print(usersJson);
%>
这种方式下,JSTL 没有用武之地,因为 JSP 不再负责视图渲染,而是作为数据源。
最佳实践与注意事项
- 优先考虑前后端分离:对于新的 Web 应用,强烈推荐前后端分离架构,后端提供 RESTful API 返回 JSON,前端使用 Vue, React, Angular 或原生/AJAX 获取数据并渲染。
- **服务器端 JSON �



还没有评论,来说两句吧...