Maven plugin

194 阅读3分钟

一、如何手写一个maven plugin

maven plugin的作用就是在maven生命周期的某一个阶段去完成一个事情。

  1. maven生命周期(lifecycle)中的每个阶段(phase)都可以绑定n(>=1)个插件(plugin)的目标(goal) maven.apache.org/guides/intr… blog.csdn.net/cyl101816/a…
  2. 多个goal绑定同一个phase的话,maven会从上到下依次执行
  3. 一个plugin中可以包含多个goal
  4. maven插件的命名规则:maven-xxx-plugin xxx-maven-plugin(spring喜欢这种风格)
  5. 如何在idea中调试maven插件:blog.csdn.net/xichenguan/…

1.1 maven插件的前置准备工作

第一步:maven插件pom文件需要修改打包方式

<packaging>maven-plugin</packaging>

第二步:引入依赖

<dependencies>
    <!-- 写注解插件必引入 -->
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-plugin-api</artifactId>
        <version>3.5.2</version>
    </dependency>
    
    <!-- 注解方式定义插件时才用得到 -->
    <dependency>
        <groupId>org.apache.maven.plugin-tools</groupId>
        <artifactId>maven-plugin-annotations</artifactId>
        <version>3.5.2</version>
    </dependency>
    
    <!-- 生成插件描述信息 plugin.xml-->
    <dependency>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-plugin-plugin</artifactId>
        <version>3.5</version>
    </dependency>
    
    <!-- 获取maven工程的pom配置信息-->
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-project</artifactId>
        <version>2.2.1</version>
    </dependency>
</dependencies>

第三步:在build文件中引用插件描述信息依赖

    <build>
        <plugins>
            <!-- 生成插件描述信息 plugin.xml-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-plugin-plugin</artifactId>
                <version>3.5</version>
            </plugin>
        </plugins>
    </build>

示意图

image.png

image.png

1.2 实现方式

1.2.1 注释方式实现(不推荐,已经废弃)

在注解里面写@goal 就会被识别到

/**
 * @goal comment
 * @version 1.0.0
 * @since 1.0.0
 * 注意:注释的方式不能与注解方式混用
 */
public class CommentMoJo extends AbstractMojo {
    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        Log log = getLog();
        log.info("执行了goal:comment的execute方法");
    }
}

1.2.2 注解方式实现

@Mojo注解的name就是goal的名字,defaultPhase设置默认绑定的phase,不写默认是package

@Mojo(name = "annotation", defaultPhase = LifecyclePhase.PACKAGE)
public class AnnotationMoJo extends AbstractMojo {

    @Parameter(defaultValue = "${project}")
    private MavenProject project;

    @Parameter(required = true)
    private String name;

    @Parameter(required = false)
    private String age;
    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        Log log = getLog();
        log.info("执行了goal:annotation的execute方法");
        // 获取到最终jar包的名字
        String packaging = project.getPackaging();
        String finalName = project.getBuild().getFinalName();
        log.info("获取到最终jar包的名字:"+finalName+"."+packaging);
        log.info("name的值:"+name);
        log.info("age的值:"+age);
    }
}

获取<plugin><configuration>里面的参数配置

    // 获取maven pom文件上下文
    @Parameter(defaultValue = "${project}")
    private MavenProject project;

    // required = true代表这个参数是必须的
    @Parameter(required = true)
    private String name;

    @Parameter(required = false)
    private String age;

1.3 在项目中使用maven plugin

<build>
        <plugins>
            <plugin>
                <groupId>com.example</groupId>
                <artifactId>mavenplugin</artifactId>
                <version>0.0.2-SNAPSHOT</version>
                <configuration>
<!--                可以被maven插件代码里面的@Parameter获取到-->
                    <name>cgy</name>
                </configuration>
                <executions>
                    <execution>
                        <id>comment</id>
                        <phase>package</phase>
                        <goals>
                            <goal>comment</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>anno</id>
<!--                绑定的phase,没指定可以alt+友键查看<goal>annotation</goal>写的默认的阶段-->
                        <phase>package</phase>
<!--                goal是就是这个插件的执行name-->
                        <goals>
                            <goal>annotation</goal>
                        </goals>
                    </execution>
                </executions>
<!--                当插件的依赖不能传递时需要使用方显式引入-->
                <dependencies>
                    <dependency>
                        <groupId>commons-io</groupId>
                        <artifactId>commons-io</artifactId>
                        <version>2.13.0</version>

<!--                        <scope>provided</scope>-->
<!--                        <optional>true</optional>-->
                    </dependency>
                </dependencies>
            </plugin>
            
            <!--                这个插件是spring的打包插件-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.6.11</version>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <phase>package</phase>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
<scope>provided</scope>
<optional>true</optional>

在Maven的pom.xml文件中,<scope>provided</scope><optional>true</optional> 是用来指定依赖关系的两个元素。

<scope>provided</scope> 表示该依赖在项目的编译和测试阶段需要,但在运行阶段由运行环境(例如 JDK 或应用服务器)提供。也就是说,这个依赖只会在编译和测试时使用,不会被打包到生成的最终可执行文件中。常见的例子是使用 Java EE 的一些 API,例如 Servlet API ,因为在运行时这些 API 已经由应用服务器提供。

<optional>true</optional> 表示这个依赖是可选的。当一个项目A依赖于项目B时,<optional>true</optional> 标志被用在项目B的依赖项目C上。这表示项目A需要项目B,但项目A不需要项目C。因此,当其他项目依赖于项目A时,它们将自动包含项目B,但不会自动包含项目C,除非它们显式地声明了对项目C的依赖。这个标志用途常见于多模块的Maven项目,项目间的可选依赖关系可以避免不必要的传递依赖。

<configuration>标签放在<execution>下面可以缩小影响范围,放在<plugin>标签下面对这个插件的都生效

1.4 查看maven生成的plugin.xml

这里有一个spring的打包插件

<plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.6.11</version>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <phase>package</phase>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

alt+点击<goal>repackage</goal>可以查看这个goal生成的plugin.xml文件

image.png

1.5 plugin的依赖

image.png 当插件的依赖不能传递时需要使用方显式的引入依赖。

<dependency>
        <groupdId>commons-io</groupdId>
        <artifactId>commons-io</artifactId>
        <version>2.13.0</version>
        <!-- 当插件的依赖不能传递时需要使用方显式的引入依赖-->
        <scope>provided</scope>
        <!--  optional元素默认值(false) 不依赖传递-->
        <optional>true</optional>
    </dependency>

二、idea里面的maven插件含义

idea的maven插件 image.png

三、 常用的插件

一般我们写java项目只需要用一个打包插件即可,我们通常使用spring-boot-maven-pluginmaven assembly plugin这两个插件

spring-boot-maven-plugin介绍

maven-assembly-plugin插件的使用方法

maven-assembly-plugin插件的官方使用方法

maven-assembly-plugin插件的assembly文件官方介绍

自己写一个maven插件