目标
- 能够使用SSM框架集成为Maven项目
- 能够运用聚合与继承(多模块开发)
- 能够运用版本控制
- 能够使用Maven进行单元测试
- 能够通过Profile构建多环境开发
- 能够使用Maven属性管理
1)分模块开发与设计
1.1)工程模块划分
按照下图对项目进行模块的划分:
好处:降低耦合,方便团队协作
1.2)ssm_pojo拆分
-
新建模块:ssm_pojo
-
拷贝原始项目中对应的相关内容到ssm_pojo模块中:实体类(User)
1.3)ssm_dao拆分
-
新建模块:ssm_dao
-
拷贝原始项目中的下列相关内容到ssm_dao模块中
-
pom.xml:
引入数据层相关坐标即可:spring, mybatis, spring 整合mybatis, mysql, druid, pagehelper
删除springmvc相关坐标
<dependencies> <!--spring环境--> <!--spring环境--> <!--spring环境--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.9.RELEASE</version> </dependency> <!--mybatis环境--> <!--mybatis环境--> <!--mybatis环境--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.3</version> </dependency> <!--mysql环境--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!--spring整合jdbc--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.9.RELEASE</version> </dependency> <!--spring整合mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.3</version> </dependency> <!--druid连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> <!--分页插件坐标--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.2</version> </dependency> </dependencies>
-
添加ssm_pojo依赖
-
对ssm_pojo模块执行install指令,将其安装到本地仓库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aKecZ5u4-1638536942766)(assets/image-20200910221327763.png)] -
install执行过程
-
-
在ssm_dao模块的pom.xml中添加
<!--导入资源文件pojo--> <dependency> <groupId>com.xxx</groupId> <artifactId>ssm_pojo</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
-
数据层接口(UserDao)
-
复制src\main\resources\com\xxx\dao\UserDao.xml
-
复制applicationContext.xml后修改
<!--开启bean注解扫描--> <context:component-scan base-package="com.xxx"/> <!--加载properties文件--> <context:property-placeholder location="classpath*:jdbc.properties"/> <!--数据源--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--整合mybatis到spring中--> <bean class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="typeAliasesPackage" value="com.xxx.domain"/> <!--分页插件--> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <props> <prop key="helperDialect">mysql</prop> <prop key="reasonable">true</prop> </props> </property> </bean> </array> </property> </bean> <!--映射扫描--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.xxx.dao"/> </bean>
1.4)ssm_service拆分
- 新建模块:ssm_service
- 拷贝原始项目中对应的相关内容到ssm_service模块中
-
pom.xml:引入业务层相关坐标即可,删除springmvc相关坐标
-
spring
-
junit
-
spring 整合junit
<dependencies> <!--导入资源文件dao--> <dependency> <groupId>com.xxx</groupId> <artifactId>ssm_dao</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--spring环境--> <!--spring环境--> <!--spring环境--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.9.RELEASE</version> </dependency> <!--其他组件--> <!--其他组件--> <!--其他组件--> <!--junit单元测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <!--spring整合junit--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.1.9.RELEASE</version> </dependency> </dependencies>
-
直接依赖ssm_dao
对ssm_dao模块执行install指令,将其安装到本地仓库
-
在ssm_service模块的pom.xml中添加
<!--导入资源文件dao-->
<dependency>
<groupId>com.xxx</groupId>
<artifactId>ssm_dao</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
-
间接依赖ssm_pojo(由ssm_dao模块负责依赖关系的建立)
-
业务层接口与实现类(UserService、UserServiceImpl)
-
Spring配置文件
<!--开启bean注解扫描--> <context:component-scan base-package="com.xxx"/> <!--开启注解式事务--> <tx:annotation-driven transaction-manager="txManager"/> <!--事务管理器--> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
-
修改service模块spring核心配置文件名(包含main和test包下),添加模块名称:applicationContext-service.xml
-
修改dao模块spring核心配置文件名(包含main和test包下),添加模块名称:applicationContext-dao.xml
-
修改单元测试引入的配置文件名称,由单个文件修改为多个文件
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:applicationContext-service.xml", "classpath:applicationContext-dao.xml"}) public class UserServiceTest { }
1.5)ssm_controller拆分
-
新建模块:ssm_controller
-
打开pom.xml文件,添加打包方式配置
<packaging>war</packaging>
-
拷贝原始项目中对应的相关内容到ssm_controller模块中
pom.xml:引入表现层相关坐标即可spring, springmvc, jackson, servlet, tomcat服务器插件
<dependencies> <!--springmvc环境--> <!--springmvc环境--> <!--springmvc环境--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.9.RELEASE</version> </dependency> <!--jackson相关坐标3个--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <!--servlet环境--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> </dependencies> <build> <!--设置插件--> <plugins> <!--具体的插件配置--> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.1</version> <configuration> <port>80</port> <path>/</path> </configuration> </plugin> </plugins> </build>
-
直接依赖ssm_service
对ssm_service模块执行install指令,将其安装到本地仓库
-
在ssm_controller模块的pom.xml中添加
<dependency>
<groupId>com.xxx</groupId>
<artifactId>ssm_service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
-
间接依赖ssm_dao、ssm_pojo
-
表现层控制器类与相关设置类(UserController、异常相关……)
-
spring-mvc.xml配置文件
<mvc:annotation-driven/> <context:component-scan base-package="com.xxx.controller"/>
-
修改web.xml配置文件中加载spring环境的配置文件名称,使用通配,加载所有applicationContext-开始的配置文件
易错点:classpath*<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext-*.xml</param-value> </context-param> <!--启动服务器时,通过监听器加载spring运行环境--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:spring-mvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
小结
分模块开发注意事项
-
模块中仅包含当前模块对应的功能类与配置文件
-
spring核心配置根据模块功能不同进行独立制作
-
当前模块所依赖的模块通过导入坐标的形式引入
-
web.xml需要加载所有的spring核心配置文件
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext-*.xml</param-value> </context-param>
2)聚合
2.1)多模块构建维护
分模块开发后,每次要运行ssm_controller都需要对ssm_pojo, ssm_dao, ssm_service执行install,非常的麻烦,如何解决呢?
2.2)聚合
-
作用:聚合用于快速构建maven工程,一次性构建多个项目/模块。
-
制作方式:
-
创建一个空模块ssm,打包类型定义为pom
<packaging>pom</packaging>
-
定义当前模块进行构建操作时关联的其他模块名称
<modules> <module>../ssm_controller</module> <module>../ssm_service</module> <module>../ssm_dao</module> <module>../ssm_pojo</module> </modules>
注意事项:参与聚合操作的模块最终执行顺序与模块间的依赖关系有关,与配置顺序无关
-
-
完整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"> <modelVersion>4.0.0</modelVersion> <groupId>com.xxx</groupId> <artifactId>ssm</artifactId> <version>1.0-SNAPSHOT</version> <!--定义该工程用于进行构建管理--> <packaging>pom</packaging> <!--管理的工程列表--> <modules> <!--具体的工程名称--> <module>../ssm_controller</module> <module>../ssm_service</module> <module>../ssm_dao</module> <module>../ssm_pojo</module> </modules> </project>
-
执行instal打包所有module
- 原来需要install4次的操作,现在只需要install ssm模块即可
3)继承
3.1)模块依赖关系维护
多个module引用了相同的坐标,为了避免重复编写版本号和不同版本的兼容性问题。
3.2)继承
- 作用:通过继承可以实现在子工程中沿用父工程中的配置
- maven中的继承与java中的继承相似,在子工程中配置继承关系
3.3)继承依赖定义
-
在父工程中定义依赖管理,使用标签
<!--声明此处进行依赖管理--> <dependencyManagement> <!--具体的依赖--> <dependencies> <!--spring环境--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.9.RELEASE</version> </dependency> <dependencies> <dependencyManagement>
-
在子工程中声明其父工程坐标与对应的位置, = Java中的extends
<!--定义该工程的父工程--> <parent> <groupId>com.xxx</groupId> <artifactId>ssm</artifactId> <version>1.0-SNAPSHOT</version> <!--填写父工程的pom文件--> <relativePath>../ssm/pom.xml</relativePath> </parent>
3.4)继承依赖使用
在子工程中引入依赖,无需声明依赖版本,版本号继承自父工程中依赖的版本
<dependencies>
<!--spring环境-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies>
3.5)继承的资源
groupId:项目组ID,项目坐标的核心元素
version:项目版本,项目坐标的核心因素
description:项目的描述信息
organization:项目的组织信息
inceptionYear:项目的创始年份
url:项目的URL地址
developers:项目的开发者信息
contributors:项目的贡献者信息
distributionManagement:项目的部署配置
issueManagement:项目的缺陷跟踪系统信息
ciManagement:项目的持续集成系统信息
scm:项目的版本控制系统西溪
malilingLists:项目的邮件列表信息
properties:自定义的Maven属性
dependencies:项目的依赖配置
dependencyManagement:项目的依赖管理配置
repositories:项目的仓库配置
build:包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
reporting:包括项目的报告输出目录配置、报告插件配置等
3.6)继承与聚合对比(了解)
作用:
- 聚合用于快速构建项目
- 继承用于快速配置
相同点:
- 聚合与继承的pom.xml文件打包方式均为pom,可以将两种关系制作到同一个pom文件中
- 聚合与继承均属于设计型模块,并无实际的模块内容
不同点:
- 聚合是在当前模块中配置关系,聚合可以感知到参与聚合的模块有哪些
- 继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己
4)属性
4.1)版本统一的重要性
4.2)属性类别
1.自定义属性
2.内置属性
3.Setting属性
4.Java系统属性
5.环境变量属性
4.3)自定义属性
作用:等同于定义变量,方便统一维护
定义格式:
<!--定义自定义属性-->
<properties>
<spring.version>5.1.9.RELEASE</spring.version>
<junit.version>4.12</junit.version>
</properties>
调用格式:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
4.4)内置属性(了解)
作用:使用maven内置属性,快速配置
调用格式:
${basedir}
${version} = ${project.version}
4.5)Setting属性(了解)
作用:使用Maven配置文件setting.xml中的标签属性,用于动态配置
调用格式:
${settings.localRepository}
4.6)Java系统属性(了解)
作用:读取Java系统属性
调用格式
${user.home}
系统属性查询方式
mvn help:system
4.7)环境变量属性(了解)
作用:读取操作系统中的环境变量
调用格式
${env.JAVA_HOME}
环境变量属性查询方式
mvn help:system
5)版本管理(了解)
5.1)工程版本区分
5.2)工程版本类别
- SNAPSHOT(快照版本)
- 项目开发过程中,为方便团队成员合作,解决模块间相互依赖和时时更新的问题,开发者对每个模块进行构建的时候,输出的临时性版本叫快照版本(测试阶段版本)
- 快照版本会随着开发的进展不断更新
- RELEASE(发布版本)
- 项目开发到进入阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构件文件是稳定的,即便进行功能的后续开发,也不会改变当前发布版本内容,这种版本称为发布版本
5.3)工程版本号约定
约定规范:
- <主版本>.<次版本>.<增量版本>.<里程碑版本>
- 主版本:表示项目重大架构的变更,如:spring5相较于spring4的迭代
- 次版本:表示有较大的功能增加和变化,或者全面系统地修复漏洞
- 增量版本:表示有重大漏洞的修复
- 里程碑版本:表明一个版本的里程碑(版本内部)。这样的版本同下一个正式版本相比,相对来说不是很稳定,有待更多的测试
范例:
- 5.1.9.RELEASE
6)资源配置(了解)
6.1)资源配置多文件维护
将项目的所有资源配置信息比如jdbc.properties统一放到pom.xml文件中
6.2)配置文件引用pom属性
-
作用:在任意配置文件中加载pom文件中定义的属性
-
配置方式:pom.xml
<properties> <spring.version>5.1.9.RELEASE</spring.version> <junit.version>4.12</junit.version> <jdbc.url>jdbc:mysql://127.0.0.1:3306/ssm_db</jdbc.url> </properties>
调用格式:jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=${jdbc.url} jdbc.username=root jdbc.password=xxx
-
开启配置文件加载pom属性
<!--配置资源文件对应的信息--> <resources> <resource> <!--设定配置文件对应的位置目录,支持使用属性动态设定路径--> <directory>${project.basedir}/src/main/resources</directory> <!--开启对配置文件的资源加载过滤--> <filtering>true</filtering> </resource> </resources>
7)多环境开发配置
7.1)多环境兼容
开发环境(development):开发环境是程序猿们专门用于开发的服务器
测试环境(testing):测试同学干活的环境,一般会由测试同学自己来部署,然后在此环境进行测试
生产环境(production):项目上线后正式提供对外服务的环境
三个环境也可以说是系统开发的三个阶段:开发->测试->上线,其中生产环境也就是通常说的真实环境。
7.2)多环境配置
<!--创建多环境-->
<profiles>
<!--定义具体的环境:生产环境-->
<profile>
<!--定义环境对应的唯一名称-->
<id>pro_env</id>
<!--定义环境中专用的属性值-->
<properties>
<jdbc.url>jdbc:mysql://127.1.1.1:3306/ssm_db</jdbc.url>
</properties>
</profile>
<!--定义具体的环境:开发环境-->
<profile>
<id>dev_env</id>
……
</profile>
</profiles>
7.3)加载指定环境
作用:加载指定环境配置
调用格式
mvn 指令 -P 环境定义id
#在idea中Alt+F12打开控制台执行如下命令
#范例
mvn install -P dep_env
快捷指定方法:
7.4)设置默认启动环境
<profile>
...
<!--设置默认启动-->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
8)跳过测试(了解)
8.1)跳过测试环节的应用场景
整体模块功能未开发
模块中某个功能未开发完毕
单个功能更新调试导致其他功能失败
快速打包
……
8.2)使用命令跳过测试
使用命令行
mvn install -D skipTests
8.3)在idea中跳过测试(常用)
8.4)使用配置跳过测试
<skipTests>true</skipTests><!--设置跳过测试-->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<skipTests>true</skipTests><!--设置跳过测试-->
<includes> <!--包含指定的测试用例-->
<include>**/User*Test.java</include>
</includes>
<excludes><!--排除指定的测试用例-->
<exclude>**/User*TestCase.java</exclude>
</excludes>
</configuration>
</plugin>
9)私服
9.1)私服的必要性
9.2)Nexus简介
Nexus是Sonatype公司的一款maven私服产品
下载地址:https://help.sonatype.com/repomanager3/download
9.3)使用Nexus
-
启动服务器(命令行启动)
nexus.exe /run nexus
-
访问服务器(默认端口:8081)http://localhost:8081
-
修改基础配置信息
-
安装路径下etc目录中nexus-default.properties文件保存有nexus基础配置信息,例如默认访问端口
application-port=8081 application-host=0.0.0.0 nexus-args=${jetty.etc}/jetty.xml,${jetty.etc}/jetty-http.xml,${jetty.etc}/jetty-requestlog.xml nexus-context-path=/
- 修改服务器运行配置信息
-
安装路径下bin目录中nexus.vmoptions文件保存有nexus服务器启动对应的配置,例如默认占用内存空间
-Xms512m -Xmx512m -XX:MaxDirectMemorySize=2703m -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=../sonatype-work/nexus3/log/jvm.log -XX:-OmitStackTraceInFastThrow -Djava.net.preferIPv4Stack=true
9.4)私服资源获取
9.5)仓库分类
-
宿主仓库hosted :保存无法从外网中央仓库获取的资源,比如如下两种资源
-
自主研发
-
第三方非开源项目
-
-
代理仓库proxy
- 代理远程仓库,通过nexus访问其他公共仓库,例如中央仓库
-
仓库组group
-
将若干个仓库组成一个群组,简化配置
-
仓库组不能保存资源,属于设计型仓库
-
9.6)手动上传组件
上传资源时提供对应的信息
-
保存的位置(宿主仓库)
-
资源文件
-
对应坐标
9.7)idea访问私服与组件上传
9.8)idea访问私服
1.配置本地仓库访问私服的权限(setting.xml):C:\Users\your-username\m2\settings.xml
<servers>
<server>
<id>xxx-release</id>
<username>admin</username>
<password>admin</password>
</server>
<server>
<id>xxx-snapshots</id>
<username>admin</username>
<password>admin</password>
</server>
</servers>
2.配置本地仓库资源来源(setting.xml)
<mirrors>
<mirror>
<id>nexus-xxx</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/repository/maven-public/</url>
</mirror>
</mirrors>
maven自动获取jar过程如下所示:
9.9)idea组件上传
配置当前项目访问私服上传资源的保存位置(pom.xml)
<distributionManagement>
<repository>
<id>xxx-release</id>
<url>http://localhost:8081/repository/xxx-release/</url>
</repository>
<snapshotRepository>
<id>xxx-snapshots</id>
<url>http://localhost:8081/repository/xxx-snapshots/</url>
</snapshotRepository>
</distributionManagement>
两种上传方式:
-
发布资源到私服命令
mvn deploy
-
使用idea的maven插件
上传过程如下所示:
扩展-Maven的依赖传递
1 什么是依赖传递
在maven中,依赖是可以传递的,假设存在三个项目,分别是项目A,项目B以及项目C。假设C依赖B,B依赖A,那么我们可以根据maven项目依赖的特征不难推出项目C也依赖A。
通过上面的图可以看到,我们的web项目直接依赖了spring-webmvc,而spring-webmvc依赖了sping-aop、spring-beans等。最终的结果就是在我们的web项目中间接依赖了spring-aop、spring-beans等。
2 什么是依赖冲突
由于依赖传递现象的存在, spring-webmvc 依赖 spirng-beans-4.2.4,spring-aop 依赖 spring-beans-5.0.2,但是发现 spirng-beans-4.2.4 加入到了工程中,而我们希望 spring-beans-5.0.2 加入工程。这就造成了依赖冲突。
3 如何解决依赖冲突
1.使用maven提供的依赖调解原则
- 第一声明者优先原则
- 路径近者优先原则
2.排除依赖
3.锁定版本
4 依赖调节原则——第一声明者优先原则
在 pom 文件中定义依赖,以先声明的依赖为准。其实就是根据坐标导入的顺序来确定最终使用哪个传递过来的依赖。
结论: 通过上图可以看到,spring-aop和spring-webmvc都传递过来了spring-beans,但是因为spring-aop在前面,所以最终使用的spring-beans是由spring-aop传递过来的,而spring-webmvc传递过来的spring-beans则被忽略了。
5 排除依赖
可以使用exclusions标签将传递过来的依赖排除出去。
6 版本锁定-继承父工程的版本
采用直接锁定版本的方法确定依赖jar包的版本,版本锁定后则不考虑依赖的声明顺序或依赖的路径,以锁定的版本为准添加到工程中,此方法在企业开发中经常使用。
版本锁定的使用方式:
第一步:在dependencyManagement标签中锁定依赖的版本
第二步:在dependencies标签中声明需要导入的maven坐标
①在dependencyManagement标签中锁定依赖的版本
②在dependencies标签中声明需要导入的maven坐标