web,jsp,html网站中英文切换,资源国际化解决方案及代码(其中包含动态切换数据源及URL拦截器)

项目需求:
在现有系统的基础上,实现网站的中英文切换,要求现有代码基本保持不变。
解决方案:
在经过众多的方案筛选后,选出了一个比较合适的方案。方案如下。

首先要实现网站的中英文切换总共分为两部分。

第一部分是网站上的静态文字。

第二部分是从数据库查询出来的数据。

第一部分解决方案:

使用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 Page
js_zh.properties 中文资源文件

label_username=用户名
label_password=密码
button_login=登陆
count=登陆页面
js.properties 默认资源文件(这个是因为初始化i18n报错加上的,不知道有什么用,找不到会报404)

label_username=username
label_password=password
button_login=login
count=Login Page
JavaScript 脚本

$(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的id

public 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
--------------------- 
版权声明:本文为CSDN博主「Change_Code」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33251859/article/details/77773038

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值