1. Maven 基础

  • Maven 是一个项目管理工具,它包含了一个 项目对象模型 (POM:Project Object Model),一组标准集合,一个项目生命周期 (Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。

  • Maven 可以解决的问题:

    • jar 包管理
    • Java 文件编译
    • 单元测试
    • 项目打包
  • Maven 的依赖管理:maven 工程中不直接将 jar 包导入到工程中,而是通过在 pom.xml 文件中添加所需 jar
    包的坐标,这样就很好的避免了 jar 直接引入进来,在需要用到 jar 包的时候,只要查找 pom.xml 文件,再通过 pom.xml 文件中的坐标,到一个专门用于”存放 jar 包的仓库”(maven 仓库)中根据坐标从而找到这些 jar 包,再把这些 jar 包拿去运行。

  • 项目的一键构建:

    • 项目从编译、测试、运行、打包、安装 ,部署整个过程都交给 maven 进行管理,这个过程称为构建。
    • 一键构建:指的是整个构建过程,使用一个 maven 命令就可以轻松完成整个工作。
  • Maven 仓库

    • 本地仓库:用来存储从远程仓库或中央仓库下载的插件和 jar 包,项目使用的一些插件或 jar 包,
      优先从本地仓库查找,默认本地仓库位置在 {user.dir}/.m2/repository,{user.dir}表示 windows 用户目录。
    • 远程仓库:如果本地需要插件或者 jar 包,本地仓库没有,默认去远程仓库下载。远程仓库可以在互联网内也可以在局域网内。
    • 中央仓库 :在 maven 软件中内置一个远程仓库地址 http://repo1.maven.org/maven2 ,它是中央仓库,服务于整个互联网,它是由 Maven 团队自己维护,里面存储了非常全的 jar 包,它包含了世界上大部分流行的开源项目构件。
  • 全局 setting 与用户 setting

    maven 仓库地址、私服等配置信息需要在 setting.xml 文件中配置,分为全局配置和用户配置。
    在 maven 安装目录下的有 conf/setting.xml 文件,此 setting.xml 文件用于 maven 的所有 project
    项目,它作为 maven 的全局配置。
    如需要个性配置则需要在用户配置中设置,用户配置的 setting.xml 文件默认的位置在:${user.dir}
    /.m2/settings.xml 目录中,${user.dir} 指 windows 中的用户目录。
    maven 会先找用户配置,如果找到则以用户配置文件为准,否则使用全局配置文件。

  • Maven 工程的目录结构

    • 如果是普通的 Java 项目,那么就没有 webapp 目录。
  • mvn 命令

    • tomcat:run :进入 maven 工程目录(当前目录有 pom.xml 文件),运行 tomcat:run 命令。会部署项目并给出访问地址。
    • clean:clean 是 maven 工程的清理命令,执行 clean 会删除 target 目录及内容,清理编译信息。
    • validate: 验证工程是否正确,所有需要的资源是否可用。
    • compile:compile 是 maven 工程的编译命令,作用是将 src/main/java 下的文件编译为 class 文件输出到 target 目录下。
    • test:test 是 maven 工程的测试命令 mvn test,会执行 src/test/java 下的单元测试类。此命令执行时会自动执行 compile 命令。
    • package:package 是 maven 工程的打包命令,对于 Java 工程执行 package 打成 jar 包,对于 Web 工程打成 war 包。此命令会自动执行 compile 和 test 命令。(常用)
    • verify
    • install:install 是 maven 工程的安装命令,执行 install 将 maven 打成 jar 包或 war 包发布到本地仓库。此命令会执行 compile,test,package 命令。
    • site
    • deploy:部署,运行此命令前需要先配置,会先执行 compile、test、package、install。参考:maven命令deploy使用
  • maven 生命周期

    • maven 有三个生命周期,清理生命周期,默认生命周期,站点生命周期。
  • maven 概念模型图

  • IDEA → Settings → Maven → Runner → VM Options:-DarchetypeCatalog=internal,此参数确保不联网的情况下 IDEA 也能创建 Maven 工程。

  • 使用 IDEA 提供的骨架创建 Maven 的 Java 工程,maven-archetype-quickstart

    • 如需要,在 main 目录下手动创建 resources 目录,并标记为资源文件夹。
  • 不使用骨架的时候会创建一个跟 maven 的 Java 工程标准目录的工程,包括 resources,推荐不使用骨架创建 maven 的 Java 工程。

  • 使用 IDEA 提供的骨架创建 Maven 的 Web 工程,maven-archetype-webapp

    • 需要在 main 下创建 Java 目录,并标记为 Sources Root
    • Project Structs → model → Source Root 的对勾勾上
  • 如在 pom.xml 中需要查找 jar 包的版本信息,去 maven 中央仓库,官方有每个版本的配置信息,贴过来会自动开始下载。

  • 可以点击这个图标输入命令,比如 tomcat:run

  • tomcat:run 运行项目的时候,Tomcat 插件所用的 jar 包与 pom.xml 中配置的 jar 冲突(servlet 需要用此包,所以配置),此时,可以用 scope 标签配置 pom 中 jar 包的作用域为 provided,表示只在写代码的时候起作用。

  • Junit 作用域改为 test

  • maven 内置 Tomcat 插件为 6.0 版本,不支持 jdk8,需要改为 tomcat7,运行命令是 tomcat7:run

    <plugin>
      <groupId>org.apache.tomcat.maven</groupId>
      <artifactId>tomcat7-maven-plugin</artifactId>
      <version>2.2</version>
    </plugin>
    
  • 自定义模板:settings → Live Templates,定义完以后需要添加要在什么文件使用,可以自定义上述模板。

  • maven 调试:运行配置 → 添加 Maven →填写运行命令

    然后就可以运行和调试了。

  • pom 基本配置:

    • <project > :文件的根节点 .
    • <modelversion > : pom.xml 使用的对象模型版本
    • <groupId > :组织名称 + 项目名称
    • <artifactId > :模块名称,子项目名或模块名称
    • <version > :产品的版本号 ,snapshot 为快照版本即非正式版本,release 为正式发布版本。
    • <packaging > :打包类型,一般有 jar、war、pom 等
    • <name > :项目的显示名,常用于 Maven 生成的文档。
    • <description > :项目描述,常用于 Maven 生成的文档。
    • <dependencies> :项目依赖构件配置,配置项目依赖构件的坐标
    • <build> :项目构建配置,配置编译、运行插件等。
  • 依赖范围:

    • compile:编译范围,指 A 在编译时依赖 B,此范围为默认依赖范围。编译范围的依赖会用在
      编译、测试、运行,由于运行时需要所以编译范围的依赖会被打包。
    • provided:provided 依赖只有在当 JDK 或者一个容器已提供该依赖之后才使用, provided 依
      赖在编译和测试时需要,在运行时不需要,比如:servlet API 被 Tomcat 容器提供。
    • runtime:runtime 依赖在运行和测试系统的时候需要,但在编译的时候不需要。比如:JDBC
      的驱动包。由于运行时需要所以 runtime 范围的依赖会被打包。
    • test:test 范围依赖 在编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用,
      比如:junit。由于运行时不需要所以 test 范围依赖不会被打包。
    • system:system 范围依赖与 provided 类似,但是你必须显式的提供一个对于本地系统中 JAR
      文件的路径,需要指定 systemPath 磁盘路径,system 依赖不推荐使用。
  • 热部署:maven+tomcat 插件 +Jrebel 实现热部署:Jrebel 启动项目,改变类以后,Ctrl+f9 构建项目,触发 Jrebel 重新加载,直接刷新网页即可。

  • 关于 target 目录,maven 运行时的目录结构。

    • target 用于存放编译、打包后的输出文件,tomcat 的配置也在这里面。
    • 对于静态资源,运行时并不放入target 目录,而是还在webapp 目录下,运行时直接访问 webapp 下的静态资源文件。(tomcat插件运行项目,不重启服务器,修改静态资源,没有缓存的情况下,可以加载,说明直接访问,不需要重新部署静态文件)
    • 对于 JSP 文件,则将编译后的文件放置在 target\tomcat\work 目录下。

2. maven 基础回顾

maven 是一个项目管理工具。

  • 依赖管理:maven 对项目中 jar 包的管理过程。传统工程我们直接把 jar 包放置在项目中。maven 工程真正的 jar 包放置在仓库中,项目中只用放置 jar 包的坐标。
  • 一键构建:maven 自身集成了 tomcat 插件,可以对项目进行编译,测试,打包,安装,发布等操作。

仓库的种类:本地仓库,远程仓库【私服】,中央仓库。

3. Jar 包冲突的解决

直接依赖:项目中直接导入的 jar 包,就是该项目的直接依赖包。

依赖传递:当我们导入 jar 包的时候,会把这个 jar 依赖的 jar 包也导入进来。

jar 包冲突:当所依赖的 jar 包是同一个,但版本不同的时候,就出现了 jar 包冲突。

解决 jar 包冲突的方式

第一声明者优先原则:两个依赖传递导入的 jar 包,谁先声明,项目使用谁。

路径近者优先原则:直接依赖比传递依赖优先。

排除依赖:

<dependency>
  <groupId>org. springframework</groupId> 
  <artifactId>spring-beans</artifactId> 
  <version>4.2.4.RELEASE</version>
  <exclusions>
    <exclusion>
      <groupId>org. springframework</groupId> 
      <artifactId>spring-core</artifactId> 
    </exclusion>
  </exclusions>
</dependency>

锁定版本

为了防止 jar 包冲突,我们常常使用锁定版本的方法,来防止 jar 包冲突。

<properties>
  <spring.version>5.0.2.RELEASE</spring-version> 
</properties>

<dependencyManagement>
  <dependencies>
      <!-- 这里锁定版本为5.0.2.RELEASE -->
      <dependency>
        <groupld>org.springframework</groupId> 
        <artifactId>spring-beans</artifactId> 
        <version>${spring.version}</version> 
      </dependency>
  </dependencies>
</dependencyManagement>

在工程中锁定依赖的版本并不代表在工程中添加了依赖,如果工程需要添加锁定版本的依赖则需要单独添加dependencies 标签,如下:

<dependencies>
  <dependency>
    <groupld>org.springframework</groupId> 
    <artifactId>spring-beans</artifactId> 
  </dependency>
</dependencies>

上边添加的依赖并没有指定版本,原因是已在 dependencyManagement 中锁定了版本,所以在 dependency 下不需要再指定版本。

maven 工程是可以分父子依赖关系的。

凡是依赖别的项目后,拿到的别的项目的依赖包,都属于传递依赖。

比如:当前 A 项目,被 B 项目依赖。那么我们 A 项目中所有 jar 包都会传递到项目中。
B 项目开发者,如果再在 B 项目中导入一套 ssm 框架的 jar 包,对于 B 项目是直接依赖。
那么直接依赖的 jar 包就会把我们 A 项目传递过去的 jar 包覆盖掉。

为了防止以上情况的出现。我们可以把 A 项目中主要 jar 包的坐标锁住,那么其他依赖该项目的项目中,即便是有同名 jar 包直接依赖,也无法覆盖。

4. 拆分与聚合的思想

maven 解决代码可重用和便于维护问题上是这么解决的:

maven 把一个完整的项目,分成不同的独立模块,这些模块都有各自独立的坐标。哪个地方需要其中某个模块,就直接引用该模块的坐标即可。

今后如果公司开发一个新项目,我们先考虑问题不是 dao,service,utils,domain 如何编写,我们要考虑的是,dao,service,utils,domain 这些模块是否已经存在,如果存在直接引用。这就是maven拆分的思想。

我们可以把拆分零散的模块聚合到一起编写一个完整的项目,这就是 maven 聚合思想。

工程和模块的区别:

工程不等于完整的项目,模块也不等于完整的项目,一个完整的项目看的是代码,代码完整,就可以说这是一个完整的项目和此项目是工程和模块没有关系。

工程天生只能使用自己内部资源,工程天生是独立的。后天可以和其他工程或模块建立关联关系。模块天生不是独立的,模块天生是属于父工程的,模块一旦创建,所有父工程的资源都可以使用。

父子工程之间,子模块天生集成父工程,可以使用父工程所有资源。子模块之间天生是没有任何关系的。

父子工程之间不用建立关系,继承关系是先天的,不需要手动建立。

平级直接的引用叫依赖,依赖不是先天的,依赖是需要后天建立的。

// 父工程
<groupId>com.itheima</groupId>
<artifactId>maven_parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
    <module>maven_day02_dao</module>
    <module>maven_day02_service</module>
    <module>maven_day02_web</module>
</modules>

// 子工程之间依赖
// service 层引用 dao 层
<dependencies>
    <dependency>
        <groupId>com.itheima</groupId>
        <artifactId>maven_dao</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>
// web 层引用 service 层
<dependencies>
    <dependency>
        <groupId>com.itheima</groupId>
        <artifactId>maven_service</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

传递依赖的包是否能用

image.png

实际开发中,如果传递依赖丢失,表现形式就是 jar 包的坐标导不进去,我们的做法就是直接再导入一次。

模块之间的相互引用

配置好模块之间的相互依赖之后。

maven_dao 模块中 /resources/spring/applicationContext-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
			    http://www.springframework.org/schema/beans/spring-beans.xsd
			    http://www.springframework.org/schema/context
			    http://www.springframework.org/schema/context/spring-context.xsd
			    http://www.springframework.org/schema/aop
			    http://www.springframework.org/schema/aop/spring-aop.xsd
			    http://www.springframework.org/schema/tx
			    http://www.springframework.org/schema/tx/spring-tx.xsd
			    http://www.springframework.org/schema/mvc
			    http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--dao层配置文件开始-->
    <!--配置连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///maven"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <!--配置生产SqlSession对象的工厂-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--扫描pojo包,给包下所有pojo对象起别名-->
        <property name="typeAliasesPackage" value="com.itheima.domain"/>
    </bean>

    <!--扫描接口包路径,生成包下所有接口的代理对象,并且放入spring容器中-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.itheima.dao"/>
    </bean>
    <!--dao层配置文件结束-->

</beans>

maven_service 模块中 /resources/spring/applicationContext-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
			    http://www.springframework.org/schema/beans/spring-beans.xsd
			    http://www.springframework.org/schema/context
			    http://www.springframework.org/schema/context/spring-context.xsd
			    http://www.springframework.org/schema/aop
			    http://www.springframework.org/schema/aop/spring-aop.xsd
			    http://www.springframework.org/schema/tx
			    http://www.springframework.org/schema/tx/spring-tx.xsd
			    http://www.springframework.org/schema/mvc
			    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--service层配置文件开始-->

    <!--组件扫描配置-->
    <context:component-scan base-package="com.itheima.service"/>

    <!--aop面向切面编程,切面就是切入点和通知的组合-->
    <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--配置事务的通知-->
    <tx:advice id="advice">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!--配置切面-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.itheima.service.impl.*.*(..))"/>
        <aop:advisor advice-ref="advice" pointcut-ref="pointcut"/>
    </aop:config>
    <!--service层配置文件结束-->
