当前位置:首页 > 文章列表 > 文章 > java教程 > Java StringTemplate怎样安全拼接结构化文本

Java StringTemplate怎样安全拼接结构化文本

来源:17golang原创 2026-11-04 17:02:11 0浏览 收藏

Java 的 StringTemplate 适合把固定文本、表达式和值组织成一个可交给处理器的输入,但“能插值”不等于“已经安全转义”。真正稳妥的做法是:先确认运行版本,再根据数据格式选择处理器;SQL 交给 PreparedStatement 做参数绑定,JSON 交给序列化库做转义,不能把 STR 当成通用安全层。

官方文档:https://docs.oracle.com/en/java/javase/22/language/string-templates.html

实践要点
  • StringTemplate 只在 Java 21/22 作为预览特性提供,Java 23 起已撤回,不能当作当前稳定 API。
  • STR 负责普通插值,RAW 暴露片段和值;校验、转义和参数绑定必须由专门处理器完成。
  • 结构化文本的安全边界不在模板语法本身,而在 JSON 序列化、SQL 参数化和失败回退策略。

一、先确认 StringTemplate 的版本与触发场景

StringTemplate 的设计是“模板片段 + 嵌入表达式 + 模板处理器”。Java 21 首次预览,Java 22 二次预览;Oracle 的迁移说明指出,这项特性原计划在 Java 23 再预览,但后来因设计尚未形成共识而撤回。因此,下面的语法只适合维护 Java 21/22 预览代码、阅读旧实验项目或评估模板处理器设计,不适合直接作为 Java 23 及以后生产代码的稳定依赖。

StringTemplate 片段、值、处理器与 Java 版本边界的静态说明图
图1:StringTemplate 处理器关系说明图,展示片段、值与处理器之间的职责边界。

在 Java 22 预览环境中,最小示例需要同时打开预览开关:

# Java 22 只用于演示预览语法,编译和运行必须保持同一版本。
javac --enable-preview --release 22 Demo.java
java --enable-preview Demo

普通文本可以使用内置的 STR:

String user = "Duke";
// STR 只把表达式结果插入文本,不负责 JSON、SQL 等格式的安全编码。
String message = STR."Hello, \{user}";

如果需求只是日志、提示语或内部展示文本,STR 足够直观;一旦结果要被解析器、数据库或下游协议消费,就应进入专门的结构化处理流程。

二、让模板处理器接管结构化输入

RAW 不会替你把输入变成安全字符串,它提供模板的 fragments() 和 values()。自定义 Processor 可以在这里做类型限制、转义、占位符替换或构造别的返回类型。这个分层很重要:模板负责表达固定结构,处理器负责决定外部输入怎样进入结构。

import java.util.List;
import static java.lang.StringTemplate.RAW;

// 只允许受控的文本片段进入展示用途;协议编码仍应交给专门库。
static String safeDisplay(StringTemplate template) {
    List values = template.values();
    for (Object value : values) {
        // 展示层先拒绝控制字符,避免把日志格式和业务文本混在一起。
        if (value instanceof String text && text.chars().anyMatch(Character::isISOControl)) {
            throw new IllegalArgumentException("输入包含控制字符");
        }
    }
    // 仅完成普通插值;这里没有声称完成 JSON 或 SQL 转义。
    return template.interpolate();
}

String name = "Duke";
String result = safeDisplay(RAW."用户:\{name}");

这里的检查只是一个展示层例子,不是通用安全实现。比如 JSON 的引号、反斜杠、换行符和 Unicode 控制字符都有自己的编码规则;自己写几条 replace 很容易漏掉边界。需要 JSON 时,应把对象交给 Jackson、JSON-B 等序列化组件,让它根据目标格式生成字符串或字节。

三、用参数绑定组合 SQL

StringTemplate 最适合展示“自定义处理器可以改变返回类型”的思路。SQL 场景中,固定 SQL 片段可以保留,动态值必须变成参数,而不是直接进入 SQL 文本。处理器可以把片段拼成问号占位符,再按照原顺序绑定值:

