本文详解 Struts2 中如何像 Spring Boot 的 application.properties 一样集中管理应用级配置(如 applicationId、timeout),介绍 struts.properties、全局资源包(struts.custom.i18n.resources)及自定义 TextProvider 等主流方案,并说明非敏感标识类配置的安全存储原则。
本文详解 struts2 中如何像 spring boot 的 `application.properties` 一样集中管理应用级配置(如 `applicationid`、`timeout`),介绍 `struts.properties`、全局资源包(`struts.custom.i18n.resources`)及自定义 `textprovider` 等主流方案,并说明非敏感标识类配置的安全存储原则。
在 Struts2 中,虽无原生的 @Value 或 @ConfigurationProperties 注解机制,但其通过分层、可扩展的配置体系,完全支持应用级属性的统一定义与跨组件访问。核心路径有三条:基础框架配置、国际化资源驱动的键值管理、以及面向定制化需求的扩展实现。
一、基础配置:struts.properties(适用于框架级与轻量应用属性)
struts.properties 是 Struts2 启动时自动加载的默认配置文件(位于 src/main/resources/),适合存放全局常量型参数,例如:
# src/main/resources/struts.properties struts.custom.i18n.resources=app-config applicationId=prod-2024-webapp api.timeout=30000
⚠️ 注意:struts.properties 中仅支持以 struts. 开头的框架保留键;自定义键(如 applicationId)虽可写入,但不会被 Struts2 自动注入或解析——它仅作为静态文本存在,需配合其他机制读取。
二、推荐方案:全局消息资源包(*.properties + struts.custom.i18n.resources)
这是最贴近 Spring Boot application.properties 语义的实践方式,专为“应用级可读配置”设计:
-
创建配置文件(如 app-config.properties):
# src/main/resources/app-config.properties applicationId=prod-2024-webapp api.timeout=30000 thirdparty.api.endpoint=https://api.example.com/v1
-
注册为全局资源(两种方式任选其一):
- ✅ 推荐:在 struts.xml 中声明(清晰、可版本控制):
<struts> <constant name="struts.custom.i18n.resources" value="app-config" /> <!-- 可叠加多个,用逗号分隔:value="app-config,db-config" --> </struts> - 或在 struts.properties 中等效配置:
struts.custom.i18n.resources=app-config
- ✅ 推荐:在 struts.xml 中声明(清晰、可版本控制):
-
在 Action 中安全获取值(继承 ActionSupport 即可):
public class ApiCallAction extends ActionSupport { private String appId = getText("applicationId"); // ✅ 自动解析 private int timeout = Integer.parseInt(getText("api.timeout")); // 需手动类型转换 public String execute() { System.out.println("Calling with ID: " + appId + ", timeout: " + timeout); return SUCCESS; } }✅ getText() 方法会按 Locale 优先级自动查找所有已注册的资源包,支持占位符(如 getText("welcome.message", Arrays.asList("John"))),且线程安全。
三、进阶扩展:自定义 TextProvider(适用于动态/外部化配置)
当配置需来自数据库、Consul、环境变量或需运行时刷新时,可实现 TextProvider:
public class DatabaseTextProvider extends ReloadableResourceBundleTextProvider {
@Override
protected ResourceBundle doGetBundle(String bundleName, Locale locale) {
// 从 DB 加载 key-value 映射并构造 ResourceBundle
Map<String, String> dbProps = loadFromDatabase(bundleName);
return new ListResourceBundle() {
@Override
protected Object[][] getContents() {
return dbProps.entrySet().stream()
.map(e -> new Object[]{e.getKey(), e.getValue()})
.toArray(Object[][]::new);
}
};
}
}并在 struts.xml 中替换默认提供者:
<constant name="struts.localizedTextProvider" value="com.example.DatabaseTextProvider" />
安全性说明:何时可将 applicationId 等存于 properties?
✅ 可以且推荐:applicationId、timeout、endpoint 等不包含密钥、令牌、密码或私有凭证的标识性、行为性配置,属于标准运维参数,明文存储在 classpath 下的 .properties 文件中是业界通用做法(与 Spring Boot 的 application.properties 安全模型一致)。
❌ 严禁:任何 api.secret.key、db.password、jwt.private.key 等敏感信息——应使用环境变量、KMS 或专用密钥管理服务,并通过 System.getProperty() 或 System.getenv() 动态注入(避免硬编码与版本控制泄露)。
总结建议
| 场景 | 推荐方案 | 优势 |
|---|---|---|
| 快速启动、少量静态配置 | struts.custom.i18n.resources + app-config.properties | 零依赖、开箱即用、天然支持多语言占位符 |
| 配置需热更新或来源异构 | 自定义 TextProvider | 完全可控,可集成任意配置中心 |
| 仅需框架参数(非业务属性) | struts.properties(限 struts.* 键) | 启动期强校验,避免误配 |
最终,Struts2 的配置哲学是「约定优于配置,扩展高于封闭」——它不强制单一入口,而是提供从简单到复杂、从静态到动态的完整能力链。合理选用资源包机制,即可获得媲美现代框架的配置体验。










