为什么要用统一配置?
我们做项目时用到的配置比如数据库配置等...我们都是写死在项目里面,如果需要更改,那么也是的修改配置文件然后再投产上去,那么问题来了,如果做集群的呢,有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