LocaleResolver 实际使用很少,所以艿艿也没特别细看,就看了下 AcceptHeaderLocaleResolver 类。
这里艿艿就转载 N3verL4nd 的 《SpringMVC 源码解析 —— LocaleResolver》 。
1. LocaleResolver
LocaleResolver 是一个解决国际化的策略接口。它包含两个方法:#resolveLocale(...)
和 #setLocale(...)
,代码如下:
public interface LocaleResolver {
Locale resolveLocale(HttpServletRequest request); void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);
}
|
实现此接口的类:
LocaleResolver 类图
SpringMVC 默认使用的是:AcceptHeaderLocaleResolver 。
`DispatcherServlet.properties`
public class AcceptHeaderLocaleResolver implements LocaleResolver {
private final List<Locale> supportedLocales = new ArrayList<>(4);
@Nullable private Locale defaultLocale;
public void setSupportedLocales(@Nullable List<Locale> locales) { this.supportedLocales.clear(); if (locales != null) { this.supportedLocales.addAll(locales); } }
public List<Locale> getSupportedLocales() { return this.supportedLocales; }
public void setDefaultLocale(@Nullable Locale defaultLocale) { this.defaultLocale = defaultLocale; }
@Nullable public Locale getDefaultLocale() { return this.defaultLocale; }
@Override public Locale resolveLocale(HttpServletRequest request) { Locale defaultLocale = getDefaultLocale(); if (defaultLocale != null && request.getHeader("Accept-Language") == null) { return defaultLocale; } Locale requestLocale = request.getLocale(); if (isSupportedLocale(requestLocale)) { return requestLocale; } Locale supportedLocale = findSupportedLocale(request); if (supportedLocale != null) { return supportedLocale; } return (defaultLocale != null ? defaultLocale : requestLocale); }
private boolean isSupportedLocale(Locale locale) { List<Locale> supportedLocales = getSupportedLocales(); return (supportedLocales.isEmpty() || supportedLocales.contains(locale)); }
@Nullable private Locale findSupportedLocale(HttpServletRequest request) { Enumeration<Locale> requestLocales = request.getLocales(); while (requestLocales.hasMoreElements()) { Locale locale = requestLocales.nextElement(); if (getSupportedLocales().contains(locale)) { return locale; } } return null; }
@Override public void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale) { throw new UnsupportedOperationException( "Cannot change HTTP accept header - use a different locale resolution strategy"); }
}
|
#resolveLocale(...)
方法的处理流程:
- 如果 HTTP 请求头里不含有
Accept-Language
,并且默认的语言环境 defaultLocale
不为空,则使用默认的语言环境。否则,从请求里获得 Locale 。
- 而一般的我们没有配置
supportedLocales
与defaultLocale
属性(需要配置注入),所以 AcceptHeaderLocaleResolver 使用Accept-Language
来构造 Locale 对象。
3. AbstractLocaleResolver
public abstract class AbstractLocaleResolver implements LocaleResolver {
@Nullable private Locale defaultLocale; public void setDefaultLocale(@Nullable Locale defaultLocale) { this.defaultLocale = defaultLocale; } @Nullable protected Locale getDefaultLocale() { return this.defaultLocale; } }
|
4. LocaleContextResolver
public interface LocaleContextResolver extends LocaleResolver {
LocaleContext resolveLocaleContext(HttpServletRequest request); void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable LocaleContext localeContext); }
|
5. AbstractLocaleContextResolver
public abstract class AbstractLocaleContextResolver extends AbstractLocaleResolver implements LocaleContextResolver {
@Nullable private TimeZone defaultTimeZone; public void setDefaultTimeZone(@Nullable TimeZone defaultTimeZone) { this.defaultTimeZone = defaultTimeZone; } @Nullable public TimeZone getDefaultTimeZone() { return this.defaultTimeZone; } @Override public Locale resolveLocale(HttpServletRequest request) { Locale locale = resolveLocaleContext(request).getLocale(); return (locale != null ? locale : request.getLocale()); } @Override public void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale) { setLocaleContext(request, response, (locale != null ? new SimpleLocaleContext(locale) : null)); } }
|
6. SessionLocaleResolver
public class SessionLocaleResolver extends AbstractLocaleContextResolver {
public static final String LOCALE_SESSION_ATTRIBUTE_NAME = SessionLocaleResolver.class.getName() + ".LOCALE"; public static final String TIME_ZONE_SESSION_ATTRIBUTE_NAME = SessionLocaleResolver.class.getName() + ".TIME_ZONE"; private String localeAttributeName = LOCALE_SESSION_ATTRIBUTE_NAME; private String timeZoneAttributeName = TIME_ZONE_SESSION_ATTRIBUTE_NAME;
public void setLocaleAttributeName(String localeAttributeName) { this.localeAttributeName = localeAttributeName; }
public void setTimeZoneAttributeName(String timeZoneAttributeName) { this.timeZoneAttributeName = timeZoneAttributeName; }
@Override public Locale resolveLocale(HttpServletRequest request) { Locale locale = (Locale) WebUtils.getSessionAttribute(request, this.localeAttributeName); if (locale == null) { locale = determineDefaultLocale(request); } return locale; }
@Override public LocaleContext resolveLocaleContext(final HttpServletRequest request) { return new TimeZoneAwareLocaleContext() { @Override public Locale getLocale() { Locale locale = (Locale) WebUtils.getSessionAttribute(request, localeAttributeName); if (locale == null) { locale = determineDefaultLocale(request); } return locale; } @Override @Nullable public TimeZone getTimeZone() { TimeZone timeZone = (TimeZone) WebUtils.getSessionAttribute(request, timeZoneAttributeName); if (timeZone == null) { timeZone = determineDefaultTimeZone(request); } return timeZone; } }; }
@Override public void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable LocaleContext localeContext) {
Locale locale = null; TimeZone timeZone = null; if (localeContext != null) { locale = localeContext.getLocale(); if (localeContext instanceof TimeZoneAwareLocaleContext) { timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone(); } } WebUtils.setSessionAttribute(request, this.localeAttributeName, locale); WebUtils.setSessionAttribute(request, this.timeZoneAttributeName, timeZone); }
protected Locale determineDefaultLocale(HttpServletRequest request) { Locale defaultLocale = getDefaultLocale(); if (defaultLocale == null) { defaultLocale = request.getLocale(); } return defaultLocale; }
@Nullable protected TimeZone determineDefaultTimeZone(HttpServletRequest request) { return getDefaultTimeZone(); }
}
|
666. 彩蛋
参考和推荐如下文章: