1. 程式人生 > >SSH專案實戰OA-Zookeeper管理配置檔案

SSH專案實戰OA-Zookeeper管理配置檔案

為什麼要用統一配置?

我們做專案時用到的配置比如資料庫配置等...我們都是寫死在專案裡面,如果需要更改,那麼也是的修改配置檔案然後再投產上去,那麼問題來了,如果做叢集的呢,有100臺機器,這時候做修改那就太不切實際了;那麼就需要用到統一配置管理啦。

解決思路

一,把公共配置抽取出來,儲存到資料庫中.

每個需要配置資訊的模組都從資料庫中獲取.但是這個方法明顯不符合我們系統的架構,無論是dao工程或者是web工程都要直接操作資料庫,並且需要配置hibernate,這樣既不安全也不方便.另外,如果需要修改配置檔案,必須手動地讓工程重新從資料庫獲取資料.

這個方法對於我們分散式系統肯定是不是呀的啦.但我們還有第二種方案.

二,把公共配置抽取出來,儲存到資料庫中,並且把配置釋出到Zookeeper中.

這個方法雖然同樣是從資料庫中獲取配置資訊,但也有所不同.這種方法只需要有一個工程操作資料庫,讀取資料庫中的配置資訊.那麼其他工程要如何獲取到配置資訊呢?當一個工程A從資料庫中獲取到配置資訊之後,立即將配置資訊釋出到Zookeeper中,而其他工程只需要從Zookeeper中獲取配置資訊,而不需要操作資料庫.另外,Zookeeper提供監聽器功能,無論哪個工程修改了Zookeeper中的配置資訊,其他工程都能知道,並且重新從Zookeeper中獲取配置資訊,而工程A也會將修改的配置資訊更新到資料庫中.

 

zookeeper實現統一配置管理

首先,我們需要在資料庫中增加一個實體表Config.

 

在新建完實體表後,就要在工程中新增實體類.由於這個類會被所有工程所用到,所以我們要把Config放在公共工程OA-common中

在OA-common中新增com.QEcode.OA.common.pojo包.

新建Config實體類

public class Config implements Serializable {
    Long id;
    String configName;
    String configValue;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getConfigName() {
        return configName;
    }
    public void setConfigName(String configName) {
        this.configName = configName;
    }
    public String getConfigValue() {
        return configValue;
    }
    public void setConfigValue(String configValue) {
        this.configValue = configValue;
    }
    public Config(){
	
    }
    public Config(String configName, String configValue) {
	super();
	this.configName = configName;
	this.configValue = configValue;
    }
    
}

 

搭建OA-portal-dao工程

 

 

在pom.xml檔案中新增依賴

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.QEcode</groupId>
    <artifactId>OA-portal</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>OA-portal-dao</artifactId>
  
   <dependencies>
  	<!-- hibernate -->
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-core</artifactId>
	</dependency>
  	<!-- MySql -->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
      </dependency>
      <!-- 連線池 -->
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
      </dependency>
      <!-- Spring -->
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-context</artifactId>
       </dependency>
       <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
		</dependency>
		
		<!-- zookeeper的客戶端,你要連線zookeeper,需要把以下兩個jar包加進來 -->
		<dependency>
		    <groupId>org.apache.zookeeper</groupId>
		    <artifactId>zookeeper</artifactId>
		</dependency>
		<dependency>
		    <groupId>com.github.sgroschupf</groupId>
		    <artifactId>zkclient</artifactId>
		</dependency>
  </dependencies>
  
  
  
</project>

 

搭建OA-portal-interface工程

這個工程暫時不用新增依賴

 

搭建OA-portal-service工程

 

 

在pom.xml中新增依賴,可以把OA-system-service中的依賴複製過來

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.QEcode</groupId>
    <artifactId>OA-portal</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>OA-portal-service</artifactId>
  <packaging>war</packaging>
  <dependencies>
		<!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
		</dependency>
		<!-- dubbo相關 -->
		<dependency>
		    <groupId>com.alibaba</groupId>
		    <artifactId>dubbo</artifactId>
		    <!-- 排除依賴 -->
		    <exclusions>
		        <exclusion>
		            <groupId>org.springframework</groupId>
		            <artifactId>spring</artifactId>
		        </exclusion>
		        <exclusion>
		            <groupId>org.jboss.netty</groupId>
		            <artifactId>netty</artifactId>
		        </exclusion>
		    </exclusions>
		</dependency>
		
		<!-- zookeeper的客戶端,你要連線zookeeper,需要把以下兩個jar包加進來 -->
		<dependency>
		    <groupId>org.apache.zookeeper</groupId>
		    <artifactId>zookeeper</artifactId>
		</dependency>
		<dependency>
		    <groupId>com.github.sgroschupf</groupId>
		    <artifactId>zkclient</artifactId>
		</dependency>


		<dependency>
			<groupId>com.QEcode</groupId>
			<artifactId>OA-portal-dao</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>com.QEcode</groupId>
			<artifactId>OA-portal-interface</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		
		<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>
		
		
		
  </dependencies>
