Windows10下GlassFish与Tomcat创建服务后日期显示为问号问题
问题分析与解决方案
这个问题我之前也碰到过!核心原因就是Windows服务的运行环境和你交互式登录时的Locale(区域设置)不一致,导致Java程序无法正确获取日期格式化所需的Locale资源。
为什么会出现这种差异?
- 当你直接运行GlassFish/Tomcat(非服务模式)时,程序是在你当前登录用户的会话下运行的,会继承该用户的Locale配置,所以
SimpleDateFormat默认使用这个Locale就能正常格式化日期。 - 但把它们做成Windows服务后,默认会以Local System账户运行,这个账户的Locale设置可能和你登录的用户完全不同,甚至是一个未正确配置的Locale。Java在找不到对应Locale的日期格式化资源时,就会输出
??这类占位符,GlassFish日志的????-??-??T??:??:??.???+0530也是同样的道理。 - 而当你显式传入
Locale.XX参数时,Java不再依赖系统环境的Locale,直接使用你指定的Locale资源,所以日期显示就正常了。
几种可行的解决方案
1. 代码层面显式指定Locale(最推荐,不受环境影响)
不管部署环境怎么变,在使用日期格式化类时始终显式指定Locale,彻底避免依赖系统默认Locale。
比如把原来的代码:
String dateInString = new SimpleDateFormat(pattern).format(new Date()); out.println(dateInString);
修改为:
// 根据你的需求指定Locale,比如中文用Locale.CHINA,英文用Locale.US String dateInString = new SimpleDateFormat(pattern, Locale.CHINA).format(new Date()); out.println(dateInString);
如果你用的是Java 8及以上版本,更推荐使用新的日期时间API,同样显式指定Locale:
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Locale; // ... DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern, Locale.CHINA); String dateInString = LocalDateTime.now().format(formatter); out.println(dateInString);
2. 修改服务的运行账户为你的登录用户
如果不想修改代码,可以让服务使用你平时登录Windows的用户账户运行,这样服务会继承该用户的Locale配置:
- 按下
Win + R,输入services.msc打开服务管理器 - 找到GlassFish或Tomcat服务,右键选择「属性」
- 切换到「登录」选项卡,选择「此账户」,输入你的用户名和密码,点击「确定」
- 重启服务,之后日期格式化和日志显示应该都会恢复正常
3. 修改系统默认Locale(适合必须用Local System账户的场景)
如果必须使用Local System账户运行服务,可以修改系统级的Locale设置:
- 打开「控制面板」→「区域」→「管理」选项卡
- 点击「更改系统区域设置」,选择你需要的区域(比如「中文(中国)」)
- 重启电脑后,服务的Locale会同步这个系统设置,问题即可解决
内容的提问来源于stack exchange,提问作者Sanal S
相关产品推荐
相关产品推荐

