什么是设置在Tomcat中的时区一个web应用程序的最佳方式? 我已经看到了改变的命令行参数或环境变量为Tomcat选项,但有一种方法来设置它是自包含的WAR文件,而不是依赖于任何Tomcat的配置?
编辑:再次强调,我正在寻找可以包含一个WAR文件中,不依赖于Tomcat配置的解决方案。 为了把它的另一种方式,可以在一个Web应用程序被配置为具有比相同的Tomcat实例运行其他应用程序不同的时区?
什么是设置在Tomcat中的时区一个web应用程序的最佳方式? 我已经看到了改变的命令行参数或环境变量为Tomcat选项,但有一种方法来设置它是自包含的WAR文件,而不是依赖于任何Tomcat的配置?
编辑:再次强调,我正在寻找可以包含一个WAR文件中,不依赖于Tomcat配置的解决方案。 为了把它的另一种方式,可以在一个Web应用程序被配置为具有比相同的Tomcat实例运行其他应用程序不同的时区?
我发现的唯一方法是设置一个过滤器,并更改时区的过滤器,
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
TimeZone savedZone = TimeZone.getDefault();
TimeZone.setDefault(webappZone);
chain.doFilter(request, response);
TimeZone.setDefault(savedZone);
}
该setDefault()
将更改线程的区域。 所以一切都在过滤器内的线程中运行将有一个不同的默认时区。 我们要改回来,因为线程被其他应用程序共享。 你也需要做同样为您init()
destroy()
方法和任何其他线程可能会在应用程序启动。
我不得不这样做,因为第三方库假定默认时区,我们没有源代码。 这是一个烂摊子,因为这改变登录时区,但我们不希望登录不同的时间。 处理这个正确的方法是在暴露给最终用户的任何时间值使用特定的时区。
编辑:我错了这一点。 此编辑纠正它。
答案是,你不能可移植性设置(默认设置)时区为一个单一的Web应用程序。 但是,如果你使用的是Java 6(至少),该java.util.TimeZone
类实现的默认时区的方法getDefault()
setDefault()
和setDefault(TimeZone)
使用可继承线程局部。 换句话说,调用setDefault()
只影响当前线程以及未来的子线程。
该行为不是在Sun的Javadoc 文档 。 它的工作原理为Java 6和5(见上文),但有没有保证,将在旧或新的Sun的JRE工作。 不过,我会感到非常惊讶如果Sun决定改变/还原为默认的时区一个“全球性”的模式。 这将打破太多现有的应用程序,并且除了全局是不好的。
系统变量设置为CATALINA_OPTS=-Duser.timezone=America/Denver
您还可以指定在$ TOMCAT_HOME /斌/ catalina.sh或%TOMCAT_HOME%\ BIN \ catalina.bat中文件CATALINA_OPTS为好。
以下是可接受的时区列表。
资源
在JDK 6,太阳/ Oracle已经改变时区的实施。 在JDK 5.0 setDefault始终,而不是设置时区在一个线程局部变量跨JVM和导致的几个问题。 孙承认这是一个错误,并固定在JDK 1.6。
在JDK 1.6起(我检查两个JDK 1.6和JDK 1.7的源代码),如果没有一个安全管理器启动JVM(或者它不设置与System.SetsecurityManager()
setDefault
方法设置它跨越全球的JVM和不是在一个线程特定的方式。 如果要设置只在一定的线程,那么你必须有一个安全管理器启动JVM。
当您使用安全管理器启动Tomcat JVM,您需要提供个人权限这对我们来说是没有启动,因为我们是在发行周期的后期。 因此,在安全策略文件中,我们提供的所有权限,我们推翻了默认的Java安全管理器选择地拒绝了时区的写入权限。 由于与时区级延迟初始化的问题,我需要调用Timezone.getDefault()
在静态块,使得初始化的TimeZone类SecurityManager的进场之前。
这是我的测试程序。
--Policy文件test.policy
grant {
permission java.security.AllPermission;
};
- 定制的安全管理
import java.security.Permission;
import java.util.TimeZone;
public class CustomSecurityManager extends SecurityManager {
static {
TimeZone.getDefault().getDisplayName();
}
public CustomSecurityManager() {
super();
}
public void checkPermission(Permission perm) throws SecurityException,NullPointerException
{
String propertyName = perm.getName();
String actionName = perm.getActions();
if(propertyName != null && actionName != null)
{
if(propertyName.equalsIgnoreCase("user.timezone")
&& actionName.equalsIgnoreCase("write"))
{
throw new SecurityException("Timezone write is not permitted.");
}
}
}
}
- JVM启动参数
-Djava.security.manager = CustomSecurityManager -Djava.security.policy = C:/workspace/test/src/test.policy
退房的SimpleTimeZone 。 您可以创建基于一个时区ID的实例,并用它来显示日期/使用时区的时间。 如果你愿意,你可以阅读从项目的具体配置文件ID。
最好的办法是,因此通过web.xml中接受而不是使用默认的JVM时区的明确的时区配置修改Web应用程序。
http://seamframework.org/Documentation/JSFEnhancementDefaultApplicationTimeZone
在Java 7 / Tomcat的7,有一个变通方法/黑客工具,使开发人员可以设置每个web应用独特的时区。 我们有我们的应用程序来实现这一点,因为我们必须支持在同一个JVM不同的默认时区运行多个web应用。
我见过的堆栈溢出的其他解决方案并不能完全解决问题。
我还调查了Java源代码的时区,我发现了一种有一个动态的时区返回作为通过注入JavaAWTAccess界面的自定义实现所有来电的默认时区。 这可以通过看Thread类加载器,并从中确定实际的web应用环境,然后处理该适当地根据一些web应用程序的名称时区映射来完成。
再次,这是应用服务器的特定,而且必须做不同的是Tomcat,Jetty的时,JBoss等,这种方法也是JVM实现特定的(仅适用于甲骨文/ Sun),但我相信可以扩展到OpenJDK的和其他人。
我们对Oracle JDK 7 SE + Tomcat的7核实工作方案,部署在Windows和Linux中,托管在不同的时区的多个web应用。
你也可以使用一个VM参数来定义它
-Djdk.util.TimeZone.allowSetDefault=true