</project>

 

 

service層

接下來,把OA-system-service中resources目錄下所有檔案複製到OA-portal-service中

 

修改applicationContext-dao.xml檔案.

將spring掃描的包改為com.QEcode.OA.portal.dao

 

 

完整的applicationContext-dao.xml檔案如下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        ">
     <!-- 載入配置檔案 -->
    <context:property-placeholder location="classpath:resource/*.properties"/>    
     <!-- 配置spring容器建立時要掃描的包 -->
    <context:component-scan base-package="com.QEcode.OA.portal.dao"></context:component-scan>   
     <!-- 配置hibernateTemplate,用於持久層 -->
   <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
   		<property name="sessionFactory" ref="sessionFactory"></property>
   </bean>
   <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
   		<property name="dataSource" ref="dataSource"/>
		<!-- hibernate引數設定 -->
		<property name="hibernateProperties">
			<props>
				<!-- 資料庫方言 -->
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
				<!-- 顯示sql語句-->
				<prop key="hibernate.show_sql">true</prop>
				<!-- 格式化SQL語句 -->
				<prop key="hibernate.format_sql">true</prop>
				<!-- create:根據對映關係生成表 -->
				<prop key="hibernate.hbm2ddl.auto">update</prop>
				<prop key="current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</prop>
			</props>
		</property>
   </bean>
	 <!-- 資料庫連線池 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
        destroy-method="close">
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="maxActive" value="${jdbc.maxActive}" />
        <property name="minIdle" value="${jdbc.minIdle}" />
    </bean>   
</beans>

 

修改applicationContext-service.xml檔案.

修改spring掃描的包

修改在註冊中心註冊的名字

修改埠號,因為20880被OA-system-service所使用

完整的applicationContext-service.xml檔案如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://code.alibabatech.com/schema/dubbo 
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        ">

	<!-- 配置spring容器建立時要掃描的包 -->
    <context:component-scan base-package="com.QEcode.OA.portal.service.impl"></context:component-scan>
	<!-- 使用dubbo釋出服務 -->
	<!-- 提供方應用資訊,用於計算依賴關係 -->
	<dubbo:application name="OA-portal" />
	<dubbo:registry protocol="zookeeper" address="${dubbo.address}" />
	<!-- 用dubbo協議在20881埠暴露服務 -->
	<dubbo:protocol name="dubbo" port="20881" />
	<!-- 宣告需要暴露的服務介面 -->
	

</beans>

修改applicationContext-trans.xml檔案.

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        ">
    <!-- 配置事務管理器 -->
   <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
   		<property name="sessionFactory" ref="sessionFactory"></property>
   </bean>     
   
	<!-- 通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 傳播行為 -->
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="create*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="select*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
        </tx:attributes>
    </tx:advice>
    <!-- 切面 -->
    <aop:config>
        <aop:advisor advice-ref="txAdvice"
            pointcut="execution(* com.QEcode.OA.portal.service.*.*(..))" />
    </aop:config>
        
        
</beans>       

 

修改web.xml檔案

將OA-system-service的web.xml檔案中spring監聽器複製過來

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name>OA-portal-service</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
 
   <!-- 載入spring容器 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext-*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
 
</web-app>

 

Dao層

 

在OA-portal-dao中src/main/java中新建 com.QEcode.OA.portal.dao.impl包.

在包下新建ZookeeperDao類,由於這個類比較簡單,所以不用建立介面了.

ZookeeperDao類內容如下:

@Repository
public class ZookeeperDao {
    
    @Resource(name="hibernateTemplate")
    protected HibernateTemplate hibernateTemplate;
    
    /**
     * @Description:從資料庫中獲取所有配置資訊
     * @return
     */
    public List<Config> findConfigFromDB(){
	//查詢語句
	String sql = "select *from config";
	Session session = hibernateTemplate.getSessionFactory().openSession();
	//執行查詢
	Query query = session.createSQLQuery(sql);
	//獲取查詢結果
	List<Object[]>  list = query.list();
	List<Config> configs = new ArrayList<Config>();
	//將結果中的內容存到Cofig列表中
	for(Object[] objs : list){
	    Config config = new Config((String)objs[0],(String)objs[1]);
	    configs.add(config);
	}
	return configs;
    session.close();
    }
    