</beans>

maven_web 模块中 /resources/spring/applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
			    http://www.springframework.org/schema/beans/spring-beans.xsd
			    http://www.springframework.org/schema/context
			    http://www.springframework.org/schema/context/spring-context.xsd
			    http://www.springframework.org/schema/aop
			    http://www.springframework.org/schema/aop/spring-aop.xsd
			    http://www.springframework.org/schema/tx
			    http://www.springframework.org/schema/tx/spring-tx.xsd
			    http://www.springframework.org/schema/mvc
			    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <import resource="classpath:spring/applicationContext-dao.xml"/>
    <import resource="classpath:spring/applicationContext-service.xml"/>
</beans>

mave_web 模块中 web.xml 文件

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

  <!--编码过滤器-->
  <filter>
    <filter-name>encoding</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>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!--配置spring核心监听器-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!--重新指定spring配置文件的路径-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>

  <!--springmvc的核心servlet-->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

可见,maven 可以将零散的模块聚合在一起。

5. 私服【远程仓库】

5.1 搭建私服环境

安装 Nexus,Nexus 是 Maven 仓库管理器,通过 nexus 可以搭建 maven 仓库,同时 nexus 还提供强大的仓库管理功能,构件搜索功能等。

nexus 的仓库有 4 种类型

  • hosted,宿主仓库,部署自己的 jar 到这个类型的仓库,包括 releases 和 snapshot 两部分,Releases 公司内部发布版本仓库、 Snapshots 公司内部测试版本仓库
  • proxy,代理仓库,用于代理远程的公共仓库,如 maven 中央仓库,用户连接私服,私服自动去中央仓库下载 jar 包或者插件。
  • group,仓库组,用来合并多个 hosted/proxy 仓库,通常我们配置自己的 maven 连接仓库组。
  • virtual(虚拟):兼容 Maven1 版本的 jar 或者插件

