Simplify default locale/timezone resolution in cookie/session locale resolvers
At present, the customization of the default locale and timezone resolution in CookieLocaleResolver and SessionLocaleResolver requires subclassing them and overriding determineDefaultLocale and/or determineDefaultTimeZone methods. This commit simplifies resolution of the default locale and timezone resolution by introducing dedicated functions for these purposes, thus allowing customization without needing to resort to subclassing the locale resolvers. Closes gh-27609
This commit is contained in:
committed by
Sam Brannen
parent
94cc2da33b
commit
864dcf67d8
@@ -18,6 +18,7 @@ package org.springframework.web.servlet.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.function.Function;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@@ -50,6 +51,7 @@ import org.springframework.web.util.WebUtils;
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Jean-Pierre Pawlak
|
||||
* @author Vedran Pavic
|
||||
* @since 27.02.2003
|
||||
* @see #setDefaultLocale
|
||||
* @see #setDefaultTimeZone
|
||||
@@ -94,6 +96,15 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
|
||||
@Nullable
|
||||
private TimeZone defaultTimeZone;
|
||||
|
||||
private Function<HttpServletRequest, Locale> defaultLocaleFunction = request -> {
|
||||
Locale defaultLocale = getDefaultLocale();
|
||||
if (defaultLocale == null) {
|
||||
defaultLocale = request.getLocale();
|
||||
}
|
||||
return defaultLocale;
|
||||
};
|
||||
|
||||
private Function<HttpServletRequest, TimeZone> defaultTimeZoneFunction = request -> getDefaultTimeZone();
|
||||
|
||||
/**
|
||||
* Create a new instance of {@link CookieLocaleResolver} using the
|
||||
@@ -137,8 +148,8 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
|
||||
* @since 5.1.7
|
||||
* @see #setDefaultLocale
|
||||
* @see #setDefaultTimeZone
|
||||
* @see #determineDefaultLocale
|
||||
* @see #determineDefaultTimeZone
|
||||
* @see #setDefaultLocaleFunction(Function)
|
||||
* @see #setDefaultTimeZoneFunction(Function)
|
||||
*/
|
||||
public void setRejectInvalidCookies(boolean rejectInvalidCookies) {
|
||||
this.rejectInvalidCookies = rejectInvalidCookies;
|
||||
@@ -186,6 +197,35 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
|
||||
return this.defaultTimeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the function used to determine the default locale for the given request,
|
||||
* called if no {@link Locale} session attribute has been found.
|
||||
* <p>The default implementation returns the specified default locale,
|
||||
* if any, else falls back to the request's accept-header locale.
|
||||
* @param defaultLocaleFunction the function used to determine the default locale
|
||||
* @since 6.0
|
||||
* @see #setDefaultLocale
|
||||
* @see jakarta.servlet.http.HttpServletRequest#getLocale()
|
||||
*/
|
||||
public void setDefaultLocaleFunction(Function<HttpServletRequest, Locale> defaultLocaleFunction) {
|
||||
Assert.notNull(defaultLocaleFunction, "defaultLocaleFunction must not be null");
|
||||
this.defaultLocaleFunction = defaultLocaleFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the function used to determine the default time zone for the given request,
|
||||
* called if no {@link TimeZone} session attribute has been found.
|
||||
* <p>The default implementation returns the specified default time zone,
|
||||
* if any, or {@code null} otherwise.
|
||||
* @param defaultTimeZoneFunction the function used to determine the default time zone
|
||||
* @since 6.0
|
||||
* @see #setDefaultTimeZone
|
||||
*/
|
||||
public void setDefaultTimeZoneFunction(Function<HttpServletRequest, TimeZone> defaultTimeZoneFunction) {
|
||||
Assert.notNull(defaultTimeZoneFunction, "defaultTimeZoneFunction must not be null");
|
||||
this.defaultTimeZoneFunction = defaultTimeZoneFunction;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Locale resolveLocale(HttpServletRequest request) {
|
||||
@@ -260,9 +300,9 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
|
||||
}
|
||||
|
||||
request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,
|
||||
(locale != null ? locale : determineDefaultLocale(request)));
|
||||
(locale != null ? locale : this.defaultLocaleFunction.apply(request)));
|
||||
request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,
|
||||
(timeZone != null ? timeZone : determineDefaultTimeZone(request)));
|
||||
(timeZone != null ? timeZone : this.defaultTimeZoneFunction.apply(request)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,9 +331,9 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
|
||||
removeCookie(response);
|
||||
}
|
||||
request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,
|
||||
(locale != null ? locale : determineDefaultLocale(request)));
|
||||
(locale != null ? locale : this.defaultLocaleFunction.apply(request)));
|
||||
request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,
|
||||
(timeZone != null ? timeZone : determineDefaultTimeZone(request)));
|
||||
(timeZone != null ? timeZone : this.defaultTimeZoneFunction.apply(request)));
|
||||
}
|
||||
|
||||
|
||||
@@ -335,13 +375,11 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
|
||||
* @return the default locale (never {@code null})
|
||||
* @see #setDefaultLocale
|
||||
* @see jakarta.servlet.http.HttpServletRequest#getLocale()
|
||||
* @deprecated as of 6.0, in favor of {@link #setDefaultLocaleFunction(Function)}
|
||||
*/
|
||||
@Deprecated
|
||||
protected Locale determineDefaultLocale(HttpServletRequest request) {
|
||||
Locale defaultLocale = getDefaultLocale();
|
||||
if (defaultLocale == null) {
|
||||
defaultLocale = request.getLocale();
|
||||
}
|
||||
return defaultLocale;
|
||||
return this.defaultLocaleFunction.apply(request);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -352,10 +390,12 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
|
||||
* @param request the request to resolve the time zone for
|
||||
* @return the default time zone (or {@code null} if none defined)
|
||||
* @see #setDefaultTimeZone
|
||||
* @deprecated as of 6.0, in favor of {@link #setDefaultTimeZoneFunction(Function)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
protected TimeZone determineDefaultTimeZone(HttpServletRequest request) {
|
||||
return getDefaultTimeZone();
|
||||
return this.defaultTimeZoneFunction.apply(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.web.servlet.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.function.Function;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
@@ -25,6 +26,7 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
@@ -54,6 +56,7 @@ import org.springframework.web.util.WebUtils;
|
||||
* against the current {@code HttpServletRequest}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Vedran Pavic
|
||||
* @since 27.02.2003
|
||||
* @see #setDefaultLocale
|
||||
* @see #setDefaultTimeZone
|
||||
@@ -85,6 +88,15 @@ public class SessionLocaleResolver extends AbstractLocaleContextResolver {
|
||||
|
||||
private String timeZoneAttributeName = TIME_ZONE_SESSION_ATTRIBUTE_NAME;
|
||||
|
||||
private Function<HttpServletRequest, Locale> defaultLocaleFunction = request -> {
|
||||
Locale defaultLocale = getDefaultLocale();
|
||||
if (defaultLocale == null) {
|
||||
defaultLocale = request.getLocale();
|
||||
}
|
||||
return defaultLocale;
|
||||
};
|
||||
|
||||
private Function<HttpServletRequest, TimeZone> defaultTimeZoneFunction = request -> getDefaultTimeZone();
|
||||
|
||||
/**
|
||||
* Specify the name of the corresponding attribute in the {@code HttpSession},
|
||||
@@ -106,12 +118,40 @@ public class SessionLocaleResolver extends AbstractLocaleContextResolver {
|
||||
this.timeZoneAttributeName = timeZoneAttributeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the function used to determine the default locale for the given request,
|
||||
* called if no {@link Locale} session attribute has been found.
|
||||
* <p>The default implementation returns the specified default locale,
|
||||
* if any, else falls back to the request's accept-header locale.
|
||||
* @param defaultLocaleFunction the function used to determine the default locale
|
||||
* @since 6.0
|
||||
* @see #setDefaultLocale
|
||||
* @see jakarta.servlet.http.HttpServletRequest#getLocale()
|
||||
*/
|
||||
public void setDefaultLocaleFunction(Function<HttpServletRequest, Locale> defaultLocaleFunction) {
|
||||
Assert.notNull(defaultLocaleFunction, "defaultLocaleFunction must not be null");
|
||||
this.defaultLocaleFunction = defaultLocaleFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the function used to determine the default time zone for the given request,
|
||||
* called if no {@link TimeZone} session attribute has been found.
|
||||
* <p>The default implementation returns the specified default time zone,
|
||||
* if any, or {@code null} otherwise.
|
||||
* @param defaultTimeZoneFunction the function used to determine the default time zone
|
||||
* @since 6.0
|
||||
* @see #setDefaultTimeZone
|
||||
*/
|
||||
public void setDefaultTimeZoneFunction(Function<HttpServletRequest, TimeZone> defaultTimeZoneFunction) {
|
||||
Assert.notNull(defaultTimeZoneFunction, "defaultTimeZoneFunction must not be null");
|
||||
this.defaultTimeZoneFunction = defaultTimeZoneFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale resolveLocale(HttpServletRequest request) {
|
||||
Locale locale = (Locale) WebUtils.getSessionAttribute(request, this.localeAttributeName);
|
||||
if (locale == null) {
|
||||
locale = determineDefaultLocale(request);
|
||||
locale = this.defaultLocaleFunction.apply(request);
|
||||
}
|
||||
return locale;
|
||||
}
|
||||
@@ -123,7 +163,7 @@ public class SessionLocaleResolver extends AbstractLocaleContextResolver {
|
||||
public Locale getLocale() {
|
||||
Locale locale = (Locale) WebUtils.getSessionAttribute(request, localeAttributeName);
|
||||
if (locale == null) {
|
||||
locale = determineDefaultLocale(request);
|
||||
locale = SessionLocaleResolver.this.defaultLocaleFunction.apply(request);
|
||||
}
|
||||
return locale;
|
||||
}
|
||||
@@ -132,7 +172,7 @@ public class SessionLocaleResolver extends AbstractLocaleContextResolver {
|
||||
public TimeZone getTimeZone() {
|
||||
TimeZone timeZone = (TimeZone) WebUtils.getSessionAttribute(request, timeZoneAttributeName);
|
||||
if (timeZone == null) {
|
||||
timeZone = determineDefaultTimeZone(request);
|
||||
timeZone = SessionLocaleResolver.this.defaultTimeZoneFunction.apply(request);
|
||||
}
|
||||
return timeZone;
|
||||
}
|
||||
@@ -167,13 +207,11 @@ public class SessionLocaleResolver extends AbstractLocaleContextResolver {
|
||||
* @return the default locale (never {@code null})
|
||||
* @see #setDefaultLocale
|
||||
* @see jakarta.servlet.http.HttpServletRequest#getLocale()
|
||||
* @deprecated as of 6.0, in favor of {@link #setDefaultLocaleFunction(Function)}
|
||||
*/
|
||||
@Deprecated
|
||||
protected Locale determineDefaultLocale(HttpServletRequest request) {
|
||||
Locale defaultLocale = getDefaultLocale();
|
||||
if (defaultLocale == null) {
|
||||
defaultLocale = request.getLocale();
|
||||
}
|
||||
return defaultLocale;
|
||||
return this.defaultLocaleFunction.apply(request);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,10 +222,12 @@ public class SessionLocaleResolver extends AbstractLocaleContextResolver {
|
||||
* @param request the request to resolve the time zone for
|
||||
* @return the default time zone (or {@code null} if none defined)
|
||||
* @see #setDefaultTimeZone
|
||||
* @deprecated as of 6.0, in favor of {@link #setDefaultTimeZoneFunction(Function)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
protected TimeZone determineDefaultTimeZone(HttpServletRequest request) {
|
||||
return getDefaultTimeZone();
|
||||
return this.defaultTimeZoneFunction.apply(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
* @author Juergen Hoeller
|
||||
* @author Rick Evans
|
||||
* @author Sam Brannen
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
class CookieLocaleResolverTests {
|
||||
|
||||
@@ -410,4 +411,24 @@ class CookieLocaleResolverTests {
|
||||
assertThat(localeCookie.getValue()).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomDefaultLocaleFunction() {
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
|
||||
resolver.setDefaultLocaleFunction(request -> Locale.GERMAN);
|
||||
|
||||
assertThat(resolver.resolveLocale(request)).isEqualTo(Locale.GERMAN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomDefaultTimeZoneFunction() {
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
|
||||
resolver.setDefaultTimeZoneFunction(request -> TimeZone.getTimeZone("GMT+1"));
|
||||
|
||||
TimeZoneAwareLocaleContext context = (TimeZoneAwareLocaleContext) resolver.resolveLocaleContext(request);
|
||||
assertThat(context.getLocale()).isEqualTo(Locale.TAIWAN);
|
||||
assertThat(context.getTimeZone()).isEqualTo(TimeZone.getTimeZone("GMT+1"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
package org.springframework.web.servlet.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
|
||||
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
|
||||
@@ -31,6 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
class SessionLocaleResolverTests {
|
||||
|
||||
@@ -94,4 +97,25 @@ class SessionLocaleResolverTests {
|
||||
assertThat(resolver.resolveLocale(request)).isEqualTo(Locale.TAIWAN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomDefaultLocaleFunction() {
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
|
||||
SessionLocaleResolver resolver = new SessionLocaleResolver();
|
||||
resolver.setDefaultLocaleFunction(request -> Locale.GERMAN);
|
||||
|
||||
assertThat(resolver.resolveLocale(request)).isEqualTo(Locale.GERMAN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomDefaultTimeZoneFunction() {
|
||||
request.addPreferredLocale(Locale.TAIWAN);
|
||||
|
||||
resolver.setDefaultTimeZoneFunction(request -> TimeZone.getTimeZone("GMT+1"));
|
||||
|
||||
TimeZoneAwareLocaleContext context = (TimeZoneAwareLocaleContext) resolver.resolveLocaleContext(request);
|
||||
assertThat(context.getLocale()).isEqualTo(Locale.TAIWAN);
|
||||
assertThat(context.getTimeZone()).isEqualTo(TimeZone.getTimeZone("GMT+1"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user