Introduce LocaleContextResolver in WebFlux
This commit introduces LocaleContextResolver interface, which is used at ServerWebExchange level to resolve Locale, TimeZone and other i18n related informations. It follows Spring MVC locale resolution patterns with a few differences: - Only LocaleContextResolver is supported since LocaleResolver is less flexible - Support is implemented in the org.springframework.web.server.i18n package of spring-web module rather than in spring-webflux in order to be able to leverage it at ServerWebExchange level 2 implementations are provided: - FixedLocaleContextResolver - AcceptHeaderLocaleContextResolver It can be configured with both functional or annotation-based APIs. Issue: SPR-15036
This commit is contained in:
@@ -24,11 +24,13 @@ import java.util.function.Consumer;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.http.codec.multipart.Part;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.server.i18n.LocaleContextResolver;
|
||||
|
||||
/**
|
||||
* Contract for an HTTP request-response interaction. Provides access to the HTTP
|
||||
@@ -98,6 +100,11 @@ public interface ServerWebExchange {
|
||||
*/
|
||||
Mono<MultiValueMap<String, Part>> getMultipartData();
|
||||
|
||||
/**
|
||||
* Return the {@link LocaleContext} using the configured {@link LocaleContextResolver}.
|
||||
*/
|
||||
LocaleContext getLocaleContext();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the one of the {@code checkNotModified} methods
|
||||
* in this contract were used and they returned true.
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.Optional;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.http.codec.multipart.Part;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
@@ -90,6 +91,11 @@ public class ServerWebExchangeDecorator implements ServerWebExchange {
|
||||
return getDelegate().getPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleContext getLocaleContext() {
|
||||
return getDelegate().getLocaleContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<MultiValueMap<String, String>> getFormData() {
|
||||
return getDelegate().getFormData();
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -45,6 +46,7 @@ import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.server.i18n.LocaleContextResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebSession;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
@@ -82,6 +84,8 @@ public class DefaultServerWebExchange implements ServerWebExchange {
|
||||
|
||||
private final Mono<WebSession> sessionMono;
|
||||
|
||||
private final LocaleContextResolver localeContextResolver;
|
||||
|
||||
private final Mono<MultiValueMap<String, String>> formDataMono;
|
||||
|
||||
private final Mono<MultiValueMap<String, Part>> multipartDataMono;
|
||||
@@ -89,20 +93,19 @@ public class DefaultServerWebExchange implements ServerWebExchange {
|
||||
private volatile boolean notModified;
|
||||
|
||||
|
||||
/**
|
||||
* Alternate constructor with a WebSessionManager parameter.
|
||||
*/
|
||||
public DefaultServerWebExchange(ServerHttpRequest request, ServerHttpResponse response,
|
||||
WebSessionManager sessionManager, ServerCodecConfigurer codecConfigurer) {
|
||||
WebSessionManager sessionManager, ServerCodecConfigurer codecConfigurer, LocaleContextResolver localeContextResolver) {
|
||||
|
||||
Assert.notNull(request, "'request' is required");
|
||||
Assert.notNull(response, "'response' is required");
|
||||
Assert.notNull(sessionManager, "'sessionManager' is required");
|
||||
Assert.notNull(codecConfigurer, "'codecConfigurer' is required");
|
||||
Assert.notNull(localeContextResolver, "'localeContextResolver' is required");
|
||||
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.sessionMono = sessionManager.getSession(this).cache();
|
||||
this.localeContextResolver = localeContextResolver;
|
||||
this.formDataMono = initFormData(request, codecConfigurer);
|
||||
this.multipartDataMono = initMultipartData(request, codecConfigurer);
|
||||
}
|
||||
@@ -190,6 +193,11 @@ public class DefaultServerWebExchange implements ServerWebExchange {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleContext getLocaleContext() {
|
||||
return this.localeContextResolver.resolveLocaleContext(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<MultiValueMap<String, String>> getFormData() {
|
||||
return this.formDataMono;
|
||||
|
||||
@@ -31,9 +31,11 @@ import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.server.i18n.LocaleContextResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.handler.WebHandlerDecorator;
|
||||
import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver;
|
||||
import org.springframework.web.server.session.DefaultWebSessionManager;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
|
||||
@@ -83,6 +85,8 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
|
||||
|
||||
private ServerCodecConfigurer codecConfigurer;
|
||||
|
||||
private LocaleContextResolver localeContextResolver;
|
||||
|
||||
|
||||
public HttpWebHandlerAdapter(WebHandler delegate) {
|
||||
super(delegate);
|
||||
@@ -119,6 +123,16 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
|
||||
this.codecConfigurer = codecConfigurer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a custom {@link LocaleContextResolver}. The provided instance is set on
|
||||
* each created {@link DefaultServerWebExchange}.
|
||||
* <p>By default this is set to {@link org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver}.
|
||||
* @param localeContextResolver the locale context resolver to use
|
||||
*/
|
||||
public void setLocaleContextResolver(LocaleContextResolver localeContextResolver) {
|
||||
this.localeContextResolver = localeContextResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured {@link ServerCodecConfigurer}.
|
||||
*/
|
||||
@@ -126,6 +140,13 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
|
||||
return (this.codecConfigurer != null ? this.codecConfigurer : ServerCodecConfigurer.create());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured {@link LocaleContextResolver}.
|
||||
*/
|
||||
public LocaleContextResolver getLocaleContextResolver() {
|
||||
return (this.localeContextResolver != null ? this.localeContextResolver : new AcceptHeaderLocaleContextResolver());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
|
||||
@@ -140,7 +161,7 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
|
||||
}
|
||||
|
||||
protected ServerWebExchange createExchange(ServerHttpRequest request, ServerHttpResponse response) {
|
||||
return new DefaultServerWebExchange(request, response, this.sessionManager, getCodecConfigurer());
|
||||
return new DefaultServerWebExchange(request, response, this.sessionManager, getCodecConfigurer(), getLocaleContextResolver());
|
||||
}
|
||||
|
||||
private void logHandleFailure(Throwable ex) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.http.codec.ServerCodecConfigurer;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.server.i18n.LocaleContextResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebExceptionHandler;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
@@ -68,6 +69,9 @@ public class WebHttpHandlerBuilder {
|
||||
/** Well-known name for the ServerCodecConfigurer in the bean factory. */
|
||||
public static final String SERVER_CODEC_CONFIGURER_BEAN_NAME = "serverCodecConfigurer";
|
||||
|
||||
/** Well-known name for the LocaleContextResolver in the bean factory. */
|
||||
public static final String LOCALE_CONTEXT_RESOLVER_BEAN_NAME = "localeContextResolver";
|
||||
|
||||
|
||||
private final WebHandler webHandler;
|
||||
|
||||
@@ -79,6 +83,8 @@ public class WebHttpHandlerBuilder {
|
||||
|
||||
private ServerCodecConfigurer codecConfigurer;
|
||||
|
||||
private LocaleContextResolver localeContextResolver;
|
||||
|
||||
|
||||
/**
|
||||
* Private constructor.
|
||||
@@ -112,6 +118,8 @@ public class WebHttpHandlerBuilder {
|
||||
* {@link #WEB_SESSION_MANAGER_BEAN_NAME}.
|
||||
* <li>{@link ServerCodecConfigurer} [0..1] -- looked up by the name
|
||||
* {@link #SERVER_CODEC_CONFIGURER_BEAN_NAME}.
|
||||
*<li>{@link LocaleContextResolver} [0..1] -- looked up by the name
|
||||
* {@link #LOCALE_CONTEXT_RESOLVER_BEAN_NAME}.
|
||||
* </ul>
|
||||
* @param context the application context to use for the lookup
|
||||
* @return the prepared builder
|
||||
@@ -144,6 +152,14 @@ public class WebHttpHandlerBuilder {
|
||||
// Fall back on default
|
||||
}
|
||||
|
||||
try {
|
||||
builder.localeContextResolver(
|
||||
context.getBean(LOCALE_CONTEXT_RESOLVER_BEAN_NAME, LocaleContextResolver.class));
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// Fall back on default
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -234,6 +250,16 @@ that's */
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link LocaleContextResolver} to set on the
|
||||
* {@link ServerWebExchange WebServerExchange}.
|
||||
* @param localeContextResolver the locale context resolver
|
||||
*/
|
||||
public WebHttpHandlerBuilder localeContextResolver(LocaleContextResolver localeContextResolver) {
|
||||
this.localeContextResolver = localeContextResolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build the {@link HttpHandler}.
|
||||
@@ -252,6 +278,9 @@ that's */
|
||||
if (this.codecConfigurer != null) {
|
||||
adapted.setCodecConfigurer(this.codecConfigurer);
|
||||
}
|
||||
if (this.localeContextResolver != null) {
|
||||
adapted.setLocaleContextResolver(this.localeContextResolver);
|
||||
}
|
||||
|
||||
return adapted;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.server.i18n;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.SimpleLocaleContext;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* {@link LocaleContextResolver} implementation that simply uses the primary locale
|
||||
* specified in the "Accept-Language" header of the HTTP request (that is,
|
||||
* the locale sent by the client browser, normally that of the client's OS).
|
||||
*
|
||||
* <p>Note: Does not support {@code setLocale}, since the accept header
|
||||
* can only be changed through changing the client's locale settings.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @since 5.0
|
||||
*/
|
||||
public class AcceptHeaderLocaleContextResolver implements LocaleContextResolver {
|
||||
|
||||
private final List<Locale> supportedLocales = new ArrayList<>(4);
|
||||
|
||||
private Locale defaultLocale;
|
||||
|
||||
|
||||
/**
|
||||
* Configure supported locales to check against the requested locales
|
||||
* determined via {@link HttpHeaders#getAcceptLanguageAsLocales()}.
|
||||
* @param locales the supported locales
|
||||
*/
|
||||
public void setSupportedLocales(List<Locale> locales) {
|
||||
this.supportedLocales.clear();
|
||||
if (locales != null) {
|
||||
this.supportedLocales.addAll(locales);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured list of supported locales.
|
||||
*/
|
||||
public List<Locale> getSupportedLocales() {
|
||||
return this.supportedLocales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a fixed default locale to fall back on if the request does not
|
||||
* have an "Accept-Language" header (not set by default).
|
||||
* @param defaultLocale the default locale to use
|
||||
*/
|
||||
public void setDefaultLocale(Locale defaultLocale) {
|
||||
this.defaultLocale = defaultLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* The configured default locale, if any.
|
||||
*/
|
||||
@Nullable
|
||||
public Locale getDefaultLocale() {
|
||||
return this.defaultLocale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleContext resolveLocaleContext(ServerWebExchange exchange) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
List<Locale> acceptableLocales = request.getHeaders().getAcceptLanguageAsLocales();
|
||||
if (this.defaultLocale != null && acceptableLocales.isEmpty()) {
|
||||
return new SimpleLocaleContext(this.defaultLocale);
|
||||
}
|
||||
Locale requestLocale = acceptableLocales.isEmpty() ? null : acceptableLocales.get(0);
|
||||
if (isSupportedLocale(requestLocale)) {
|
||||
return new SimpleLocaleContext(requestLocale);
|
||||
}
|
||||
Locale supportedLocale = findSupportedLocale(request);
|
||||
if (supportedLocale != null) {
|
||||
return new SimpleLocaleContext(supportedLocale);
|
||||
}
|
||||
return (defaultLocale != null ? new SimpleLocaleContext(defaultLocale) : new SimpleLocaleContext(requestLocale));
|
||||
}
|
||||
|
||||
private boolean isSupportedLocale(@Nullable Locale locale) {
|
||||
if (locale == null) {
|
||||
return false;
|
||||
}
|
||||
List<Locale> supportedLocales = getSupportedLocales();
|
||||
return (supportedLocales.isEmpty() || supportedLocales.contains(locale));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Locale findSupportedLocale(ServerHttpRequest request) {
|
||||
List<Locale> requestLocales = request.getHeaders().getAcceptLanguageAsLocales();
|
||||
for (Locale locale : requestLocales) {
|
||||
if (getSupportedLocales().contains(locale)) {
|
||||
return locale;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocaleContext(ServerWebExchange exchange, @Nullable LocaleContext locale) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Cannot change HTTP accept header - use a different locale context resolution strategy");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.server.i18n;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
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.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* {@link LocaleContextResolver} implementation
|
||||
* that always returns a fixed default locale and optionally time zone.
|
||||
* Default is the current JVM's default locale.
|
||||
*
|
||||
* <p>Note: Does not support {@code setLocale(Context)}, as the fixed
|
||||
* locale and time zone cannot be changed.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @since 5.0
|
||||
*/
|
||||
public class FixedLocaleContextResolver implements LocaleContextResolver {
|
||||
|
||||
private final Locale locale;
|
||||
|
||||
private final TimeZone timeZone;
|
||||
|
||||
|
||||
/**
|
||||
* Create a default FixedLocaleResolver, exposing a configured default
|
||||
* locale (or the JVM's default locale as fallback).
|
||||
*/
|
||||
public FixedLocaleContextResolver() {
|
||||
this(Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FixedLocaleResolver that exposes the given locale.
|
||||
* @param locale the locale to expose
|
||||
*/
|
||||
public FixedLocaleContextResolver(Locale locale) {
|
||||
this(locale, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FixedLocaleResolver that exposes the given locale and time zone.
|
||||
* @param locale the locale to expose
|
||||
* @param timeZone the time zone to expose
|
||||
*/
|
||||
public FixedLocaleContextResolver(Locale locale, @Nullable TimeZone timeZone) {
|
||||
Assert.notNull(locale, "Locale must not be null");
|
||||
this.locale = locale;
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleContext resolveLocaleContext(ServerWebExchange exchange) {
|
||||
return new TimeZoneAwareLocaleContext() {
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return locale;
|
||||
}
|
||||
@Override
|
||||
public TimeZone getTimeZone() {
|
||||
return timeZone;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocaleContext(ServerWebExchange exchange, @Nullable LocaleContext localeContext) {
|
||||
throw new UnsupportedOperationException("Cannot change fixed locale - use a different locale context resolution strategy");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.server.i18n;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* Interface for web-based locale context resolution strategies that allows
|
||||
* for both locale context resolution via the request and locale context modification
|
||||
* via the HTTP exchange.
|
||||
*
|
||||
* <p>The {@link org.springframework.context.i18n.LocaleContext} object can potentially
|
||||
* includes associated time zone and other locale related information.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @since 5.0
|
||||
* @see LocaleContext
|
||||
*/
|
||||
public interface LocaleContextResolver {
|
||||
|
||||
/**
|
||||
* Resolve the current locale context via the given exchange.
|
||||
*
|
||||
* <p>The returned context may be a
|
||||
* {@link org.springframework.context.i18n.TimeZoneAwareLocaleContext},
|
||||
* containing a locale with associated time zone information.
|
||||
* Simply apply an {@code instanceof} check and downcast accordingly.
|
||||
* <p>Custom resolver implementations may also return extra settings in
|
||||
* the returned context, which again can be accessed through downcasting.
|
||||
* @param exchange current server exchange
|
||||
* @return the current locale context (never {@code null}
|
||||
*/
|
||||
LocaleContext resolveLocaleContext(ServerWebExchange exchange);
|
||||
|
||||
/**
|
||||
* Set the current locale context to the given one,
|
||||
* potentially including a locale with associated time zone information.
|
||||
* @param exchange current server exchange
|
||||
* @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 org.springframework.context.i18n.SimpleLocaleContext
|
||||
* @see org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext
|
||||
*/
|
||||
void setLocaleContext(ServerWebExchange exchange, @Nullable LocaleContext localeContext);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Locale related support classes.
|
||||
* Provides standard LocaleContextResolver implementations.
|
||||
*/
|
||||
@NonNullApi
|
||||
package org.springframework.web.server.i18n;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
Reference in New Issue
Block a user