Maven02

1.Maven 的传递依赖

  • 1.1 什么是传递依赖
    • 当 A 依赖 B、B 依赖 C,在 A 中导入 B 后会自动导入 C,C 是 A 的传递依赖,如果 C
      依赖 D 则 D 也可能是 A 的传递依赖。
  • 1.2 依赖版本冲突解决
    • 1.2.1 什么是依赖版本冲突

      • 当一个项目依赖的构件比较多时,它们相互之前存在依赖,当你需要对依赖版本统一管理时如果让 maven 自动来处理可能并不能如你所愿。
    • 1.2.2 依赖调解原则

      • maven 自动按照下边的原则调解:
        • 1、第一声明者优先原则
          • 在 pom 文件定义依赖,先声明的依赖为准。
        • 2、路径近者优先原则
          • 例如:A 依赖 spirng-beans-4.2.4,A 依赖 B 依赖 spirng-beans-3.0.5,则 spring-beans-4.2.4 优 先 被 依 赖 在 A 中 , 因 为 spring-beans-4.2.4 相 对 spirng-beans-3.0.5 被 A 依赖的路径最近。
    • 1.2.3 排除依赖

      • 依赖版本冲突的问题可以通过排除依赖的方式来解决,将传递依赖中不合理的依赖排除,使用合理的依赖来构建我们的工程。
      • 排除依赖可以在依赖的配置 dependency 中使用 exclusion 标签来进行排除操作。
    • 1.2.4 锁定版本

      • 面对众多的依赖,有一种方法不用考虑依赖路径、声明优化等因素可以采用直接锁定版本的方法确定依赖构件的版本,版本锁定后则不考虑依赖的声明顺序或依赖的路径,以锁定的版本的为准添加到工程中,此方法在企业开发中常用。锁定依赖的版本可以使用 dependencyManagement 标签来设置。
      • 需要注意的是在工程中锁定依赖的版本并不代表在工程中添加了依赖,如果工程需要添加锁定版本的依赖则需要单独添加标签。

2.分模块构建工程

  • 基于上边的三个工程分析,我们将持久层,业务层、控制器和视图表现层可以分为三个
    不同的模块来处理,创建一个 parent 工程将通用的 pom 配置抽取出来,然后聚合多个模块
    运行。

  • 2.1 需求
    • 2.1.1 需求描述
      • 将 工程拆分为多个模块开发:
        • Dao 模块
        • Service 模块
        • Web 模块
    • 2.1.2 理解继承和聚合
      • 通常继承和聚合同时使用。
      • 何为继承?
        • 继承是为了消除重复,如果将 dao、service、web 分开创建独立的工程则每个工程的 pom.xml 文件中的内容存在重复,如设置编译版本、锁定 spring 的版本的等,可以将这些重复的配置提取出来在父工程的 pom.xml 中定义
      • 何为聚合?
        • 开发通常是分组分模块开发,每个模块开发完成要运行整个工程需要将每个模块聚合在一起运行,比如:dao、service、web 三个工程最终会打一个独立的 war 运行。
  • 2.2 实例实现
    • 创建父工程,new–>project…–>maven–>由于是父工程,所以不需要选择create来点击某一项。
    • 右击父工程,new–>Module–>如果是web子模块,则选择wabapp来进行创建,其余选择quickStart来创建。
    • 注意:
      • 子模块目录结构为:不可少目录结构,否则会找不到,这里因为少了java目录报错
      • web
        • scr
          • main
            • java
            • resources
              • com.yiran.servlet
            • webapp(web子模块独有)
          • test
        • target
        • pom.xml

Maven02

Maven02

  • 2.3 父工程的pom.xml配置