SQL 参数绑定与 JSON 序列化安全边界的静态说明图
图2:结构化文本安全边界说明图,展示 SQL 参数绑定与 JSON 序列化各自承担的职责。
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.StringJoiner;

final class QueryTemplate {
    private final Connection connection;

    QueryTemplate(Connection connection) {
        this.connection = connection;
    }

    PreparedStatement prepare(StringTemplate template) throws SQLException {
        // 用问号替换片段之间的值,动态数据不会成为 SQL 语法的一部分。
        StringJoiner query = new StringJoiner("?");
        template.fragments().forEach(query::add);
        PreparedStatement statement = connection.prepareStatement(query.toString());

        int index = 1;
        for (Object value : template.values()) {
            // 按类型绑定,未知类型回退为字符串参数,不拼接进 SQL。
            if (value instanceof Integer number) {
                statement.setInt(index++, number);
            } else {
                statement.setString(index++, String.valueOf(value));
            }
        }
        return statement;
    }
}

// try-with-resources 负责释放 PreparedStatement,参数值只进入绑定槽位。
try (PreparedStatement statement = new QueryTemplate(connection)
        .prepare(RAW."select id, name from users where name = \{userName}")) {
    var rows = statement.executeQuery();
    // 这里继续读取结果集;实际项目还应按驱动规范关闭 ResultSet。
}

这个示例的安全性来自“占位符 + 绑定”,不是来自 RAW 或字符串模板语法。表名、列名、排序方向这类不能作为普通参数绑定的结构,必须使用白名单映射;不能让用户输入直接决定 SQL 关键字或标识符。

四、为 JSON 和多行文本设置门禁

StringTemplate 的文本块很适合把邮件、HTML 或配置草稿写得清楚,但写得像 JSON 不代表它就是合法且安全的 JSON。下面这种形式只是视觉上整齐,恶意引号仍可能改变结构:

String userName = request.getParameter("name");
// 这是错误示范:STR 不会替 JSON 字符串自动加引号或转义。
String json = STR."{\"name\":\"\{userName}\"}";

更可靠的流程是先构造 Java 对象,再调用 JSON 库序列化;如果确实要实现自定义 Processor,也要在处理器中逐项检查值类型并使用成熟的编码器,不能把 template.interpolate() 当作最终 JSON。

上线前可以把门禁写成四条规则:

检查项允许的做法失败处理
JDK 版本只在锁定的 Java 21/22 预览环境评估Java 23+ 改回稳定字符串/序列化方案
SQL 动态值片段固定、值走 PreparedStatement拒绝原始拼接并记录调用点
JSON 数据对象交给 JSON 序列化库序列化异常进入错误分支
处理器异常保留类型检查和资源关闭返回明确错误,不输出半成品文本

如果项目必须跨多个 JDK 版本,建议把 StringTemplate 放在实验性适配层,并为稳定实现保留接口。这样即使预览特性继续变化,业务代码仍可切换到 MessageFormat、文本块、JSON 库或 JDBC 参数绑定,而不用全项目改写。

相关问题

STR 能自动防止 JSON 注入吗?

不能。STR 只做插值,JSON 的引号、反斜杠和控制字符应由 JSON 序列化器处理。

StringTemplate 能直接替代 PreparedStatement 吗?

不能。只有自定义处理器把值转换为占位符并逐项绑定时,才形成参数化查询;直接插入 SQL 文本仍然不安全。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Java Gatherer怎样在 Stream 中维护窗口状态Java Gatherer怎样在 Stream 中维护窗口状态
上一篇
Java Gatherer怎样在 Stream 中维护窗口状态
Java HexFormat 怎样把字节数组转换为可读十六进制
下一篇
Java HexFormat 怎样把字节数组转换为可读十六进制
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    883次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    880次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    965次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    947次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    775次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码