5.2 将 jar 包发布到私服

  1. 配置 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>
    
  2. 配置项目 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 这里 id 和 settings.xml 配置 id 对应

5.3 从私服下载 jar 包

管理项目组

nexus 中包括很多仓库,hosted 中存放的是企业自己发布的 jar 包及第三方公司的 jar 包,proxy 中存放的是中央仓库的 jar,为了方便从私服下载 jar 包可以将多个仓库组成一个仓库组 (group),每个工程需要连接私服的仓库组下载 jar 包。

在 settings.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>

6. 如何安装第三方jar包

6.1 导入到本地库

先 CMD进入到 jar 包所在位置,运行

mvn install:install-file -DgroupId=com.alibaba -DartifactId=fastjson -Dversion=1.1.37 -Dfile= fastjson-1.1.37.jar -Dpackaging=jar

6.2 导入到私服

需要在 maven 软件的核心配置文件 settings.xml 中配置第三方仓库的 server 信息

<server> 
  <id>thirdparty</id> 
  <username>admin</username>
  <password>admin123</password> 
</server>

才能执行一下命令

mvn deploy:deploy-file -DgroupId=com.alibaba -DartifactId=fastjson -Dversion=1.1.37 
-Dpackaging=jar -Dfile=fastjson-1.1.37.jar 
-Durl=http://localhost:8081/nexus/content/repositories/thirdparty/ 
-DrepositoryId=thirdparty