    /**
     * @Description:將配置檔案上傳到資料庫中
     * @param configName
     * @param configValue
     */
    public void saveConfigToDB(String configName,String configValue){
	String sql = "insert into config(config_name,config_value) value('"+configName+"','"+configValue+"')";
	Session session = hibernateTemplate.getSessionFactory().openSession();
	session.createSQLQuery(sql);
    session.close();
    }

}

 

可以看到,我們雖然使用了HibernateTemplate物件,但是我們依然使用原始的sql語句來操作資料庫,這是因為Cofig實體類並沒有在hibernate中配置或者使用註解來標識其與資料庫中的config表相關聯,所以我們不能直接通過hql語句來操作資料庫.

 

 

 

 

service層

Dao層用於獲取資料庫中的配置資訊,而service層則是將Dao層從資料庫中獲取到的資訊上傳搭到Zookeeper中.

在OA-portal-interface工程中新建com.QEcode.OA.portal.service包

 

在該包下建立介面ZookeeperService,該介面只有一個方法,syncConfigToZk,將配置資訊上傳到Zookeeper中

public interface ZookeeperService {

    public void syncConfigToZk();

}

 

 

在OA-portal-servic-工程下的com.QEcode.OA.portal.service.impl包新建一個類ZookeeperServiceImpl,實現了ZookeeperService

在建立好ZookeeperServiceImpl類之後,先不用急著寫內容,因為OA-portal-dao工程是新建的,所以還沒有在OA-portal-service中新增

OA-portal-dao依賴.

<dependency>

<groupId>com.QEcode</groupId>

<artifactId>OA-portal-dao</artifactId>

<version>0.0.1-SNAPSHOT</version>

</dependency>

現在OA-portal-service工程的pom.xml檔案如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.QEcode</groupId>
    <artifactId>OA-portal</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>OA-portal-service</artifactId>
  <packaging>war</packaging>
  <dependencies>
		<!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
		</dependency>
		<!-- dubbo相關 -->
		<dependency>
		    <groupId>com.alibaba</groupId>
		    <artifactId>dubbo</artifactId>
		    <!-- 排除依賴 -->
		    <exclusions>
		        <exclusion>
		            <groupId>org.springframework</groupId>
		            <artifactId>spring</artifactId>
		        </exclusion>
		        <exclusion>
		            <groupId>org.jboss.netty</groupId>
		            <artifactId>netty</artifactId>
		        </exclusion>
		    </exclusions>
		</dependency>
		
		<!-- zookeeper的客戶端,你要連線zookeeper,需要把以下兩個jar包加進來 -->
		<dependency>
		    <groupId>org.apache.zookeeper</groupId>
		    <artifactId>zookeeper</artifactId>
		</dependency>
		<dependency>
		    <groupId>com.github.sgroschupf</groupId>
		    <artifactId>zkclient</artifactId>
		</dependency>


		<dependency>
			<groupId>com.QEcode</groupId>
			<artifactId>OA-portal-dao</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>com.QEcode</groupId>
			<artifactId>OA-portal-interface</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		
		<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>
		
		
		
  </dependencies>
</project>

好,下面讓我們來實現將配置資訊上傳到Zookeeper中

@Service
public class ZookeeperServiceImpl implements ZookeeperService {
    
    @Autowired
    private ZookeeperDao zookeeperDao;
    
    @Value("${zookeeper.address}")
    private String address;
    
    private String path = "/config/";
    /**
     * @Description:將配置資訊上傳到Zookeeper中
     */
    public void syncConfigToZk(){
	ZkClient zk = new ZkClient(address);
	List<Config> configs = zookeeperDao.findConfigFromDB();
	for(Config config:configs){
	    //判斷在Zookeeper中是否已經存在該配置資訊並且配置資訊與資料庫中的資訊一樣
	   
	    //如果沒有該節點
	    if(!zk.exists(path+config.getConfigName())){
		 //在Zookeeper中/config/目錄下建立子節點
		   zk.createPersistent(path+config.getConfigName(),config.getConfigName());
	    }else{
		//如果存在該節點,但配置資訊不一樣
		 String value = zk.readData(path+config.getConfigName());
		if(value.equals(config.getConfigValue())){
		    zk.createPersistent(path+config.getConfigName(),config.getConfigName());
		}
	    }
	}
	zk.close();
    }
    
}

 

