How do I set the timezone in Tomcat for a single web app?

前端 未结 8 1917
春和景丽
春和景丽 2021-02-05 13:00

What is the best way to set the time zone in Tomcat for a single web app? I\'ve seen options for changing the command-line parameters or environment variables for Tomcat, but is

相关标签:
8条回答
  • 2021-02-05 13:29

    The only way I found is to setup a filter and change the timezone in the filter,

    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);
    }
    

    The setDefault() changes the zone for the thread. So everything running in the thread inside the filter will have a different default timezone. We have to change it back because the thread is shared by other apps. You also need to do the same for your init(), destroy() methods and any other thread you might start in your application.

    I had to do this because a third-party library assumes default timezone and we don't have source code. It was a mess because this changes log timezone but we don't want log in different times. The correct way to handle this is to use a specific timezone in any time value exposed to end users.

    0 讨论(0)
  • 2021-02-05 13:30

    Set the system variable to CATALINA_OPTS=-Duser.timezone=America/Denver

    You can also specify the CATALINA_OPTS in the $TOMCAT_HOME/bin/catalina.sh or %TOMCAT_HOME%\bin\catalina.bat file as well.

    Here's a list of acceptable timezones.

    Source

    0 讨论(0)
  • 2021-02-05 13:31

    Check out the SimpleTimeZone. You can create an instance based on a time zone ID and use that to display dates/times using that time zone. If you wanted, you could read that ID from a project specific configuration file.

    0 讨论(0)
  • 2021-02-05 13:32

    You can also use a VM argument to define it

    -Djdk.util.TimeZone.allowSetDefault=true
    
    0 讨论(0)
  • 2021-02-05 13:46

    In JDK 6, Sun/Oracle has changed the implementation of Timezone. In JDK 5.0 setDefault sets the timezone in a thread local variable always and not across the JVM and that caused a few issues. Sun acknowledged this as a bug and fixed in JDK 1.6.

    In JDK 1.6 onwards ( I checked the source code for both JDK 1.6 and JDK 1.7) if the JVM is not started with a security manager ( or it's not set with System.SetsecurityManager()), setDefault method sets it globally across the JVM and not in a thread specific way. If you want to set it only for a given thread then you have to start JVM with a security manager.

    When you start Tomcat JVM with a security manager you need to provide individual permissions which was a no starter for us as we were late in the release cycle. Hence in the security policy file we provided all permissions and we overrode the default JAVA security manager to selectively deny the timezone write access. Due to lazy initialization issue with Timezone class I needed to call Timezone.getDefault() in the static block that makes the Timezone class initialized before the securityManager comes into play.

    Here is my test program.

    --Policy file test.policy

    grant {
            permission java.security.AllPermission;
    
    };
    

    -- Custom Security Manager

    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 startup Parameters

    -Djava.security.manager=CustomSecurityManager -Djava.security.policy=C:/workspace/test/src/test.policy

    0 讨论(0)
  • 2021-02-05 13:46

    Updated answer from '21: These days, you should only run one application per JVM, and set the TZ in system properties.

    Obsolete answer from '09: The best way is to modify the web application so it accepts explicit time zone configuration through web.xml instead of using the default JVM timezone.

    0 讨论(0)
提交回复
热议问题