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

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

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

    于吉吉的技術(shù)博客

    建造高性能門戶網(wǎng)

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      65 隨筆 :: 6 文章 :: 149 評(píng)論 :: 0 Trackbacks
    前段時(shí)間我們的系統(tǒng)接到新增多一個(gè)頻道的需求,原本我們的系統(tǒng)只是針對(duì)于廣州的業(yè)務(wù),現(xiàn)在需要新增另一個(gè)城市上海,經(jīng)過(guò)和產(chǎn)品人員溝通和分析,城市之間的業(yè)務(wù)邏輯除了一些小差異基本還是一樣的,數(shù)據(jù)庫(kù)的結(jié)構(gòu)經(jīng)過(guò)整合兩個(gè)城市也可以達(dá)到一樣的結(jié)構(gòu),但上海需要獨(dú)立出另一個(gè)數(shù)據(jù)庫(kù).

    我們以前發(fā)布器的做法是用作為方法的一個(gè)參數(shù)由調(diào)用者一直傳到訪問(wèn)對(duì)象(索引或數(shù)據(jù)庫(kù)),雖然這種做法一樣可以很快的實(shí)現(xiàn),但是將數(shù)據(jù)庫(kù),索引的選擇和業(yè)務(wù)邏輯混搭在一起的設(shè)計(jì)在感覺上是比較混亂,并且不利于將來(lái)多個(gè)城市(頻道)的建立,所以選了通過(guò)ThreadLocal來(lái)實(shí)現(xiàn)多數(shù)據(jù)源的動(dòng)態(tài)切換.

    ThreadLocal 是一個(gè)依賴于執(zhí)行線程的存儲(chǔ)器,對(duì)它就只有簡(jiǎn)單的一個(gè)set和get方法,不同線程之間是相互獨(dú)立的。簡(jiǎn)單地講,就是:這個(gè)線程set了一個(gè)對(duì)象入去,只有這個(gè)線程自己可以把它get出來(lái),其它線程是get不出來(lái)的。

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

    首先定義一個(gè)filter,通過(guò)filter取得域名,因?yàn)槲覀兊挠蛎袔в谐鞘械臉?biāo)志,如廣州是http://gz.***.com,上海是http://sh.***.com,通過(guò)取得的域名,我們?nèi)〉贸鞘械谋硎痉胚M(jìn)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;
        }

    }

    建立多個(gè)與之對(duì)應(yīng)的數(shù)據(jù)源


        
    <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" /> <!-- 默認(rèn)城市為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);
        }
        ..
        
        
    //通過(guò)適配者的設(shè)計(jì)模式動(dòng)態(tài)的切換實(shí)現(xiàn)類,這樣就實(shí)現(xiàn)了在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;
        }
        
    //主要是下面這一段,通過(guò)SpObserver.getCity() 獲取相應(yīng)的城市(頻道)名字
        public DataSource getDataSource(){
            String city 
    = SpObserver.getCity();
            
    if(city == null || city.equals(""|| city.equals("null"))
                city 
    = "gz";
            
    return getDataSource("atomDataSource_"+city);
        }
        ...
    }

    這樣在各個(gè)層中的實(shí)現(xiàn)我們就不需去關(guān)注究竟是哪個(gè)城市的接口,因?yàn)槊總€(gè)請(qǐng)求都附帶了ThreadLocal的相應(yīng)信息

    關(guān)于ThreadLocal具體可看-->通通透透理解ThreadLocal

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

    評(píng)論

    # re: 動(dòng)態(tài)切換多數(shù)據(jù)源的配置[未登錄] 2010-08-24 11:07 Jet
    Spring中有個(gè)DataSourceHolder,可以直接拿來(lái)用。  回復(fù)  更多評(píng)論
      


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲欧美日韩综合久久久| 四只虎免费永久观看| 外国成人网在线观看免费视频 | 国产高清在线免费视频| 永久免费的网站在线观看| 麻豆视频免费播放| 1000部拍拍拍18勿入免费视频软件| 久9这里精品免费视频| 免费无码av片在线观看| 在线免费观看h片| 在线毛片片免费观看| 免费视频成人手机在线观看网址| 在线播放免费人成毛片乱码| 光棍天堂免费手机观看在线观看| 国产成人免费AV在线播放| 久久免费公开视频| 91免费人成网站在线观看18| 日韩中文字幕精品免费一区| 免费无码又爽又刺激聊天APP| 女人18毛片特级一级免费视频| 91嫩草私人成人亚洲影院| 亚洲乱亚洲乱淫久久| 中文字幕亚洲色图| 亚洲毛片基地日韩毛片基地| 亚洲成a人片毛片在线| 亚洲中文字幕无码久久2020| 亚洲AV无码专区国产乱码不卡| 老司机午夜性生免费福利| 久久久久久噜噜精品免费直播| 青柠影视在线观看免费高清 | 精品国产日韩久久亚洲| 亚洲码和欧洲码一码二码三码| 免费在线观看亚洲| 精品国产污污免费网站入口在线| 久久九九AV免费精品| 国内精品乱码卡1卡2卡3免费 | 四虎影视无码永久免费| 日韩免费高清大片在线| 成人毛片免费观看视频在线| 亚洲电影日韩精品| 亚洲另类激情综合偷自拍|