spring的國際化

通常客戶端的語言特性,是經過cookie來傳遞的,也能夠經過request的請求中得到locale的值。 java

先看CookieGenerator.java web

public void addCookie(HttpServletResponse response, String cookieValue) {
		Assert.notNull(response, "HttpServletResponse must not be null");
		Cookie cookie = createCookie(cookieValue);
		Integer maxAge = getCookieMaxAge();
		if (maxAge != null) {
			cookie.setMaxAge(maxAge);
		}
		if (isCookieSecure()) {
			cookie.setSecure(true);
		}
		if (isCookieHttpOnly()) {
			cookie.setHttpOnly(true);
		}
		response.addCookie(cookie);
		if (logger.isDebugEnabled()) {
			logger.debug("Added cookie with name [" + getCookieName() + "] and value [" + cookieValue + "]");
		}
	}

這個地方就是response中回寫cookie來存儲locale的值。cookieName表明的是cookie的key值。若是咱們採用的CookieLocaleResolver.java是本地的locale解析器。默認設置的cookieName是 spring

public static final String DEFAULT_COOKIE_NAME = CookieLocaleResolver.class.getName() + ".LOCALE";

繼承自LocaleResolver的兩個方法實現以下: cookie

public Locale resolveLocale(HttpServletRequest request) {
		// Check request for pre-parsed or preset locale.
		Locale locale = (Locale) request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);
		if (locale != null) {
			return locale;
		}

		// Retrieve and parse cookie value.
		Cookie cookie = WebUtils.getCookie(request, getCookieName()); --批量在cookie中匹配對應key值的cookie
		if (cookie != null) {
			locale = StringUtils.parseLocaleString(cookie.getValue());
			if (logger.isDebugEnabled()) {
				logger.debug("Parsed cookie value [" + cookie.getValue() + "] into locale '" + locale + "'");
			}
			if (locale != null) {
				request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME, locale);--設置到request請求中,在spring的攔截器會使用時,攔截request時使用。
				return locale;
			}
		}

		return determineDefaultLocale(request); --若是前面的cookie沒有讀取出來的話,讀取的是request中包含的locale信息。
	}

	public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
		if (locale != null) {
			// Set request attribute and add cookie.
			request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME, locale); --設置請求中的locale信息
			addCookie(response, locale.toString()); --添加cookie到response中,設置到客戶端中。
		}
		else {
			// Set request attribute to fallback locale and remove cookie.
			request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME, determineDefaultLocale(request));
			removeCookie(response);
		}
	}
看一下攔截器對request的操做,是在類LocaleChangeInterceptor中引用:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws ServletException {

		String newLocale = request.getParameter(this.paramName); --查看請求參數中是否有locale的參數名,感受spring這個地方的處理略顯粗糙了點
		if (newLocale != null) {
			LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request); --從spring的容器中獲取localeResolver的實現
			if (localeResolver == null) {
				throw new IllegalStateException("No LocaleResolver found: not in a DispatcherServlet request?");
			}
			localeResolver.setLocale(request, response, StringUtils.parseLocaleString(newLocale));
		}
		// Proceed in any case.
		return true;
	}
接下來查看的是:
public static LocaleResolver getLocaleResolver(HttpServletRequest request) {
		return (LocaleResolver) request.getAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE); --在請求的屬性中是否有localeResolver的實現
	}

調用方法是DispatcherServlet.java中: session

public static final String LOCALE_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".LOCALE_RESOLVER";
這裏指定的是locale的解析類的key值。 DispatcherServlet也包含其餘的如上下文和主題等的生成。

初始化的時候指定對應的key值,對應到調用的地方是: mvc

protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context); --初始化localeResolver
		initThemeResolver(context);
		initHandlerMappings(context);
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
		initFlashMapManager(context); }

初始化本地化解析的方法調用以下: app

private void initLocaleResolver(ApplicationContext context) {
		try {
			this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);//bean的值是localeResolver,定義bean值的時候須要bean的id爲localeResolver.
			if (logger.isDebugEnabled()) {
				logger.debug("Using LocaleResolver [" + this.localeResolver + "]");
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			// We need to use the default.
			this.localeResolver = getDefaultStrategy(context, LocaleResolver.class); //沒找到時候採起的默認策略的localeResolver爲org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate LocaleResolver with name '" + LOCALE_RESOLVER_BEAN_NAME +
						"': using default [" + this.localeResolver + "]");
			}
		}
	}

spring的mvc攔截器會攔截客戶端的請求來抓取到合適的locale解析器來得到locale的屬性,從而經過resourceBundle來得到對應的屬性文件裏面的值。須要注意的點是bean的id須要設置成localeResolverthis

分析一下i18n包下的幾個類: spa

AcceptHeaderLocaleResolver --是獲取請求頭中的locale對象 線程

CookieLocaleResolver --獲取的是cookie中傳遞的locale對象,若是cookie 不存在,獲取的也是請求頭中的locale對象。其中默認的cookieName是:


public static final String DEFAULT_COOKIE_NAME = CookieLocaleResolver.class.getName() + ".LOCALE";
SessionLocaleResolver --是從session中來獲取的locale值,用會話來保持。默認的key值是:



public static final String LOCALE_SESSION_ATTRIBUTE_NAME = SessionLocaleResolver.class.getName() + ".LOCALE";
FixedLocaleResolver -- 是獲取請求頭中的locale對象,不一樣點是能夠經過java代碼來寫入想要的locale對象。


上面只是spring的保持和傳遞locale對象的方式,也能夠經過線程的方式來將locale綁定到ThreadLocale上面。來保持在一次請求過程當中locale的值。取值的方式也能夠參照前面的幾種。

後續會加上ResourceBundle中調用的邏輯處理。

相關文章
相關標籤/搜索