本文详解 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/),适合存放全局常量型参数,例如:
⚠️ 注意:struts.properties 中
仅支持以 struts. 开头的框架保留键
;自定义键(如 applicationId)虽可写入,但
不会被 Struts2 自动注入或解析
——它仅作为静态文本存在,需配合其他机制读取。
二、推荐方案:全局消息资源包(*.properties + struts.custom.i18n.resources)
这是最贴近 Spring Boot application.properties 语义的实践方式,专为“应用级可读配置”设计:
创建配置文件
(如 app-config.properties):
注册为全局资源
(两种方式任选其一):
✅ 推荐:在 struts.xml 中声明(清晰、可版本控制):
或在 struts.properties 中等效配置:
在 Action 中安全获取值
(继承 ActionSupport 即可):
✅ getText() 方法会按 Locale 优先级自动查找所有已注册的资源包,支持占位符(如 getText("welcome.message", Arrays.asList("John"))),且线程安全。
三、进阶扩展:自定义 TextProvider(适用于动态/外部化配置)
当配置需来自数据库、Consul、环境变量或需运行时刷新时,可实现 TextProvider:
并在 struts.xml 中替换默认提供者:
安全性说明:何时可将 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 的配置哲学是「约定优于配置,扩展高于封闭」——它不强制单一入口,而是提供从简单到复杂、从静态到动态的完整能力链。合理选用资源包机制,即可获得媲美现代框架的配置体验。
# src/main/resources/struts.properties
struts.custom.i18n.resources=app-config
applicationId=prod-2024-webapp
api.timeout=30000# src/main/resources/app-config.properties
applicationId=prod-2024-webapp
api.timeout=30000
thirdparty.api.endpoint=https://api.example.com/v1
struts.custom.i18n.resources=app-configpublic 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;
}
}public class DatabaseTextProvider extends ReloadableResourceBundleTextProvider {
@Override
protected ResourceBundle doGetBundle(String bundleName, Locale locale) {
// 从 DB 加载 key-value 映射并构造 ResourceBundle
Map 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);
}
};
}
} 