在经过众多的方案筛选后,选出了一个比较合适的方案。方案如下。
首先要实现网站的中英文切换总共分为两部分。
第一部分是网站上的静态文字。
第二部分是从数据库查询出来的数据。
第一部分解决方案:
使用jquery的i18n插件,有关该插件的详细描述,请自行百度,这里不做过多的介绍。
第二部分解决方案:
数据库:采用ABC三个库,A库放英文数据,B库放中文数据,C库主要存放用户的登陆权限信息。BC两个库是原本就有的,A库是此方案新加的库。
后台:使用springMVC的拦截器功能,对所有的请求进行拦截,然后从cookie中获取到页面当前使用语言的标识(此标识是在前端通过事件手动加的),通过标识的判断,动态的切换使用的数据源(主要是对AB两个库进行切换)
以上方案后台不用更改任何业务代码,前台需要在原有代码的基础上增加一些内容。
详细代码:
第一部分(静态文字)
准备工作:
js:jquery-2.0.3.min.js,jquery.i18n.properties-1.0.9.js,bootstrap.min.js
css:bootstrap.min.css
开始
cookies.js cookie工具类,用来操作页面的cookie
var cookie={ //cookie工具类 setCookie:function(c_name,value,expiredays){ //设值 var exdate=new Date() exdate.setDate(exdate.getDate()+expiredays) document.cookie=c_name+ "=" +escape(value)+ ((expiredays==null) ? "" : ";expires="+exdate.toGMTString()) }, getCookie:function(c_name){ //取值 if (document.cookie.length>0) { c_start=document.cookie.indexOf(c_name + "=") if (c_start!=-1) { c_start=c_start + c_name.length+1 c_end=document.cookie.indexOf(";",c_start) if (c_end==-1) c_end=document.cookie.length return unescape(document.cookie.substring(c_start,c_end)) } } return ""; }, checkCookie:function(){ //验证 username=getCookie('username') if (username!=null && username!="") {alert('Welcome again '+username+'!')} else { username=prompt('Please enter your name:',"") if (username!=null && username!="") { setCookie('username',username,365) } } } }upload.jsp 测试页面
<body> <button class="btn" οnclick="changeZh()">中文</button> <button class="btn" οnclick="changeEn()">English</button> <div class="container"> <div class="row"> <div class="col-lg-8 col-lg-offset-2"> <div class="page-header"> <h2 id="count" class="lang">登陆页面</h2> </div> <form id="defaultForm" method="get" class="form-horizontal" action="${pageContext.request.contextPath}/sys/login/m"> <div class="form-group"> <label id="label_username" class="lang col-lg-3 control-label"></label> <div class="col-lg-5"> <input type="text" class="form-control" name="loginName" /> </div> </div> <div class="form-group"> <label id="label_password" class="lang col-lg-3 control-label"></label> <div class="col-lg-5"> <input type="password" class="form-control" name="password" /> </div> </div> <div class="form-group"> <div class="col-lg-9 col-lg-offset-3"> <button id="button_login" type="submit" class="lang btn btn-primary"></button> </div> </div> </form> </div> </div> </div> </body>properties资源文件(中英文切换的文字来源,所有页面上的中英版静态文字都会在这个文件提前定义好) js_en.properties 英文资源文件
label_username=username label_password=password button_login=login count=Login Pagejs_zh.properties 中文资源文件
label_username=用户名 label_password=密码 button_login=登陆 count=登陆页面js.properties 默认资源文件(这个是因为初始化i18n报错加上的,不知道有什么用,找不到会报404)
label_username=username label_password=password button_login=login count=Login PageJavaScript 脚本
$(function(){ //初始化页面内容 $.i18n.properties({ name : 'js', //资源文件名称 path : '${pageContext.request.contextPath}/i18n/', //资源文件路径 mode : 'map', //用Map的方式使用资源文件中的值 language : 'zh', //中文 对应properties文件名的"zh"两个字 也就是说path+name+language就是你资源文件的路径 callback : function() {//加载成功后设置显示内容 changeValue(); } }); cookie.setCookie("lang", "zn", 1); //将页面选择的语言通过cookie记录下来,后台会用到 }); function changeZh(){ //中文切换 $.i18n.properties({ name : 'js', //资源文件名称 path : '${pageContext.request.contextPath}/i18n/', //资源文件路径 mode : 'map', //用Map的方式使用资源文件中的值 language : 'zh', callback : function() {//加载成功后设置显示内容 changeValue(); } }); cookie.setCookie("lang", "cn", 1); } function changeEn(){ //英文切换 $.i18n.properties({ name : 'js', //资源文件名称 path : '${pageContext.request.contextPath}/i18n/', //资源文件路径 mode : 'map', //用Map的方式使用资源文件中的值 language :'en', callback : function() {//加载成功后设置显示内容 changeValue(); } }); cookie.setCookie("lang", "en", 1); } function changeValue(){ //公共的赋值事件,需要在标签中定义一个id名(需要和properties文件中的Key相同), //和一个class属性(名字随便起,主要是为了遍历所有需要切换文字的标签) $('.lang').each(function(){ var tagName=$(this).prop("tagName"); if(tagName=="INPUT"){ //不同的标签不同的赋值方法 $(this).val($.i18n.prop($(this).attr("id"))) }else{ $(this).html($.i18n.prop($(this).attr("id"))) } }) }至此第一部分的代码结束,下面是测试结果
中文
英文
第二部分(后台数据)
首先我们需要写动态切换数据源的代码,主要用到springAbstractRoutingDataSource类,此类是由spring提供的一个切换数据源的路由类
DataSourceContextHolder.java 数据源切换工具类,用来保存当前选择的数据源
public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static void setDbType(String dbType) { contextHolder.set(dbType); } public static String getDbType() { return ((String) contextHolder.get()); } public static void clearDbType() { contextHolder.remove(); } } DataSourceName.java 用来存放数据源的名字也就是bean的idpublic interface DataSourceName { static final String DATA_EN="dataSourceEn"; static final String DATA_CN="dataSourceCn"; }DynamicDataSource.java 路由类 关键类 继承AbstractRoutingDataSource public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDbType(); } } xml文件 <!--数据源 A--> <bean id="dataSourceCn" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <!-- 使用properties来配置 --> <property name="driverClassName"> <value>${jdbc_driverClassName}</value> </property> <property name="url"> <value>${jdbc_url_cn}</value> </property> <property name="username"> <value>${jdbc_username}</value> </property> <property name="password"> <value>${jdbc_password}</value> </property> </bean> <!--数据源 B--> <bean id="dataSourceEn" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <!-- 使用properties来配置 --> <property name="driverClassName"> <value>${jdbc_driverClassName}</value> </property> <property name="url"> <value>${jdbc_url_en}</value> </property> <property name="username"> <value>${jdbc_username}</value> </property> <property name="password"> <value>${jdbc_password}</value> </property> </bean> <!-- 数据源路由 --> <bean id="dataSource" class="com.lin.common.dataSource.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="dataSourceCn" value-ref="dataSourceCn"/> <entry key="dataSourceEn" value-ref="dataSourceEn"/> </map> </property> <!-- 默认数据源 --> <property name="defaultTargetDataSource" ref="dataSourceCn"/> </bean> <!-- 自动扫描了所有的XxxxMapper.xml对应的mapper接口文件,这样就不用一个一个手动配置Mpper的映射了,只要Mapper接口类和Mapper映射文件对应起来就可以了。 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.lin.dao" /> </bean> <!-- 配置Mybatis的文件 ,mapperLocations配置**Mapper.xml文件位置,configLocation配置mybatis-config文件位置--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mapperLocations" value="classpath*:com/lin/mapper/*.xml"/> <property name="configLocation" value="classpath:mybatis/mybatis-config.xml" /> <!-- <property name="typeAliasesPackage" value="com.tiantian.ckeditor.model" /> --> </bean> 动态切换数据源的代码结束 然后我们需要一个拦截器,来拦截所有的请求(除登陆外) 主要用到HandlerInterceptorAdapter类 此类是由springMVC提供的拦截器,可以在请求前,请求中,请求后对URL进行拦截,这里我们主要用到请求前的方法
CommonInterceptor.java 拦截器
public class CommonInterceptor extends HandlerInterceptorAdapter { private final Logger log = LoggerFactory.getLogger(CommonInterceptor.class); /** * 在业务处理器处理请求之前被调用 * 如果返回false * 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链 * 如果返回true * 执行下一个拦截器,直到所有的拦截器都执行完毕 * 再执行被拦截的Controller * 然后进入拦截器链, * 从最后一个拦截器往回执行所有的postHandle() * 接着再从最后一个拦截器往回执行所有的afterCompletion() */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info("==============登陆拦截开始=================="); String sessionId = request.getSession().getId(); log.info("==============sessionID:"+sessionId+"=============="); PersonnelVo user=UserUtils.findUserByCache(sessionId); if(user==null){ log.info("====未登陆跳转到登陆页面==="); response.addHeader("t", "111"); // request.getRequestDispatcher("/upload.jsp").forward(request, response); response.sendRedirect("http://localhost/ssm_test/upload.jsp"); return false; } log.info("==============登陆拦截结束=================="); log.info("============数据源选择开始========"); Cookie[] cooks=request.getCookies(); //获取cookie String lang=""; for (Cookie cookie : cooks) { //从cookie中拿到标识 System.out.println(cookie.getValue()); if(cookie.getValue().equals("en")||cookie.getValue().equals("cn")){ lang=cookie.getValue(); } } //通过标识切换数据源 DataSourceContextHolder.setDbType(lang.equals("cn")?DataSourceName.DATA_CN:DataSourceName.DATA_EN); log.info("============数据源选择结束========"); return true; } } springmvc.xml <!-- 配置拦截器 --> <mvc:interceptors> <mvc:interceptor> <!-- 需要拦截的包名 --> <mvc:mapping path="/fileUpload/**"/> <bean class="com.lin.common.filter.CommonInterceptor"></bean> </mvc:interceptor> </mvc:interceptors> web.xml <!-- 对静态资源添加列外 (不拦截静态资源写在mvc分发器之前)--> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> <url-pattern>*.css</url-pattern> <url-pattern>*.jpg</url-pattern> </servlet-mapping> 至此第二部分结束
以上便是解决方案的所有代码 如果有不明白的地方或指正或需要整个项目的请加群499950895
