Spring MVC源码解析 - LocaleResolver组件

本文主要介绍了Spring MVC中的LocaleResolver组件,包括AcceptHeaderLocaleResolver、AbstractLocaleResolver、CookieLocaleResolver以及LocaleChangeInterceptor的工作原理。默认情况下,Spring MVC通过Accept-Language头来判断客户端本地化类型,同时支持通过session、cookie或请求参数切换。此外,还讨论了如何配置LocaleChangeInterceptor动态改变请求的本地化类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

目录

前言 

一.  LocaleResolver 

二.  AcceptHeaderLocaleResolver

 三.  AbstractLocaleResolver

四.  CookieLocaleResolver

五.  LocaleChangeInterceptor

 


 

前言 

参考:《Spring4.x 企业应用开发实战》

一般情况下,web应用根据浏览器的设置来判断客户端的本地化类型。用户可以在浏览器中修改本地化类型。

浏览器中设置的本地化类型通过请求报文头中的"Accept-Language"参数的设置发送给服务端,服务端以此判断客户端本地化类型。也可以通过session、cookie或者请求参数的方式即可切换本地化类型。Spring MVC在收到请求时,会寻找LocaleResolver,然后找到后使用它来获取请求所对应的本地化类型信息。除此之外呢,还可以装配一个动态修改本地化类型的拦截器,这样的话,通过指定一个参数就可以控制单个请求的本地化类型。

一.  LocaleResolver 

/**
 * 基于网络的本地语言解析策略,针对本地请求策略和请求、响应的本地语言的修改
 */
public interface LocaleResolver {

	/**
	 * 解析当前给定请求的本地语言。
	 */
	Locale resolveLocale(HttpServletRequest request);

	/**
	 * 设置当前的locale
	 */
	void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);

}

 

二.  AcceptHeaderLocaleResolver

根据HTTP报文头的"Accept-Language"参数确定本地化类型。如果没有显示定义本地化解析器,Spring MVC默认使用AcceptHeaderLocaleResolver。 

/**
 *
 * LocaleResolver的实现类,简单地使用HTTP请求头的"accept-language"指定的基础locale。
 * locale,是由客户端浏览器发送的本地语言,正常情况下,是客户端操作系统的本地语言。
 *
 * 注意: 别去使用setLocale去设置locale,因为accept-header只能通过改变客户端的本地语言设置。
 *
 */
public class AcceptHeaderLocaleResolver implements LocaleResolver {

	private final List<Locale> supportedLocales = new ArrayList<>(4);

	@Nullable
	private Locale defaultLocale;


	/**
	 * 配置支持的本地语言集合
	 */
	public void setSupportedLocales(List<Locale> locales) {
		this.supportedLocales.clear();
		this.supportedLocales.addAll(locales);
	}

	/**
	 * 获取配置的支持的本地语言集合
	 */
	public List<Locale> getSupportedLocales() {
		return this.supportedLocales;
	}

	/**
	 * 如果请求没有“Accept-Language”头,配置一个固定不变的默认的本地语言。
	 */
	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();
		// 设置了默认的本地语言 && 请求头中没有“Accept-Language”
		if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
			return defaultLocale;
		}
		Locale requestLocale = request.getLocale();
		List<Locale> supportedLocales = getSupportedLocales();
		if (supportedLocales.isEmpty() || supportedLocales.contains(requestLocale)) {
			return requestLocale;
		}
		Locale supportedLocale = findSupportedLocale(request, supportedLocales);
		if (supportedLocale != null) {
			return supportedLocale;
		}
		return (defaultLocale != null ? defaultLocale : requestLocale);
	}

	/**
	 * 找到支持给定请求的本地语言
	 */
	@Nullable
	private Locale findSupportedLocale(HttpServletRequest request, List<Locale> supportedLocales) {
		Enumeration<Locale> requestLocales = request.getLocales();
		Locale languageMatch = null;
		while (requestLocales.hasMoreElements()) {
			Locale locale = requestLocales.nextElement();
			if (supportedLocales.contains(locale)) {
				if (languageMatch == null || languageMatch.getLanguage().equals(locale.getLanguage())) {
					// Full match: language + country, possibly narrowed from earlier language-only match
					return locale;
				}
			}
			else if (languageMatch == null) {
				// Let's try to find a language-only match as a fallback
				for (Locale candidate : supportedLocales) {
					if (!StringUtils.hasLength(candidate.getCountry()) &&
							candidate.getLanguage().equals(locale.getLanguage())) {
						languageMatch = candidate;
						break;
					}
				}
			}
		}
		return languageMatch;
	}

	/** 
	 * 上文有说道,不要通过setLocale的方式设置locale,这里呢,直接抛出一个运行时异常。
	 */
	@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");
	}

}

 三.  AbstractLocaleResolver

/**
 * LocaleResolver的抽象基础实现类,提供了一个默认的本地语言的支持
 */
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;
	}

}

/**
 * LocaleResolver的拓展,添加了对locale context的支持
 */
public interface LocaleContextResolver extends LocaleResolver {

	/**
	 * 解析给定请求的当前的本地语言上下文
	 */
	LocaleContext resolveLocaleContext(HttpServletRequest request);

	/**
	 * 设置当前的本地语言上下文
	 */
	void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response,
			@Nullable LocaleContext localeContext);

}
/**
 * LocaleContextResolver的抽象基础实现类,提供了对默认本地语言和默认时区的支持
 */
public abstract class AbstractLocaleContextResolver extends AbstractLocaleResolver implements LocaleContextResolver {

	@Nullable
	private TimeZone defaultTimeZone;


	/**
	 * 设置默认的time zone
	 */
	public void setDefaultTimeZone(@Nullable TimeZone defaultTimeZone) {
		this.defaultTimeZone = defaultTimeZone;
	}

	/**
	 * 获取默认的time zone
	 */
	@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));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值