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"  onclick="changeZh()">中文</button> <button class="btn" onclick="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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章