Maven高级:分模块、聚合继承、多环境部署与私服搭建

个人主页: Hygge_Code
个人格言: “既然选择了远方,便不顾风雨兼程”

在这里插入图片描述

Maven高级特性:分模块、聚合继承与多环境配置

一、分模块开发与设计

1. 分模块开发的核心目标

图例:
在这里插入图片描述
从 左边单体 → 右边聚合工程 的优点

  • 代码臃肿、职责混乱(分包 != 模块化,没有强制的隔离机制) → 按功能 / 分层拆分模块(如用户模块、订单模块、通用工具模块)
  • 依赖版本混乱、冲突频发 → 父工程统一管理所有依赖版本
  • 构建效率低(改一行代码需全量构建)→ 支持单独构建某个子模块
  • 团队协作冲突多 → 不同团队维护不同子模块,降低代码冲突概率
  • 配置重复 → 父工程统一配置插件、编译版本等,子模块自动继承

2. 模块拆分原则与实战

分模块遵循「高内聚、低耦合」,优先按技术分层拆分(中小型项目首选),大型项目可结合业务功能拆分。以下是基于用户管理项目的完整拆分案例:

(1)项目整体结构
maven-user(父工程,pom打包)
├─ maven-pojo(实体类模块,jar打包)
├─ maven-utils(工具类模块,jar打包)
├─ maven-dao(数据访问模块,jar打包)
├─ maven-service(业务逻辑模块,jar打包)
└─ maven-servlet(Web控制模块,war打包)
(2)各模块详细实现
① 父工程(maven-user)

无业务代码,仅负责统一依赖、插件配置,打包方式为 pom

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.xq</groupId>
<artifactId>maven-user</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging> <!-- 父工程必须为pom打包 -->
  <!-- 统一管理依赖(后续通过dependencyManagement优化) -->
    <<dependencies>
      <!-- Servlet依赖 -->
        <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
        </dependency>
        <!-- 数据库相关依赖 -->
          <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.18</version>
          </dependency>
          <dependency>
          <groupId>c3p0</groupId>
          <artifactId>c3p0</artifactId>
          <version>0.9.1.2</version>
          </dependency>
          <!-- 工具类依赖 -->
            <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.6</version>
            </dependency>
          </</dependencies>
          <!-- Tomcat插件配置 -->
            <build>
              <plugins>
                <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                  <configuration>
                  <port>8088</port>
                  <path>/</path>
                  </configuration>
                </plugin>
              </plugins>
            </build>
          </project>
② 实体类模块(maven-pojo)

映射数据库表,仅包含实体类与 get/set 方法,无依赖:

package com.xq.pojo;
public class User {
private Integer id;
private String name;
private String username;
private String password;
// 其他属性(gender/age/address等)
// get/set方法与toString方法
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
// 其余get/set方法省略
}

模块 pom.xml 仅需继承父工程:

<project>
  <parent>
  <groupId>com.xq</groupId>
  <artifactId>maven-user</artifactId>
  <version>1.0-SNAPSHOT</version>
  </parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>maven-pojo</artifactId>
</project>
③ 工具类模块(maven-utils)

在父工程上,右键,新建模块(使用maven构建,不使用骨架创建)。然后创建工具类类封,装通用工具,如数据库连接工具:

package com.xq.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class DataSourceConfig {
// 加载c3p0-config.xml配置
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 获取数据源
public static DataSource getDataSource() {
return dataSource;
}
// 获取数据库连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}

模块 pom.xml 继承父工程,无需额外依赖(父工程已统一引入)。

④ 数据访问模块(maven-dao)

负责数据库 CRUD,依赖 maven-pojomaven-utils

// UserDao接口
package com.xq.dao;
import com.xq.pojo.User;
import java.util.List;
public interface UserDao {
List<User> findAll(); // 查询所有用户
  }
  // UserDao实现类
  package com.xq.dao.impl;
  import com.xq.dao.UserDao;
  import com.xq.pojo.User;
  import com.xq.utils.DataSourceConfig;
  import org.apache.commons.dbutils.QueryRunner;
  import org.apache.commons.dbutils.handlers.BeanListHandler;
  import java.sql.SQLException;
  import java.util.List;
  public class UserDaoImpl implements UserDao {
  private QueryRunner runner = new QueryRunner(DataSourceConfig.getDataSource());
  @Override
  public List<User> findAll() {
    String sql = "select * from user";
    try {
    return runner.query(sql, new BeanListHandler<>(User.class));
      } catch (SQLException e) {
      throw new RuntimeException(e);
      }
      }
      }

模块 pom.xml 引入依赖:

<project>
  <parent>
  <groupId>com.xq</groupId>
  <artifactId>maven-user</artifactId>
  <version>1.0-SNAPSHOT</version>
  </parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>maven-dao</artifactId>
  <<dependencies>
    <!-- 依赖实体类模块 -->
      <dependency>
      <groupId>com.xq</groupId>
      <artifactId>maven-pojo</artifactId>
      <version>1.0-SNAPSHOT</version>
      </dependency>
      <!-- 依赖工具类模块 -->
        <dependency>
        <groupId>com.xq</groupId>
        <artifactId>maven-utils</artifactId>
        <version>1.0-SNAPSHOT</version>
        </dependency>
      </</dependencies>
    </project>
⑤ 业务逻辑模块(maven-service)

在父工程上,右键,新建模块(使用maven构建,不使用骨架创建):处理业务逻辑,依赖 maven-dao(需要dao模块里面的数据):

// UserService接口
package com.xq.service;
import com.xq.pojo.User;
import java.util.List;
public interface UserService {
List<User> findUser();
  }
  // UserService实现类
  package com.xq.service.impl;
  import com.xq.dao.UserDao;
  import com.xq.dao.impl.UserDaoImpl;
  import com.xq.pojo.User;
  import com.xq.service.UserService;
  import java.util.List;
  public class UserServiceImpl implements UserService {
  private UserDao userDao = new UserDaoImpl();
  @Override
  public List<User> findUser() {
    return userDao.findAll(); // 调用DAO层方法
    }
    }

模块 pom.xml 依赖 maven-dao 模块。

⑥ Web控制模块(maven-servlet)

在父工程上,右键,新建模块(使用maven构建,使用骨架创建)。然后创建servle:接收前端请求,依赖 maven-service(servlet模块需要调用service模块里面的数据),打包方式为 war

package com.xq.servlet;
import com.xq.pojo.User;
import com.xq.service.UserService;
import com.xq.service.impl.UserServiceImpl;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/showUserList")
public class UserServlet extends HttpServlet {
private UserService userService = new UserServiceImpl();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf-8");
List<User> userList = userService.findUser();
  request.setAttribute("list", userList);
  // 转发到JSP页面
  try {
  request.getRequestDispatcher("/list.jsp").forward(request, response);
  } catch (Exception e) {
  e.printStackTrace();
  }
  }
  }

模块 pom.xml 依赖 maven-service 模块,并继承父工程的 Tomcat 插件。

二、聚合与继承

1. 聚合:一键构建所有模块

我们思考一个问题:
 上面的各个模块是分开独立开发的,彼此互相独立,互补影响。假设如果现在maven-dao模块更新升级了,那么其他模块是如何感知dao模块发生了变化的?
在这里插入图片描述
解决方案:
 会不会有一个工程,专门对这些模块进行管理。对这些模块进行统一的编译、测试、打包等操作。一旦一个模块发生了变化,会同时对其他模块也进行编译、测试、打包。此时就需要用到聚合的思想。

聚合的作用:用于快速构建maven工程,一次性管理多个模块

(1)父工程配置聚合

在父工程 pom.xml 中添加 <modules> 标签,声明子模块:

<modules>
<module>maven-pojo</module>
<module>maven-utils</module>
<module>maven-dao</module>
<module>maven-service</module>
<module>maven-servlet</module>
</modules>
(2)聚合特性
  • 执行 mvn clean compile 时,Maven 按依赖顺序自动编译所有模块(如先编译pojo,再构建 dao);
  • 支持增量构建,仅重新构建修改过的模块及其依赖模块。

我们的父工程为maven-user,专门用来管理其他的子模块,我们测试一下:
在这里插入图片描述

2. 继承:复用配置,避免冗余

