maven-compiler-plugin 与spring-boot-maven-plugin 区别

spring boot中打包插件spring-boot-maven-plugin和maven-jar-plugin的关联

用spring boot快速开发时,通常用spring-boot-maven-plugin插件将springboot的应用程序打包成jar文件,然后通过java -jar运行,很方便。但是如果是部署到服务器上,每次更改代码后替换的包都比较大,至少30MB以上,依赖jar多的甚至超过100MB,传输效率就降低了,其实真正的代码jar是很小的,所以要想办法给jar瘦身。

一、maven-jar-plugin
maven-jar-plugin是jar包生成插件,提供了manifest的配置,生成jar包中一般存放的是.class文件已经resources目录下的东西,文件很小。

二、spring-boot-maven-plugin
从官网的介绍来看,spring-boot-maven-plugin主要目标是spring-boot的启动、停止、运行和repackage,对于打包来说那就是repackage,也就是说它实现的打包功能是重新打包,原始jar包还是由maven-jar-plugin生成的

spring-boot-maven-plugin

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

maven-compiler-plugin

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

maven-jar-plugin和spring-boot-maven-plugin打包生成的文件
在这里插入图片描述

 

spring boot中打包插件spring-boot-maven-plugin和maven-jar-plugin的关联_spring-boot-maven-plugin maven-jar-plugin-CSDN博客

简介

用spring boot快速开发时,通常用spring-boot-maven-plugin插件将springboot的应用程序打包成jar文件,然后通过java -jar运行,很方便。但是如果是部署到服务器上,每次更改代码后替换的包都比较大,至少30MB以上,依赖jar多的甚至超过100MB,传输效率就降低了,其实真正的代码jar是很小的,所以要想办法给jar瘦身。

一、maven-jar-plugin

maven-jar-plugin是jar包生成插件,提供了manifest的配置,生成jar包中一般存放的是.class文件已经resources目录下的东西,文件很小。

二、spring-boot-maven-plugin

从官网的介绍来看,spring-boot-maven-plugin主要目标是spring-boot的启动、停止、运行和repackage,对于打包来说那就是repackage,也就是说它实现的打包功能是重新打包,原始jar包还是由maven-jar-plugin生成的。
在这里插入图片描述

三、区别和联系

我们将普通插件maven-jar-plugin生成的包和spring-boot-maven-plugin生成的包进行比较,发现使用spring-boot-maven-plugin生成的jar中主要增加了两部分,第一部分是lib目录,这里存放的是应用的Maven依赖的jar包文件,第二部分是spring boot loader相关的类,所以通常spring-boot-maven-plugin插件打的jar包程为fatjar或者胖jar。

四、总结

所以如果是用部署到生产或者服务器环境最好通过maven-jar-plugin打包,初次打包可以结合maven-assembly-plugin打成压缩文件,以后只需要传送更改的代即可。

转载地址:https://www.jianshu.com/p/19b9634ab412

spring-boot-maven-plugin插件是将springboot的应用程序打包成fat jar的插件。首先我们说一下啥叫fat jar。fat jar 我们暂且叫他胖jar吧,实在是找不到官方叫法了。我们一般的jar,里面放的是.class文件已经resources目录下的东西,但是fat jar 它可以把jar作为内容包含进去。也就是说,spring boot 借助spring-boot-maven-plugin将所有应用启动运行所需要的jar都包含进来,从逻辑上将具备了独立运行的条件。

我们将普通插件maven-jar-plugin生成的包和spring-boot-maven-plugin生成的包unzip,比较一下他们直接的区别,发现使用spring-boot-maven-plugin生成的jar中主要增加了两部分,第一部分是lib目录,这里存放的是应用的Maven依赖的jar包文件,第二部分是spring boot loader相关的类,这个我们下一节再说spring boot 的加载流程。

在项目中需要先加入spring-boot-maven-plugin。

           <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>1.3.2.RELEASE</version>
                <configuration>
                    <mainClass>test.ApplicationMain</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

