从JavaWeb编年史的远古时代,一直到白银时代,我们见证了JavaWeb开发模式的大致变迁。说白了,就是不断解耦合的过程。接下来我们来聊聊项目架构的演变,之所以我把它划到了JavaWeb编年史(黄金时代),是因为在早期的JavaWeb项目中,很少有架构的概念,基本就是一个单体项目,然后不断在已有项目上堆砌新的功能。所以,当我们开始有了架构的概念,其实也是一种非常大的进步,我个人称之为黄金时代,哈哈。
对于小公司来说,大部分项目都比较小,交给一个人开发足以,使用单体项目也无所谓。但是,随着互联网的发展,项目的功能越来越多,就得考虑把项目进行拆分,从而进一步解耦。
JavaWeb编年史 - 黄金时代,就是架构不断升级的年代,各种新的思想层出不穷,但是目的只有一个:拆分项目,进一步解耦。(其实也并没有特别严谨的时间顺序啦,如此行文只是为了统一下文章风格哈)
模块化时代
在解释模块化之前,我们先回顾一下,面向对象的三大特性是什么?
哦,聪明的你肯定立刻就想到继承、封装和多态。面向对象使得Java代码能够轻易被复用,Java程序变得更加灵活。
现在,我们把宾语换成Java项目,就变成了:面向对象使得Java项目能够轻易被复用,Java程序变得更加灵活。
是啊,如果受体变成项目,项目之间也去实现继承,那么很多功能就可以得到复用。而maven可以通过聚合工程,来实现这一点,这个功能是maven本来就具备的。那么,只要我们是用maven来搭建项目,就可以实现真正的模块化开发。
回想一下上一节的springboot项目,结构是这样的:
项目根据package来进行模块划分,看似没有问题,但是非常不好维护。
主要体现在:
1.如果其他项目有类似的功能,则需要每一个项目都写重复的代码,比如xxxService、xxxDao等。
2.团队协作的时候,不管你是用SVN还是git,都有极大概率多人操作同一个类,不利于版本管理。
3.项目如果体量越来越大,则文件会越来越多,整体会变得臃肿。
因此,需要用模块化的方法将这些package分化,简单来说就是把一个个package变成一个个module。
moudle叫做组件,或者叫子工程、子项目都可以。
2.演示将单体项目模块化
刚才那张图,我们需要将每一个package拆出来,做成一个module,最终项目结构就变成了这样:
下面我们依次来介绍各个模块的作用。
web-api
这个是接口模块,主要是提供服务给外界,对应于之前的controller层。
因为是前后端一体的项目,这边继续保留webapp。如果做的是前后端分离项目,则不需要webapp。
注意,启动配置这边要填写这个,否则访问不了JSP页面。
然后webapp的目录要进行如下配置,否则也是访问不了页面的。
web-api是整个工程的门面。
pom文件:
<?xml version="1.0" encoding="UTF-8"?> <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"> <parent> <artifactId>web1</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>web-api</artifactId> <dependencies> <dependency> <groupId>org.example</groupId> <artifactId>web-model</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.example</groupId> <artifactId>web-service</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
从pom中可以看到,web-api需要依赖web-service,web-model。
web-service
这是服务模块,为web-api提供服务支持,对应原来的service。
pom文件
<?xml version="1.0" encoding="UTF-8"?> <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"> <parent> <artifactId>web1</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>web-service</artifactId> <dependencies> <dependency> <groupId>org.example</groupId> <artifactId>web-model</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.example</groupId> <artifactId>web-dao</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
从pom中可以看到,web-service需要依赖web-dao,web-model。
web-dao
这是数据访问模块,对应原来的dao。
pom文件
<?xml version="1.0" encoding="UTF-8"?> <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"> <parent> <artifactId>web1</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>web-dao</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.example</groupId> <artifactId>web-model</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
从pom中可以看到,web-dao需要依赖web-model。
web-common
这是公共模块,主要放置一些工具包和类库,因为项目只是演示,所以目前这是一个空模块。
父项目
父项目就是这个web7,其余5个模块都是在这个项目里面的。
体现在pom文件,就是
<modules> <module>web-common</module> <module>web-api</module> <module>web-dao</module> <module>web-model</module> <module>web-service</module> </modules>
然后每一个模块的pom中都有一个parent
<parent> <artifactId>web1</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent>
也就是说,那5个模块都是父项目的子项目,继承自父项目。
打包方式:
<packaging>pom</packaging>
还有,顶层的父项目的打包方式必须为pom,表明这是一个聚合工程。pom工程就像是一个公共类,给下面的子模块提供了maven依赖版本号,方便控制版本。其实也没有什么特别神秘的地方。
模块化的好处
我们一般所说的模块化,就是指的maven聚合项目。
聚合的意义
对于一个大型的项目,如果我们直接作为一个工程开发,由于相互之间的依赖我们只能从头到尾由一组人开发,否则就会出现一个类好多人开发,相互更改的混乱局面,这个时候我们就将项目进行了横向和纵向的拆分。
所谓的横向的拆分就是我们平常说的三层架构,将项目分成了web层,service层、dao层(web层也被叫做表现层,service层也被叫做业务层,dao层也被持久层),可以理解为将一个功能模块的不同调用过程进行了水平方向的拆分。
所谓的纵向拆分就是将一个项目的多个功能模块进行了,可以理解为为了完成一个系统,深度(纵向)分析需要有哪些功能,然后将这些功能独立出来,进行了(纵向)拆分。
横向拆分后,每个功能模块进行了单独的开发之后,项目整合的时候就需要有一个能够整合这些项目或者模块的工程,这就是所谓聚合工程的意义。