下面以开发一个spring+springmvc+mybatis框架整合程序为例说明分布式开发过程。后台有三大功能模块,分别是用户模块,账户模块,学生模块。划分后的分布式项目分别是smmvc-common(公共模块)、smmvc-user-facade(用户服务接口模块)、smmvc-user-service(用户服务提供者模块)、smmvc-acct-facade(账务服务接口模块)、smmvc-acct-service(账务服务提供者模块)、smmvc-student-facade(学生服务接口模块)、smmvc-student-service(学生服务提供者模块)、smmvc -web(服务消费者模块)。
环境:
jdk1.7+myeclipse8.6.1+maven3.3.9+mysql5.6+dubbo2.5.3+zookeeper-3.4.6+spring3.2.2+springmvc+mybatis3.2.2
数据库服务器2台
用户表的数据保存到11上,其它表的数据保存到6上。
1. 搭建smmvc-common(公共项目)
公共模块:我们可以把服务提供者和消费者都可能用到的东西都放到这里来,到时候让服务提供者和消费者来依赖它即可。例如我们这里把公共的dao层代码BaseDao,工具类MD5加密类,公共的配置文件(连接池及注册中心地址配置),以及服务提供者和消费者全部的依赖的jar包都配置公共模块里面,如图所示:
smmvc-common搭建完毕后,需要以jar包的形式发布到maven本地库中,如图所示操作:
2. 搭建smmvc-user-facade(用户服务接口项目)和smmvc-user-service(用户服务提供者项目)
服务接口模块非常简单,只需写对外发布的接口以及依赖的实体类。但是我们必须把它单独划分成一个工程,因为服务提供者和消费者都要用到它。如图所示:
同理,搭建完毕后,需要以jar包的形式发布到maven本地库中,跟第一个工程操作类似,这里就不截图了。
接下来 搭建smmvc-user-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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wx</groupId> <artifactId>smmvc-user-service</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 项目jdk版本配置 --> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.7</source> <target>1.7</target> <encoding>utf-8</encoding> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>com.wx</groupId> <artifactId>smmvc-common</artifactId> <version>0.0.1-SNAPSHOT</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupId>com.wx</groupId> <artifactId>smmvc-user-facade</artifactId> <version>0.0.1-SNAPSHOT</version> <type>jar</type> <scope>compile</scope> </dependency> </dependencies> </project>
服务提供者的配置文件dubbo-provider.xml如下:
<?xml version="1.0" encoding="UTF8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!-- 提供方应用信息,用于计算依赖关系 --> <dubbo:application name="smmvc-service-user" /> <!-- 使用zookeeper注册中心暴露服务地址 --> <dubbo:registry protocol="zookeeper" address="${dubbo.register.address}" /> <!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 用户服务接口 --> <dubbo:service interface="com.wx.service.IUserBiz" ref="userBiz" /> </beans>
当spring容器启动后,会生成userBiz的实例,<dubbo:service interface="com.wx.service.IUserBiz" ref="userBiz" />表示以接口名com.wx.service.IUserBiz向注册中心注册服务,提供的对象是userBiz,这个对象里面就包含的提供服务的数据。
============================spring核心配置文件applicationContext.xml如下所示:
<?xml version="1.0" encoding="UTF8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- 导入dubble配置 --> <import resource="classpath:configs/dubbo-provider.xml"/> <!-- 扫描包含注解类所在的包 --> <context:component-scan base-package="com.wx.dao.*"></context:component-scan> <context:component-scan base-package="com.wx.biz"></context:component-scan> <bean id="config" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:service.properties</value> <value>classpath:druidConfig_11.properties</value> </list> </property> </bean> <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="${driverClassName}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> <property name="filters" value="${filters}" /> <property name="initialSize" value="${initialSize}" /> <property name="maxActive" value="${maxActive}" /> <property name="minIdle" value="${minIdle}" /> <property name="maxWait" value="${maxWait}" /> <property name="validationQuery" value="${validationQuery}" /> <property name="testWhileIdle" value="${testWhileIdle}" /> <property name="testOnBorrow" value="${testOnBorrow}" /> <property name="testOnReturn" value="${testOnReturn}" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="${maxPoolPreparedStatementPerConnectionSize}" /> <property name="removeAbandoned" value="${removeAbandoned}" /> <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /> <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" /> <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" /> </bean> <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="druidDataSource"></property> <property name="configLocation"> <value>classpath:configs/mybatis-config.xml</value> </property> <property name="mapperLocations"> <list> <value>classpath:configs/mappers/*.xml</value> </list> </property> </bean> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sessionFactory"></constructor-arg> </bean> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="druidDataSource"></property> </bean> <tx:advice id="txAdvise" transaction-manager="txManager"> <tx:attributes> <tx:method name="find*" read-only="true"/> <tx:method name="search*" read-only="true"/> <tx:method name="query*" read-only="true"/> <tx:method name="get*" read-only="true"/> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="do*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="del*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut expression="execution(* com.wx.biz.*.*(..))" id="myCut"/> <aop:advisor advice-ref="txAdvise" pointcut-ref="myCut"/> </aop:config> </beans>接下来创建测试类启动服务:
package dubbo.test; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * * @描述: 启动Dubbo服务用的MainClass. * @作者: wx * @创建时间: 2015-11-5,下午9:47:55 . * @版本: 1.0 */ public class DubboProvider { private static final Log log = LogFactory.getLog(DubboProvider.class); public static void main(String[] args) { try { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:configs/applicationContext.xml"); context.start(); } catch (Exception e) { log.error("== DubboProvider context start error:",e); } synchronized (DubboProvider.class) { while (true) { try { DubboProvider.class.wait(); } catch (InterruptedException e) { log.error("== synchronized error:",e); } } } } }单击右键运行,没报错,服务就正常启动了,这时候可以在监控中心看到如下结果:
3. 搭建smmvc-acct-facade(账户服务接口项目)和smmvc-acct-service(账户服务提供者项目) 以及搭建smmvc-student-facade(学生服务接口项目)和smmvc-student-service(学生服务提供者项目) 与上面的类似,就不重复演示了。搭建完毕后的项目如图所示:
3. 搭建smmvc-web(服务消费者项目)
消费者模块搭建的是一个maven web工程,如下图所示:
-------------------------------------------------------------------------
如图所示:消费者工程需要依赖smmvc-common和smmvc-user-facade,smmvc-acct-facade,smmvc-student-facade
消费者和服务提供者都启动后,监控界面如图所示:
-------------------------------------------------