默认是在package阶段执行spring-boot-maven-plugin repackage这个目标。我们看一下RepackageMojo的关键方法execute

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        if (this.project.getPackaging().equals("pom")) {
            getLog().debug("repackage goal could not be applied to pom project.");
            return;
        }
        if (this.skip) {
            getLog().debug("skipping repackaging as per configuration.");
            return;
        }
        //得到项目中的原始的jar,就是使用maven-jar-plugin生成的jar
        File source = this.project.getArtifact().getFile();
        //要写入的目标文件,就是fat jar
        File target = getTargetFile();
        Repackager repackager = new Repackager(source) {
            //从source中寻找spring boot 应用程序入口的main方法。
            @Override
            protected String findMainMethod(JarFile source) throws IOException {
                long startTime = System.currentTimeMillis();
                try {
                    return super.findMainMethod(source);
                }
                finally {
                    long duration = System.currentTimeMillis() - startTime;
                    if (duration > FIND_WARNING_TIMEOUT) {
                        getLog().warn("Searching for the main-class is taking some time, "
                                + "consider using the mainClass configuration "
                                + "parameter");
                    }
                }
            }
        };
        //如果插件中指定了mainClass就直接使用
        repackager.setMainClass(this.mainClass);
        if (this.layout != null) {
            getLog().info("Layout: " + this.layout);
            repackager.setLayout(this.layout.layout());
        }
        //寻找项目运行时依赖的jar,过滤后
        Set<Artifact> artifacts = filterDependencies(this.project.getArtifacts(),
                getFilters(getAdditionalFilters()));
        //将Artifact转化成Libraries 
        Libraries libraries = new ArtifactsLibraries(artifacts, this.requiresUnpack,
                getLog());
        try {
            LaunchScript launchScript = getLaunchScript();
            //进行repackage
            repackager.repackage(target, libraries, launchScript);
        }
        catch (IOException ex) {
            throw new MojoExecutionException(ex.getMessage(), ex);
        }
        if (this.classifier != null) {
            getLog().info("Attaching archive: " + target + ", with classifier: "
                    + this.classifier);
            this.projectHelper.attachArtifact(this.project, this.project.getPackaging(),
                    this.classifier, target);
        }
        else if (!source.equals(target)) {
            this.project.getArtifact().setFile(target);
            getLog().info("Replacing main artifact " + source + " to " + target);
        }
    }

基本上重要的步骤都有注释,应该不难理解的。再来看下面,当然也不是重点,看看就行。

public void repackage(File destination, Libraries libraries,
            LaunchScript launchScript) throws IOException {
        if (destination == null || destination.isDirectory()) {
            throw new IllegalArgumentException("Invalid destination");
        }
        if (libraries == null) {
            throw new IllegalArgumentException("Libraries must not be null");
        }
        if (alreadyRepackaged()) {
            return;
        }
        destination = destination.getAbsoluteFile();
        File workingSource = this.source;
        //如果源jar与目标jar的文件路径及名称是一致的
        if (this.source.equals(destination)) {
            //将源jar重新命名为原名称+.original,同时删除原来的源jar
            workingSource = new File(this.source.getParentFile(),
                    this.source.getName() + ".original");
            workingSource.delete();
            renameFile(this.source, workingSource);
        }
        destination.delete();
        try {
            //将源jar变成JarFile 
            JarFile jarFileSource = new JarFile(workingSource);
            try {
                repackage(jarFileSource, destination, libraries, launchScript);
            }
            finally {
                jarFileSource.close();
            }
        }
        finally {
            if (!this.backupSource && !this.source.equals(workingSource)) {
                deleteFile(workingSource);
            }
        }
    }

