欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

maven系列--依赖

程序员文章站 2022-05-22 21:24:48
...

dependency

依赖写法

问题引出

        如果Maven项目要引入某个依赖,需要三要素:groupId、artifactId和version,例如:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>

步骤

1. 进入maven仓库网站:http://mvnrepository.com/
2. 检索关键字spring-webmvc
3.找到最匹配的结果
4.点击想要的版本(version列中的链接)
5.上一步结束后,就会出现Maven、Grable等依赖的写法

dependency其他项

systemPath

    当maven依赖本地而非repository中的jar包,sytemPath指明本地jar包路径,例如:

<dependency>
    <groupid>org.hamcrest</groupid>
    <artifactid>hamcrest-core</artifactid>
    <version>1.5</version>
    <scope>system</scope>
    <systempath>${basedir}/WebContent/WEB-INF/lib/hamcrest-core-1.3.jar</systempath>
</dependency>

type

    引入某一个依赖时,必须指定type,这是因为用于匹配dependency引用和dependencyManagement部分的最小信息集实际上是{groupId,artifactId,type,classifier}。
    在很多情况下,这些依赖关系将引用没有classifier的jar依赖。这允许我们将标识设置为{groupId,artifactId},因为type的默认值是jar,并且默认classifier为null。
    type的值一般有jar、war、pom等,声明引入的依赖的类型。

classifier

    classifier它表示在相同版本下针对不同的环境或者jdk使用的jar,如果配置了这个元素,则会将这个元素名在加在最后来查找相应的jar,例如:

<classifier>jdk17</classifier>
<classifier>jdk18</classifier>

    Classifier可能是最容易被忽略的Maven特性,但它确实非常重要,我们也需要它来帮助规划坐标。
    设想这样一个情况,有一个jar项目,就说是 dog-cli-1.0.jar 吧,运行它用户就能在命令行上画一只小狗出来。现在用户的要求是希望你能提供一个zip包,里面不仅包含这个可运行的jar,还得包含源代码和文档,换句话说,这是比较正式的分发包。这个文件名应该是怎样的呢?dog-cli-1.0.zip?不够清楚,仅仅从扩展名很难分辨什么是Maven默认生成的构件,什么是额外配置生成分发包。如果能是dog-cli-1.0-dist.zip就最好了。这里的dist就是classifier,默认Maven只生成一个构件,我们称之为主构件,那当我们希望Maven生成其他附属构件的时候,就能用上classifier。常见的classifier还有如dog-cli-1.0-sources.jar表示源码包,dog-cli-1.0-javadoc.jar表示JavaDoc包等等。

optional

        指依赖是否可选,默认为false,即子项目默认都继承。若设置为true,则子项目必需显示的引入,与dependencyManagement里定义的依赖类似 。 

依赖原则

最短路径原则

A -> B -> C -> D(V1)
F -> G -> D(V2)

假设test依赖于D,这时maven会采用最短路径原则,选择V2版本的D。
因为V1版本的D是由A包间接依赖的,整个依赖路径长度为3,而V2版本的D是由F包间接依赖的,整个依赖路径长度为2。

优先声明原则

A -> B -> D(V1)
F -> G -> D(V2)

如果两个jar包版本路径深度相同,maven会根据pom文件声明的顺序加载,使用优先声明的版本

直引覆盖原则

多次直引不同版本的jar时,使用最后声明的版本。

如果再pom文件中,同时引用了如上两个版本,则会使用4.3.20.RELEASE版本

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.3.17.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.3.20.RELEASE</version>
</dependency>

依赖范围

    范围(scope)定义了类包在项目的使用阶段。项目阶段包括: 编译,运行,测试和发布(打包)。

依赖范围说明

说明

compile

缺省值,表示当前依赖参与项目的所有阶段(编译,运行,测试和发布),属于强依赖。

provided

参与编译,运行,测试,不参与发布。

 类似compile,区别在于不参与发布(打包阶段进行了exclude操作)。

 此依赖的发布由运行的环境来提供,比如tomcat或者基础类库等等。

system

