结合maven和dubbo进行项目模块划分和模块依赖

maven模块划分的好处

首先我们聊聊为什么要使用maven进行模块划分。  (本节内容参考maven 为何要模块划分-聚合/继承

为了防止传递依赖,我们各个模块之间尽量用直接依赖的方式。本篇文章介绍多模块化开发,我们做过Maven项目的都知道,我们的项目一般都是分模块的,每个模块都会对应着一个POM.xml文件,它们之间通过继承和聚合(也称多模块,multi-module)相互关联。

我们换另一种思路想想,那么我们能不能一个项目就用一个模块。这样开起来很方便,简单明了,那么做起来呢,接下来我们分析一下。

假设我们有这么一个项目,整个项目构建一个war包,而每一层放到各自的Package里面。如下:

Itoo-Exam
com.tgb.itoo.exam.dao —–负责与数据库的交互,封装了hibernate的交互类
com.tgb.itoo.exam.service—-负责处理业务逻辑,放Service接口及其实现类
com.tgb.itoo.exam.web——-负责与客户端的交互,主要放action/controller,jsp等等
com.tgb.itoo.exam.util——–工具类

那么随着我们项目的扩大,Maven项目也会越来越大,那么会遇到下面的几个问题:
1、首先build整个项目的时间越来越长,尽管你一直在web层工作,但你不得不build整个项目
2、模块化体现不出来,如果我们只负责维护某个模块,因为我们所有的模块都在一个war包中,那么我们可以随意修改其他模块(权限的控制),导致版本管理混乱,冲突。同时因为模块太多,太大,不好维护。
很多人都在同时修改这个war包,将导致工作无法顺利进行。
3、pom.xml本来是可以继承、复用的,但是如果我们新建一个项目,只能依赖于这个war包,那么会把这个war包的相关的前台的东西依赖过来,导致项目管理混乱。

这样的管理是混乱的,没有遵守一个设计模式原则:“高内聚,低耦合”。相反在代码内部,所有的东西都耦合在了一起。因此我们需要划分模块。


另外,随着技术的飞速发展和各类用户对软件的要求越来越高,软件本身变得越来越复杂,设计人员开始采用各种方式进行开发,于是就有了我们的分层架构、分层模块来提高代码的清晰和重用。从而实现了系统内部的高内聚、低耦合。

模块化的好处

1、方便重用,当我们再开发一条teacher线的时候,我们只需要引用itoo-base,itoo-exam-api,这些包都是复用的,称为我们平台复用的基础类库,供所有的项目使用。这是模块化最重要的一个目的。

3、灵活性。比如我们这些公共的jar包,itoo-base,itoo-tool,itoo-exam-api等这些jar包,我们不需要再当源码,只需要deploy到nexus,其他人从nexus下载即可。代码的可维护性、可扩展性好,并且保证了项目独立性与完整性。

5、上篇文章写得DependencyManagement与dependencies,父项目中管理jar包版本。使得整个项目的测试版本与发布版本一致。

使用模块化配置,复用性强,防止pom变得过于庞大,方便构建;针对项目的管理更方便,每一个模块都是独立的,抽象出一个父类来管理第三方jar的版本,开发人员只需要开发自己的线,其他的都不用管,灵活;基于此种基础我们还可以做分布式。

上面提到了我们用父项目聚合子项目,子项目继承父项目。怎么使用maven的模块聚合和继承,构建多模块工程可以参考

Eclipse创建Maven多模块工程


maven模块划分的方案

先简单描述一个简单测试项目需求:   (本节内容参考:Maven划分项目模块经验)
现需要开发一个用于管理用户信息项目(项目名为:edu),主要功能是管理系统使用用户信息(user)。

划分步骤为: 
1. 将项目进行划分需要详细了解项目按照垂直划分(项目大的功能需求)可以划分几个模块。 
2. 将划分出来的项目进行横向划分,分别分出对应的 WEB层、Service接口层、Service接口实现层、Dao层。 
3. 确定项目的 GroupId(命名规则为:公司网址反写加上项目名 例如:com.hysky.edu) 和 ArtifactId(命名规则为:项目名-横向模块名-垂直模块名 例如:edu-web-user),建立项目基本工程模型。 
4. 建立一个Maven父工程(packaging为POM类型)用于管理整个项目Jar包、项目所使用的插件、项目发布Maven私库地址、全局POM使用常量,所有的项目都继承这个项目配置。 
5. 建立一个Maven工程(packaging为jar类型)用于管理整个项目使用的配置文件。例如 jdbc数据库连接地址、注册中心连接地址等等,所有工程需要依赖这个工程。 
6. 可以建立一个Maven工程(packaging为POM类型)用于管理所有工程统一操作,使用 Maven聚合(module)所有项目,Maven会自动识别项目依赖关系,可以依次进行命令操作。 
7. 将所有项目都需要使用的公共工具类可以抽取出来,新建立一个 Maven工程(packaging为jar类型),方便所有开发依赖使用工具类。

maven与dubbo结合进行模块划分

根据本人的实际工作经验,以usr项目为例,maven模块划分如下:

制定项目模块命名规则:

项目名-横向模块名-打包类型

1、项目名即为usr

2、横向模块可以划分为WEB层、Service接口层、Service接口实现层、Dao层。

   本人将之分成3种类型:

  •    cjpt(MVC层,又分为view层,用于前端页面工程,和控制层,用于controller类、filter类等)
  •    hxfw(业务层,用于业务实现类,以及Dao层)
  •    hxfw-api(业务接口层,用于业务接口和POJO)

3、打包类型可以划分为web(表示打成war包)、java(表示打成jar包)。

最终,把项目划分为五个模块:

  • usr-cjpt-web     放置前端页面的工程
  • usr-cjpt-java     放置controller类、filter类的工程
  • usr-hxfw-java    放置业务实现类、Dao的工程
  • usr-hxfw-api-java   放置业务接口和POJO的工程
  • usr-hxfw-web     放置整个项目配置文件的工程

由于我们是与dubbo结合的,所以

usr-cjpt-java 是消费方

usr-hxfw-java 是提供方

usr-cjpt-web和usr-hxfw-web是部署到tomcat的war应用。

模块依赖关系如下图:


关于为什么使用一个公共的maven工程来存放pojo和服务接口,再被consumer工程和provider工程依赖,可以参考

dubbo在项目中的应用

可能会让人困惑的是,为什么是把usr-hxfw-web打成war包?

在很多博客的示例中 ,说的都是把消费方和提供方打成war包,部署到tomcat中。(比如 Dubbo项目配置 这篇博客)

1、api-dubbo;——统一的接口,用来连接消费者和生产者,最后打成jar包 
2、consumer-dubbo;——消费者,也就是web层,接口的调用者,最后打成war包; 

3、producer-dubbo;——生产者,也就是业务层,接口的服务提供者,最后打成war包;  

请记住,那些只是简单示例,不是说一定要把消费方打成war包,消费方才能调用服务。也不是说一定要把提供方打成war包,提供方才能提供服务。只要把消费方和提供方部署到tomcat容器即可。

上面usr-cjpt-web和usr-hxfw-web打成war包,部署到tomcat容器。但是应为usr-cjpt-web依赖了消费方usr-cjpt-java,以及usr-hxfw-web依赖了提供方usr-hxfw-java,所以消费方usr-cjpt-java和提供方usr-hxfw-java同样会部署到tomcat容器。


在笔者所在的公司中,usr-hxfw-web除了用于代替usr-hxfw-java打成war包,还是用于添加sql文件,并依赖自维护数据库jar包,在容器启动时执行sql脚本的;用于添加spring的appclication-context.xml,配置扫描@service等注解(即除了@Controller之外的注解)。

<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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-3.1.xsd">
	<context:annotation-config />
	<context:component-scan base-package="com.usr">
		<context:exclude-filter type="annotation"
			expression="org.springframework.stereotype.Controller" />
	</context:component-scan>		
</beans>

而usr-cjpt-web添加的appclication-context.xml,则配置扫描@Contoller等注解。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" 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-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
	<context:component-scan base-package="com.usr" />
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/pages/" />
		<property name="suffix" value=".jsp" />
		<property name="viewClass"
			value="org.springframework.web.servlet.view.JstlView" />
	</bean>



</beans>

ps:上述这些spring配置不是一定要在这2个工程配置。假如它们依赖的jar包已经添加Application-context.xml进行了spring配置,则这2个工程可以不再添加Application-context.xml。因为在它们的web.xml中配置的是加载类路径下的spring文件夹下的*.xml。这也就包括了所依赖jar包下的spring文件夹下的Application-context.xml。

比如上面模块依赖中,usr-hxfw-web工程依赖了usr-hxfw-java工程,如果usr-hxfw-java工程添加了Application-context.xml,或者usr-hxfw-java工程依赖的其它jar包添加了Application-context.xml,那么,即使usr-hxfw-web工程不添加Application-context.xml,也能实现@service等注解扫描。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值