这一步所做的是清理工作,如果源jar同目标文件路径名称等一致,将源jar重命名,原来的文件删除。为目标文件腾位置。下面的重点来了。

    private void repackage(JarFile sourceJar, File destination, Libraries libraries,
            LaunchScript launchScript) throws IOException {
        JarWriter writer = new JarWriter(destination, launchScript);
        try {
            final List<Library> unpackLibraries = new ArrayList<Library>();
            final List<Library> standardLibraries = new ArrayList<Library>();
            libraries.doWithLibraries(new LibraryCallback() {
                @Override
                public void library(Library library) throws IOException {
                    File file = library.getFile();
                    if (isZip(file)) {
                        if (library.isUnpackRequired()) {
                            unpackLibraries.add(library);
                        }
                        else {
                            standardLibraries.add(library);
                        }
                    }
                }
            });
            //按照规则写入manifest文件
            writer.writeManifest(buildManifest(sourceJar));
            Set<String> seen = new HashSet<String>();
            writeNestedLibraries(unpackLibraries, seen, writer);
           //写入源jar中的内容
            writer.writeEntries(sourceJar);
           //写入标准的jar,依赖的jar
            writeNestedLibraries(standardLibraries, seen, writer);
            if (this.layout.isExecutable()) {
               //写入spring boot loader的类
                writer.writeLoaderClasses();
            }
        }
        finally {
            try {
                writer.close();
            }
            catch (Exception ex) {
                // Ignore
            }
        }
    }

上面就是一通写,将所需要的内容全部写入到目标文件中。然后就有了我们的fat jar。

SpringBoot入门之spring-boot-maven-plugin - 简书 (jianshu.com)

maven-compiler-plugin 插件详解-CSDN博客

maven 是个管理工具,如果我们不告诉它我们的代码要使用什么样的 jdk 版本编译的话,它就会用 maven-compiler-plugin 默认的 jdk 版本来进行处理,这样就容易出现版本不匹配,以至于可能导致编译不通过的问题。

maven 的默认编译使用的 jdk 版本有时候不通用,使用 maven-compiler-plugin 插件可以指定项目源码的 jdk 版本,编译后的 jdk 版本,以及编码。

maven-compiler-plugin

maven-compiler-plugin 插件是一个 Maven 插件,用来编译项目代码;自从3.0开始默认的编译器是 javax.tools.JavaCompiler,用来编译 Java 源码;如果你想强制插件使用 javac 编译器,你必须配置插件的属性 forceJavacCompilerUse;还要注意,当前默认源(source)设置为 1.6,默认目标(target)设置为 1.6。独立运行 Maven 和 JDK,可以通过 source 和 target 选项更改他们的默认值;

1. maven-compiler-plugin插件当前最高版本是3.8.0下载地址:http://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin

2. 插件设置的各种参数信息请查看

http://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#forceJavacCompilerUse

 
  1. <build>
  2. <plugins>
  3. <plugin>
  4. <groupId>org.apache.maven.plugins</groupId>
  5. <artifactId>maven-compiler-plugin</artifactId>
  6. <version>3.8.0</version>
  7. <configuration>
  8. <source>1.8</source>
  9. <target>1.8</target>
  10. <encoding>UTF-8</encoding>
  11. </configuration>
  12. </plugin>
  13. </plugins>
  14. </build>
 
 
  1. <plugin>
  2. <!-- 指定maven编译的jdk版本,如果不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 -->
  3. <groupId>org.apache.maven.plugins</groupId>
  4. <artifactId>maven-compiler-plugin</artifactId>
  5. <version>3.1</version>
  6. <configuration>
  7. <!-- 一般而言,target与source是保持一致的,但是,有时候为了让程序能在其他版本的jdk中运行(对于低版本目标jdk,源代码中不能使用低版本jdk中不支持的语法),会存在target不同于source的情况 -->
  8. <source>1.8</source> <!-- 源代码使用的JDK版本 -->
  9. <target>1.8</target> <!-- 需要生成的目标class文件的编译版本 -->
  10. <encoding>UTF-8</encoding><!-- 字符集编码 -->
  11. <skipTests>true</skipTests><!-- 跳过测试 -->
  12. <verbose>true</verbose>
  13. <showWarnings>true</showWarnings>
  14. <fork>true</fork><!-- 要使compilerVersion标签生效,还需要将fork设为true,用于明确表示编译版本配置的可用 -->
  15. <executable><!-- path-to-javac --></executable><!-- 使用指定的javac命令,例如:<executable>${JAVA_1_4_HOME}/bin/javac</executable> -->
  16. <compilerVersion>1.3</compilerVersion><!-- 指定插件将使用的编译器的版本 -->
  17. <meminitial>128m</meminitial><!-- 编译器使用的初始内存 -->
  18. <maxmem>512m</maxmem><!-- 编译器使用的最大内存 -->
  19. <compilerArgument>-verbose -bootclasspath ${java.home}\lib\rt.jar</compilerArgument><!-- 这个选项用来传递编译器自身不包含但是却支持的参数选项 -->
  20. </configuration>
  21. </plugin>
 

