1. maven入门

1. 絮絮叨叨

  • 做项目开发的时候,使用到了kafka producer,明明人家的编程示例只需要添加kafka-client依赖

  • 自己一旦运行起来以后,就开发报错,提示找不到org/slf4j/LoggerFactory

  • 然后,绕了一大圈,最终在添加以下maven后解决了问题:

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-jdk14</artifactId>
        <version>1.7.25</version>
    </dependency>
    
  • 后来,同事告诉自己好好地去看看kafka-client的依赖传递,看看人家对slf4j的配置是怎样的。

  • 自己回家发现,之前买的《maven实战》动都没动过,于是准备好好学习一下

  • 毕竟自己接触了这么多Java项目,发现大部分都是使用maven去做依赖管理的,不学习以后只会耗费更多的时间在maven各种问题处理上 😂

2. 一些基础知识

2.1 关于pom文件

  • maven项目的核心是pom.xml,这是maven项目实现项目构建、依赖管理、项目信息管理的关键。
  • pom: Project Object Model,项目对象模型

以我自己的项目JianzhiOffer为例,它最原始的pom文件如下:

  1. 第一行:xml头,指定了xml文档的版本和编码方式
  2. 第一个标签<project>,pom文件的根元素,里面地一些声明可以不用关注
  3. <modelVersion>标签,指定了pom的版本,目前固定为4.0.0
  4. <groupId>标签,一般包含了项目所在的组织或公司信息,例如,公司为sunrise的internet部门,则一般可以为com.sunrise.internet
  5. <artifactId>标签,当前maven项目在group中的唯一ID
  6. <version>标签,项目版本号,一般起始版本号为1.0-SNAPSHOT,后续不断更新为1.01.1-SNAPSHOT1.1
    <?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>org.example</groupId>
        <artifactId>jianzhioffer</artifactId>
        <version>1.0-SNAPSHOT</version>
    </project>
    

2.2 其他知识

  • 两种目录: maven项目在src目录下,应该包含miantest两个目录,前者用于存放主代码,后者用于存放测试代码。
  • 代码的包名: 一般默认的前缀固定为groupId.artifactId,示例pom中的包名应该为org.example.jianzhioffer。并且,maintest目录的包名应该一致
  • 类名: 自己在主代码中创建了一个HelloWorld类,在测试代码中对应的类名为HelloWorldTest
  • 方法名:HelloWorld类创建了一个sayHello()方法,则在测试代码中,对应的单元测试方法为testSayHello()

3. 代码编译

