模块化的解决方案

OSGi

是一种模块化标准。是真正意义的上模块化,Eclipse 就是基于OSGi进行开发的。热插拔,每个模块都有自己的classLoader,不同classLoader之间,通过服务来进行通信。

Maven

使用maven的方式来进行模块化,主要是代码组织,以及代码重用度角度来进行模块化。

实践

emacsist-project

创建该项目,用于被继承,以及聚合各个模块。

它的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>

	<!-- 总pom -->
	<groupId>org.emacsist</groupId>
	<artifactId>emacsist-project</artifactId>
	<version>1.0.0</version>
	<packaging>pom</packaging>

	<name>emacsist-project</name>
	<url>http://emacsist.github.io</url>

	<properties>
		<spring.version>3.2.14.RELEASE</spring.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<modules>
		<!-- 工具类模块 -->
		<module>../emacsist-kit</module>
		<module>../emacsist-email</module>
		<module>../emacsist-http</module>
		<module>../emacsist-redis</module>

		<!-- weibosdk -->
		<module>../weibosdk-base</module>
		<module>../weibosdk-redis</module>
		<module>../weibosdk-dao</module>
		<module>../weibosdk-rabbitmq</module>
		<module>../weibosdk-service</module>
		<module>../common-pojo</module>
		<module>../weibosdk-web</module>
		<module>../weibosdk-interceptor</module>
	</modules>

	<dependencyManagement>
		<dependencies>
			<!-- Spring -->
			<dependency>
				<groupId>org.springframework</groupId>
				<artifactId>spring-test</artifactId>
				<version>${spring.version}</version>
			</dependency>
            ...为了本文的篇幅,以下依赖忽略
		</dependencies>
	</dependencyManagement>
</project>

dependencyManagement元素,主要是用于模块之间的版本一致管理。

emacsist-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>

	<!-- 属于 emacsist-project 的子模块,继承父模块 -->
	<parent>
		<groupId>org.emacsist</groupId>
		<artifactId>emacsist-project</artifactId>
		<version>1.0.0</version>
		<relativePath>../emacsist-project/pom.xml</relativePath>
	</parent>
	<groupId>org.emacsist.weibosdk</groupId>
	<artifactId>weibosdk-dao</artifactId>
	<packaging>jar</packaging>

	<name>weibosdk-dao</name>
	<url>http://maven.apache.org</url>

	<profiles>
		<profile>
			<id>default</id>
			<activation>
				<activeByDefault>true</activeByDefault>
			</activation>
			<properties>
				<!-- 开发环境的配置文件 -->
			</properties>
		</profile>

		<profile>
			<id>product</id>
			<properties>
				<!-- 生产环境的配置文件 -->
			</properties>
		</profile>
	</profiles>


	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
	</dependencies>

	<build>
		<sourceDirectory>src/main/java</sourceDirectory>
		<scriptSourceDirectory>${runtime.env}</scriptSourceDirectory>
		<resources>
			<resource>
				<directory>src/main/java</directory>
				<includes>
					<include>**/*.xml</include>
				</includes>
				<filtering>false</filtering>
			</resource>
			<resource>
				<directory>${runtime.env}</directory>
				<includes>
					<include>**/*.xml</include>
					<include>**/*.json</include>
					<include>**/*.properties</include>
				</includes>
				<filtering>true</filtering>
			</resource>
		</resources>
	</build>

</project>

代码组织未例:

src/main/env/dev: 开发环境的配置文件 src/main/env/product: 生产环境的配置文件 src/main/java/: 主源码 src/test/java: 测试源码 src/test/env/dev: 测试环境的配置文件

配置文件里,包含如下文件:

mybatis-config.xml:mybatis配置文件,放在dao这个模块。即各自的模块,负责配置各自的配置文件

weibosdk-jdbc.properties:jdbc配置文件

weibosdk-module-dao.xml: dao模块的spring的配置文件,只需要配置属于dao的内容即可.