Maven之pom.xml继承父pom.xml配置,如何移除父pom中的依赖_maven排除父类pom中的引用的jar-CSDN博客

前言

maven是java项目的管理和构建工具。我们可以通过引入不同依赖,以满足项目开发。项目越大,引入的依赖就越多,带来的管理问题也就越来越突出。
因此,统一的依赖管理就显得尤为重要!


提示:以下是本篇文章正文内容,下面案例可供参考

一、项目间的依赖关系

示例:

二、使用步骤

1.父pom

使用dependencyManagement 和 pluginManagement ,声明子类POM中可能用到的依赖和插件,但并不会引入实际的依赖,或造成实际的插件调用行为,但能够约束子类POM中的依赖和插件配置的声明。
代码如下(示例):

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tomandersen</groupId>
    <artifactId>HadoopCustomModules</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <!--模块名称-->
    <modules>
        <module>flume</module>
        <module>log-collector</module>
    </modules>

    <!--事先声明版本属性-->
    <properties>
        <slf4j.version>1.7.20</slf4j.version>
        <logback.version>1.0.7</logback.version>
    </properties>


    <!--在父类Maven中使用dependencyManagement声明依赖便于子类Module继承使用,也便于进行依赖版本控制-->
    <dependencyManagement>
        <dependencies>
            <!--阿里巴巴开源json解析框架-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.51</version>
            </dependency>

            <!--日志生成框架-->
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>${logback.version}</version>
            </dependency>

            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>${logback.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <build>
        <!--在父类Maven中使用pluginManagement管理插件便于子类Module继承使用,也便于进行依赖版本控制-->
        <pluginManagement>
            <plugins>
                <!--配置Maven项目compiler插件-->
                <!--此工具不会打包依赖-->
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.3.2</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>

				<!--配置Maven项目assembly插件-->
            	<!--此工具会将全部依赖打包-->
                <plugin>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <configuration>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                        <archive>
                            <manifest>
                                <!--子类Maven通过mainClass标签设置成主类的全类名FQCN-->
                                <!--<mainClass></mainClass>-->
                            </manifest>
                        </archive>
                    </configuration>
                    <executions>
                        <execution>
                            <id>make-assembly</id>
                            <phase>package</phase>
                            <goals>
                                <goal>single</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

            </plugins>
        </pluginManagement>

    </build>

2.子POM

1)在子类POM中声明父类POM
2)配置实际使用的 dependency 和 plugin,只需要声明 groupId 和 artifactId 就可以,只有声明的才会进行实际的依赖引入或插件调用
3)版本在父POM中统一管理,不用指定版本。指定版本,则覆盖父类配置信息

代码如下(示例):

    <!--声明父类POM-->
    <parent>
        <artifactId>HadoopCustomModules</artifactId>
        <groupId>com.tomandersen</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <!--子类POM信息-->
    <groupId>com.tomandersen</groupId>
    <artifactId>log-collector</artifactId>

    <dependencies>
        <!--阿里巴巴开源json解析框架-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>

        <!--日志生成框架-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <!--如果不配置,则不会引进父pom中的依赖-->
