You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JSTL中动态修改Map键值对——Spring MVC+JSP场景

解决JSP循环中修改Map键值对(用于XSS防护)的几种方案

嘿,这个需求很常见,尤其是做XSS防护的时候!针对你用Spring MVC + JSP构建的应用,要在遍历Map时修改mapItem的键和值,这里有几个实用的方案,适配不同的场景:

1. 用JSTL的fn:escapeXml直接转义输出(最推荐)

如果你的核心需求是XSS防护,最规范的做法是在输出时对内容做HTML转义,而不是修改原Map的数据。JSTL的fn标签库自带的escapeXml函数,可以自动把HTML特殊字符(比如<转成&lt;)转义成纯文本,避免恶意脚本被浏览器执行。

步骤很简单:

  • 先引入fn标签库
  • 输出key和value时用fn:escapeXml包裹

修改后的JSP代码:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<%@ page import="java.util.ArrayList"%>
<%@ page import="java.util.HashMap"%>
<% 
ArrayList<HashMap<String, String>> listOfMap = new ArrayList<HashMap<String, String>>(); 
HashMap<String, String> map; 
for (int i = 0; i < 3; i++) { 
    map = new HashMap<String, String>(); 
    map.put("key1", "value1" + i); 
    map.put("key2", "<script>alert('xss')</script>" + i); // 模拟恶意内容
    listOfMap.add(map); 
} 
request.setAttribute("listOfMap", listOfMap); 
%>
<html>
<body>
<c:forEach items="${listOfMap}" var="maps">
    <c:forEach items="${maps}" var="mapItem">
        ${fn:escapeXml(mapItem.key)} ${fn:escapeXml(mapItem.value)} <br />
    </c:forEach>
</c:forEach>
</body>
</html>

这样输出的内容会被安全转义,恶意代码只会显示成普通文本,完美解决XSS问题。

2. 在循环内用<c:set>自定义处理键值

如果你除了XSS防护,还需要对key或value做其他自定义修改(比如加前缀、截断长度),可以用<c:set>标签在循环里创建处理后的变量,再输出:

<c:forEach items="${listOfMap}" var="maps">
    <c:forEach items="${maps}" var="mapItem">
        <%-- 处理key:转义后加个前缀 --%>
        <c:set var="processedKey" value="${fn:escapeXml(mapItem.key)}_processed" />
        <%-- 处理value:转义后只取前10个字符 --%>
        <c:set var="processedValue" value="${fn:escapeXml(fn:substring(mapItem.value, 0, 10))}" />
        ${processedKey} ${processedValue} <br />
    </c:forEach>
</c:forEach>

这种方式灵活度很高,你可以根据需求随便调整处理逻辑。

3. 后端提前处理数据(符合Spring MVC最佳实践)

Spring MVC的最佳实践是尽量少在JSP里写业务逻辑,所以更推荐你在Controller层就把Map的键值对处理好,再传到JSP页面渲染:

示例Controller代码:

@Controller
public class DemoController {
    @GetMapping("/demo")
    public String demo(Model model) {
        List<Map<String, String>> listOfMap = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            Map<String, String> map = new HashMap<>();
            // 用Spring自带的HtmlUtils做HTML转义
            String processedKey = HtmlUtils.htmlEscape("key1" + i);
            String processedValue = HtmlUtils.htmlEscape("<script>alert('xss')</script>" + i);
            map.put(processedKey, processedValue);
            listOfMap.add(map);
        }
        model.addAttribute("listOfMap", listOfMap);
        return "demo"; // 对应你的JSP视图名
    }
}

然后JSP里直接输出处理好的内容就行,不用再写任何处理逻辑:

<c:forEach items="${listOfMap}" var="maps">
    <c:forEach items="${maps}" var="mapItem">
        ${mapItem.key} ${mapItem.value} <br />
    </c:forEach>
</c:forEach>

这种方式让代码职责更清晰,Controller管数据处理,JSP只管渲染,后期维护也更方便。

4. 自定义EL函数(复杂逻辑复用场景)

如果你的处理逻辑很复杂,而且要在多个JSP里复用,可以自定义EL函数:

  1. 先写一个Java工具类,封装处理逻辑:
public class XssUtils {
    public static String escape(String input) {
        // 这里可以实现自定义的转义逻辑,比如除了HTML转义还处理其他特殊字符
        return HtmlUtils.htmlEscape(input);
    }
}
  1. 在WEB-INF下创建一个tld文件(比如custom-functions.tld),注册你的EL函数:
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee"
        version="2.1">
    <tlib-version>1.0</tlib-version>
    <short-name>custom</short-name>
    <uri>http://your-domain.com/custom-functions</uri>
    <function>
        <name>escapeXss</name>
        <function-class>com.yourpackage.XssUtils</function-class>
        <function-signature>java.lang.String escape(java.lang.String)</function-signature>
    </function>
</taglib>
  1. 在JSP里引入标签库,直接调用自定义函数:
<%@ taglib uri="http://your-domain.com/custom-functions" prefix="custom"%>

<c:forEach items="${listOfMap}" var="maps">
    <c:forEach items="${maps}" var="mapItem">
        ${custom:escapeXss(mapItem.key)} ${custom:escapeXss(mapItem.value)} <br />
    </c:forEach>
</c:forEach>

这种方式适合需要复用复杂处理逻辑的场景,不用在每个JSP里重复写代码。


总结一下:如果只是做XSS防护,优先用fn:escapeXml或者后端提前处理;如果需要自定义修改逻辑,用<c:set>或者自定义EL函数就好。

内容的提问来源于stack exchange,提问作者MiniSu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 20:32:33