参数说明

  • DgroupId 和 DartifactId 构成了该 jar 包在 pom.xml 的坐标,项目就是依靠这两个属性定位。

自己起名字也行。

  • Dfile 表示需要上传的 jar 包的绝对路径。
  • Durl 私服上仓库的位置,打开 nexus -> repositories 菜单,可以看到该路径。
  • DrepositoryId 服务器的表示 id,在 nexus 的 configuration 可以看到。
  • Dversion 表示版本信息,

关于 jar 包准确的版本

包的名字上一般会带版本号,如果没有那可以解压该包,会发现一个叫 MANIFEST.MF 的文件,这个文件就有描述该包的版本信息。

比如 Specification-Version: 2.2 可以知道该包的版本了。

上传成功后,在 nexus 界面点击 3rd party 仓库可以看到这包。

7. 问题汇总

7.1 多模块项目 install 错误

多模块项目:
image-20211214190834421

mall-security 依赖 mall-common , maven intsall 将 mall-common 安装至本地仓库后,对 mall-security 进行 mvn install, 报错

Failed to execute goal on project     Could not resolve dependencies for projec

解决方案

先对父项目 进行 install, 再对子模块 install

8. mvnw

参考文档:
.mvn目录&mvnw和mvnw.cmd文件说明
Maven Wrapper