@Value("zookeeper.address")表示從resources目錄下的*.properties中獲取value,當然前提是,你在spring的配置檔案中匯入*.properties

我們在applicationContext-dao.xml中已經配置了

同時,zookeeper.address在resource.properties檔案中配置

 

最後,要通過dubbo把服務釋出出去

在OA-portal-service工程中的applicationContext-service.xml中配置dubbo資訊

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://code.alibabatech.com/schema/dubbo 
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        ">

	<!-- 配置spring容器建立時要掃描的包 -->
    <context:component-scan base-package="com.QEcode.OA.portal.service.impl"></context:component-scan>
	<!-- 使用dubbo釋出服務 -->
	<!-- 提供方應用資訊,用於計算依賴關係 -->
	<dubbo:application name="OA-portal" />
	<dubbo:registry protocol="zookeeper" address="${dubbo.address}" />
	<!-- 用dubbo協議在20881埠暴露服務 -->
	<dubbo:protocol name="dubbo" port="20881" />
	<!-- 宣告需要暴露的服務介面 -->
	<!-- Zookeeper服務 -->
	<!-- <dubbo:service interface="com.QEcode.OA.portal.service.ZookeeperService" ref="zookeeperServiceImpl"></dubbo:service>
	 -->
	
		
</beans>

 

最後,我們需要再解壓一個新的Tomcat並改名為OA-portal-service,修改該Tomcat的埠為8002 8083 8012

controller層

引用dubbo服務

首先將關於dubbo的依賴複製到OA-portal-web工程的pom.xml

<!-- dubbo相關 -->

<dependency>

    <groupId>com.alibaba</groupId>

    <artifactId>dubbo</artifactId>

    <!-- 排除依賴 -->

    <exclusions>

        <exclusion>

            <groupId>org.springframework</groupId>

            <artifactId>spring</artifactId>

        </exclusion>

        <exclusion>

            <groupId>org.jboss.netty</groupId>

            <artifactId>netty</artifactId>

        </exclusion>

    </exclusions>

</dependency>

 

<!-- zookeeper的客戶端,你要連線zookeeper,需要把以下兩個jar包加進來 -->

<dependency>

    <groupId>org.apache.zookeeper</groupId>

    <artifactId>zookeeper</artifactId>

</dependency>

<dependency>

    <groupId>com.github.sgroschupf</groupId>

    <artifactId>zkclient</artifactId>

</dependency>

 

完整的pom.xml檔案如下:

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.QEcode</groupId>
    <artifactId>OA-portal</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>OA-portal-web</artifactId>
  <packaging>war</packaging>
  
  <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <!-- JSP相關 -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <!-- struts2 -->
		<dependency>
			<groupId>org.apache.struts</groupId>
			<artifactId>struts2-core</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.struts</groupId>
			<artifactId>struts2-spring-plugin</artifactId>
		</dependency>
  </dependencies>
  
</project>

然後,把OA-portal-service工程下src/main/resources/resource目錄中的resource.properties檔案複製到OA-portal-web工程下

 

修改spring目錄下的applicationContext.xml,新增dubbo約束

 

然後在applicationContext.xml中新增dubbo引用

 

完整的applicationContext.xml檔案內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        ">
    <!-- 配置spring容器建立時要掃描的包 -->
    <context:component-scan base-package="com.QEcode.OA.controller"></context:component-scan>
    
</beans>        

在controller層,我們要完成的任務是從Zookeeper中獲取到配置資訊,不過我們要把從Zookeeper獲取配置資訊的功能放在OA-common工程,因為這個功能會被其他工程所用到.

在OA-common工程的sec/main/java目錄下新建包com.QEcode.OA.common.utils

 

由於我們要在OA-common工程內使用Zookeeper,所以要在pom.xml檔案新增Zookeeper的依賴

 <!-- zookeeper的客戶端,你要連線zookeeper,需要把以下兩個jar包加進來 -->

<dependency>

    <groupId>org.apache.zookeeper</groupId>

    <artifactId>zookeeper</artifactId>

</dependency>

<dependency>

    <groupId>com.github.sgroschupf</groupId>

    <artifactId>zkclient</artifactId>

</dependency>

 

