国际化:页面响应式布局同页面针对不一样的设备进行相应的显示,国际化则是同页面针对不一样的地区/语言进行相应的自适应的显示web
国际化消息资源的封装类,主要配置不一样地区和国家相应对象的表示内容,通常使用properties文件进行封装spring
Locale对象的解析器,主要用于解析Locale对象以及负责Locale对象在Session中存储mvc
Locale对象改变拦截器(可理解成Tomcat的监听器:区别在于前者Servlet采用Servlet容器实现,Spring采用IOC容器实现),当页面的locale对象发生改变时,该拦截器会进行相应的处理,不然不处理app
工做流程:核心类:LocaleChangeInterceptoride
public static final String DEFAULT_PARAM_NAME = "locale"; private String paramName = DEFAULT_PARAM_NAME; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException { String newLocale = request.getParameter(getParamName()); if (newLocale != null) { if (checkHttpMethod(request.getMethod())) { LocaleResolver 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)); } catch (IllegalArgumentException ex) { if (isIgnoreInvalidLocale()) { logger.debug("Ignoring invalid locale value [" + newLocale + "]: " + ex.getMessage()); } else { throw ex; } } } } return true; } public String getParamName() { return this.paramName; }
preHandle:HandlerInterceptor接口的标准方法,主要用于Handler处理前的拦截处理,从LocaleChangeInterceptor的源码可看出,当页面请求参数包含locale的参数时,内部会自动建立和DispatherServlet绑定的localeResolver对象(例如SessionLocaleResolver),而后调用布局
localeResolver.setLocale(request, response, parseLocaleValue(newLocale))
进行Locale对象的设置,这里咱们查看setLocale方法在SessionLocaleResolver中的实现:this
@Override public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, 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, LOCALE_SESSION_ATTRIBUTE_NAME, locale); WebUtils.setSessionAttribute(request, TIME_ZONE_SESSION_ATTRIBUTE_NAME, timeZone); }
从源码中能够看出,SessionLocaleResolver主要完成Locale和TimeZone对象在Session中的存储,这样经过SpringMVC国际化整个流程的Locale和TimeZone的设置就所有完成了,当客户端访问对应的资源时IOC容器内部的ResourceBundleMessageSource会自动根据Locale对象去获取不一样的页面显示的资源文件,达到不一样的语言/地区页面不一样的显示的效果spa
注意:debug
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="defaultEncoding" value="UTF-8" /> <property name="useCodeAsDefaultMessage" value="true" /> <property name="basenames"> <list> <value>config/i18n</value> </list> </property> </bean>
目录结构:code
i18n_en_US.properties:
user.name=name user.passwd=passwd page.language:English page.description:Page Language i18n.tile:Internationization
i18n_zh_CN.properties:
user.name:\u7528\u6237\u540D user.passwd:\u5BC6\u7801 page.language:Simple Chinese page.description:\u9875\u9762\u8BED\u8A00 i18n.tile:\u56FD\u9645\u5316
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"/>
<mvc:interceptors> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/> </mvc:interceptors>
@RequestMapping("/handlerInernationization/i18n") public String handlerInernationization(Locale locale) { String user = resourceBundleMessageSource.getMessage("i18n.title", null, locale); System.err.println("resourceBundleMessageSource:" + locale + ":i18n.title=" + user); return "i18n"; }
效果: 访问URL: http://127.0.0.1:8080/springmvc_experience/handlerInernationization/i18n?locale=zh_CN
访问URL: http://127.0.0.1:8080/springmvc_experience/handlerInernationization/i18n?locale=en_US