如何为tomcat中的每个虚拟主机设置TimeZone [英] How set TimeZone for each virtual host in tomcat

查看:143
本文介绍了如何为tomcat中的每个虚拟主机设置TimeZone的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有用于 3个区域(蒙古,土库曼等)的网络应用.然后将它们部署在 tomcat的虚拟主机上.现在,我需要为每个应用程序设置时区.我怎样才能做到这一点? 我为每个应用程序实现了 ServerContextListener 界面,以设置 TimeZone :

I have web apps for 3 regions(Mongolia,Turkmenia, etc). And they are deployed on tomcat's virtual host. Now I need set timezone for each application. How can I do that? I implemented ServerContextListener interface for each apps to set TimeZone:

@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
    TimeZone timeZone=TimeZone.getTimeZone("Asia/Ulan_Bator");
//  TimeZone timeZone=TimeZone.getTimeZone("Asia/Ashgabat");
    timeZone.setDefault(timeZone);
}

但是在部署后,每个应用程序都具有相同的TimeZone.

But after deploy each apps has same TimeZone.

P.S:对不起,我的英语:)

P.S: Sorry for my English :)

推荐答案

ZoneId,而不是TimeZone

可怕的传统日期时间类早在几年前就被现代的 java.time 类所取代,并采用了JSR310.

ZoneId, not TimeZone

The terrible legacy date-time classes were supplanted years ago by the modern java.time classes with the adoption of JSR 310.

TimeZone替换为 ZoneId & ZoneOffset .

TimeZone in replaced by ZoneId & ZoneOffset.

ZoneId z = ZoneId.of( "Asia/Ulan_Bator" ) ;

避免使用默认时区

避免依赖JVM当前的默认时区.

Avoid default time zone

Avoid relying on the JVM’s current default time zone.

JVM仅一个一个默认时区.调用TimeZone.setDefault立即会影响该JVM中所有应用程序的所有线程中的所有代码.

There is only one default time zone for the JVM. Calling TimeZone.setDefault immediately affects all code in all threads of all apps within that JVM.

但是在部署后,每个应用程序都具有相同的TimeZone.

But after deploy each apps has same TimeZone.

因此,您不能为每个Web应用程序设置其他默认时区.如果所有Web应用程序都在同一个Servlet容器中运行,则所有Web应用程序共享相同的默认时区.

So you cannot set a different default time zone per web app. If all the web apps are running in the same Servlet container, then all the web apps share the same default time zone.

一种更好的方法是将期望/期望的时区作为可选参数显式传递给各种 java.time 方法.例如,如果要捕获在特定时区中看到的当前时刻,请将所需的ZoneId对象传递给now方法.

A better approach is to explicitly pass the desired/expected time zone as the optional argument to various java.time methods. For example, if you want to capture the current moment as seen in a particular time zone, pass the desired ZoneId object to the now method.

ZoneId z = ZoneId.of( "Asia/Ashgabat" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;

为每个Web应用程序设置时区,而不是依赖JVM当前的默认时区.

Rather than depend on the JVM’s current default time zone, set a time zone for each of your web apps.

您已接近解决方案.启动每个Web应用程序时,您需要指定其默认值.做到这一点的地方是contextInitialized 方法> ServletContextListener ,如您的问题中所示.

You were close to a solution. When each web app launches, you need to specify its default. The place to do that is in the contextInitialized method in your class implementing the ServletContextListener as shown in your Question.

在该方法内,指定所需的时区.

Inside that method, specify the desired time zone.

ZoneId z = ZoneId.of( "Asia/Ashgabat" ) ;

但是该变量超出范围,并在contextInitialized方法的结尾消失.因此,我们需要在某个地方存储对该ZoneId对象的引用.但是哪里? Servlet规范仅为应用程序中跨代码所需的此类全局"变量或常量定义了一个位置.

But that variable goes out of scope and disappears at the end of the contextInitialized method. So we need to store a reference to that ZoneId object somewhere. But where? The Servlet spec defines a place just for such "global" variables or constants you need across code within your app.

您的contextInitialized方法传递了 ServletContextEvent .该对象引用了 ServletContext 代表正在启动的Web应用程序的当前实例的对象.

Your contextInitialized method is passed a ServletContextEvent. That object holds a reference to the ServletContext object representing the current instance of your web app that is launching.

ServletContext myWebAppContext = servletContextEvent.getContext() ;

属性(键值存储)

ServletContext可以方便地维护属性"的简单键值存储.键是String,值是Object.我们可以为每个Web应用程序的默认时区组成一个字符串名称,并将ZoneId传递为Object值.将它们传递给

Attributes (key-value store)

That ServletContext conveniently maintains a simple key-value store of "attributes". The key is a String, the value an Object. We can make up a string name for our per-web-app default time zone, and pass the ZoneId as the Object value. Pass these to ServletContext::setAttribute.

String key = "com.example.acme_webapp.zoneid" ;
Object value = ZoneId.of( "Asia/Ashgabat" ) ;
myWebAppContext.setAttribute( key , value ) ;

在您应用的代码中,

In your app's code, look up the context and attribute anytime you need. Ask the Servlet request being serviced for its context.

ServletContext context = request.getServletContext() ;

询问存储的属性中的值.

Ask for the value from the stored attribute.

Object value = context.getAttribute( "com.example.acme_webapp.zoneid.mongolia" ) ;

Object放回ZoneId.我们知道这应该可行,但是对于防御性编程,您可能需要检查instanceof.

Cast the Object back to a ZoneId. We know that should work, but for defensive programming you may want to check instanceof.

ZoneId z = ( ZoneId ) value ;

然后继续您的工作.就像我们上面讨论的那样,也许您想捕获在该区域中看到的时间.

Then proceed with your work. Perhaps you want to capture the time as seen in that zone, just as we discussed above.

ZonedDateTime zdt = ZonedDateTime.now( z ) ;

提示:您可能需要定义一个枚举来处理属性名称的那些多个区域字符串.复制粘贴字符串值是一项风险工作.参见教程.

Tip: You might want to define an enum to handle those multiple region strings for the attributes names. Copy-pasting string values is risk business. See tutorial.

请注意,尽管每个Web应用程序实例都有其自己的线程安全 ,使用不可变对象模式.

Note that while each web app instance has its own ZoneId object, that object is being shared across threads. A Servlet environment is by definition highly-threaded, each request being serviced on a thread. So that ZoneId is being shared across any number of threads. But that is okay. Fortunately, the java.time classes are thread-safe by design, using the immutable objects pattern.

强制性Servlet线程并发提示:任何进行Servlet编码的人都应该阅读并重新阅读这本书: Java并发实践 ,作者:Brian Goetz,Tim Peierls,Joshua Bloch,Joseph Bowbeer,David Holmes,Doug Lea.

Obligatory Servlet threading concurrency tip: Anyone doing Servlet coding should be reading and re-reading this book: Java Concurrency in Practice by Brian Goetz, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes, Doug Lea.

这篇关于如何为tomcat中的每个虚拟主机设置TimeZone的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