完整的pom.xml檔案如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.QEcode</groupId>
    <artifactId>OA-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>OA-common</artifactId>
  
 <!-- 依賴工具類的jar包 -->
    <dependencies>      
        <!-- 時間操作元件 -->          
         <dependency>
             <groupId>joda-time</groupId>
             <artifactId>joda-time</artifactId>
         </dependency>
         <!-- Apache工具元件 -->
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
         </dependency>
         <dependency>     
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-io</artifactId>
         </dependency>
         <dependency>         
             <groupId>commons-net</groupId>
             <artifactId>commons-net</artifactId>
         </dependency>
         <!-- Jackson Json處理工具包 -->
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
         </dependency>
         <!-- quartz任務排程框架 -->
         <dependency>
             <groupId>org.quartz-scheduler</groupId>
             <artifactId>quartz</artifactId>
         </dependency>
         <!-- 單元測試 -->
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
         <!-- 日誌處理 -->
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-log4j12</artifactId>
         </dependency>
         <!-- zookeeper的客戶端,你要連線zookeeper,需要把以下兩個jar包加進來 -->
		<dependency>
		    <groupId>org.apache.zookeeper</groupId>
		    <artifactId>zookeeper</artifactId>
		</dependency>
		<dependency>
		    <groupId>com.github.sgroschupf</groupId>
		    <artifactId>zkclient</artifactId>
		</dependency>
    </dependencies>

</project>

 

新增完依賴後,在utils包下建立ZookeeperUtils類

 

具體內容如下:

public class ZookeeperUtils {
    //Zookeeper地址
    private static String address = "192.168.43.150:2181";
    //配置資訊所在節點
    private static String path =  "/config/"; 
    
    /**
     * @Description:根據配置資訊名稱獲取配置資訊內容
     * @param configName
     * @return
     */
    public static Config getConfig(String configName){
	if(zk.exists(path+configName)){
	    String configValue = zk.readData(path+configName);
	    Config config = new Config(configName, configValue);
	    return config;
	}
	return null;
    }
    
    
}

我們把配置資訊上傳到Zookeeper的config節點下,但是之前我們是沒有建立這個節點的,所以,我們要先在Zookeeper中建立config節點

在虛擬機器中啟動Zookeeper

 

使用Zookeeper服務端

 

建立config節點

 

檢視Zookeeper,可以看到已經建立了config節點

至此,我們已經基本實現Zookeeper管理配置檔案功能,但我們還沒指定工程什麼時候從資料庫獲取配置資訊並且上傳到Zookeeper中.考慮到這個功能的性質,我們需要在OA-portal-service啟動的時候就要從資料庫中獲取配置資訊,並上傳到Zookeeper中.所以,我們需要配置一個監聽器,在專案啟動的時候,就呼叫這個功能.

在OA-portal-service工程下的src/main/java目錄中新建包com.QEcode.OA.portal.listener

在該包下建立InitServletContextListener類,並實現ServletContextListener介面

在此之前,我們需要在pom.xml中新增servlet的依賴

<dependency>

            <groupId>javax.servlet</groupId>

            <artifactId>servlet-api</artifactId>

            <scope>provided</scope>

        </dependency>

public class InitServletContextListener implements ServletContextListener {

    /**
     * @Description:初始化
     * @param sce
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
	ServletContext application = sce.getServletContext();
	//得到service例項
	ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(application);
	ZookeeperService zookeeperService = (ZookeeperService) ac.getBean("zookeeperServiceImpl");
	//將配置資訊上傳到Zookeeper中
	zookeeperService.syncConfigToZk();
	System.out.println("------------配置資訊上傳成功------------");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
	

    }

}

從上面程式碼可以看到,我們獲取bean的方式和以往的不同,不是使用註解來注入,而是要獲取WebApplicationContext容器,再從容器中獲取.

為什麼會這樣呢?因為以往我們是在spring容器中使用註解,而Listener是由servlet容器管理的.而servlet容器並不認得@Autowired註解,所以不能直接使用註解來注入bean,那麼怎麼在spring容器外面獲取到spring容器bean例項的引用呢?這就需要用到spring為我們提供的WebApplicationContextUtils工具類,該工具類的作用是獲取到spring容器的引用,進而獲取到我們需要的bean例項

最後,還要在web.xml中配置我們的監聽器


 <!-- 用於初始化配置資訊 -->
   <listener>
  	<listener-class>com.QEcode.OA.portal.listener.InitServletContextListener</listener-class>
  </listener>
  <context-param>
  	<param-name>contextConfigLocation</param-name>
  	<param-value>classpath:spring/applicationContext-*.xml</param-value>
  </context-param>

 

 

 

===============================================================================================

在寫部落格的時候,可能在專案中有一些問題沒有被發現,在我修改後,忘記寫到部落格上,所以我將這個專案上傳到github上,大家可以在github上獲取專案的程式碼

下面是github地址,大家Fork and Star


OA-Reconsitution