3.1 实战

  • 在主代码中创建HelloWorld

    package org.example.jianzhioffer;
    
    public class HelloWorld {
        public String syaHello(String name) {
            return "Hello, " + name + "!";
        }
    
        public static void main(String[] args) {
            HelloWorld helloWorld = new HelloWorld();
            String msg = helloWorld.syaHello("World");
            System.out.println(msg);
        }
    }
    
  • 使用如下命令进行代码编译:

    mvn clean compile
    
  • 从mvn的输出可以看出,maven先是clean了字节码文件所在的target/目录,然后执行resources任务(尚未使用到,暂不讨论), 最后执行compile任务,在target/目录生成了最新的字节码文件。

    [INFO] Scanning for projects...
    [INFO] 
    [INFO] ----------------------< org.example:jianzhioffer >----------------------
    [INFO] Building jianzhioffer 1.0-SNAPSHOT
    [INFO] --------------------------------[ jar ]---------------------------------
    [INFO] 
    [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ jianzhioffer ---
    [INFO] Deleting /Users/xxx/IdeaProjects/JianzhiOffer/target
    [INFO] 
    [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ jianzhioffer ---
    [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
    [INFO] Copying 0 resource
    [INFO] 
    [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ jianzhioffer ---
    [INFO] Changes detected - recompiling the module!
    [WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
    [INFO] Compiling 1 source file to /Users/xxx/IdeaProjects/JianzhiOffer/target/classes
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  1.682 s
    [INFO] Finished at: 2021-03-17T09:31:59+08:00
    [INFO] ------------------------------------------------------------------------
    

3.2 编译报错:请使用 -source 7 或更高版本 ...

  • 如果编译时,遇到以下错误提示说明需要配置maven的compiler插件,使其支持更高版本的jdk

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project test: Compilation failure
    [ERROR] /Users/xxx/IdeaProjects/Test/src/main/java/org/example/test/queue/Main.java:[8,69] -source 1.5 中不支持 diamond 运算符
    [ERROR]   (请使用 -source 7 或更高版本以启用 diamond 运算符)
    
  • 解决办法: 在pom中添加以下信息

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    

4. 代码测试

  • 代码测试,主要是指单元测试
  • 作为一个程序员,本人觉得单元测试是必须的,在单元测试中去尽可能多地覆盖各种情况,可以有效减少集成测试时的bug数,提高代码质量

4.1 添加junit依赖

  • 本人选择使用junit进行单元测试,因此在pom文件中添加了junit的依赖。

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
  • <dependencies>是所有依赖的根目录,<dependency>为具体的依赖

  • <scope>:指定了依赖的作用范围

    • 这里指定的是test,表明该依赖只能在测试代码中使用,不能在主代码中使用。
    • 也就是说,不能在主代码中,以import的形式引用junit任何代码。
  • 如果不明确指定<scope>,则默认为compile,在主代码和测试代码中都可以使用该依赖。

4.2 单元测试的代码

  • 在测试代码中,创建了对应的测试类,并编写好的sayHello()方法进行单元测试。
  • 使用@Test注解,表明这是一个测试方法,执行maven的test命令时,会自动执行该方法
    package org.example.jianzhioffer;
    
    import org.junit.Assert;
    import org.junit.Test;
    
    public class HelloWorldTest {
        @Test
        public void testSayHello() {
            HelloWorld helloWorld = new HelloWorld();
            String msg = helloWorld.syaHello("lucy");
            Assert.assertEquals("Hello, lucy!", msg);
        }
    }
    

4.3 执行单元测试

  • 使用如下命令执行单元测试

    mvn clean test
    
  • 从输出可以看出,maven的执行顺序为:

    clean --> resources: resources  --> compile: compile --> resources: testResouerces --> compile: testCompile  --> test
    
  • 最终的输出可以看出,此次测试的执行情况:

    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running org.example.jianzhioffer.HelloWorldTest
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.061 sec
    
    Results :
    
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    

5. 代码打包与安装

5.1 mvn package

  • 我们编写程序,可能大部分时候只是要求编程的IDE(如idea)能简单执行就ok了

  • 但是,总有一些时候,你有类似这样的需求:你本地编写的代码需要打包成jar文件,放到服务器上运行。

  • 这时候,maven的打包功能就派上用场了,只需要如下命令就可以轻松完成项目的打包:

    mvn clean package
    
  • 由于没有在pom文件中指定打包类型,默认会将项目打包成jar文件

  • 完成打包后,可以在target/目录看到对应的jar。其命名由artifactIdversion共同构成

  • 提示: 用户可以自己通过输出命令,分析maven打包时执行的任务顺序。

5.2 mvn install

  • 现在我们已经得到了项目的jar文件,如果想要在其他项目使用该文件,需要将其拷贝到对应的项目中才能生效

  • 如果想要其他项目直接使用这个jar,需要将其安装到本地仓库

  • 使用如下命令完成jar的安装

    mvn clean install
    
  • 通过输出我们可以发现,maven已经将jar安装到了我们的本地仓库

    [INFO] Installing /Users/xxx/IdeaProjects/JianzhiOffer/target/jianzhioffer-1.0-SNAPSHOT.jar to /Users/xxx/repo/org/example/jianzhioffer/1.0-SNAPSHOT/jianzhioffer-1.0-SNAPSHOT.jar
    [INFO] Installing /Users/xxx/IdeaProjects/JianzhiOffer/pom.xml to /Users/xxx/repo/org/example/jianzhioffer/1.0-SNAPSHOT/jianzhioffer-1.0-SNAPSHOT.pom
    

6. 如何让jar变得可运行?

  • 其实啊,我一直都有一个疑问,我这个jar,能像在idea中一样,直接运行main方法吗?

  • 如果不能,那我拿他有何用,因为我就是想把它放到服务器上去执行的 😂

  • 通过执行如下命令发现,好像目前的jar确实不支持 😂

    java -jar jianzhioffer-1.0-SNAPSHOT.jar
    
  • 执行上述命令,被告知没有主清单属性:

    jianzhioffer-1.0-SNAPSHOT.jar中没有主清单属性
    
  • 其实,我们解压缩jar,找到META-INF/MANIFEST.MF文件,或发现其中确实没有Main-Class这一行数据。

  • 这时,需要借助maven-shade-plugin,去指定Main-Class,才能在执行jar时,自动执行main方法。

  • 在pom文件中添加以下内容:
    最重要的是,要在<mainClass>标签中,指定main方法所在的类

    <build>
        <plugins>
            <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>org.example.jianzhioffer.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    
  • 再次执行install命令,发现target/目录下出现了两个jar。前缀为originjar,是之前打包的jar

  • 执行最新版本的jar,发现能正确找到main方法并执行

7. 总结

  • 从初始的学习来看,maven在编译、测试、打包、安装上都非常地方便,通过添加对应的标签,可以实现依赖添加、指定main方法所在的类等。
  • <dependency>中的<groupId><artifactId><version>就像坐标的x、y、z,通过指定这两个属性,可以轻松的找到对应的jar。这时,而具体使用哪个版本的jar可以通过<version>去指定。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值