LocaleContextHolder provides support for framework-level default settings
Issue: SPR-15017
This commit is contained in:
@@ -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 {
|
|||||||
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 {
|
|||||||
return locale;
|
return locale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Locale.getDefault();
|
return (defaultLocale != null ? defaultLocale : Locale.getDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -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 {
|
|||||||
* @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 {
|
|||||||
return timeZone;
|
return timeZone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TimeZone.getDefault();
|
return (defaultTimeZone != null ? defaultTimeZone : TimeZone.getDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|||||||
*
|
*
|
||||||
* @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");
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* 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 {
|
|||||||
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 {
|
|||||||
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
|
||||||
|
|||||||
Reference in New Issue
Block a user