<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    于吉吉的技術博客

    建造高性能門戶網

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      65 隨筆 :: 6 文章 :: 149 評論 :: 0 Trackbacks
    前段時間我們的系統接到新增多一個頻道的需求,原本我們的系統只是針對于廣州的業務,現在需要新增另一個城市上海,經過和產品人員溝通和分析,城市之間的業務邏輯除了一些小差異基本還是一樣的,數據庫的結構經過整合兩個城市也可以達到一樣的結構,但上海需要獨立出另一個數據庫.

    我們以前發布器的做法是用作為方法的一個參數由調用者一直傳到訪問對象(索引或數據庫),雖然這種做法一樣可以很快的實現,但是將數據庫,索引的選擇和業務邏輯混搭在一起的設計在感覺上是比較混亂,并且不利于將來多個城市(頻道)的建立,所以選了通過ThreadLocal來實現多數據源的動態切換.

    ThreadLocal 是一個依賴于執行線程的存儲器,對它就只有簡單的一個set和get方法,不同線程之間是相互獨立的。簡單地講,就是:這個線程set了一個對象入去,只有這個線程自己可以把它get出來,其它線程是get不出來的。

    好了,下面是具體顯示的方式

    首先定義一個filter,通過filter取得域名,因為我們的域名中帶有城市的標志,如廣州是http://gz.***.com,上海是http://sh.***.com,通過取得的域名,我們取得城市的表示放進ThreadLocal.set(city);

    public class DataSourceFilter extends HttpServlet implements Filter {

    public void doFilter(ServletRequest request, ServletResponse response,
          FilterChain filterChain) {
          HttpServletRequest req 
    = (HttpServletRequest) request;
          String servername 
    = req.getServerName();
          SpObserver.putCityByDomain(servername);
          filterChain.doFilter(request, response);
      }

    }

    public class SpObserver {
        
    private static ThreadLocal<String> local = new ThreadLocal<String>();    

        
    public static void putCityByDomain(String domain) {
            String city 
    = publicconfig.getCityMap().get(domain);//拆分domain,獲取城市名
            local.set(city);
        }
        
    public static String getCity() {
            String city 
    = (String) local.get();
            
    return city;
        }

    }

    建立多個與之對應的數據源


        
    <bean id="atomDataSource_gz"
            class
    ="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init"
            destroy-method
    ="close">
            
    <property name="uniqueResourceName">
                
    <value>mysql/gz</value>
            
    </property>
            
    <property name="xaDataSourceClassName">
                
    <value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>
            
    </property>
            
    <property name="xaProperties">
                
    <props>
                    
    <prop key="URL"><![CDATA[${jdbc_gz.url}]]></prop>
                    
    <prop key="user"><![CDATA[${jdbc_gz.username}]]></prop>
                    
    <prop key="password"><![CDATA[${jdbc_gz.password}]]></prop>
                
    </props>
            
    </property>
            
    <property name="maxPoolSize">
                
    <value>50</value>
            
    </property>
            
    <property name="minPoolSize">
                
    <value>5</value>
            
    </property>
            
    <property name="loginTimeout">
                
    <value>20</value>
            
    </property>
            
    <property name="testQuery">
                
    <value>SELECT 1</value>
            
    </property>
        
    </bean>

    <bean id="atomDataSource_sh"
            class
    ="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init"
            destroy-method
    ="close">
            
    <property name="uniqueResourceName">
                
    <value>mysql/sh</value>
            
    </property>
            
    <property name="xaDataSourceClassName">
                
    <value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>
            
    </property>
            
    <property name="xaProperties">
                
    <props>
                    
    <prop key="URL"><![CDATA[${jdbc_sh.url}]]></prop>
                    
    <prop key="user"><![CDATA[${jdbc_sh.username}]]></prop>
                    
    <prop key="password"><![CDATA[${jdbc_sh.password}]]></prop>
                
    </props>
            
    </property>
            
    <property name="maxPoolSize">
                
    <value>50</value>
            
    </property>
            
    <property name="minPoolSize">
                
    <value>5</value>
            
    </property>
            
    <property name="loginTimeout">
                
    <value>20</value>
            
    </property>
            
    <property name="testQuery">
                
    <value>SELECT 1</value>
            
    </property>
        
    </bean>

        
    <bean id="dataSource" class="com.***.shine.constant.MultiDataSource">  
            
    <property name="dataSource" ref="atomDataSource_gz" /> <!-- 默認城市為gz -->
        
    </bean>


    public class MultiDataSource extends AtomikosDataSourceBean implements ApplicationContextAware {
        
    private ApplicationContext applicationContext = null;
        
    private DataSource dataSource = null;
        
    public Connection getConnection() throws SQLException {
            
    return getDataSource().getConnection();
        }
        
    public Connection getConnection(String arg0, String arg1)
                
    throws SQLException {
            
    return getDataSource().getConnection(arg0, arg1);
        }
        ..
        
        
    //通過適配者的設計模式動態的切換實現類,這樣就實現了在DataSourceBean中,我們是要注入atomDataSource_gz還是atomDataSource_sh
        public DataSource getDataSource(String dataSourceName) {
            
    try{
                
    if(dataSourceName==null||dataSourceName.equals("")){
                    
    return this.dataSource;
                }
                
    return (DataSource)this.applicationContext.getBean(dataSourceName);
            }
    catch(NoSuchBeanDefinitionException ex){
                
    throw new DaoException("There is not the dataSource <name:"+dataSourceName+"> in the applicationContext!");
            }
        }
        
        
    public void setDataSource(DataSource dataSource) {
            
    this.dataSource = dataSource;
        }
        
    //主要是下面這一段,通過SpObserver.getCity() 獲取相應的城市(頻道)名字
        public DataSource getDataSource(){
            String city 
    = SpObserver.getCity();
            
    if(city == null || city.equals(""|| city.equals("null"))
                city 
    = "gz";
            
    return getDataSource("atomDataSource_"+city);
        }
        ...
    }

    這樣在各個層中的實現我們就不需去關注究竟是哪個城市的接口,因為每個請求都附帶了ThreadLocal的相應信息

    關于ThreadLocal具體可看-->通通透透理解ThreadLocal

    posted on 2010-08-23 16:22 陳于喆 閱讀(3462) 評論(1)  編輯  收藏 所屬分類: spring

    評論

    # re: 動態切換多數據源的配置[未登錄] 2010-08-24 11:07 Jet
    Spring中有個DataSourceHolder,可以直接拿來用。  回復  更多評論
      


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 黄网站色视频免费看无下截| 在线涩涩免费观看国产精品 | 中美日韩在线网免费毛片视频| 亚洲熟妇中文字幕五十中出| 少妇太爽了在线观看免费视频| 亚洲无mate20pro麻豆| 免费二级毛片免费完整视频| 国产免费无码一区二区| 伊人久久亚洲综合影院首页| 国产国拍亚洲精品福利| 99在线精品视频观看免费| 免费看一级一级人妻片 | 亚洲成人黄色网址| heyzo亚洲精品日韩| 亚洲美女免费视频| 夜夜爽妓女8888视频免费观看| 亚洲日韩国产精品无码av| 亚洲国产精品一区二区三区久久 | 日日麻批免费40分钟无码| 精品亚洲视频在线| 亚洲天堂一区二区| 亚洲AV日韩精品一区二区三区| 18禁成人网站免费观看| caoporm碰最新免费公开视频 | 久久国产乱子伦精品免费强| 亚洲色一区二区三区四区| 久久狠狠高潮亚洲精品| 亚洲av午夜成人片精品电影| 丁香花免费高清视频完整版| a毛片在线还看免费网站| 免费亚洲视频在线观看| 亚洲AV成人一区二区三区在线看| 国产V亚洲V天堂无码久久久| 国产精品免费看久久久久| 国产一卡二卡四卡免费| 污污网站免费观看| 两性色午夜免费视频| 精品免费AV一区二区三区| 亚洲久悠悠色悠在线播放| 亚洲精品日韩专区silk| 亚洲阿v天堂在线|