<?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.yiran</groupId>
    <artifactId>eBuy-parent</artifactId>
    <!-- 父工程的包装类型为pom,webapp模块为war,其余都为jar -->
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <!-- 其子模块有 -->
    <modules>
        <module>eBuy-dao</module>
        <module>eBuy-service</module>
        <module>eBuy-pojo</module>
        <module>eBuy-utils</module>
        <module>eBuy-web</module>
    </modules>


    <!-- 按模块开发,不点击create创建项目,作为父项目。指定使用版本 -->
    <properties>
        <servlet-version>3.1.0</servlet-version>
        <jsp-version>2.0</jsp-version>
        <jstl-version>1.2</jstl-version>
        <druid-version>1.1.10</druid-version>
        <junit-version>4.10</junit-version>
        <mysql-version>5.1.6</mysql-version>
    </properties>

    <!-- 公用依赖定义 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <!-- 这里类似于el表达式 -->
                <version>${servlet-version}</version>
                <!-- 设置依赖范围,防止使用服务器插件时和服务器插件中的包冲突报错 -->
                <scope>provided</scope>
            </dependency>

            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jsp-api</artifactId>
                <version>${jsp-version}</version>
                <scope>provided</scope>
                <exclusions>
                    <exclusion>
                        <groupId>javax.servlet</groupId>
                        <artifactId>javax.servlet-api</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>

            <dependency>
                <groupId>javax.servlet.jsp.jstl</groupId>
                <artifactId>jstl</artifactId>
                <version>${jstl-version}</version>
            </dependency>

            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit-version}</version>
            </dependency>

            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql-version}</version>
                <!-- 数据库 runtime时使用 -->
                <scope>runtime</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <!-- 打包工程名 -->
        <finalName>eBuy-parent</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>

                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version>
                    <configuration>
                        <!-- 可以灵活配置工程路径 -->
                        <path>/maven01</path>
                        <!-- 可以灵活配置端口号 -->
                        <port>8080</port>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>
  • 2.4 子模块如何依赖其他子模块和继承父模块pom.xml
<?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>eBuy-parent</artifactId>
        <groupId>com.yiran</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eBuy-web</artifactId>
    <!-- webapp是war 其余的为jar -->
    <packaging>war</packaging>

    <name>eBuy-web Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- 依赖其他模块,和依赖父工程的包 -->
        <dependency>
            <groupId>com.yiran</groupId>
            <artifactId>eBuy-service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>com.yiran</groupId>
            <artifactId>eBuy-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <scope>provided</scope>
            <exclusions>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>


        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

    </dependencies>

    <build>
        <finalName>eBuy-web</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->

                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version>
                    <configuration>
                        <!-- 可以灵活配置工程路径 -->
                        <path>/web</path>
                        <!-- 可以灵活配置端口号 -->
                        <port>8080</port>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

  • 2.5 遇到的一些问题解决
    • webapp无法创建servlet,maven projects中为灰色
    • 服务器能够启动,页面500,无法解析jsp
      • webapp中pom.xml 的jsp依赖和服务器中的jsp包冲突,修改scope为provided即可
    • servlet无法访问,404报错
      • webapp中main目录下少了一层java目录结构。

