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