Spring+Hibernate 實現不同域名訪問同一專案,自定義Filter根據域名選擇對應的資料來源

Musk_Coder發表於2019-02-28

AbstractRoutingDataSource 實現切換資料來源的原理

檢視這個類可以發現。它繼承了DataSource,那麼找到他的getConnection方法

public Connection getConnection() throws SQLException {

return this.determineTargetDataSource().getConnection();
複製程式碼

}

protected DataSource determineTargetDataSource() {

Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");

Object lookupKey = this.determineCurrentLookupKey();

DataSource dataSource = (DataSource)this.resolvedDataSources.get(lookupKey);

if(dataSource == null && (this.lenientFallback || lookupKey == null)) {

    dataSource = this.resolvedDefaultDataSource;

}

if(dataSource == null) {

    throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");

} else {

    return dataSource;

}
複製程式碼

}

可以看出關鍵程式碼determineTargetDataSource中,這裡處理了資料來源切換,那麼只需要寫一個子類,將determineCurrentLookupKey這個方法重寫下,即可做到資料來源切換。

資料來源配置

用到的部分程式碼如下,其餘的用專案中的即可:

-資料庫配置檔案

#------------main MySQL ------------

hibernate.dialect=org.hibernate.dialect.MySQLDialect

jdbc.driver=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://47.94.18.202:3306/jxncpshop?useUnicode=true&characterEncoding=UTF-8

jdbc.username=root

jdbc.password=root

#------------main MySQL2 ------------

#openData.hibernate.dialect=org.hibernate.dialect.MySQLDialect

openData.jdbc.driver=com.mysql.jdbc.Driver

openData.jdbc.url=jdbc:mysql://47.94.18.202:3306/jnncpshop?useUnicode=true&characterEncoding=UTF-8

openData.jdbc.username=root

openData.jdbc.password=root

url1=http://www.jnncpshop.com:8081/

url2=http://www.jxncpshop.com:8081/

applicationContext.xml的配置

此處程式碼中需要主義的地方有:dataSource配置的key要和後面修改資料庫是的名稱保持一致,

-切換資料來源和事務管理的先後順序:這裡通過order 來設定優先順序,保證切換資料來源的切面在事務管理之前

-sessionFactory配置注意的地方的地方:將預設的資料庫配置取消,不然會無法切換

1:動態選擇資料來源 方法類

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**

  • Created by Administrator on 2019/1/16.

*/

public class ChooseDataSourceextends AbstractRoutingDataSource{

@Override

protected Object determineCurrentLookupKey() {
複製程式碼

String dataSource = HandleDataSource.getDataSource();

HandleDataSource.clearDataSource();//每次設定完清除,保證獲取預設資料庫

    return dataSource;
複製程式碼

}

}

2:資料來源切換類

package com.ewebtd.eshop.admin.common;

/**

  • Created by Administrator on 2019/1/16.

*/

public class HandleDataSource {

// 資料來源名稱執行緒池,ThreadLocal是執行緒安全的,並且不能在多執行緒之間共享

public static final ThreadLocalholder =new ThreadLocal();
複製程式碼

public static void setDataSource(String dataSource){

holder.set(dataSource);

}

public static String getDataSource(){

return ((String)holder.get());

}

public static void clearDataSource() {

holder.remove();

}

}

3.資料來源名稱配置類

/**

  • 資料來源配置名稱--與配置檔案中的key同名

  • Created by Administrator on 2019/1/16.

*/

public class DataSourceConst {

public static final StringDEFAULT ="default";

public static final StringSITE_MAIN ="siteMain";

}

4.自定義Filter實現根據域名去在每次請求前判斷要選擇的資料來源

import com.ewebtd.eshop.admin.common.DataSourceConst;

import com.ewebtd.eshop.admin.common.HandleDataSource;

import javax.servlet.*;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.BufferedReader;

import java.io.FileReader;

import java.io.IOException;

import java.util.Properties;

/**

  • Created by Administrator on 2019/1/16.

*/

public class ChooseDataSourceFilterimplements Filter{

@Override

public void init(FilterConfig filterConfig)throws ServletException {
複製程式碼

}

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {
複製程式碼

if (!(servletRequestinstanceof HttpServletRequest) || !(servletResponseinstanceof HttpServletResponse)) {

throw new ServletException("OncePerRequestFilter just supports HTTP requests");

}

HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;

HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;

StringBuffer url = httpRequest.getRequestURL();

String tempContextUrl = url.delete(url.length() - httpRequest.getRequestURI().length(), url.length()).append("/").toString();

Properties properties =new Properties();

BufferedReader bufferedReader =new BufferedReader(new FileReader("E:/1227/source/trunk/eshop/eshopadmin/src/main/java/com/ewebtd/eshop/config/db.properties"));

properties.load(bufferedReader);

// if(tempContextUrl.equals("www.jnncpshop.com:8081/")){

    if(tempContextUrl.equals(properties.getProperty("url1"))){
複製程式碼

HandleDataSource.setDataSource(DataSourceConst.SITE_MAIN);

}else if(tempContextUrl.equals(properties.getProperty("url2"))){

HandleDataSource.setDataSource(DataSourceConst.DEFAULT);

}

filterChain.doFilter(servletRequest, servletResponse);

return;

}

@Override

public void destroy() {
複製程式碼

}

}

5.在web.xml中配置一下,過濾所有請求,注意在過濾器執行鏈的順序

ChooseDataSourceFilter

com.ewebtd.eshop.admin.filter.ChooseDataSourceFilter

ChooseDataSourceFilter

/*

測試的話需要修改本機hosts檔案,對127.0.0.1做域名對映,然後重啟電腦

啟動tomcat,效果如圖:

Spring+Hibernate 實現不同域名訪問同一專案,自定義Filter根據域名選擇對應的資料來源

Spring+Hibernate 實現不同域名訪問同一專案,自定義Filter根據域名選擇對應的資料來源

相關文章