3.私服

  • 正式开发,不同的项目组开发不同的工程。dao 工程开发完毕,发布到私服。service 从
    私服下载 dao。

  • 公司在自己的局域网内搭建自己的远程仓库服务器,称为私服,私服服务器即是公司内
    部的 maven 远程仓库,每个员工的电脑上安装 maven 软件并且连接私服服务器,员工将自
    己开发的项目打成 jar 并发布到私服服务器,其它项目组从私服服务器下载所依赖的构件
    (jar)。 私服还充当一个代理服务器,当私服上没有 jar 包会从互联网中央仓库自动下载

  • 3.1 搭建私服环境
  • 3.1.1 下载 nexus
    • Nexus 是 Maven 仓库管理器,通过 nexus 可以搭建 maven 仓库,同时 nexus 还提供强大的仓库管理功能,构件搜索功能等。
    • 下载 Nexus, 下载地址:http://www.sonatype.org/nexus/archived/
  • 3.1.2 安装 nexus
    • 解压 nexus-2.12.0-01-bundle.zip,进入 bin 目录:
    • cmd执行 nexus.bat install
    • 安装完成,可以在服务中查看
  • 3.1.3 卸载 nexus
    • cmd 进入 nexus 的 bin 目录,执行:nexus.bat uninstall
    • 查看 window 服务列表 nexus 已被删除。
  • 3.1.4 启动 nexus
    • 方法 1:
      • cmd 进入 bin 目录,执行 nexus.bat start
    • 方法 2:
      • 直接启动 nexus 服务
    • 查看 nexus 的配置文件 conf/nexus.properties
    # Jetty section
    application-port=8081 # nexus 的访问端口配置
    application-host=0.0.0.0 # nexus 主机监听配置(不用修改)
    nexus-webapp=${bundleBasedir}/nexus # nexus 工程目录
    nexus-webapp-context-path=/nexus  # nexus 的 web 访问路径
    # Nexus section
    nexus-work=${bundleBasedir}/../sonatype-work/nexus # nexus 仓库目录
    runtime=${bundleBasedir}/nexus/WEB-INF # nexus 运行程序目录
    访问:
    http://localhost:8081/nexus/
    
    • 使用 Nexus 内置账户 admin/admin123 登陆:
    • 点击右上角的 Log in,输入账号和密码 登陆
  • 3.1.5 仓库类别
      1. hosted,宿主仓库,部署自己的 jar 到这个类型的仓库,包括 releases 和 snapshot 两部分,Releases 公司内部发布版本仓库、 Snapshots 公司内部测试版本仓库
      1. proxy,代理仓库,用于代理远程的公共仓库,如 maven 中央仓库,用户连接私服,私服自动去中央仓库下载 jar 包或者插件。
      1. group,仓库组,用来合并多个 hosted/proxy 仓库,通常我们配置自己的 maven 连接仓库组。
      1. virtual(虚拟):兼容 Maven1 版本的 jar 或者插件 nexus 仓库默认在 sonatype-work 目录中:
    • central:代理仓库,代理中央仓库
    • apache-snapshots :代理仓库 存储 snapshots 构件,代理地址 https://repository.apache.org/snapshots/
    • central-m1 :virtual 类型仓库,兼容 Maven1 版本的 jar 或者插件
    • releases :本地仓库,存储 releases 构件。
    • snapshots :本地仓库,存储 snapshots 构件。
    • thirdparty :第三方仓库
    • public :仓库组
  • 3.2 将项目发布到私服
  • 3.2.1 需求
    • 企业中多个团队协作开发通常会将一些公用的组件、开发模块等发布到私服供其它团队或模块开发人员使用。
    • 本例子假设多团队分别开发 dao、service、web,某个团队开发完在 dao 会将 dao 发布到私服供 service 团队使用,本例子会将 dao 工程打成 jar 包发布到私服。
  • 3.2.2 配置
    • 第一步: 需要在客户端即部署 dao 工程的电脑上配置 maven 环境,并修改 settings.xml 文件,配置连接私服的用户和密码 。
    • 此用户名和密码用于私服校验,因为私服需要知道上传都 的账号和密码 是否和私服中的账号和密码 一致。
      <server>
          <id>releases</id>
          <username>admin</username>
          <password>admin123</password>
      </server>
      <server>
          <id>snapshots</id>
          <username>admin</username>
          <password>admin123</password>
      </server>
      
      • releases 连接发布版本项目仓库
      • snapshots 连接测试版本项目仓库
    • 第二步: 配置项目 pom.xml
    • 配置私服仓库的地址,本公司的自己的 jar 包会上传到私服的宿主仓库,根据工程的版本号决定上传到哪个宿主仓库,如果版本为 release 则上传到私服的 release 仓库,如果版本为 snapshot 则上传到私服的 snapshot 仓库
      <distributionManagement>
          <repository>
              <id>releases</id>
              <url>http://localhost:8081/nexus/content/repositories/releases/</url>
          </repository>
          <snapshotRepository>
              <id>snapshots</id>
              <url>http://localhost:8081/nexus/content/repositories/snapshots/</url>
          </snapshotRepository>
      </distributionManagement>
      
      • 注意:pom.xml 这里 和 settings.xml 配置 对应!
  • 3.2.3 测试
    • 将项目 dao 工程打成 jar 包发布到私服:
    • 1、首先启动 nexus
    • 2、对 dao 工程执行 deploy 命令
      • 根据本项目pom.xml中version定义决定发布到哪个仓库,如果version定义为snapshot,执行deploy后查看nexus的snapshot仓库,如果version定义为release则项目将发布到nexus的 release 仓库
  • 3.3 从私服下载 jar 包
  • 3.3.1 需求
    • 没有配置 nexus 之前,如果本地仓库没有,去中央仓库下载,通常在企业中会在局域网内部署一台私服服务器,有了私服本地项目首先去本地仓库找 jar,如果没有找到则连接私服从私服下载 jar 包,如果私服没有 jar 包私服同时作为代理服务器从中央仓库下载 jar 包,这样做的好处是一方面由私服对公司项目的依赖 jar 包统一管理,一方面提高下载速度,项目连接私服下载 jar 包的速度要比项目连接中央仓库的速度快的多。
  • 3.3.2 管理仓库组
    • nexus中包括很多仓库,hosted中存放的是企业自己发布的jar包及第三方公司的jar包,proxy 中存放的是中央仓库的 jar,为了方便从私服下载 jar 包可以将多个仓库组成一个仓库组,每个工程需要连接私服的仓库组下载 jar 包。
    • 将右边的"Avaiable Repositories"中的仓库拖到左边的"Ordered Group Repository"中形成仓库组
  • 3.3.3 在 setting.xml 中配置仓库
    • 在客户端的 setting.xml 中配置私服的仓库,由于 setting.xml 中没有 repositories 的配置标签需要使用 profile 定义仓库。
    <profile>
        <!--profile 的 id-->
        <id>dev</id>
        <repositories>
            <repository>
                <!--仓库 id,repositories 可以配置多个仓库,保证 id 不重复-->
                <id>nexus</id>
                <!--仓库地址,即 nexus 仓库组的地址-->
                <url>http://localhost:8081/nexus/content/groups/public/</url>
                <!--是否下载 releases 构件-->
                <releases>
                <enabled>true</enabled>
                </releases>
                <!--是否下载 snapshots 构件-->
                <snapshots>
                <enabled>true</enabled>
                </snapshots>
            </repository>
        </repositories>
        <pluginRepositories>
            <!-- 插件仓库,maven 的运行依赖插件,也需要从私服下载插件 -->
            <pluginRepository>
                <!-- 插件仓库的 id 不允许重复,如果重复后边配置会覆盖前边 -->
                <id>public</id>
                <name>Public Repositories</name>
                <url>http://localhost:8081/nexus/content/groups/public/</url>
            </pluginRepository>
        </pluginRepositories>
    </profile>
    
    • 使用 profile 定义仓库需要**才可生效。
    <activeProfiles>
        <activeProfile>dev</activeProfile>
    </activeProfiles>
    
    • 配置成功后通过 eclipse 查看有效 pom,有效 pom 是 maven 软件最终使用的 pom 内容,程序员不直接编辑有效 pom,打开有效 pom
    • 下边的 pom 内容中有两个仓库地址,maven 会先从前边的仓库的找,如果找不到 jar 包再从下边的找,从而就实现了从私服下载 jar 包。
    <repositories>
        <repository>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
                <id>public</id>
                <name>Public Repositories</name>
                <url>http://localhost:8081/nexus/content/groups/public/</url>
        </repository>
        <repository>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>central</id>
            <name>Central Repository</name>
            <url>https://repo.maven.apache.org/maven2</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>Public Repositories</name>
            <url>http://localhost:8081/nexus/content/groups/public/</url>
        </pluginRepository>
        <pluginRepository>
            <releases>
                <updatePolicy>never</updatePolicy>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>central</id>
            <name>Central Repository</name>
            <url>https://repo.maven.apache.org/maven2</url>
        </pluginRepository>
    </pluginRepositories>
    
  • 3.1 install命令和deploy命令
    • install命令 – 下载到本地
    • deploy命令 – 下载到本地并部署到私服(私服要自己设置)