使用上与provided相同。

    不同之处:该依赖从本地文件系统中提取(需要显式提供包含依赖的jar),而不是从maven仓库中提取,其会参照systemPath的属性进行提取依赖。

test

只在测试时使用,参与编译、运行、测试。不会随项目发布。

runtime

只在运行时使用。参与运行和测试阶段。

    一般这种类库都是接口与实现相分离的类库,比如JDBC类库,在编译之时仅依赖相关的接口,在具体的运行之时,才需要具体的mysql、oracle等等数据的驱动程序。

import

maven2.0.9版本后出的属性,import只能在dependencyManagement的中使用,能解决maven单继承问题,import依赖关系实际上并不参与限制依赖关系的传递性。

问题解决示例

SpringBoot代码上加了测试

HelloApplicationTests.java(所在路径:src/main/java/com.example.rabbitmqhello)

package com.example.rabbitmqhello;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = HelloApplication.class)
public class HelloApplicationTests{
    @Autowired
    private Sender sender;
    @Test
    public void hello() throws Exception {
        sender.send();
    }
}

发现@RunWith(SpringJUnit4ClassRunner.class)被标红,鼠标放上去提示:Cannot resolve symbol "SpringJUnit4ClassRunner"

原因

        测试类一般是放在src/test/java,而不是放在src/main/java下。maven在编译的时候,src/main/java下是不引用<scope>test</scope>的jar,而编译src/test/java下的测试这会引用<scope>test</scope>的jar。

        本处在src/main/java中使用测试注解,但不会引用到相关类,就会找不到SpringJUnitClassRunner.class。

解决方法

法一:将测试包的<scope>test</scope>改为<scope>compile</scope>

法1:直接修改pom.xml   
法2:File=> Project Structure=> Project Settings=> Modules=> 选中相应模块=> Dependencies=> 修改相应包为compile 

 法二:将代码所在文件夹属性设为test

法1:将代码放到src/test/java下
法2:将所在文件夹标记为Test:右键此文件夹=> Mark Directories As=> Test Sources Root

依赖的传递性与排除

依赖的传递性:A依赖B,B依赖C,A能否使用C呢?那要看B依赖C的范围是否是compile,如果是则可用,否则不可用。

a.可以传递的依赖不必在每个工程中都重复声明,在“最下面”的工程中依赖一次即可。
b.非compile范围的依赖不能传递,所以在各个工程模块中,如果有需要就得重复声明。如servlrt-api。

依赖的排除

依赖的排除:如果我们不想通过 A->B->C>D1 引入 D1 的话,那么我们在声明引入 A 的时候将 D1 排除掉。
排除的原因一般有:1.依赖不够/不够稳定 2.与其他的包冲突(同名包)

示例:将 redis 的 lettuce依赖排除

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <!--不依赖Redis的异步客户端lettuce -->
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

排除所有依赖

            <exclusions>
                <exclusion>
                    <groupId>*</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>

dependencyManagement

    在Maven多模块的时候,管理依赖关系是非常重要的,各种依赖包冲突,查询问题起来非常复杂,于是就用到了<dependencyManagement>。

父模块:

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.44</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

子模块中只需要<groupId>和<artifactId>即可,如:

   <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
   </dependencies>

说明

        使用dependencyManagement可以统一管理项目的版本号,确保应用的各个项目的依赖和版本一致,不用每个模块项目都弄一个版本号,不利于管理,当需要变更版本号的时候只需要在父类容器里更新,不需要任何一个子项目的修改;如果某个子项目需要另外一个特殊的版本号时,只需要在自己的模块dependencies中声明一个版本号即可。子类就会使用子类声明的版本号,不继承于父类版本号。

与dependencies区别

1)Dependencies
    所有声明在dependencies里的依赖都会自动引入,并默认被所有的子项目继承。

2)dependencyManagement
    只是声明依赖,并不自动实现引入,因此子项目需要显式声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。

