代码之家  ›  专栏  ›  技术社区  ›  sk.

如何在Tomcat中为单个web应用程序设置时区?

  •  15
  • sk.  · 技术社区  · 16 年前

    在Tomcat中为单个web应用程序设置时区的最佳方法是什么?我已经看到了更改Tomcat命令行参数或环境变量的选项,但是否有一种方法可以在WAR文件中自包含并且不依赖于任何Tomcat配置来设置它?

    8 回复  |  直到 16 年前
        1
  •  8
  •   ZZ Coder    16 年前

    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() 方法以及您可能在应用程序中启动的任何其他线程。

    我不得不这样做,因为第三方库假设默认时区,而我们没有源代码。这很混乱,因为这会改变日志时区,但我们不想在不同的时间登录。处理此问题的正确方法是在向最终用户公开的任何时间值中使用特定的时区。

        2
  •  8
  •   Stephen C    16 年前

    答案是你不能 便携式 java.util.TimeZone getDefault() , setDefault() setDefault(TimeZone) 使用可继承的本地线程。换言之,呼叫

    行为是 在Sun Javadocs中。它适用于Java 6和5(见上文),但不能保证它适用于较旧或较新的Sun JRE。然而,如果Sun决定更改/恢复默认时区的“全局”模型,我会非常惊讶。它会破坏太多现有的应用程序,而且全局变量也很糟糕。

        3
  •  7
  •   Cuga    16 年前

    将系统变量设置为 CATALINA_OPTS=-Duser.timezone=America/Denver

    Here's a list of acceptable timezones.

    Source

        4
  •  3
  •   jonsca    13 年前

    在JDK 6中,Sun/Oracle更改了时区的实现。在JDK 5.0中,setDefault总是在线程局部变量中设置时区,而不是跨JVM设置时区,这导致了一些问题。Sun承认这是一个错误,并在JDK 1.6中进行了修复。

    在JDK 1.6之后(我检查了JDK 1.6和JDK 1.7的源代码),如果JVM没有使用安全管理器启动(或者没有设置 System.SetsecurityManager() setDefault 该方法在JVM中全局设置它,而不是以特定于线程的方式。如果你只想为给定的线程设置它,那么你必须用安全管理器启动JVM。

    Timezone.getDefault()

    这是我的测试程序。

    --策略文件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启动参数

        5
  •  0
  •   Tai Squared    16 年前

    看看 SimpleTimeZone 。您可以基于时区ID创建实例,并使用该ID显示使用该时区的日期/时间。如果需要,可以从特定于项目的配置文件中读取该ID。

        6
  •  0
  •   Mikael Gueck    16 年前

    • 使用Timezone.setDefault()不起作用,因为它会改变整个JVM的时区。

    我还研究了TimeZone的Java源代码,我找到了一种方法,通过注入JavaAWTAccess接口的自定义实现,将动态时区作为所有调用者的默认时区返回。这可以通过查看Thread类加载器来实现,并从中确定实际的webapp上下文,然后根据一些webapp名称到时区的映射来适当地处理它。

        7
  •  0
  •   Brijoy    14 年前

    -Djdk.util.TimeZone.allowSetDefault=true
    
        8
  •  0
  •   zzhu8192    12 年前

    从'21更新的答案: 如今,每个JVM只应运行一个应用程序,并在系统属性中设置TZ。

    2009年的过时答案:

        9
  •  0
  •   Icegras    9 年前
    推荐文章