继承让子模块复用父工程的依赖、插件配置(类似于java中的继承关系),核心优化是通过 <dependencyManagement> 统一版本,避免子模块继承无用依赖:

(1)父工程优化:使用 dependencyManagement
<dependencyManagement>
  <dependencies>
    <!--管理自己的依赖-->
      <!-- 子模块共享依赖,统一版本 -->
        <dependency>
        <groupId>com.xq.service</groupId>
        <artifactId>maven-service</artifactId>
        <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
        <groupId>com.xq.dao</groupId>
        <artifactId>maven-dao</artifactId>
        <version>1.0-SNAPSHOT</version>
        </dependency>
        <!-- 子模块间依赖 -->
          <dependency>
          <groupId>com.xq.pojo</groupId>
          <artifactId>maven-pojo</artifactId>
          <version>1.0-SNAPSHOT</version>
          </dependency>
          <dependency>
          <groupId>com.xq.utils</groupId>
          <artifactId>maven-utils</artifactId>
          <version>1.0-SNAPSHOT</version>
          </dependency>
          <dependency>
          <groupId>com.xq.servlet</groupId>
          <artifactId>maven-servlet</artifactId>
          <version>1.0-SNAPSHOT</version>
          </dependency>
          <!-- servlet依赖的jar包start -->
            <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <!-- <scope>provided</scope>-->
            </dependency>
            <!-- servlet依赖的jar包start -->
              <!-- jsp依赖jar包start -->
                <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>javax.servlet.jsp-api</artifactId>
                <version>2.3.1</version>
                <!-- <scope>provided</scope>-->
                </dependency>
                <!-- jsp依赖jar包end -->
                  <!--jstl标签依赖的jar包start -->
                    <dependency>
                    <groupId>javax.servlet</groupId>
                    <artifactId>jstl</artifactId>
                    <version>1.2</version>
                    <!--<scope>provided</scope>-->
                    </dependency>
                    <!-- JSTL实现包 -->
                      <dependency>
                      <groupId>org.apache.taglibs</groupId>
                      <artifactId>taglibs-standard-impl</artifactId>
                      <version>1.2.5</version>
                      </dependency>
                      <!--jstl标签依赖的jar包end -->
                        <dependency>
                        <groupId>c3p0</groupId>
                        <artifactId>c3p0</artifactId>
                        <version>0.9.1.2</version>
                        </dependency>
                        <!--beanUtils的依赖-->
                          <dependency>
                          <groupId>commons-beanutils</groupId>
                          <artifactId>commons-beanutils</artifactId>
                          <version>1.8.3</version>
                          </dependency>
                          <!--dbutils组件 封装了原生的jdbc-->
                            <dependency>
                            <groupId>commons-dbutils</groupId>
                            <artifactId>commons-dbutils</artifactId>
                            <version>1.6</version>
                            </dependency>
                            <!--logging-->
                              <dependency>
                              <groupId>commons-logging</groupId>
                              <artifactId>commons-logging</artifactId>
                              <version>1.1.1</version>
                              </dependency>
                              <!--mysql驱动-->
                                <dependency>
                                <groupId>mysql</groupId>
                                <artifactId>mysql-connector-java</artifactId>
                                <version>5.1.18</version>
                                </dependency>
                              </dependencies>
                            </dependencyManagement>
                            <!-- 插件版本管理 -->
                              <build>
                                <pluginManagement>
                                  <plugins>
                                    <plugin>
                                    <groupId>org.apache.tomcat.maven</groupId>
                                    <artifactId>tomcat7-maven-plugin</artifactId>
                                    <version>2.1</version>
                                      <configuration>
                                      <port>8088</port>
                                      <path>/</path>
                                      </configuration>
                                    </plugin>
                                  </plugins>
                                </pluginManagement>
                              </build>
(2)子模块引用依赖(无需写版本)

在子模块中按照自己的需求,引入对应的依赖,此时不需要加依赖的版本号了,
因为在父工程里面已经定义好了:

<!-- maven-utils模块示例 -->
  <dependencies>
    <!--dbutils组件 封装了原生的jdbc-->
      <dependency>
      <groupId>commons-dbutils</groupId>
      <artifactId>commons-dbutils</artifactId>
      </dependency>
      <!--logging-->
        <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        </dependency>
        <!--mysql驱动-->
          <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          </dependency>
          <!--c3p0-->
            <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            </dependency>
          </dependencies>
          <!-- maven-servlet模块示例 -->
            <build>
              <plugins>
                <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                  <configuration>
                  <port>8088</port>
                  <path>/</path>
                  </configuration>
                </plugin>
              </plugins>
            </build>

3. 聚合与继承对比

特性聚合(Aggregation)继承(Inheritance)
核心作用统一构建子模块,控制构建顺序统一配置,复用依赖/插件版本
配置位置父工程 pom.xml<modules>子模块 pom.xml<parent>
依赖感知父工程知道所有子模块父工程不知道哪些子模块继承自己
打包要求父工程必须为 pom 打包子模块按功能为 jar/war 打包

三、属性与版本管理

1. 自定义属性:统一版本维护

在定义依赖的版本的时候,我们可以使用属性来描述,方便维护管理。
定义格式:
在这里插入图片描述
调用格式:
在这里插入图片描述
改造我们的父工程:

<properties>
<javax.servlet-api>3.1.0</javax.servlet-api>
<javax.servlet.jsp-api>2.3.1</javax.servlet.jsp-api>
<jstl>1.2</jstl>
<taglibs-standard-impl>1.2.5</taglibs-standard-impl>
<c3p0>0.9.1.2</c3p0>
<commons-beanutils>1.8.3</commons-beanutils>
<commons-dbutils>1.6</commons-dbutils>
<commons-logging>1.1.1</commons-logging>
<mysql>5.1.18</mysql>
</properties>

在pom.xml我们如下定义:
在这里插入图片描述

2. 版本管理

(1)版本类型
  • 快照版本(SNAPSHOT):开发中版本,如 1.0-SNAPSHOT,每次构建自动更新
  • 发布版本(RELEASE):稳定版本,如 1.0.RELEASE,发布后不再修改
测试

我们在maven-pojo上面自定义版本:
在这里插入图片描述
然后打包:
在这里插入图片描述
观察本地仓库:
在这里插入图片描述

(2)版本号规范(并不是所有的都严格遵循)

在这里插入图片描述

3. 配置文件引用 POM 属性

在配置文件中直接引用 POM 定义的属性,实现配置动态化:

(1)在maven-dao中定义属性:
<!-- maven-dao模块 -->
  <properties>
  <user.name>admin</user.name>
  <user.age>25</user.age>
  </properties>
(2)在maven-daouser.properties中加载这些属性值
user.name=${user.name}
user.age=${user.age}
(3)开启属性过滤(POM 配置)
<build>
  <resources>
    <resource>
      <!--从任意子模块的根目录开始加载,不管任何子模块都可以加载-->
      <directory>${project.basedir}/src/main/resources</directory>
        <!-- 开启配置属性的读取,取值false就不能读取 -->
        <filtering>true</filtering>
        </resource>
      </resources>
    </build>

打包后配置文件会自动替换为:user.name=adminuser.age=25

四、多环境配置

在实际开发中,生产环境的配置和开发环境的配置是不一样的。比如生产环境使用的数据库和开发环境的数据库就不一样。那么在项目由开发环境切换到生产环境的时候,配置应该如何更改?
在这里插入图片描述

在maven-dao中我们定义不同的数据库连接信息:

<profiles>
  <!--生产环境的数据库信息-->
    <profile>
      <!--环境名称,自定义-->
      <id>pro-env</id> <!--product-->
        <properties>
        <jdbc.url>jdbc:mysql://127.1.1.1:3306/ssm_db</jdbc.url>
        </properties>
      </profile>
      <!--开发环境的数据库信息-->
        <profile>
        <id>dev-env</id>  <!--develop-->
          <properties>
          <jdbc.url>jdbc:mysql://127.1.1.1:3308/ssm_db</jdbc.url>
          </properties>
        </profile>
      </profiles>

在properties文件中指定:

jdbc.url=${jdbc.url}

那么如何根据指定的开发环境进行运行呢:

格式: 指令 –P 环境名称

在这里插入图片描述
运行打包之后,我们在本地仓库看看配置信息:
在这里插入图片描述