<!--        <dependency>-->
<!--            <groupId>ch.qos.logback</groupId>-->
<!--            <artifactId>logback-classic</artifactId>-->
<!--        </dependency>-->
    </dependencies>

    <build>
        <plugins>
            <!--自定义Maven项目编译器compiler插件相关配置-->
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
            </plugin>

            <!--自定义Maven项目汇编assembly插件相关配置-->
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <!--此处设置成主类的全名-->
                            <mainClass>com.tomandersen.appclient.AppMain</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

三、重复依赖,依赖冲突

由于一些dependency中包含了某个jar,然后我们又导入了其他jar,不知不觉中造成jar冲突,或者是重复依赖……这样整个项目的jar就会越来越冗余,庞大

方法一:把父pom依赖的jar包排除掉

  1. 如何查看依赖树图
    在这里插入图片描述

  2. 放大后,会看到一些红线,这就是冲突的jar。一般选择低版本depedency,点击右键——Exclude
    在这里插入图片描述去除了冲突或者重复的jar,maven会在对应pom的depedency中加 <exclusions>用于去掉某个依赖里的jar。
    在这里插入图片描述

方法一:把父pom依赖的jar包覆盖掉

举例:
在这里插入图片描述
假如我们在项目pom中引入一个统一的依赖管理项目。

在common-base中引入了
在这里插入图片描述

但是我们想在datasource中使用最新版本的依赖,可以直接在datasource的pom中指定版本。
在这里插入图片描述
这样就可以使用最新的版本了。

但是,在依赖树图中,我们会看到又多了一条红线。也就意味着可能存在冲突。

重点、重点、重点、

########################################
产生冲突的原因,是因为根据 maven依赖最短路径原则,必然是产生了两个 相同路径长度 的依赖,版本不一致导致的。
########################################
强调一下,树图的红线并不影响项目的正常运行和打包,maven打包时会按照最短路径把需要的jar打包。

所以,只要定义一个更短路径的依赖就可以解决。

比如我打的包时start,只要在start模块的pom中再引入一次依赖,就可以解决冲突ClassNotFoundException的问题。

maven删除不必要的依赖;优化pom依赖研究_没用的maven依赖-CSDN博客

maven如何去除没有使用的依赖:

项目做了比较大的改动。
以前很多的依赖都没有用了。
能否让maven或者eclipse自动检索,哪些依赖是没有被使用的。标记出来或者直接删除。

方法1:

好像没有这个功能。你可以手动筛选。把不是必须的包配置注释掉。如果报异常,就把需要的包的注释打开。

方法2:

>mvn dependency:analyze

[INFO] --- maven-dependency-plugin:2.8:analyze (default-cli) @ wtp-core ---
[WARNING] Used undeclared dependencies found:
[WARNING]    org.springframework:spring-beans:jar:3.2.3.RELEASE:compile
[WARNING] Unused declared dependencies found:
[WARNING]    junit:junit:jar:4.7:test
[WARNING]    org.springframework:spring-test:jar:3.2.3.RELEASE:test
[WARNING]    org.slf4j:jcl-over-slf4j:jar:1.6.1:runtime
[WARNING]    org.slf4j:slf4j-log4j12:jar:1.6.1:runtime
[WARNING]    commons-lang:commons-lang:jar:2.5:test

方法3:

可以用 查看项目依赖:mvn dependency:analyze; 或 mvn dependency:analyze -DignoreNonCompile

查看项目直接和传递依赖:mvn dependency:tree ;

查看maven构建时有效的pom:mvn help:effective-pom 来看哪些jar是不需要的,再排除就好了。

posted @ 2024-01-02 16:10  CharyGao  阅读(2327)  评论(0编辑  收藏  举报