问题:使用 IDEA 自动构建的 springboot 项目目录下有 .mvn 目录和 mvnw、mvnw.cmd 文件,它们的作用是什么?

我们使用 Maven 时,基本上只会用到 mvn 这一个命令。有些童鞋可能听说过 mvnw,这个是啥?

mvnw是 Maven Wrapper 的缩写。因为我们安装 Maven 时,默认情况下,系统所有项目都会使用全局安装的这个 Maven 版本。但是,对于某些项目来说,它可能必须使用某个特定的 Maven 版本,这个时候,就可以使用 Maven Wrapper,它可以负责给这个特定的项目安装指定版本的 Maven,而其他项目不受影响。

简单地说,Maven Wrapper 就是给一个项目提供一个独立的,指定版本的 Maven 给它使用。

安装 Maven Wrapper

运行

mvn wrapper:wrapper
# 指定或更改 maven 版本号
mvn wrapper:wrapper -Dmaven=3.5.4

安装后目录如下

my-project
├── .mvn
│   └── wrapper
│       ├── MavenWrapperDownloader.java
│       ├── maven-wrapper.jar
│       └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   └── resources
    └── test
        ├── java
        └── resources

发现多了 mvnw、mvnw.cmd 和 .mvn 目录,我们只需要把 mvn 命令改成 mvnw 就可以使用跟项目关联的 Maven