五、Maven私服

 我们的项目都是协同开发的,并不是一个人开发所有的模块。如果每个人开发不同的模块,当我们需要别人的模块时,怎么获取?用硬盘拷贝吗?很显然不可取。
 应该怎么办? -> 可不可以把大家开发的模块都放在一个公共的服务器上,大家需要别人的模块时,只需要从这个公共的服务器去获取就可以。
在这里插入图片描述

Maven私服搭建(以Nexus为例)

1. 安装nexus(自行安装,跳过)
2. 私服资源获取

在这里插入图片描述
仓库的分类:
在这里插入图片描述

3. 登录私服后创建仓库

点击 sign in,输入指定的用户和密码登录之后,创建仓库:
在这里插入图片描述

在这里插入图片描述

点击创建仓库后,选择maven2(hosted),点击进入仓库
在这里插入图片描述
点击创建,创建之后:
在这里插入图片描述
将创建的仓库加入到仓库组里面来(添加到maven-public这个组),点击maven-public这个组,进入到添加页面:
在这里插入图片描述
在这里插入图片描述
添加后,点击保存

4. 向仓库上传资源

点击进入仓库后点击上传组件:
在这里插入图片描述
在这里插入图片描述
最后点击upload按钮,完成的效果:
在这里插入图片描述

IDEA环境中资源上传与下载

在这里插入图片描述

  • 配置maven客户端的settings配置文件
<!--配置访问xq-mixed的仓库名称、用户名、密码-->
  <server>
  <id>xq-mixed</id>
  <username>admin</username>
  <password>admin</password>
  </server>
  • 配置私服的地址(也是在maven的settings中)
<!--私服-->
  <mirror>
  <id>nexus-xq</id>  <!--(这个名字无所谓)-->
  <mirrorOf>*</mirrorOf>
  <url>http://localhost:8081/repository/maven-public/</url>
  </mirror>
  • 配置当前项目访问私服上传资源保存的位置(在pom.xml中配置)
<distributionManagement>
  <repository>
  <id>xq-mixed</id>
  <url>http://localhost:8081/repository/xq-mixed/</url>
  </repository>
</distributionManagement>
  • 发布资源到私服的命令 mvn deploy
    在这里插入图片描述
    查看控制台效果:
    在这里插入图片描述
    最后在私服上面查看是否上传成功:
    在这里插入图片描述

nexus代理阿里云仓库

为了提高资源的下载速度,我们也可以在nexus官方仓库中添加国内阿里云maven仓
库。具体操作如下:

  • 第一步:点击repositories
    在这里插入图片描述
  • 点击 create repository,选中maven(proxy)
    在这里插入图片描述
  • 设置阿里云
    阿里云仓库url:http://maven.aliyun.com/nexus/content/groups/public
    在这里插入图片描述
  • 将创建的仓库添加到仓库组maven-public,并把阿里云代理仓库设置为第一位
    在这里插入图片描述
  • 设置maven的setting.xml文件
<!-- 使用nexus 配置镜像 -->
  <mirror>
  <id>nexus-central</id>
  <mirrorOf>*</mirrorOf>
  <name>Nexus Central</name>
  <url>http://localhost:8081/repository/maven-public/</url>
  </mirror>

或者在项目的pom.xml里面指定仓库路径:

<repositories>
  <repository>
  <id>nexus-central</id>
  <name>nexus-central</name>
  <url>http://localhost:8081/repository/maven-public/</url>
    <releases>
    <enabled>true</enabled>
    </releases>
    <snapshots>
    <enabled>true</enabled>
    </snapshots>
  </repository>
</repositories>

作用:
配置后,所有依赖请求都会先发给我的 Nexus 私服:
✅ 私服里有缓存的依赖 → 直接从私服下载(局域网速度,毫秒级);
✅ 私服里没有的依赖 → 私服自动从阿里云 / 中央仓库下载并缓存,后续团队所有人再用都不用重复下载


如果我的内容对你有帮助,请 点赞 评论 收藏 。创作不易,大家的支持就是我坚持下去的动力!
在这里插入图片描述

posted @ 2026-02-13 17:16  gccbuaa  阅读(4)  评论(0)    收藏  举报