diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/client/MockMvcWebTestClient.java b/spring-test/src/main/java/org/springframework/test/web/servlet/client/MockMvcWebTestClient.java index 4a58df0c0c4d..f240da38dbd9 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/client/MockMvcWebTestClient.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/client/MockMvcWebTestClient.java @@ -45,7 +45,7 @@ import org.springframework.web.servlet.FlashMapManager; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.LocaleContextResolver; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; @@ -335,9 +335,9 @@ ControllerSpec mappedInterceptors( /** * Provide the LocaleResolver to use. *

This is delegated to - * {@link StandaloneMockMvcBuilder#setLocaleResolver(LocaleResolver)}. + * {@link StandaloneMockMvcBuilder#setLocaleResolver(LocaleContextResolver)}. */ - ControllerSpec localeResolver(LocaleResolver localeResolver); + ControllerSpec localeResolver(LocaleContextResolver localeResolver); /** * Provide a custom FlashMapManager. diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/client/StandaloneMockMvcSpec.java b/spring-test/src/main/java/org/springframework/test/web/servlet/client/StandaloneMockMvcSpec.java index b7b1f4d44881..588d3492e113 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/client/StandaloneMockMvcSpec.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/client/StandaloneMockMvcSpec.java @@ -31,7 +31,7 @@ import org.springframework.web.servlet.FlashMapManager; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.LocaleContextResolver; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; @@ -135,7 +135,7 @@ public StandaloneMockMvcSpec singleView(View view) { } @Override - public StandaloneMockMvcSpec localeResolver(LocaleResolver localeResolver) { + public StandaloneMockMvcSpec localeResolver(LocaleContextResolver localeResolver) { this.mockMvcBuilder.setLocaleResolver(localeResolver); return this; } diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/StandaloneMockMvcBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/StandaloneMockMvcBuilder.java index 2671c5217e14..e3219ff436ea 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/setup/StandaloneMockMvcBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/setup/StandaloneMockMvcBuilder.java @@ -51,7 +51,7 @@ import org.springframework.web.servlet.FlashMapManager; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.LocaleContextResolver; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer; @@ -121,7 +121,7 @@ public class StandaloneMockMvcBuilder extends AbstractMockMvcBuilder viewResolvers; - private LocaleResolver localeResolver = new AcceptHeaderLocaleResolver(); + private LocaleContextResolver localeResolver = new AcceptHeaderLocaleResolver(); @Nullable private FlashMapManager flashMapManager; @@ -297,7 +297,7 @@ public StandaloneMockMvcBuilder setSingleView(View view) { * Provide a LocaleResolver instance. * If not provided, the default one used is {@link AcceptHeaderLocaleResolver}. */ - public StandaloneMockMvcBuilder setLocaleResolver(LocaleResolver localeResolver) { + public StandaloneMockMvcBuilder setLocaleResolver(LocaleContextResolver localeResolver) { this.localeResolver = localeResolver; return this; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java index 1ea651d3b840..8b3d4d6e73ff 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java @@ -120,7 +120,7 @@ * implementation for Servlet 3 is included. The MultipartResolver bean name is * "multipartResolver"; default is none. * - *

  • Its locale resolution strategy is determined by a {@link LocaleResolver}. + *
  • Its locale resolution strategy is determined by a {@link LocaleContextResolver}. * Out-of-the-box implementations work via HTTP accept header, cookie, or session. * The LocaleResolver bean name is "localeResolver"; default is * {@link org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver}. @@ -156,6 +156,7 @@ * @author Chris Beams * @author Rossen Stoyanchev * @author Sebastien Deleuze + * @author Vedran Pavic * @see org.springframework.web.HttpRequestHandler * @see org.springframework.web.servlet.mvc.Controller * @see org.springframework.web.context.ContextLoaderListener @@ -313,9 +314,9 @@ public class DispatcherServlet extends FrameworkServlet { @Nullable private MultipartResolver multipartResolver; - /** LocaleResolver used by this servlet. */ + /** LocaleContextResolver used by this servlet. */ @Nullable - private LocaleResolver localeResolver; + private LocaleContextResolver localeResolver; /** ThemeResolver used by this servlet. */ @Nullable @@ -543,7 +544,7 @@ else if (logger.isDebugEnabled()) { */ private void initLocaleResolver(ApplicationContext context) { try { - this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class); + this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleContextResolver.class); if (logger.isTraceEnabled()) { logger.trace("Detected " + this.localeResolver); } @@ -553,7 +554,7 @@ else if (logger.isDebugEnabled()) { } catch (NoSuchBeanDefinitionException ex) { // We need to use the default. - this.localeResolver = getDefaultStrategy(context, LocaleResolver.class); + this.localeResolver = getDefaultStrategy(context, LocaleContextResolver.class); if (logger.isTraceEnabled()) { logger.trace("No LocaleResolver '" + LOCALE_RESOLVER_BEAN_NAME + "': using default [" + this.localeResolver.getClass().getSimpleName() + "]"); @@ -1186,13 +1187,8 @@ private void processDispatchResult(HttpServletRequest request, HttpServletRespon */ @Override protected LocaleContext buildLocaleContext(final HttpServletRequest request) { - LocaleResolver lr = this.localeResolver; - if (lr instanceof LocaleContextResolver) { - return ((LocaleContextResolver) lr).resolveLocaleContext(request); - } - else { - return () -> (lr != null ? lr.resolveLocale(request) : request.getLocale()); - } + LocaleContextResolver lr = this.localeResolver; + return (lr != null ? lr.resolveLocaleContext(request) : request::getLocale); } /** @@ -1379,8 +1375,13 @@ else if (logger.isDebugEnabled()) { */ protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine locale for request and apply it to the response. - Locale locale = - (this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale()); + Locale locale = null; + if (this.localeResolver != null) { + locale = this.localeResolver.resolveLocaleContext(request).getLocale(); + } + if (locale == null) { + locale = request.getLocale(); + } response.setLocale(locale); View view; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/LocaleContextResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/LocaleContextResolver.java index 4331c017f887..aaa783f1c082 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/LocaleContextResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/LocaleContextResolver.java @@ -42,6 +42,7 @@ * @see org.springframework.web.servlet.support.RequestContext#getTimeZone * @see org.springframework.web.servlet.support.RequestContextUtils#getTimeZone */ +@SuppressWarnings("deprecation") public interface LocaleContextResolver extends LocaleResolver { /** @@ -58,7 +59,6 @@ public interface LocaleContextResolver extends LocaleResolver { * the returned context, which again can be accessed through downcasting. * @param request the request to resolve the locale context for * @return the current locale context (never {@code null} - * @see #resolveLocale(HttpServletRequest) * @see org.springframework.web.servlet.support.RequestContextUtils#getLocale * @see org.springframework.web.servlet.support.RequestContextUtils#getTimeZone */ @@ -72,7 +72,6 @@ public interface LocaleContextResolver extends LocaleResolver { * @param localeContext the new locale context, or {@code null} to clear the locale * @throws UnsupportedOperationException if the LocaleResolver implementation * does not support dynamic changing of the locale or time zone - * @see #setLocale(HttpServletRequest, HttpServletResponse, Locale) * @see org.springframework.context.i18n.SimpleLocaleContext * @see org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext */ diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/LocaleResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/LocaleResolver.java index b4519563d6ee..89010cb111e6 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/LocaleResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/LocaleResolver.java @@ -50,7 +50,9 @@ * @see org.springframework.context.i18n.LocaleContextHolder * @see org.springframework.web.servlet.support.RequestContext#getLocale * @see org.springframework.web.servlet.support.RequestContextUtils#getLocale + * @deprecated since 6.0 in favor of {@link LocaleContextResolver} */ +@Deprecated(since = "6.0") public interface LocaleResolver { /** diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java index 3394b8eed13d..61a1cf0014c1 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java @@ -80,7 +80,7 @@ import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.LocaleContextResolver; import org.springframework.web.servlet.RequestToViewNameTranslator; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.function.support.HandlerFunctionAdapter; @@ -1158,7 +1158,7 @@ public HandlerMappingIntrospector mvcHandlerMappingIntrospector() { } @Bean - public LocaleResolver localeResolver() { + public LocaleContextResolver localeResolver() { return new AcceptHeaderLocaleResolver(); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/DispatcherServletWebRequest.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/DispatcherServletWebRequest.java index cace2a641517..0bdc96d5e98e 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/DispatcherServletWebRequest.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/DispatcherServletWebRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,12 +28,12 @@ * {@link ServletWebRequest} subclass that is aware of * {@link org.springframework.web.servlet.DispatcherServlet}'s * request context, such as the Locale determined by the configured - * {@link org.springframework.web.servlet.LocaleResolver}. + * {@link org.springframework.web.servlet.LocaleContextResolver}. * * @author Juergen Hoeller * @since 2.0 * @see #getLocale() - * @see org.springframework.web.servlet.LocaleResolver + * @see org.springframework.web.servlet.LocaleContextResolver */ public class DispatcherServletWebRequest extends ServletWebRequest { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AbstractLocaleContextResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AbstractLocaleContextResolver.java index 0b07bc682f14..17187ae8d7d1 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AbstractLocaleContextResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AbstractLocaleContextResolver.java @@ -16,6 +16,7 @@ package org.springframework.web.servlet.i18n; +import java.util.Locale; import java.util.TimeZone; import org.springframework.lang.Nullable; @@ -32,12 +33,32 @@ * @see #setDefaultLocale * @see #setDefaultTimeZone */ -public abstract class AbstractLocaleContextResolver extends AbstractLocaleResolver implements LocaleContextResolver { +public abstract class AbstractLocaleContextResolver implements LocaleContextResolver { + + @Nullable + private Locale defaultLocale; @Nullable private TimeZone defaultTimeZone; + /** + * Set a default {@link Locale} that this resolver will return if no other + * locale is found. + */ + public void setDefaultLocale(@Nullable Locale defaultLocale) { + this.defaultLocale = defaultLocale; + } + + /** + * Get the default {@link Locale} that this resolver is supposed to fall back + * to, if any. + */ + @Nullable + protected Locale getDefaultLocale() { + return this.defaultLocale; + } + /** * Set a default {@link TimeZone} that this resolver will return if no other * time zone is found. diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AbstractLocaleResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AbstractLocaleResolver.java index c851ed18e065..62a34cb6a7f1 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AbstractLocaleResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AbstractLocaleResolver.java @@ -29,7 +29,9 @@ * @author Juergen Hoeller * @since 1.2.9 * @see #setDefaultLocale + * @deprecated since 6.0 in favor of {@link AbstractLocaleContextResolver} */ +@Deprecated(since = "6.0") public abstract class AbstractLocaleResolver implements LocaleResolver { @Nullable diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolver.java index 15e514f28688..87ba5a59c2a8 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolver.java @@ -24,16 +24,18 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.springframework.context.i18n.LocaleContext; +import org.springframework.context.i18n.SimpleLocaleContext; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; -import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.LocaleContextResolver; /** - * {@link LocaleResolver} implementation that simply uses the primary locale + * {@link LocaleContextResolver} implementation that simply uses the primary locale * specified in the {@code Accept-Language} header of the HTTP request (that is, * the locale sent by the client browser, normally that of the client's OS). * - *

    Note: Does not support {@link #setLocale} since the {@code Accept-Language} + *

    Note: Does not support {@link #setLocaleContext} since the {@code Accept-Language} * header can only be changed by changing the client's locale settings. * * @author Juergen Hoeller @@ -41,7 +43,7 @@ * @since 27.02.2003 * @see jakarta.servlet.http.HttpServletRequest#getLocale() */ -public class AcceptHeaderLocaleResolver extends AbstractLocaleResolver { +public class AcceptHeaderLocaleResolver extends AbstractLocaleContextResolver { private final List supportedLocales = new ArrayList<>(4); @@ -68,21 +70,21 @@ public List getSupportedLocales() { @Override - public Locale resolveLocale(HttpServletRequest request) { + public LocaleContext resolveLocaleContext(HttpServletRequest request) { Locale defaultLocale = getDefaultLocale(); if (defaultLocale != null && request.getHeader("Accept-Language") == null) { - return defaultLocale; + return new SimpleLocaleContext(defaultLocale); } Locale requestLocale = request.getLocale(); List supportedLocales = getSupportedLocales(); if (supportedLocales.isEmpty() || supportedLocales.contains(requestLocale)) { - return requestLocale; + return new SimpleLocaleContext(requestLocale); } Locale supportedLocale = findSupportedLocale(request, supportedLocales); if (supportedLocale != null) { - return supportedLocale; + return new SimpleLocaleContext(supportedLocale); } - return (defaultLocale != null ? defaultLocale : requestLocale); + return new SimpleLocaleContext(defaultLocale != null ? defaultLocale : requestLocale); } @Nullable @@ -112,7 +114,8 @@ else if (languageMatch == null) { } @Override - public void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale) { + public void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response, + @Nullable LocaleContext localeContext) { throw new UnsupportedOperationException( "Cannot change HTTP Accept-Language header - use a different locale resolution strategy"); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java index dc3dd3acbe27..5d10530828b3 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java @@ -34,11 +34,11 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.LocaleContextResolver; import org.springframework.web.util.WebUtils; /** - * {@link LocaleResolver} implementation that uses a cookie sent back to the user + * {@link LocaleContextResolver} implementation that uses a cookie sent back to the user * in case of a custom setting, with a fallback to the configured default locale, * the request's {@code Accept-Language} header, or the default locale for the server. * diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/FixedLocaleResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/FixedLocaleResolver.java index ada77bdcd365..0865d31cf452 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/FixedLocaleResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/FixedLocaleResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ import org.springframework.lang.Nullable; /** - * {@link org.springframework.web.servlet.LocaleResolver} implementation + * {@link org.springframework.web.servlet.LocaleContextResolver} implementation * that always returns a fixed default locale and optionally time zone. * Default is the current JVM's default locale. * diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/LocaleChangeInterceptor.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/LocaleChangeInterceptor.java index 93996c9b946e..5017218bd43b 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/LocaleChangeInterceptor.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/LocaleChangeInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,11 +24,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.context.i18n.SimpleLocaleContext; import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.LocaleContextResolver; import org.springframework.web.servlet.support.RequestContextUtils; /** @@ -38,7 +39,7 @@ * @author Juergen Hoeller * @author Rossen Stoyanchev * @since 20.06.2003 - * @see org.springframework.web.servlet.LocaleResolver + * @see org.springframework.web.servlet.LocaleContextResolver */ public class LocaleChangeInterceptor implements HandlerInterceptor { @@ -116,13 +117,14 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons String newLocale = request.getParameter(getParamName()); if (newLocale != null) { if (checkHttpMethod(request.getMethod())) { - LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request); + LocaleContextResolver localeResolver = RequestContextUtils.getLocaleResolver(request); if (localeResolver == null) { throw new IllegalStateException( "No LocaleResolver found: not in a DispatcherServlet request?"); } try { - localeResolver.setLocale(request, response, parseLocaleValue(newLocale)); + localeResolver.setLocaleContext(request, response, + new SimpleLocaleContext(parseLocaleValue(newLocale))); } catch (IllegalArgumentException ex) { if (isIgnoreInvalidLocale()) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/SessionLocaleResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/SessionLocaleResolver.java index 3c4e70465f23..d2a7203a87c8 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/SessionLocaleResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/SessionLocaleResolver.java @@ -30,7 +30,7 @@ import org.springframework.web.util.WebUtils; /** - * {@link org.springframework.web.servlet.LocaleResolver} implementation that + * {@link org.springframework.web.servlet.LocaleContextResolver} implementation that * uses a locale attribute in the user's session in case of a custom setting, * with a fallback to the configured default locale, the request's * {@code Accept-Language} header, or the default locale for the server. diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java index 4167936b12ad..83a441989dcc 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContext.java @@ -32,6 +32,7 @@ import org.springframework.context.MessageSourceResolvable; import org.springframework.context.NoSuchMessageException; import org.springframework.context.i18n.LocaleContext; +import org.springframework.context.i18n.SimpleLocaleContext; import org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext; import org.springframework.context.i18n.TimeZoneAwareLocaleContext; import org.springframework.lang.Nullable; @@ -44,7 +45,6 @@ import org.springframework.web.bind.EscapedErrors; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.LocaleContextResolver; -import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.util.HtmlUtils; import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UrlPathHelper; @@ -66,6 +66,7 @@ * * @author Juergen Hoeller * @author Rossen Stoyanchev + * @author Vedran Pavic * @since 03.03.2003 * @see org.springframework.web.servlet.DispatcherServlet * @see org.springframework.web.servlet.view.AbstractView#setRequestContextAttribute @@ -225,18 +226,14 @@ public RequestContext(HttpServletRequest request, @Nullable HttpServletResponse TimeZone timeZone = null; // Determine locale to use for this RequestContext. - LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request); - if (localeResolver instanceof LocaleContextResolver) { - LocaleContext localeContext = ((LocaleContextResolver) localeResolver).resolveLocaleContext(request); + LocaleContextResolver localeResolver = RequestContextUtils.getLocaleResolver(request); + if (localeResolver != null) { + LocaleContext localeContext = localeResolver.resolveLocaleContext(request); locale = localeContext.getLocale(); if (localeContext instanceof TimeZoneAwareLocaleContext) { timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone(); } } - else if (localeResolver != null) { - // Try LocaleResolver (we're within a DispatcherServlet request). - locale = localeResolver.resolveLocale(request); - } this.locale = locale; this.timeZone = timeZone; @@ -299,7 +296,7 @@ public final Map getModel() { /** * Return the current Locale (falling back to the request locale; never {@code null}). - *

    Typically coming from a DispatcherServlet's {@link LocaleResolver}. + *

    Typically coming from a DispatcherServlet's {@link LocaleContextResolver}. * Also includes a fallback check for JSTL's Locale attribute. * @see RequestContextUtils#getLocale */ @@ -354,34 +351,34 @@ protected TimeZone getFallbackTimeZone() { /** * Change the current locale to the specified one, - * storing the new locale through the configured {@link LocaleResolver}. + * storing the new locale through the configured {@link LocaleContextResolver}. * @param locale the new locale - * @see LocaleResolver#setLocale + * @see LocaleContextResolver#setLocaleContext * @see #changeLocale(java.util.Locale, java.util.TimeZone) */ public void changeLocale(Locale locale) { - LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(this.request); + LocaleContextResolver localeResolver = RequestContextUtils.getLocaleResolver(this.request); if (localeResolver == null) { - throw new IllegalStateException("Cannot change locale if no LocaleResolver configured"); + throw new IllegalStateException("Cannot change locale if no LocaleContextResolver configured"); } - localeResolver.setLocale(this.request, this.response, locale); + localeResolver.setLocaleContext(this.request, this.response, new SimpleLocaleContext(locale)); this.locale = locale; } /** * Change the current locale to the specified locale and time zone context, - * storing the new locale context through the configured {@link LocaleResolver}. + * storing the new locale context through the configured {@link LocaleContextResolver}. * @param locale the new locale * @param timeZone the new time zone * @see LocaleContextResolver#setLocaleContext * @see org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext */ public void changeLocale(Locale locale, TimeZone timeZone) { - LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(this.request); - if (!(localeResolver instanceof LocaleContextResolver)) { + LocaleContextResolver localeResolver = RequestContextUtils.getLocaleResolver(this.request); + if (localeResolver == null) { throw new IllegalStateException("Cannot change locale context if no LocaleContextResolver configured"); } - ((LocaleContextResolver) localeResolver).setLocaleContext(this.request, this.response, + localeResolver.setLocaleContext(this.request, this.response, new SimpleTimeZoneAwareLocaleContext(locale, timeZone)); this.locale = locale; this.timeZone = timeZone; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContextUtils.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContextUtils.java index 7f438a03b09e..3201b19775d4 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContextUtils.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestContextUtils.java @@ -37,7 +37,6 @@ import org.springframework.web.servlet.FlashMap; import org.springframework.web.servlet.FlashMapManager; import org.springframework.web.servlet.LocaleContextResolver; -import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; @@ -50,6 +49,7 @@ * * @author Juergen Hoeller * @author Rossen Stoyanchev + * @author Vedran Pavic * @since 03.03.2003 * @see RequestContext * @see org.springframework.web.servlet.DispatcherServlet @@ -116,19 +116,19 @@ public static WebApplicationContext findWebApplicationContext(HttpServletRequest } /** - * Return the {@link LocaleResolver} that has been bound to the request by the + * Return the {@link LocaleContextResolver} that has been bound to the request by the * {@link DispatcherServlet}. * @param request current HTTP request * @return the current {@code LocaleResolver}, or {@code null} if not found */ @Nullable - public static LocaleResolver getLocaleResolver(HttpServletRequest request) { - return (LocaleResolver) request.getAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE); + public static LocaleContextResolver getLocaleResolver(HttpServletRequest request) { + return (LocaleContextResolver) request.getAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE); } /** * Retrieve the current locale from the given request, using the - * {@link LocaleResolver} bound to the request by the {@link DispatcherServlet} + * {@link LocaleContextResolver} bound to the request by the {@link DispatcherServlet} * (if available), falling back to the request's locale based on the * {@code Accept-Language} header or the default locale for the server. *

    This method serves as a straightforward alternative to the standard @@ -143,13 +143,19 @@ public static LocaleResolver getLocaleResolver(HttpServletRequest request) { * @see org.springframework.context.i18n.LocaleContextHolder#getLocale() */ public static Locale getLocale(HttpServletRequest request) { - LocaleResolver localeResolver = getLocaleResolver(request); - return (localeResolver != null ? localeResolver.resolveLocale(request) : request.getLocale()); + LocaleContextResolver localeResolver = getLocaleResolver(request); + if (localeResolver != null) { + Locale locale = localeResolver.resolveLocaleContext(request).getLocale(); + if (locale != null) { + return locale; + } + } + return request.getLocale(); } /** * Retrieve the current time zone from the given request, using the - * {@link TimeZoneAwareLocaleContext} in the {@link LocaleResolver} bound to + * {@link TimeZoneAwareLocaleContext} in the {@link LocaleContextResolver} bound to * the request by the {@link DispatcherServlet} (if available). *

    Note: This method returns {@code null} if no specific time zone can be * resolved for the given request. This is in contrast to {@link #getLocale} @@ -167,9 +173,9 @@ public static Locale getLocale(HttpServletRequest request) { */ @Nullable public static TimeZone getTimeZone(HttpServletRequest request) { - LocaleResolver localeResolver = getLocaleResolver(request); - if (localeResolver instanceof LocaleContextResolver localeContextResolver) { - LocaleContext localeContext = localeContextResolver.resolveLocaleContext(request); + LocaleContextResolver localeResolver = getLocaleResolver(request); + if (localeResolver != null) { + LocaleContext localeContext = localeResolver.resolveLocaleContext(request); if (localeContext instanceof TimeZoneAwareLocaleContext timeZoneAwareLocaleContext) { return timeZoneAwareLocaleContext.getTimeZone(); } diff --git a/spring-webmvc/src/main/resources/org/springframework/web/servlet/DispatcherServlet.properties b/spring-webmvc/src/main/resources/org/springframework/web/servlet/DispatcherServlet.properties index c55b61864e96..bdadfd1c1707 100644 --- a/spring-webmvc/src/main/resources/org/springframework/web/servlet/DispatcherServlet.properties +++ b/spring-webmvc/src/main/resources/org/springframework/web/servlet/DispatcherServlet.properties @@ -2,7 +2,7 @@ # Used as fallback when no matching beans are found in the DispatcherServlet context. # Not meant to be customized by application developers. -org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver +org.springframework.web.servlet.LocaleContextResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver @@ -24,4 +24,4 @@ org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework. org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver -org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager \ No newline at end of file +org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java index c52eea704079..d4f8591870ca 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java @@ -87,7 +87,7 @@ import org.springframework.web.servlet.FlashMapManager; import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.LocaleContextResolver; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.RequestToViewNameTranslator; import org.springframework.web.servlet.ThemeResolver; @@ -232,7 +232,7 @@ public void testDefaultConfig() throws Exception { assertThat(appContext.getBean(ConversionService.class)).isNotNull(); assertThat(appContext.getBean(LocalValidatorFactoryBean.class)).isNotNull(); assertThat(appContext.getBean(Validator.class)).isNotNull(); - assertThat(appContext.getBean("localeResolver", LocaleResolver.class)).isNotNull(); + assertThat(appContext.getBean("localeResolver", LocaleContextResolver.class)).isNotNull(); assertThat(appContext.getBean("themeResolver", ThemeResolver.class)).isNotNull(); assertThat(appContext.getBean("viewNameTranslator", RequestToViewNameTranslator.class)).isNotNull(); assertThat(appContext.getBean("flashMapManager", FlashMapManager.class)).isNotNull(); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java index c5c288a1ae8e..5dc7632f78ac 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -67,7 +67,7 @@ import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerMapping; -import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.LocaleContextResolver; import org.springframework.web.servlet.RequestToViewNameTranslator; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping; @@ -326,7 +326,7 @@ public void defaultPathMatchConfiguration() { @Test public void defaultLocaleResolverConfiguration() { ApplicationContext context = initContext(WebConfig.class); - LocaleResolver localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class); + LocaleContextResolver localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleContextResolver.class); assertThat(localeResolver).isNotNull(); assertThat(localeResolver).isInstanceOf(AcceptHeaderLocaleResolver.class); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolverTests.java index 6b5243d9a251..01594f733bd3 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolverTests.java @@ -49,38 +49,38 @@ class AcceptHeaderLocaleResolverTests { @Test void resolve() { - assertThat(this.resolver.resolveLocale(request(CANADA))).isEqualTo(CANADA); - assertThat(this.resolver.resolveLocale(request(US, CANADA))).isEqualTo(US); + assertThat(this.resolver.resolveLocaleContext(request(CANADA)).getLocale()).isEqualTo(CANADA); + assertThat(this.resolver.resolveLocaleContext(request(US, CANADA)).getLocale()).isEqualTo(US); } @Test void resolvePreferredSupported() { this.resolver.setSupportedLocales(Collections.singletonList(CANADA)); - assertThat(this.resolver.resolveLocale(request(US, CANADA))).isEqualTo(CANADA); + assertThat(this.resolver.resolveLocaleContext(request(US, CANADA)).getLocale()).isEqualTo(CANADA); } @Test void resolvePreferredNotSupported() { this.resolver.setSupportedLocales(Collections.singletonList(CANADA)); - assertThat(this.resolver.resolveLocale(request(US, UK))).isEqualTo(US); + assertThat(this.resolver.resolveLocaleContext(request(US, UK)).getLocale()).isEqualTo(US); } @Test void resolvePreferredAgainstLanguageOnly() { this.resolver.setSupportedLocales(Collections.singletonList(ENGLISH)); - assertThat(this.resolver.resolveLocale(request(GERMANY, US, UK))).isEqualTo(ENGLISH); + assertThat(this.resolver.resolveLocaleContext(request(GERMANY, US, UK)).getLocale()).isEqualTo(ENGLISH); } @Test void resolvePreferredAgainstCountryIfPossible() { this.resolver.setSupportedLocales(Arrays.asList(ENGLISH, UK)); - assertThat(this.resolver.resolveLocale(request(GERMANY, US, UK))).isEqualTo(UK); + assertThat(this.resolver.resolveLocaleContext(request(GERMANY, US, UK)).getLocale()).isEqualTo(UK); } @Test void resolvePreferredAgainstLanguageWithMultipleSupportedLocales() { this.resolver.setSupportedLocales(Arrays.asList(GERMAN, US)); - assertThat(this.resolver.resolveLocale(request(GERMANY, US, UK))).isEqualTo(GERMAN); + assertThat(this.resolver.resolveLocaleContext(request(GERMANY, US, UK)).getLocale()).isEqualTo(GERMAN); } @Test @@ -91,18 +91,18 @@ void resolvePreferredNotSupportedWithDefault() { MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Accept-Language", KOREA.toLanguageTag()); request.setPreferredLocales(Collections.singletonList(KOREA)); - assertThat(this.resolver.resolveLocale(request)).isEqualTo(Locale.JAPAN); + assertThat(this.resolver.resolveLocaleContext(request).getLocale()).isEqualTo(Locale.JAPAN); } @Test void defaultLocale() { this.resolver.setDefaultLocale(JAPANESE); MockHttpServletRequest request = new MockHttpServletRequest(); - assertThat(this.resolver.resolveLocale(request)).isEqualTo(JAPANESE); + assertThat(this.resolver.resolveLocaleContext(request).getLocale()).isEqualTo(JAPANESE); request.addHeader("Accept-Language", US.toLanguageTag()); request.setPreferredLocales(Collections.singletonList(US)); - assertThat(this.resolver.resolveLocale(request)).isEqualTo(US); + assertThat(this.resolver.resolveLocaleContext(request).getLocale()).isEqualTo(US); } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/CookieLocaleResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/CookieLocaleResolverTests.java index 4b9152b8961f..7fa886b6be31 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/CookieLocaleResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/CookieLocaleResolverTests.java @@ -61,7 +61,7 @@ void resolveLocale() { request.setCookies(cookie); resolver = new CookieLocaleResolver("LanguageKoekje"); - Locale loc = resolver.resolveLocale(request); + Locale loc = resolver.resolveLocaleContext(request).getLocale(); assertThat(loc.getLanguage()).isEqualTo("nl"); } @@ -141,8 +141,8 @@ void resolveLocaleContextWithInvalidTimeZoneOnErrorDispatch() { } @Test - void setAndResolveLocale() { - resolver.setLocale(request, response, new Locale("nl", "")); + void setAndResolveLocaleContext() { + resolver.setLocaleContext(request, response, new SimpleLocaleContext(new Locale("nl", ""))); MockCookie cookie = MockCookie.parse(response.getHeader(HttpHeaders.SET_COOKIE)); assertThat(cookie).isNotNull(); @@ -155,19 +155,6 @@ void setAndResolveLocale() { request = new MockHttpServletRequest(); request.setCookies(cookie); - resolver = new CookieLocaleResolver(); - Locale loc = resolver.resolveLocale(request); - assertThat(loc.getLanguage()).isEqualTo("nl"); - } - - @Test - void setAndResolveLocaleContext() { - resolver.setLocaleContext(request, response, new SimpleLocaleContext(new Locale("nl", ""))); - - Cookie cookie = response.getCookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME); - request = new MockHttpServletRequest(); - request.setCookies(cookie); - resolver = new CookieLocaleResolver(); LocaleContext loc = resolver.resolveLocaleContext(request); assertThat(loc.getLocale().getLanguage()).isEqualTo("nl"); @@ -210,7 +197,7 @@ void setAndResolveLocaleContextWithTimeZoneOnly() { @Test void setAndResolveLocaleWithCountry() { - resolver.setLocale(request, response, new Locale("de", "AT")); + resolver.setLocaleContext(request, response, new SimpleLocaleContext(new Locale("de", "AT"))); MockCookie cookie = MockCookie.parse(response.getHeader(HttpHeaders.SET_COOKIE)); assertThat(cookie).isNotNull(); @@ -225,7 +212,7 @@ void setAndResolveLocaleWithCountry() { request.setCookies(cookie); resolver = new CookieLocaleResolver(); - Locale loc = resolver.resolveLocale(request); + Locale loc = resolver.resolveLocaleContext(request).getLocale(); assertThat(loc.getLanguage()).isEqualTo("de"); assertThat(loc.getCountry()).isEqualTo("AT"); } @@ -233,7 +220,7 @@ void setAndResolveLocaleWithCountry() { @Test void setAndResolveLocaleWithCountryAsLegacyJava() { resolver.setLanguageTagCompliant(false); - resolver.setLocale(request, response, new Locale("de", "AT")); + resolver.setLocaleContext(request, response, new SimpleLocaleContext(new Locale("de", "AT"))); MockCookie cookie = MockCookie.parse(response.getHeader(HttpHeaders.SET_COOKIE)); assertThat(cookie).isNotNull(); @@ -248,7 +235,7 @@ void setAndResolveLocaleWithCountryAsLegacyJava() { request.setCookies(cookie); resolver = new CookieLocaleResolver(); - Locale loc = resolver.resolveLocale(request); + Locale loc = resolver.resolveLocaleContext(request).getLocale(); assertThat(loc.getLanguage()).isEqualTo("de"); assertThat(loc.getCountry()).isEqualTo("AT"); } @@ -261,7 +248,7 @@ void customCookie() { resolver.setCookieMaxAge(Duration.ofSeconds(10000)); resolver.setCookieSecure(true); resolver.setCookieSameSite("Lax"); - resolver.setLocale(request, response, new Locale("nl", "")); + resolver.setLocaleContext(request, response, new SimpleLocaleContext(new Locale("nl", ""))); MockCookie cookie = MockCookie.parse(response.getHeader(HttpHeaders.SET_COOKIE)); assertThat(cookie).isNotNull(); @@ -276,18 +263,10 @@ void customCookie() { request.setCookies(cookie); resolver = new CookieLocaleResolver("LanguageKoek"); - Locale loc = resolver.resolveLocale(request); + Locale loc = resolver.resolveLocaleContext(request).getLocale(); assertThat(loc.getLanguage()).isEqualTo("nl"); } - @Test - void resolveLocaleWithoutCookie() { - request.addPreferredLocale(Locale.TAIWAN); - - Locale loc = resolver.resolveLocale(request); - assertThat(loc).isEqualTo(request.getLocale()); - } - @Test void resolveLocaleContextWithoutCookie() { request.addPreferredLocale(Locale.TAIWAN); @@ -298,16 +277,6 @@ void resolveLocaleContextWithoutCookie() { assertThat(((TimeZoneAwareLocaleContext) loc).getTimeZone()).isNull(); } - @Test - void resolveLocaleWithoutCookieAndDefaultLocale() { - request.addPreferredLocale(Locale.TAIWAN); - - resolver.setDefaultLocale(Locale.GERMAN); - - Locale loc = resolver.resolveLocale(request); - assertThat(loc).isEqualTo(Locale.GERMAN); - } - @Test void resolveLocaleContextWithoutCookieAndDefaultLocale() { request.addPreferredLocale(Locale.TAIWAN); @@ -321,16 +290,6 @@ void resolveLocaleContextWithoutCookieAndDefaultLocale() { assertThat(((TimeZoneAwareLocaleContext) loc).getTimeZone()).isEqualTo(TimeZone.getTimeZone("GMT+1")); } - @Test - void resolveLocaleWithCookieWithoutLocale() { - request.addPreferredLocale(Locale.TAIWAN); - Cookie cookie = new Cookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME, ""); - request.setCookies(cookie); - - Locale loc = resolver.resolveLocale(request); - assertThat(loc).isEqualTo(request.getLocale()); - } - @Test void resolveLocaleContextWithCookieWithoutLocale() { request.addPreferredLocale(Locale.TAIWAN); @@ -343,23 +302,6 @@ void resolveLocaleContextWithCookieWithoutLocale() { assertThat(((TimeZoneAwareLocaleContext) loc).getTimeZone()).isNull(); } - @Test - void setLocaleToNull() { - request.addPreferredLocale(Locale.TAIWAN); - Cookie cookie = new Cookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME, Locale.UK.toString()); - request.setCookies(cookie); - - resolver.setLocale(request, response, null); - Locale locale = (Locale) request.getAttribute(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME); - assertThat(locale).isEqualTo(Locale.TAIWAN); - - Cookie[] cookies = response.getCookies(); - assertThat(cookies).hasSize(1); - Cookie localeCookie = cookies[0]; - assertThat(localeCookie.getName()).isEqualTo(CookieLocaleResolver.DEFAULT_COOKIE_NAME); - assertThat(localeCookie.getValue()).isEqualTo(""); - } - @Test void setLocaleContextToNull() { request.addPreferredLocale(Locale.TAIWAN); @@ -379,24 +321,6 @@ void setLocaleContextToNull() { assertThat(localeCookie.getValue()).isEqualTo(""); } - @Test - void setLocaleToNullWithDefault() { - request.addPreferredLocale(Locale.TAIWAN); - Cookie cookie = new Cookie(CookieLocaleResolver.DEFAULT_COOKIE_NAME, Locale.UK.toString()); - request.setCookies(cookie); - - resolver.setDefaultLocale(Locale.CANADA_FRENCH); - resolver.setLocale(request, response, null); - Locale locale = (Locale) request.getAttribute(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME); - assertThat(locale).isEqualTo(Locale.CANADA_FRENCH); - - Cookie[] cookies = response.getCookies(); - assertThat(cookies).hasSize(1); - Cookie localeCookie = cookies[0]; - assertThat(localeCookie.getName()).isEqualTo(CookieLocaleResolver.DEFAULT_COOKIE_NAME); - assertThat(localeCookie.getValue()).isEqualTo(""); - } - @Test void setLocaleContextToNullWithDefault() { request.addPreferredLocale(Locale.TAIWAN); @@ -424,7 +348,7 @@ void customDefaultLocaleFunction() { resolver.setDefaultLocaleFunction(request -> Locale.GERMAN); - assertThat(resolver.resolveLocale(request)).isEqualTo(Locale.GERMAN); + assertThat(resolver.resolveLocaleContext(request).getLocale()).isEqualTo(Locale.GERMAN); } @Test diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/LocaleResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/LocaleResolverTests.java index 3888670e3209..16c38f74e56b 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/LocaleResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/LocaleResolverTests.java @@ -26,7 +26,6 @@ import org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext; import org.springframework.context.i18n.TimeZoneAwareLocaleContext; import org.springframework.web.servlet.LocaleContextResolver; -import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.testfixture.servlet.MockHttpServletRequest; import org.springframework.web.testfixture.servlet.MockHttpServletResponse; import org.springframework.web.testfixture.servlet.MockServletContext; @@ -35,34 +34,35 @@ import static org.assertj.core.api.Assertions.fail; /** - * Unit tests for various {@link LocaleResolver} implementations. + * Unit tests for various {@link LocaleContextResolver} implementations. * * @author Juergen Hoeller + * @author Vedran Pavic * @since 20.03.2003 */ class LocaleResolverTests { @Test void acceptHeaderLocaleResolver() { - doTest(new AcceptHeaderLocaleResolver(), false); + doTest(new AcceptHeaderLocaleResolver(), false, false); } @Test void fixedLocaleResolver() { - doTest(new FixedLocaleResolver(Locale.UK), false); + doTest(new FixedLocaleResolver(Locale.UK), false, true); } @Test void cookieLocaleResolver() { - doTest(new CookieLocaleResolver(), true); + doTest(new CookieLocaleResolver(), true, true); } @Test void sessionLocaleResolver() { - doTest(new SessionLocaleResolver(), true); + doTest(new SessionLocaleResolver(), true, true); } - private void doTest(LocaleResolver localeResolver, boolean shouldSet) { + private void doTest(LocaleContextResolver localeResolver, boolean shouldSet, boolean timeZoneAware) { // create mocks MockServletContext context = new MockServletContext(); MockHttpServletRequest request = new MockHttpServletRequest(context); @@ -70,14 +70,14 @@ private void doTest(LocaleResolver localeResolver, boolean shouldSet) { MockHttpServletResponse response = new MockHttpServletResponse(); // check original locale - Locale locale = localeResolver.resolveLocale(request); + Locale locale = localeResolver.resolveLocaleContext(request).getLocale(); assertThat(locale).isEqualTo(Locale.UK); // set new locale try { - localeResolver.setLocale(request, response, Locale.GERMANY); + localeResolver.setLocaleContext(request, response, new SimpleLocaleContext(Locale.GERMANY)); assertThat(shouldSet).as("should not be able to set Locale").isTrue(); // check new locale - locale = localeResolver.resolveLocale(request); + locale = localeResolver.resolveLocaleContext(request).getLocale(); assertThat(locale).isEqualTo(Locale.GERMANY); } catch (UnsupportedOperationException ex) { @@ -85,66 +85,68 @@ private void doTest(LocaleResolver localeResolver, boolean shouldSet) { } // check LocaleContext - if (localeResolver instanceof LocaleContextResolver localeContextResolver) { - LocaleContext localeContext = localeContextResolver.resolveLocaleContext(request); - if (shouldSet) { - assertThat(localeContext.getLocale()).isEqualTo(Locale.GERMANY); - } - else { - assertThat(localeContext.getLocale()).isEqualTo(Locale.UK); - } + LocaleContext localeContext = localeResolver.resolveLocaleContext(request); + if (shouldSet) { + assertThat(localeContext.getLocale()).isEqualTo(Locale.GERMANY); + } + else { + assertThat(localeContext.getLocale()).isEqualTo(Locale.UK); + } + if (timeZoneAware) { boolean condition2 = localeContext instanceof TimeZoneAwareLocaleContext; assertThat(condition2).isTrue(); assertThat(((TimeZoneAwareLocaleContext) localeContext).getTimeZone()).isNull(); + } - if (localeContextResolver instanceof AbstractLocaleContextResolver) { - ((AbstractLocaleContextResolver) localeContextResolver).setDefaultTimeZone(TimeZone.getTimeZone("GMT+1")); - request.removeAttribute(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME); - localeContextResolver.resolveLocaleContext(request); + if (localeResolver instanceof AbstractLocaleContextResolver) { + ((AbstractLocaleContextResolver) localeResolver).setDefaultTimeZone(TimeZone.getTimeZone("GMT+1")); + request.removeAttribute(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME); + localeResolver.resolveLocaleContext(request); + if (timeZoneAware) { assertThat(TimeZone.getTimeZone("GMT+1")).isEqualTo(((TimeZoneAwareLocaleContext) localeContext).getTimeZone()); } + } - try { - localeContextResolver.setLocaleContext(request, response, new SimpleLocaleContext(Locale.US)); - if (!shouldSet) { - fail("should not be able to set Locale"); - } - localeContext = localeContextResolver.resolveLocaleContext(request); - assertThat(localeContext.getLocale()).isEqualTo(Locale.US); - if (localeContextResolver instanceof AbstractLocaleContextResolver) { - assertThat(TimeZone.getTimeZone("GMT+1")).isEqualTo(((TimeZoneAwareLocaleContext) localeContext).getTimeZone()); - } - else { - assertThat(((TimeZoneAwareLocaleContext) localeContext).getTimeZone()).isNull(); - } - - localeContextResolver.setLocaleContext(request, response, - new SimpleTimeZoneAwareLocaleContext(Locale.GERMANY, TimeZone.getTimeZone("GMT+2"))); - localeContext = localeContextResolver.resolveLocaleContext(request); + try { + localeResolver.setLocaleContext(request, response, new SimpleLocaleContext(Locale.US)); + if (!shouldSet) { + fail("should not be able to set Locale"); + } + localeContext = localeResolver.resolveLocaleContext(request); + assertThat(localeContext.getLocale()).isEqualTo(Locale.US); + if (localeResolver instanceof AbstractLocaleContextResolver) { + assertThat(TimeZone.getTimeZone("GMT+1")).isEqualTo(((TimeZoneAwareLocaleContext) localeContext).getTimeZone()); + } + else { + assertThat(((TimeZoneAwareLocaleContext) localeContext).getTimeZone()).isNull(); + } + + localeResolver.setLocaleContext(request, response, + new SimpleTimeZoneAwareLocaleContext(Locale.GERMANY, TimeZone.getTimeZone("GMT+2"))); + localeContext = localeResolver.resolveLocaleContext(request); + assertThat(localeContext.getLocale()).isEqualTo(Locale.GERMANY); + boolean condition1 = localeContext instanceof TimeZoneAwareLocaleContext; + assertThat(condition1).isTrue(); + assertThat(TimeZone.getTimeZone("GMT+2")).isEqualTo(((TimeZoneAwareLocaleContext) localeContext).getTimeZone()); + + localeResolver.setLocaleContext(request, response, + new SimpleTimeZoneAwareLocaleContext(null, TimeZone.getTimeZone("GMT+3"))); + localeContext = localeResolver.resolveLocaleContext(request); + assertThat(localeContext.getLocale()).isEqualTo(Locale.UK); + boolean condition = localeContext instanceof TimeZoneAwareLocaleContext; + assertThat(condition).isTrue(); + assertThat(TimeZone.getTimeZone("GMT+3")).isEqualTo(((TimeZoneAwareLocaleContext) localeContext).getTimeZone()); + + if (localeResolver instanceof AbstractLocaleContextResolver) { + ((AbstractLocaleContextResolver) localeResolver).setDefaultLocale(Locale.GERMANY); + request.removeAttribute(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME); + localeResolver.resolveLocaleContext(request); assertThat(localeContext.getLocale()).isEqualTo(Locale.GERMANY); - boolean condition1 = localeContext instanceof TimeZoneAwareLocaleContext; - assertThat(condition1).isTrue(); - assertThat(TimeZone.getTimeZone("GMT+2")).isEqualTo(((TimeZoneAwareLocaleContext) localeContext).getTimeZone()); - - localeContextResolver.setLocaleContext(request, response, - new SimpleTimeZoneAwareLocaleContext(null, TimeZone.getTimeZone("GMT+3"))); - localeContext = localeContextResolver.resolveLocaleContext(request); - assertThat(localeContext.getLocale()).isEqualTo(Locale.UK); - boolean condition = localeContext instanceof TimeZoneAwareLocaleContext; - assertThat(condition).isTrue(); - assertThat(TimeZone.getTimeZone("GMT+3")).isEqualTo(((TimeZoneAwareLocaleContext) localeContext).getTimeZone()); - - if (localeContextResolver instanceof AbstractLocaleContextResolver) { - ((AbstractLocaleContextResolver) localeContextResolver).setDefaultLocale(Locale.GERMANY); - request.removeAttribute(CookieLocaleResolver.LOCALE_REQUEST_ATTRIBUTE_NAME); - localeContextResolver.resolveLocaleContext(request); - assertThat(localeContext.getLocale()).isEqualTo(Locale.GERMANY); - } } - catch (UnsupportedOperationException ex) { - if (shouldSet) { - fail("should be able to set Locale"); - } + } + catch (UnsupportedOperationException ex) { + if (shouldSet) { + fail("should be able to set Locale"); } } } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/SessionLocaleResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/SessionLocaleResolverTests.java index de9256f4bdef..2f61daa231f5 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/SessionLocaleResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/SessionLocaleResolverTests.java @@ -22,6 +22,7 @@ import jakarta.servlet.http.HttpSession; import org.junit.jupiter.api.Test; +import org.springframework.context.i18n.SimpleLocaleContext; import org.springframework.context.i18n.TimeZoneAwareLocaleContext; import org.springframework.web.testfixture.servlet.MockHttpServletRequest; import org.springframework.web.testfixture.servlet.MockHttpServletResponse; @@ -48,27 +49,27 @@ class SessionLocaleResolverTests { void resolveLocale() { request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, Locale.GERMAN); - assertThat(resolver.resolveLocale(request)).isEqualTo(Locale.GERMAN); + assertThat(resolver.resolveLocaleContext(request).getLocale()).isEqualTo(Locale.GERMAN); } @Test void setAndResolveLocale() { - resolver.setLocale(request, response, Locale.GERMAN); - assertThat(resolver.resolveLocale(request)).isEqualTo(Locale.GERMAN); + resolver.setLocaleContext(request, response, new SimpleLocaleContext(Locale.GERMAN)); + assertThat(resolver.resolveLocaleContext(request).getLocale()).isEqualTo(Locale.GERMAN); HttpSession session = request.getSession(); request = new MockHttpServletRequest(); request.setSession(session); resolver = new SessionLocaleResolver(); - assertThat(resolver.resolveLocale(request)).isEqualTo(Locale.GERMAN); + assertThat(resolver.resolveLocaleContext(request).getLocale()).isEqualTo(Locale.GERMAN); } @Test void resolveLocaleWithoutSession() throws Exception { request.addPreferredLocale(Locale.TAIWAN); - assertThat(resolver.resolveLocale(request)).isEqualTo(request.getLocale()); + assertThat(resolver.resolveLocaleContext(request).getLocale()).isEqualTo(request.getLocale()); } @Test @@ -77,7 +78,7 @@ void resolveLocaleWithoutSessionAndDefaultLocale() throws Exception { resolver.setDefaultLocale(Locale.GERMAN); - assertThat(resolver.resolveLocale(request)).isEqualTo(Locale.GERMAN); + assertThat(resolver.resolveLocaleContext(request).getLocale()).isEqualTo(Locale.GERMAN); } @Test @@ -85,7 +86,7 @@ void setLocaleToNullLocale() throws Exception { request.addPreferredLocale(Locale.TAIWAN); request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, Locale.GERMAN); - resolver.setLocale(request, response, null); + resolver.setLocaleContext(request, response, null); Locale locale = (Locale) request.getSession().getAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME); assertThat(locale).isNull(); @@ -94,7 +95,7 @@ void setLocaleToNullLocale() throws Exception { request.addPreferredLocale(Locale.TAIWAN); request.setSession(session); resolver = new SessionLocaleResolver(); - assertThat(resolver.resolveLocale(request)).isEqualTo(Locale.TAIWAN); + assertThat(resolver.resolveLocaleContext(request).getLocale()).isEqualTo(Locale.TAIWAN); } @Test @@ -103,7 +104,7 @@ void customDefaultLocaleFunction() { resolver.setDefaultLocaleFunction(request -> Locale.GERMAN); - assertThat(resolver.resolveLocale(request)).isEqualTo(Locale.GERMAN); + assertThat(resolver.resolveLocaleContext(request).getLocale()).isEqualTo(Locale.GERMAN); } @Test diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/AbstractTagTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/AbstractTagTests.java index 28c9a03708a2..8c28c1be1500 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/AbstractTagTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/AbstractTagTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; -import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.LocaleContextResolver; import org.springframework.web.servlet.SimpleWebApplicationContext; import org.springframework.web.servlet.ThemeResolver; import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver; @@ -49,7 +49,7 @@ protected MockPageContext createPageContext() { MockHttpServletResponse response = new MockHttpServletResponse(); if (inDispatcherServlet()) { request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac); - LocaleResolver lr = new AcceptHeaderLocaleResolver(); + LocaleContextResolver lr = new AcceptHeaderLocaleResolver(); request.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, lr); ThemeResolver tr = new FixedThemeResolver(); request.setAttribute(DispatcherServlet.THEME_RESOLVER_ATTRIBUTE, tr); diff --git a/src/docs/asciidoc/web/webmvc.adoc b/src/docs/asciidoc/web/webmvc.adoc index 841b3fc8aa6f..537938ae33e1 100644 --- a/src/docs/asciidoc/web/webmvc.adoc +++ b/src/docs/asciidoc/web/webmvc.adoc @@ -904,7 +904,7 @@ See <> under <> for configuration details Most parts of Spring's architecture support internationalization, as the Spring web MVC framework does. `DispatcherServlet` lets you automatically resolve messages -by using the client's locale. This is done with `LocaleResolver` objects. +by using the client's locale. This is done with `LocaleContextResolver` objects. When a request comes in, the `DispatcherServlet` looks for a locale resolver and, if it finds one, it tries to use it to set the locale. By using the `RequestContext.getLocale()` @@ -1013,7 +1013,7 @@ modifies the corresponding `HttpSession` attributes against the current `HttpSer You can enable changing of locales by adding the `LocaleChangeInterceptor` to one of the `HandlerMapping` definitions. It detects a parameter in the request and changes the locale -accordingly, calling the `setLocale` method on the `LocaleResolver` in the dispatcher's +accordingly, calling the `setLocale` method on the `LocaleContextResolver` in the dispatcher's application context. The next example shows that calls to all `{asterisk}.view` resources that contain a parameter named `siteLanguage` now changes the locale. So, for example, a request for the URL, `https://www.sf.net/home.view?siteLanguage=nl`, changes the site @@ -1111,7 +1111,7 @@ background image with Dutch text on it. After you define themes, as described in the <>, you decide which theme to use. The `DispatcherServlet` looks for a bean named `themeResolver` to find out which `ThemeResolver` implementation to use. A theme resolver works in much the same -way as a `LocaleResolver`. It detects the theme to use for a particular request and can also +way as a `LocaleContextResolver`. It detects the theme to use for a particular request and can also alter the request's theme. The following table describes the theme resolvers provided by Spring: [[mvc-theme-resolver-impls-tbl]] @@ -2098,8 +2098,8 @@ and others) and is equivalent to `required=false`. | The HTTP method of the request. | `java.util.Locale` -| The current request locale, determined by the most specific `LocaleResolver` available (in - effect, the configured `LocaleResolver` or `LocaleContextResolver`). +| The current request locale, determined by the most specific `LocaleContextResolver` available (in + effect, the configured `LocaleContextResolver`). | `java.util.TimeZone` + `java.time.ZoneId` | The time zone associated with the current request, as determined by a `LocaleContextResolver`. @@ -3932,8 +3932,8 @@ level, <> mechanism. | The HTTP method of the request. | `java.util.Locale` -| The current request locale, determined by the most specific `LocaleResolver` available -- in - effect, the configured `LocaleResolver` or `LocaleContextResolver`. +| The current request locale, determined by the most specific `LocaleContextResolver` available -- in + effect, the configured `LocaleContextResolver`. | `java.util.TimeZone`, `java.time.ZoneId` | The time zone associated with the current request, as determined by a `LocaleContextResolver`.