9. mvn 命令

mvn 命令列表如下:

# 生命周期命令
mvn clean
mvn validate
mvn compile
mvn test
mvn package
mvn verify
mvn install
mvn site
mvn deploy
# 插件命名,插件:goal 格式
mvn clean:clean
mvn clean:help

mvn compiler:compile
mvn compiler:help
mvn compiler:testCompile

mvn jar:help
mvn jar:jar
mvn jar:test-jar
  • 只列举部分,插件命令使用格式 mvn 插件名:goal

10. pom 文件

pom 文件

11. Maven 多继承

参考 maven工程中的多继承

单继承

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.3.3.RELEASE</version>
</parent>

多继承

<dependencyManagement>
    <dependencies>
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.2.2.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Hoxton.SR1</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
</dependencyManagement>
  • pom:依赖类型,默认类型是 jar,它通常表示依赖的文件扩展名,这里使用的是 pom 表示导入的是父模块。
  • import:代表把父模块中的 jar 包导入进来,这种方式只能用在 <dependencyManagement></dependencyManagement> 中。

有无 import 区别

  1. import 只能用在 dependencyManagement 块中,它将 spring-boot-dependencies 中 dependencyManagement 下的 dependencies 插入到当前工程的 dependencyManagement 中,所以不存在依赖传递。
  2. 当没有 import 时,意思是将 spring-boot-dependencies 的 dependencies 全部插入到当前工程的 dependencies 中,并且会依赖传递。

12. Maven 仓库和镜像配置

参考:IntelliJ IDEA 配合 Maven 的一些技巧

只说明在 settings.xml 中的配置,

仓库的概念:仓库用 repositories 声明,插件仓库用 pluginRepositories 声明。

镜像的概念:镜像用 mirrors 声明, 类似于一个拦截器,拦截 jar 下载请求。

例子:

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
 
  <servers>
    <server>
      <id>rainsheep</id>
      <username>rainsheep</username>
      <password>xxxxxxxxxxxxx</password>
    </server>
  </servers>

  <mirrors>
    <mirror>
      <id>aliyun</id>
      <mirrorOf>*,!rainsheep</mirrorOf>
      <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
  </mirrors>

  <profiles>
    <profile>
      <id>myprofile</id>
      <repositories>
        <repository>
          <id>rainsheep</id>
          <name>maven-release-virtual</name>
          <url>https://xxx</url>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>rainsheep</id>
          <name>maven-release-virtual</name>
          <url>https://xxx</url>
        </pluginRepository>
      </pluginRepositories>
    </profile>
  </profiles>

  <activeProfiles>
    <activeProfile>myprofile</activeProfile>
  </activeProfiles>
</settings>
  • server 声明了访问仓库的 账号密码,id 和仓库的 id 需要一致
  • profile 是一份配置,这份配置声明了使用哪个仓库,activeProfile 默认激活配置
  • mirror 使用了阿里云镜像,若项目使用 myprofile 配置(即使用 rainsheep 仓库),则不通过镜像代理,否则通过镜像代理