示例:

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

	<bean id="uniweibov2DataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
		<property name="maxActive">
			<value>64</value>
		</property>
		<property name="maxIdle">
			<value>64</value>
		</property>
		<property name="maxWait">
			<value>0</value>
		</property>
		<property name="validationQuery">
			<value>select 1</value>
		</property>
		<property name="testWhileIdle">
			<value>true</value>
		</property>
		<property name="minEvictableIdleTimeMillis">
			<value>20000000</value>
		</property>
		<property name="timeBetweenEvictionRunsMillis">
			<value>3600000</value>
		</property>
	</bean>

	<bean id="TxManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="uniweibov2DataSource" />
	</bean>

	<tx:annotation-driven transaction-manager="TxManager"
		proxy-target-class="true" />

	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="uniweibov2DataSource" />
		<property name="configLocation" value="classpath:mybatis-config.xml" />
	</bean>

	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="org.emacsist.weibosdk.dao.mapper" />
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
	</bean>

</beans>

其他模块

其他模块,类似于上面的dao模块的 pom.xml

web模块

这个是主要的运行模块,依赖于其他子模块。主要解决的问题:聚合其他模块的配置文件以及bean这些东西。

集合其他模块的properties文件:

<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:weibo4j.properties</value>
				<value>classpath:weibosdk-core.properties</value>
				<value>classpath*:weibosdk-redis.properties</value>
				<value>classpath*:weibosdk-rabbitmq.properties</value>
				<value>classpath*:weibosdk-jdbc.properties</value>
			</list>
		</property>
		<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>

注意是classpath*:weibosdk-模块的.properties

集合其他模块的spring.xml

    <import resource="classpath*:weibosdk-module-dao.xml" />
	<import resource="classpath*:weibosdk-module-interceptor.xml" />
	<import resource="classpath*:weibosdk-module-rabbitmq.xml" />
	<import resource="classpath*:weibosdk-module-redis.xml" />
	<import resource="classpath*:weibosdk-module-task.xml" />

注意,也是classpath*:weibosdk-module-模块的.xml

表示从jar包里查找这些配置文件。因为其他模块,都被打包成了jar包。

构建,测试,运行,打包

这个在 emacsist-project下执行

构建指定模块
mvn clean install[test,package] -pl 模块1,模块2

构建指定模块,以及这些模块所依赖的模块
mvn clean install[test,package] -pl 模块1,模块2 -am

构建依赖于指定模块以及该模块本身
mvn clean install[test,package] -pl 模块 -amd

指定从哪个模块开始构建
mvn clean install[test,package] -rf 模块名

成功的话,输出类似:

[INFO]
[INFO] emacsist-project ................................... SUCCESS [  0.112 s]
[INFO] emacsist-kit ....................................... SUCCESS [  1.186 s]
[INFO] emacsist-email ..................................... SUCCESS [  0.177 s]
[INFO] emacsist-http ...................................... SUCCESS [  0.093 s]
[INFO] emacsist-redis ..................................... SUCCESS [  0.130 s]
[INFO] weibosdk-base ...................................... SUCCESS [  0.337 s]
[INFO] common-pojo ........................................ SUCCESS [  0.065 s]
[INFO] weibosdk-dao ....................................... SUCCESS [  0.231 s]
[INFO] weibosdk-service ................................... SUCCESS [  0.084 s]
[INFO] weibosdk-redis ..................................... SUCCESS [  0.137 s]
[INFO] weibosdk-rabbitmq .................................. SUCCESS [  0.200 s]
[INFO] weibosdk-web ....................................... SUCCESS [  0.845 s]
[INFO] weibosdk-interceptor ............................... SUCCESS [  0.148 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.010 s
[INFO] Finished at: 2015-10-16T17:23:27+08:00
[INFO] Final Memory: 33M/314M
[INFO] ------------------------------------------------------------------------