SonicsTorm 2019-06-27
根据客户端环境,界面显示不同的国旗图案。
在接到一个需求时,首先要理解需求,实际工作中可能需求跟产品进行多次沟通,其目的就是准确的理解,理解了需求就可以选择相应的技术方案去解决。就我们这个功能来说,需求就是可定制不同的国旗图案。选择的技术方案可利用Spring MVC提供的国际化和主题定制来解决。

源码分析
pom.xml文件
引入Spring MVC依赖以及JSP依赖,代码如下:
<!-- Spring MVC依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<!-- Servlet支持 -->
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- jsp支持-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>spring-servlet.xml文件
在classpath下新建Spring MVC配置文件,代码如下:
<!-- 启动注解扫描 -->
<mvc:annotation-driven/>
<!-- mvc controller -->
<context:component-scan base-package="com.github.dalianghe.controller" />
<!-- 默认Servlet处理静态资源 -->
<mvc:default-servlet-handler />
<!-- jsp视图映射与视图解析 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:interceptors>
<!-- 该拦截器通过参数名为”locale”的参数来拦截HTTP请求,设置LocaleResolver -->
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="locale"/>
</bean>
</mvc:interceptors>
<!-- 国际化资源文件 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<!-- 如果资源文件放在classpath下,basename的value必须有classpath:前缀,否则报错:No message found under code... -->
<property name="basename" value="classpath:i18n/messages" />
<!-- 如果在国际化资源文件中找不到对应代码的信息,就用这个代码作为名称返回 -->
<property name="useCodeAsDefaultMessage" value="true" />
</bean>
<!--CookieLocaleResolver解析器 -->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<!-- 设置默认为中国,即从客户端cookie中未找到cookieName时,使用默认locale -->
<property name="defaultLocale" value="zh_CN"/>
<!-- 设置cookieName,默认为:org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE -->
<property name="cookieName" value="locale"/>
</bean>
<!-- 加载主题资源文件 -->
<bean id="themeSource" class="org.springframework.ui.context.support.ResourceBundleThemeSource">
<!-- 指定文件前缀,即文件所在目录,如果放在classpath下,value为空(默认从classpath下加载) -->
<property name="basenamePrefix" value="theme."/>
</bean>
<!-- 主题解析器 -->
<bean id="themeResolver" class="org.springframework.web.servlet.theme.CookieThemeResolver">
<!-- 主题文件名称,如果有多个相同前缀(theme)时,
查找最终的文件名为: defaultThemeName+国际化标识,如:theme_zh_CN.properties-->
<property name="defaultThemeName" value="theme"/>
<!-- 设置theme的客户端cookie名 -->
<property name="cookieName" value="theme"/>
</bean>web.xml文件
配置Spring MVC 前端控制器,即DispatcherServlet,负责拦截用户请求,代码如下:
<servlet>
<!-- Servlet名称,可任意定义,但必须与servlet-mapping中对应 -->
<servlet-name>dispatcher</servlet-name>
<!-- 指定Spring MVC核心控制类,即J2EE规范中的前端控制器(Front Controller) -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定Spring MVC配置文件,默认在WEB-INF目录下,
切名字为[servlet-name]-servlet.xml,此文件中配置web相关内容,
比如:指定扫描Controller路径、配置逻辑视图前缀后缀、上传文件等等 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-servlet.xml</param-value>
</init-param>
<!-- 此配置的值为正整数时,表示容器启动时初始化,即调用Servlet的init方法 -->
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<!-- 定义servlet映射 -->
<servlet-mapping>
<!-- 与servlet中servlet-name对应 -->
<servlet-name>dispatcher</servlet-name>
<!-- 映射所有的url -->
<url-pattern>/</url-pattern>
</servlet-mapping>国际化属性文件
本例中创建了中国、美国及芬兰的国际化支持,配置文件如下:
messages_zh _CN.properties
message.locale=中国
messages_en _US.properties
message.locale=美国
messages_sv _FI.properties
message.locale=芬兰
主题属性文件
根据国际化配置,主题定义了中国、美国及芬兰的国旗图片,配置如下:
theme_ zh_CN.properties
background=/img/China.jpg
theme_ en_US.properties
background=/img/America.jpg
theme_ sv_FI.properties
background=/img/Finland.jpg
视图及控制器
Controller控制器代码如下:
@RequestMapping("/demo")
public String demo(HttpServletRequest request , Model model){
Locale locale = RequestContextUtils.getLocale(request);
model.addAttribute("locale",locale);
return "demo";
}JSP视图代码如下:
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
<title>Spring MVC Theme</title>
</head>
<body>
<fmt:message key="message.name"/> : <fmt:message key="message.locale"/>
<br/><br/>
<img src="<spring:theme code='background'/>" style="width: 500px;height: 300px;">
</body>
</html>本例以Firefox为客户端测试工具,测试步骤如下:
1、启动项目后,访问界面,在地址栏输入http://localhost:8088/demo,结果如下:

由图可知,此时系统使用的是默认的国际化属性文件及显示默认的国旗图案,与我们设想的一致。注意此时返回的cookie中没有国际化及主题相关的信息。
2、通过请求参数locale设置地区环境,在地址栏输入localhost:8088/demo?locale=en_US,并发起请求,结果如下:

由上图可知结果,与我们的设想一致,并且服务端通过拦截器把国际化写入了客户端cookie中。
3、修改请求参数locale的值为荷兰,即locale=sv_FI后再发起请求,结果如下:

与预期一致,测试通过。
本例使用CookieLocaleResolver和CookieThemeResolver结合实现了国际化与主题定制需求,Spring MVC为我们提供了不通实现方式的LocaleResolver和ThemeResolver,可自由组合使用,这两个策略解析器主要定制前端信息或样式,通过之前的源码分析及此案例,这块内容就分析完了,希望对大家有所帮助。
最后创建了qq群方便大家交流,可扫描加入,同时也可加我qq:276420284,共同学习、共同进步,谢谢!