常用的项

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.0.1.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    <dependencies>
</dependencyManagement>
<dependencyManagement>
    <dependencies>
        <!-- Apache Dubbo  -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-bom</artifactId>
            <version>${dubbo.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    <dependencies>
</dependencyManagement>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

引入第三方依赖

其他网址

maven 导入第三方包_qq_23476319的博客-CSDN博客_maven install 怎么引入大量的第三方包

法1 指定lib目录为编译参数

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-compiler-plugin</artifactId>
	<version>3.3</version> 
	<configuration>
		<source>1.8</source>
		<target>1.8</target>
		<encoding>UTF-8</encoding>
		<compilerArguments>
		  <extdirs>${basedir}\src\main\webapp\WEB-INF\lib</extdirs>
		</compilerArguments>
	</configuration>
</plugin>

法2 指定单个jar

<dependency>
    <!--if add it into the </dependencyManagement>, it does not work-->
    <groupId>test.search</groupId>
    <artifactId>binarySearch</artifactId>
    <version>1.0.3</version>
    <systemPath>${basedir}/tmp/binary_search.jar</systemPath>
    <scope>system</scope>
</dependency>

注意:这种方式在打包生成可执行jar文件时,抓取不到该jar文件,即 MANIFEST.MF 文件中没有该jar文件的配置信息。
解决方法:maven-shade-plugin

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.1.1</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <transformers>
                    <transformer
                            implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <mainClass>netty_in_action.chapter_2_2.EchoServer</mainClass>
                    </transformer>
                </transformers>
            </configuration>
        </execution>
    </executions>
</plugin>

 法3:将JAR包传入到MAVEN仓库服务器的 第3方仓库中

1.  可以通过  http://ip:8081/nexus 管理页面  上传到服务器

2.  通过命令行 上传JAR包  

mvn install:install-file -DgroupId=org.jboss.cache -DartifactId=jbosscache-core -Dversion=3.2.7.GA -Dpackaging=jar -Dfile=D:\jbosscache-core-3.2.7.GA.jar

一些参数说明如下:
-DgroupId=远程仓库对应的DgroupId
-DartifactId= 远程仓库对应的 DartifactId 
-Dversion=对应版本号 

POM.XML中直接引入

<dependency>
	<groupId>com.gxhs.analysis2</groupId>
	<artifactId>netty-client-distributed</artifactId>
	<version>2.0</version>
</dependency>

Jar转为pom.xml

其他网址

基于Maven中心库 通过Jar包生成Maven POM.xml的dependency_java,maven_贾小黑的博客-CSDN博客
将项目中的jar文件生成pom文件_Java_闵渭凯-CSDN博客

 本程序会在控制台中输出依赖,例如:

<dependencies>
	<dependency>
		<groupId>commons-beanutils</groupId>
		<artifactId>commons-beanutils</artifactId>
		<version>1.8.3</version>
	</dependency>
	<dependency>
		<groupId>commons-logging</groupId>
		<artifactId>commons-logging</artifactId>
		<version>1.1.3</version>
	</dependency>
	<dependency>
		<groupId>XXX</groupId>
		<artifactId>mysql-connector-java-bin</artifactId>
		<version>5.0.8</version>
	</dependency>
	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro-all</artifactId>
		<version>1.3.2</version>
	</dependency>
</dependencies>

所需包

<dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastJson</artifactId>
            <version>1.2.17</version>
        </dependency>
 
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6</version>
        </dependency>
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.9.2</version>
        </dependency>
</dependencies>
package com.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;

import org.dom4j.Element;
import org.dom4j.dom.DOMElement;
import org.jsoup.Jsoup;
import com.alibaba.fastjson.JSONObject;
public class Jar2Pom {
    public static void main(String[] args) throws FileNotFoundException, IOException {
        Element dependencies = new DOMElement("dependencies");

        File dir = new File("E:\\my_project\\test\\src\\main\\lib");        //需生成pom.xml 文件的 lib路径

        System.out.println("<dependencies>");

        for (File jar : dir.listFiles()) {
            JarInputStream jis = new JarInputStream(new FileInputStream(jar));
            Manifest mainmanifest = jis.getManifest();
            jis.close();
            //其他网站方法都少这个判断,会抛出空指针异常
            if(mainmanifest==null) {
                continue;
            }
            String bundleName = mainmanifest.getMainAttributes().getValue("Bundle-Name");
            String bundleVersion = mainmanifest.getMainAttributes().getValue("Bundle-Version");
            Element ele = null;

            StringBuffer sb = new StringBuffer(jar.getName());
            if (bundleName != null) {
                bundleName = bundleName.toLowerCase().replace(" ", "-");
                sb.append(bundleName+"\t").append(bundleVersion);
                ele = getDependices(bundleName, bundleVersion);
                //System.out.println(sb.toString());
                //System.out.println(ele.asXML());
            }
            if (ele == null || ele.elements().size() == 0) {
                bundleName = "";
                bundleVersion = "";
                String[] ns = jar.getName().replace(".jar", "").split("-");
                for (String s : ns) {
                    if (Character.isDigit(s.charAt(0))) {
                        bundleVersion += s + "-";
                    } else {
                        bundleName += s + "-";
                    }
                }
                if (bundleVersion.endsWith("-")) {
                    bundleVersion = bundleVersion.substring(0, bundleVersion.length() - 1);
                }
                if (bundleName.endsWith("-")) {
                    bundleName = bundleName.substring(0, bundleName.length() - 1);
                }
                ele = getDependices(bundleName, bundleVersion);
                sb.setLength(0);
                sb.append(bundleName+"\t").append(bundleVersion);
                //System.out.println(ele.asXML());
            }

            ele = getDependices(bundleName, bundleVersion);
            if (ele.elements().size() == 0) {
                ele.add(new DOMElement("groupId").addText("XXX"));
                ele.add(new DOMElement("artifactId").addText(bundleName));
                ele.add(new DOMElement("version").addText(bundleVersion));
            }
            System.out.println("\t" + "<dependency>");
            Iterator<DOMElement> iterator = ele.nodeIterator();
            while(iterator.hasNext()){
                System.out.println("\t\t" + iterator.next().asXML());
            }
            System.out.println("\t" + "</dependency>");

            //System.out.println("\t"+ele.asXML());
            //dependencies.add(ele);
        }
        //System.out.println(dependencies.asXML());
        System.out.println("</dependencies>");
    }
    public static Element getDependices(String key, String ver) {
        Element dependency = new DOMElement("dependency");
        // 设置代理
        // System.setProperty("http.proxyHost", "127.0.0.1");
        // System.setProperty("http.proxyPort", "8090");
        try {
            String url = "http://search.maven.org/solrsearch/select?q=a%3A%22" +
                    key + "%22%20AND%20v%3A%22" + ver + "%22&rows=3&wt=json";

            org.jsoup.nodes.Document doc = Jsoup.connect(url).ignoreContentType(true).timeout(30000).get();
            String elem = doc.body().text();
            JSONObject response = JSONObject.parseObject(elem).getJSONObject("response");
            if (response.containsKey("docs") && response.getJSONArray("docs").size() > 0) {
                JSONObject docJson = response.getJSONArray("docs").getJSONObject(0);
                Element groupId = new DOMElement("groupId");
                Element artifactId = new DOMElement("artifactId");
                Element version = new DOMElement("version");
                groupId.addText(docJson.getString("g"));
                artifactId.addText(docJson.getString("a"));
                version.addText(docJson.getString("v"));
                dependency.add(groupId);
                dependency.add(artifactId);
                dependency.add(version);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dependency;
    }
}

pom.xml生成Jar

其他网址:jar文件和pom.xml文件依赖之间的转换_Java_断橋殘雪的博客-CSDN博客

1:创建pom2jar.bat

内容如下

call mvn -f pom.xml dependency:copy-dependencies

@pause

2.创建pom.xml

在此pom.xml中添加相应依赖即可

<?xml version="1.0"?>
<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>temp.download</groupId>
	<artifactId>temp-download</artifactId>
	<version>1.0-SNAPSHOT</version> 

	<dependencies>
		<!-- 需要下载Jar包,只需要在pom.xml文件中添加相应依赖-->
		<!-- 示例 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.45</version>
		</dependency>

	</dependencies>
</project>

3.将pom2jar.bat与pom.xml放到同一个文件夹

4.双击pom2jar.bat

jar包文件会下载在target/dependency/

 

相关标签: Maven/Gradle