提交 23f04183 编写于 作者: J Juergen Hoeller

LocaleContextHolder provides support for framework-level default settings

Issue: SPR-15017
上级 36a65806
...@@ -44,10 +44,16 @@ import org.springframework.core.NamedThreadLocal; ...@@ -44,10 +44,16 @@ import org.springframework.core.NamedThreadLocal;
public abstract class LocaleContextHolder { public abstract class LocaleContextHolder {
private static final ThreadLocal<LocaleContext> localeContextHolder = private static final ThreadLocal<LocaleContext> localeContextHolder =
new NamedThreadLocal<>("Locale context"); new NamedThreadLocal<>("LocaleContext");
private static final ThreadLocal<LocaleContext> inheritableLocaleContextHolder = private static final ThreadLocal<LocaleContext> inheritableLocaleContextHolder =
new NamedInheritableThreadLocal<>("Locale context"); new NamedInheritableThreadLocal<>("LocaleContext");
// Shared default locale at the framework level
private static Locale defaultLocale;
// Shared default time zone at the framework level
private static TimeZone defaultTimeZone;
/** /**
...@@ -152,18 +158,38 @@ public abstract class LocaleContextHolder { ...@@ -152,18 +158,38 @@ public abstract class LocaleContextHolder {
setLocaleContext(localeContext, inheritable); setLocaleContext(localeContext, inheritable);
} }
/**
* Set a shared default locale at the framework level,
* as an alternative to the JVM-wide default locale.
* <p><b>NOTE:</b> This can be useful to set an application-level
* default locale which differs from the JVM-wide default locale.
* However, this requires each such application to operate against
* locally deployed Spring Framework jars. Do not deploy Spring
* as a shared library at the server level in such a scenario!
* @param locale the default locale (or {@code null} for none,
* letting lookups fall back to {@link Locale#getDefault()})
* @since 4.3.5
* @see #getLocale()
* @see Locale#getDefault()
*/
public static void setDefaultLocale(Locale locale) {
LocaleContextHolder.defaultLocale = locale;
}
/** /**
* Return the Locale associated with the current thread, if any, * Return the Locale associated with the current thread, if any,
* or the system default Locale else. This is effectively a * or the system default Locale otherwise. This is effectively a
* replacement for {@link java.util.Locale#getDefault()}, * replacement for {@link java.util.Locale#getDefault()},
* able to optionally respect a user-level Locale setting. * able to optionally respect a user-level Locale setting.
* <p>Note: This method has a fallback to the system default Locale. * <p>Note: This method has a fallback to the shared default Locale,
* either at the framework level or at the JVM-wide system level.
* If you'd like to check for the raw LocaleContext content * If you'd like to check for the raw LocaleContext content
* (which may indicate no specific locale through {@code null}, use * (which may indicate no specific locale through {@code null}, use
* {@link #getLocaleContext()} and call {@link LocaleContext#getLocale()} * {@link #getLocaleContext()} and call {@link LocaleContext#getLocale()}
* @return the current Locale, or the system default Locale if no * @return the current Locale, or the system default Locale if no
* specific Locale has been associated with the current thread * specific Locale has been associated with the current thread
* @see LocaleContext#getLocale() * @see LocaleContext#getLocale()
* @see #setDefaultLocale(Locale)
* @see java.util.Locale#getDefault() * @see java.util.Locale#getDefault()
*/ */
public static Locale getLocale() { public static Locale getLocale() {
...@@ -174,7 +200,7 @@ public abstract class LocaleContextHolder { ...@@ -174,7 +200,7 @@ public abstract class LocaleContextHolder {
return locale; return locale;
} }
} }
return Locale.getDefault(); return (defaultLocale != null ? defaultLocale : Locale.getDefault());
} }
/** /**
...@@ -217,12 +243,31 @@ public abstract class LocaleContextHolder { ...@@ -217,12 +243,31 @@ public abstract class LocaleContextHolder {
setLocaleContext(localeContext, inheritable); setLocaleContext(localeContext, inheritable);
} }
/**
* Set a shared default time zone at the framework level,
* as an alternative to the JVM-wide default time zone.
* <p><b>NOTE:</b> This can be useful to set an application-level
* default time zone which differs from the JVM-wide default time zone.
* However, this requires each such application to operate against
* locally deployed Spring Framework jars. Do not deploy Spring
* as a shared library at the server level in such a scenario!
* @param timeZone the default time zone (or {@code null} for none,
* letting lookups fall back to {@link TimeZone#getDefault()})
* @since 4.3.5
* @see #getTimeZone()
* @see TimeZone#getDefault()
*/
public static void setDefaultTimeZone(TimeZone timeZone) {
defaultTimeZone = timeZone;
}
/** /**
* Return the TimeZone associated with the current thread, if any, * Return the TimeZone associated with the current thread, if any,
* or the system default TimeZone else. This is effectively a * or the system default TimeZone otherwise. This is effectively a
* replacement for {@link java.util.TimeZone#getDefault()}, * replacement for {@link java.util.TimeZone#getDefault()},
* able to optionally respect a user-level TimeZone setting. * able to optionally respect a user-level TimeZone setting.
* <p>Note: This method has a fallback to the system default Locale. * <p>Note: This method has a fallback to the shared default TimeZone,
* either at the framework level or at the JVM-wide system level.
* If you'd like to check for the raw LocaleContext content * If you'd like to check for the raw LocaleContext content
* (which may indicate no specific time zone through {@code null}, use * (which may indicate no specific time zone through {@code null}, use
* {@link #getLocaleContext()} and call {@link TimeZoneAwareLocaleContext#getTimeZone()} * {@link #getLocaleContext()} and call {@link TimeZoneAwareLocaleContext#getTimeZone()}
...@@ -230,6 +275,7 @@ public abstract class LocaleContextHolder { ...@@ -230,6 +275,7 @@ public abstract class LocaleContextHolder {
* @return the current TimeZone, or the system default TimeZone if no * @return the current TimeZone, or the system default TimeZone if no
* specific TimeZone has been associated with the current thread * specific TimeZone has been associated with the current thread
* @see TimeZoneAwareLocaleContext#getTimeZone() * @see TimeZoneAwareLocaleContext#getTimeZone()
* @see #setDefaultTimeZone(TimeZone)
* @see java.util.TimeZone#getDefault() * @see java.util.TimeZone#getDefault()
*/ */
public static TimeZone getTimeZone() { public static TimeZone getTimeZone() {
...@@ -240,7 +286,7 @@ public abstract class LocaleContextHolder { ...@@ -240,7 +286,7 @@ public abstract class LocaleContextHolder {
return timeZone; return timeZone;
} }
} }
return TimeZone.getDefault(); return (defaultTimeZone != null ? defaultTimeZone : TimeZone.getDefault());
} }
} }
...@@ -29,11 +29,12 @@ import org.springframework.core.NamedThreadLocal; ...@@ -29,11 +29,12 @@ import org.springframework.core.NamedThreadLocal;
* @author Keith Donald * @author Keith Donald
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 3.0 * @since 3.0
* @see org.springframework.context.i18n.LocaleContextHolder
*/ */
public final class JodaTimeContextHolder { public final class JodaTimeContextHolder {
private static final ThreadLocal<JodaTimeContext> jodaTimeContextHolder = private static final ThreadLocal<JodaTimeContext> jodaTimeContextHolder =
new NamedThreadLocal<>("JodaTime Context"); new NamedThreadLocal<>("JodaTimeContext");
/** /**
......
...@@ -26,11 +26,12 @@ import org.springframework.core.NamedThreadLocal; ...@@ -26,11 +26,12 @@ import org.springframework.core.NamedThreadLocal;
* *
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 4.0 * @since 4.0
* @see org.springframework.context.i18n.LocaleContextHolder
*/ */
public final class DateTimeContextHolder { public final class DateTimeContextHolder {
private static final ThreadLocal<DateTimeContext> dateTimeContextHolder = private static final ThreadLocal<DateTimeContext> dateTimeContextHolder =
new NamedThreadLocal<>("DateTime Context"); new NamedThreadLocal<>("DateTimeContext");
/** /**
......
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -80,6 +80,11 @@ public class LocaleContextHolderTests { ...@@ -80,6 +80,11 @@ public class LocaleContextHolderTests {
assertNull(LocaleContextHolder.getLocaleContext()); assertNull(LocaleContextHolder.getLocaleContext());
assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale()); assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone()); assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
LocaleContextHolder.setDefaultLocale(Locale.GERMAN);
assertEquals(Locale.GERMAN, LocaleContextHolder.getLocale());
LocaleContextHolder.setDefaultLocale(null);
assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale());
} }
@Test @Test
...@@ -99,9 +104,14 @@ public class LocaleContextHolderTests { ...@@ -99,9 +104,14 @@ public class LocaleContextHolderTests {
assertEquals(TimeZone.getTimeZone("GMT+2"), ((TimeZoneAwareLocaleContext) LocaleContextHolder.getLocaleContext()).getTimeZone()); assertEquals(TimeZone.getTimeZone("GMT+2"), ((TimeZoneAwareLocaleContext) LocaleContextHolder.getLocaleContext()).getTimeZone());
LocaleContextHolder.setTimeZone(null); LocaleContextHolder.setTimeZone(null);
assertNull(LocaleContextHolder.getLocaleContext());
assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale()); assertEquals(Locale.getDefault(), LocaleContextHolder.getLocale());
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone()); assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
assertNull(LocaleContextHolder.getLocaleContext());
LocaleContextHolder.setDefaultTimeZone(TimeZone.getTimeZone("GMT+1"));
assertEquals(TimeZone.getTimeZone("GMT+1"), LocaleContextHolder.getTimeZone());
LocaleContextHolder.setDefaultTimeZone(null);
assertEquals(TimeZone.getDefault(), LocaleContextHolder.getTimeZone());
} }
@Test @Test
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册