精华内容
下载资源
问答
  • 自定义maven插件

    2021-03-16 20:32:46
    之前虽然一直知道maven插件是可以自定义的,不过一致没有用过。最近接触到了swagger项目中的codegen自动生成代码的功能,并且在codegen源码中,也是存在maven插件功能的,所以自己就尝试着自定义一个maven插件。并且...

    之前虽然一直知道maven插件是可以自定义的,不过一致没有用过。最近接触到了swagger项目中的codegen自动生成代码的功能,并且在codegen源码中,也是存在maven插件功能的,所以自己就尝试着自定义一个maven插件。并且从网上搜了一些资料自己写了一个demo。防止自己忘记,所以记录下来,哈哈哈!

    maven插件工程

    新建一个maven工程,名字为maven-plugin-demo1

    d1a70cb9134d4869841ca1a32c028214.png

    这里注意的是,打包方式packaging为maven-plugin。

    下面是我的maven的pom文件

    4.0.0

    site.wangxin520

    maven-plugin-demo1

    0.0.1-SNAPSHOT

    org.apache.maven.plugins

    maven-plugin-plugin

    3.2

    descriptor

    generate-resources

    org.eclipse.m2e

    lifecycle-mapping

    1.0.0

    org.apache.maven.plugins

    maven-plugin-plugin

    [3.2,)

    descriptor

    maven-plugin

    org.apache.maven.plugin-tools

    maven-plugin-annotations

    3.2

    org.apache.maven

    maven-plugin-api

    3.3.9

    当配置好maven的pom文件后,下面就开始编写一个自定义的插件java类。

    这里需要注意的是该自定义插件类,需要继承AbstractMojo.java,然后实现其中的execute方法package site.wangxin520.maven.plugin.demo.test1;

    import java.util.List;

    import org.apache.maven.plugin.AbstractMojo;

    import org.apache.maven.plugin.MojoExecutionException;

    import org.apache.maven.plugin.MojoFailureException;

    import org.apache.maven.plugins.annotations.LifecyclePhase;

    import org.apache.maven.plugins.annotations.Mojo;

    import org.apache.maven.plugins.annotations.Parameter;

    /**

    *

    * @author 王鑫

    *

    *         该类就是maven自定义插件类

    *

    */

    // mojo注解就是maven插件的注解,具体什么我忘记了。name就是后面使用该插件的时候excuation里面的,后面配置的是生命周期,我这里配置了install,即默认是安装时候执行本插件

    @Mojo(name = "mojoDemo1", defaultPhase = LifecyclePhase.INSTALL)

    public class MojoDemo1 extends AbstractMojo {

    // 配置的是本maven插件的配置,在pom使用configration标签进行配置 property就是名字,在配置里面的标签名字。在调用该插件的时候会看到

    @Parameter(property = "name")

    private String name;

    @Parameter(property = "modules")

    private List modules;

    // 执行的相关代码,即插件执行的语句。

    @Override

    public void execute() throws MojoExecutionException, MojoFailureException {

    System.out.println("!!!!!!!!!!!!!!!!!!!!");

    System.out.println(name);

    System.out.println("~~~~~~~~~~~~~~~~~~~~");

    System.out.println(modules);

    for (String string : modules) {

    System.out.println(string);

    }

    System.out.println("!!!!!!!!!!!!!!!!!!!!");

    }

    }

    当着一切都弄好后,就执行maven install,将本插件安装到本地的maven仓库中。方便后面调用。

    这里需要注意一下,maven插件的配置参数什么的,可以在maven官网看到。这里就不多做赘述了,后面我会加上连接。

    maven插件测试工程

    创建maven工程maven-plugin-test

    83c4d1bb5e634259a981f2ea077022fc.png

    为了方便后面使用,我弄成了组合工程,其中有两个模块。

    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    4.0.0

    site.wangxin520

    maven-plugin-test

    0.0.1-SNAPSHOT

    pom

    maven-plugin-part1

    maven-plugin-part2

    site.wangxin520

    maven-plugin-demo1

    0.0.1-SNAPSHOT

    mojoDemo1

    wangxin

    ${project.modules}

    上面就是添加插件的配置。

    下面就进行安装了。就可以执行自定义maven配置中的excute方法

    2d71def96131401a87d535a728454414.png

    以上就是maven自定义插件的配置和方法。是不是很简单!转载自Nixgnaw:www.wangxin520.site

    展开全文
  • 为了快速学习自定义 Maven 插件的过程,接下来将实现一个简单的 Hello Maven 插件,功能很简单:输出 Hello World 插件。具体步骤和操作如下。创建 Maven 新项目,选择 maven-archetype-plugin 项目向导,如图 1 所...

    为了快速学习自定义 Maven 插件的过程,接下来将实现一个简单的 Hello Maven 插件,功能很简单:输出 Hello World 插件。具体步骤和操作如下。

    创建 Maven 新项目,选择 maven-archetype-plugin 项目向导,如图 1 所示。

    7-1580899696.png

    图 1  选择Archetype

    单击 Next 按钮,进入设置 Maven 插件参数界面,输入要创建的插件的 groupId、artifactId 和版本,还有包名,如图 2 所示。

    10-1580899697.png

    图 2  输入坐标

    单击 Finish 按钮,Archetype 插件会自动创建好一个 Maven 插件项目。因为现在用的 Maven 是 3.x 版本的,所以有必要调整 Maven 插件项目必须依赖的 maven-plugin-api 的版本:从 2.x 改成 3.x。这里用的是 3.3.9 版本。样例项目中的 pom 配置如下,注意粗体标识部分。

    <?xml version="1.0" encoding="UTF-8"?> 4.0.0cn.com.mvn.pluginMvn.Hello.Plugin0.0.1-SNAPSHOTmaven-pluginMvn.Hello.Plugin Maven Pluginhttp://maven.apache.orgUTF-8org.apache.mavenmaven-plugin-api3.3.9org.apache.maven.plugin-toolsmaven-plugin-annotations3.2providedorg.codehaus.plexusplexus-utils3.0.8junitjunit4.7testorg.apache.maven.pluginsmaven-plugin-plugin3.2Mvn.Hello.Plugintruemojo-descriptordescriptorhelp-goalhelpmojorun-itsorg.apache.maven.pluginsmaven-invoker-plugin1.7true${project.build.directory}/it*/pom.xmlverify${project.build.directory}/local-repo src/it/settings.xmlcleantest-compileintegration-testinstallintegration-testverify

    到现在为止,基本上创建好了 Maven 插件项目。

    在 cn.com.mvn.plugin.hello 包下,创建 Java 类 HelloName,继承 AbstractMojo,并且在类上面使用 @goal 指定该 Mojo 的目标名称为 name,样例配置代码如下:

    package cn.com.mvn.plugin.hello; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; /** * @goal name */ public class HelloName extends AbstractMojo { public void execute() throws MojoExecutionException, MojoFailureException { } }

    在前面的代码基础上添加一个 name 属性,用来接收运行插件的时候传过来的 name 参数,并且使用 @parameter 将 name 属性标注成配置点,样例配置代码如下:

    package cn.com.mvn.plugin.hello; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; /** * @goal name */ public class HelloName extends AbstractMojo { /** * @parameter expression="${name}" * @required * @readonly */ String name; public void execute() throws MojoExecutionException, MojoFailureException { } }

    在 HelloName 类中的 execute() 方法中添加插件要实现的逻辑代码。这里的 HelloName 的功能很简单,只是打印问候,所以样例配置代码如下:

    package cn.com.mvn.plugin.hello; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; /** * @goal name */ public class HelloName extends AbstractMojo { /** * @parameter expression="${name}" * @required * @readonly */ String name; public void execute() throws MojoExecutionException, MojoFailureException { System.out.println("Hello" + name); } }

    这个插件的目的是打印对 name 的问候。如果 name 为空,或是空字符串,这样的问候就没什么意义了。用户就需要中止问候,并且以日志方式提示用户,样例配置代码如下:

    package cn.com.mvn.plugin.hello; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; /** * @goal name */ public class HelloName extends AbstractMojo { /** * @parameter expression="${name}" * @required * @readonly */ String name; public void execute() throws MojoExecutionException, MojoFailureException { if (this.name == null || this.name.trim().equals("")) { // 异常处理 throw new MojoExecutionException("name参数必须设置有效的值"); } else { System.out.println("Hello" + name); // 日志处理 this.getLog().info("这是运行日志提示: 执行完问候"); } } }

    到现在为止,HelloName Maven 插件的编写就完成了。要进行插件测试的话,还需要将自定义插件安装好,如果要共享给其他开发人员的话,还必须安装到私服或外面的中央仓库中。

    运行 mvn install 就可以完成在本地仓库的安装,如果要安装私服或中央仓库,请参考《Apache基金会的Archiva服务器的搭建步骤》和《Maven私服的配置和使用》教程。

    在命令行中输入如下命令。

    Mvn cn.com.mvn.plugin:Mvn.Hello.Plugin:name -Dname=zhangsan

    命令执行效果如下:

    [INFO] ————————————————————————

    [INFO] [INFO] — Mvn.Hello.Plugin:0.0.1-SNAPSHOT:name (default-cli) @ MvnDemoPlugin —

    Hello lisi

    [INFO] 这是运行日志提示:执行完问候

    [INFO] ————————————————————————

    [INFO] BUILD SUCCESS

    [INFO] ————————————————————————

    [INFO] Total time: 1.139 s

    [INFO] Finished at: 2017-01-08T11:55:48+08:00

    [INFO] Final Memory: 8M/108M

    [INFO] ————————————————————————

    创建一个简单的 Maven 项目,在它的 pom 中添加 HelloName 插件如下:

    cn.com.mvn.pluginMvn.Hello.Plugin0.0.1-SNAPSHOTnametestlisi

    执行 mvn test,可以看到如下日志。

    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

    [INFO] [INFO] — Mvn.Hello.Plugin:0.0.1-SNAPSHOT:name (default) @ MvnDemoPlugin —

    Hello lisi

    [INFO] 这是运行日志提示:执行完问候

    [INFO] ————————————————————————

    [INFO] BUILD SUCCESS

    展开全文
  • 自定义Maven打包插件

    2020-12-21 23:28:00
    比如它的打包插件maven-assembly-plugin可以根据模板配置自己想要的打包内容,但当它的模板配置无法满足自己定制化打包需求时,此时就需要我们将maven研究的更深入些,利用自定义maven插件去实现我们自己的打包逻辑...

    前言

      Maven大家都很熟悉,插件也非常丰富。比如它的打包插件maven-assembly-plugin可以根据模板配置自己想要的打包内容,但当它的模板配置无法满足自己定制化打包需求时,此时就需要我们将maven研究的更深入些,利用自定义maven插件去实现我们自己的打包逻辑。

    自定义Maven打包插件实战

    打包业务描述:

      打包时,根据需要打包的模块.json配置文件,动态打入自己需要的Controller,排除掉不需要的模块Controller类。

    打包插件设计思路:

    在这里插入图片描述

    插件使用如下:

    在这里插入图片描述

    一 、先创建Maven项目,编写pom.xml

    <?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>pre-maven-plugin</artifactId>
        <packaging>maven-plugin</packaging>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
            <maven.plugin.api>3.5.0</maven.plugin.api>
            <maven-plugin-annotations>3.5.2</maven-plugin-annotations>
            <reflections.version>0.9.10</reflections.version>
            <fastjson.version>1.2.58</fastjson.version>
            <lombok.version>1.18.16</lombok.version>
            <commons-io.version>2.6</commons-io.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.apache.maven</groupId>
                <artifactId>maven-plugin-api</artifactId>
                <version>${maven.plugin.api}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.maven.plugin-tools</groupId>
                <artifactId>maven-plugin-annotations</artifactId>
                <version>${maven-plugin-annotations}</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.reflections</groupId>
                <artifactId>reflections</artifactId>
                <version>${reflections.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>${commons-io.version}</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-plugin-plugin</artifactId>
                    <version>3.6.0</version>
                </plugin>
            </plugins>
        </build>
    
    
    </project>
    

    注意:maven插件的 packaging 必须是maven-plugin,其次是需要依赖的jar包maven-plugin-api、maven-plugin-annotations。

    二、编写插件实现类

    package mojo;
    
    import com.alibaba.fastjson.JSON;
    import dto.Module;
    import lombok.Data;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.maven.plugin.AbstractMojo;
    import org.apache.maven.plugin.MojoExecutionException;
    import org.apache.maven.plugin.MojoFailureException;
    import org.apache.maven.plugins.annotations.LifecyclePhase;
    import org.apache.maven.plugins.annotations.Mojo;
    import org.apache.maven.plugins.annotations.Parameter;
    
    import java.io.File;
    import java.io.IOException;
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    import java.nio.file.Files;
    import java.text.MessageFormat;
    import java.util.*;
    import util.*;
    
    /**
     * @author zkc
     * @version 1.0.0
     * @since 2020-12-21
     */
    @Mojo(name = "jwfRepackage", defaultPhase = LifecyclePhase.PACKAGE)
    @Data
    public class ZkcRepackageMojo extends AbstractMojo {
        /**
         * 应用的模块json配置文件,支持“,”逗号分隔多个应用
         */
        @Parameter(required = true)
        private String applicationModuleJson;
        /**
         * 配置应用模块json所在文件夹名称,默认application
         */
        @Parameter
        private String applicationFolderName = "application";
        /**
         * maven编译时classes路径,只读,不需要手动配置
         */
        @Parameter(defaultValue = "${project.compileClasspathElements}", readonly = true, required = true)
        private List<String> compilePath;
        /**
         * maven项目中版本号,只读,不需要手动配置
         */
        @Parameter(defaultValue = "${project.version}", readonly = true, required = true)
        private String projectVersion;
        /**
         * maven项目中artifactId,只读,不需要手动配置
         */
        @Parameter(defaultValue = "${project.artifactId}", readonly = true, required = true)
        private String artifactId;
    
    
        @Override
        public void execute() throws MojoExecutionException, MojoFailureException {
    
            long startTime = System.currentTimeMillis();
            System.out.println(MessageFormat.format("自定义分模块打包插件开始执行:[{0}]", startTime));
    
            // 解析应用模块json配置文件
            List<Module> moduleList = analysisApplicationModuleJson(StringUtils.split(applicationModuleJson, ","));
            if (CommonUtil.isCollectionEmpty(moduleList)) {
                System.out.println(MessageFormat.format("应用模块json解析为空:maven编译地址[{0}],应用模块json地址[{1}]", String.join(",", compilePath), applicationModuleJson));
                return;
            }
    
            // 自定义类加载器,加载原始jar包,过滤出非应用的模块Controller类
            String moduleJarPath = PathUtil.buildJarPath(compilePath) + PathUtil.buildJarName(artifactId, projectVersion);
            Set<String> excludeClasses = getExcludeClasses(moduleJarPath, moduleList);
            if (CommonUtil.isCollectionEmpty(excludeClasses)) {
                long endTime = System.currentTimeMillis();
                System.out.println(MessageFormat.format("自定义分模块打包插件结束执行,没有需要排除的模块Class,耗时:[{0}]毫秒", endTime - startTime));
                return;
            }
    
            // 删除无用的应用模块Controller类,重新打包
            try {
                JarUtil.delete(moduleJarPath, excludeClasses);
            } catch (Exception e) {
                System.out.println(MessageFormat.format("删除无用应用模块Controller类,重新打包失败:[{0}],[{1}]", moduleJarPath, excludeClasses));
                e.printStackTrace();
            }
    
            long endTime = System.currentTimeMillis();
            System.out.println(MessageFormat.format("自定义分模块打包插件结束执行,供排除[{0}]个非应用模块Class,耗时:[{1}]毫秒", excludeClasses.size(), endTime - startTime));
    
        }
    
        /**
         * 解析应用模块json配置文件
         *
         * @param moduleJsons 应用模块json配置地址
         * @return 返回解析后的模块集合
         */
        private List<Module> analysisApplicationModuleJson(String[] moduleJsons) {
            if (CommonUtil.isArrayEmpty(moduleJsons) || CommonUtil.isCollectionEmpty(compilePath)) {
                return null;
            }
            List<Module> moduleList = new ArrayList<>();
            Arrays.stream(moduleJsons).forEach(moduleJson -> {
                String moduleJsonPath = PathUtil.buildModuleJsonPath(compilePath, moduleJson, applicationFolderName);
                File jsonFile = new File(moduleJsonPath);
                if (!jsonFile.exists()) {
                    System.out.println(MessageFormat.format("应用模块json文件未找到:[{0}]", moduleJsonPath));
                }
                try {
                    List<Module> moduleListTemp = JSON.parseArray(new String(Files.readAllBytes(jsonFile.toPath())),
                            Module.class);
                    moduleList.addAll(moduleListTemp);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            return moduleList;
        }
    
        /**
         * 自定义类加载器,加载原始jar包,过滤出非应用的模块Controller类
         *
         * @param moduleJarPath 原始jar包路径
         * @param moduleList    应用模块类集合
         * @return 返回需要过滤的模块类
         */
        @SuppressWarnings("unchecked")
        private Set<String> getExcludeClasses(String moduleJarPath, List<Module> moduleList) {
            Set<String> excludeClasses = new HashSet<>();
            ModuleClassLoader moduleClassLoader = new ModuleClassLoader(moduleJarPath);
            ModuleClassLoader.getModuleClassMap().forEach((className, bytes) -> {
                // 解析@ModuleController注解
                try {
                    Class clazz = moduleClassLoader.loadClass(className);
                    Annotation[] annotations = clazz.getAnnotationsByType(moduleClassLoader.loadClass(PathUtil.MODULE_CLASS));
                    for (Annotation annotation : annotations) {
                        Class aClass = annotation.getClass();
                        try {
                            Method method = aClass.getMethod(PathUtil.MODULE_METHOD);
                            String value = (String) method.invoke(annotation);
                            boolean moduleClassFlag = moduleList.stream().anyMatch(module -> Objects.equals(module.getModuleId(), value));
                            if (!moduleClassFlag) {
                                excludeClasses.add(className);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                } catch (ClassNotFoundException e) {
                    System.out.println(MessageFormat.format("加载[{0}]类报错,因未加载对应jar包,可忽略", className));
                }
            });
            return excludeClasses;
        }
    
    }
    
    

    注意:maven插件支持注解方式和Javadoc 方式开发,本实战中使用注解方式@Mojo指定插件的目标类和插件的运行阶段。

    三、自定义类加载

    package util;
    
    import org.apache.commons.lang3.StringUtils;
    
    import java.io.*;
    import java.text.MessageFormat;
    import java.util.*;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.jar.JarEntry;
    import java.util.jar.JarFile;
    
    /**
     * @author zkc
     * @version 1.0.0
     * @since 2020-12-21
     */
    public class ModuleClassLoader extends ClassLoader {
    
        private final static Map<String, byte[]> MODULE_CLASS_MAP = new ConcurrentHashMap<>();
    
        public ModuleClassLoader(String moduleJarPath) {
            try {
                readJar(moduleJarPath);
            } catch (IOException e) {
                System.out.println(MessageFormat.format("读取jar包异常:地址[{0}]", moduleJarPath));
                e.printStackTrace();
            }
        }
    
        public static void addClass(String className, byte[] byteCode) {
            if (!MODULE_CLASS_MAP.containsKey(className)) {
                MODULE_CLASS_MAP.put(className, byteCode);
            }
        }
    
        /**
         * 遵守双亲委托规则
         *
         * @param name 类全路径
         * @return 返回类字节码对象
         */
        @Override
        protected Class<?> findClass(String name) {
            try {
                byte[] result = getClass(name);
                if (result != null) {
                    return defineClass(name, result, 0, result.length);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        private byte[] getClass(String className) {
            return MODULE_CLASS_MAP.getOrDefault(className, null);
        }
    
        private void readJar(String moduleJarPath) throws IOException {
            readJarFile(moduleJarPath);
        }
    
        private void readJarFile(String moduleJarPath) throws IOException {
            File file = new File(moduleJarPath);
            if (!file.exists()) {
                throw new FileNotFoundException();
            }
            JarFile jarFile = new JarFile(file);
            Enumeration<JarEntry> enumeration = jarFile.entries();
            while (enumeration.hasMoreElements()) {
                JarEntry jarEntry = enumeration.nextElement();
                String name = jarEntry.getName().replace("BOOT-INF/classes/", "").replace("\\", ".")
                        .replace("/", ".");
                if (isRead(name)) {
                    String className = name.replace(".class", "");
                    try (InputStream input = jarFile.getInputStream(jarEntry); ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
                        int bufferSize = 1024;
                        byte[] buffer = new byte[bufferSize];
                        int bytesNumRead;
                        while ((bytesNumRead = input.read(buffer)) != -1) {
                            baos.write(buffer, 0, bytesNumRead);
                        }
                        addClass(className, baos.toByteArray());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        private boolean isRead(String name) {
            return StringUtils.isNotBlank(name) && name.endsWith(PathUtil.CLASS)
                    && (name.startsWith(PathUtil.COMMON_CONTROLLER) || name.startsWith(PathUtil.COMMON_ANNOTATION));
        }
    
        public static Map<String, byte[]> getModuleClassMap() {
            return MODULE_CLASS_MAP;
        }
    }
    
    
    

    注意:maven插件运行时,插件的运行环境中类加载器肯定只会加载插件本身的class信息。如果你想操作应用的类,需要自定义类加载器,通过一定的寻址逻辑找到你想加载的jar包,自行加入到插件的运行环境中。

    四、备份原始springboot的jar包,生成新jar包

    package util;
    
    import org.apache.commons.io.FileUtils;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.text.MessageFormat;
    import java.util.Enumeration;
    import java.util.Set;
    import java.util.jar.JarEntry;
    import java.util.jar.JarFile;
    import java.util.jar.JarOutputStream;
    
    /**
     * @author zkc
     * @version 1.0.0
     * @since 2020-12-21
     */
    public class JarUtil {
    
        public static void delete(String jarName, Set<String> deletes) throws Exception {
            // 先备份原始jar包
            File oriFile = new File(jarName);
            if (!oriFile.exists()) {
                System.out.println(MessageFormat.format("排除类时,原始jar包不存在[{0}]", jarName));
                return;
            }
            // 以时间戳重命名备份文件名
            String bakJarName = jarName.substring(0, jarName.length() - 3) + System.currentTimeMillis() + PathUtil.JAR;
            File bakFile = new File(bakJarName);
            // 备份原始jar包
            FileUtils.copyFile(oriFile, bakFile);
            // 排除deletes中的class,重新打包新jar包文件
            JarFile bakJarFile = new JarFile(bakJarName);
            JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarName));
            Enumeration<JarEntry> entries = bakJarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                String name = entry.getName().replace("BOOT-INF/classes/", "").replace("\\", ".").replace("/", ".").replace(".class", "");
                if (!deletes.contains(name)) {
                    InputStream inputStream = bakJarFile.getInputStream(entry);
                    jos.putNextEntry(entry);
                    byte[] bytes = readStream(inputStream);
                    jos.write(bytes, 0, bytes.length);
                } else {
                    System.out.println(MessageFormat.format("排除非应用模块类:[{0}]", entry.getName()));
                }
            }
            // 关闭流
            jos.flush();
            jos.finish();
            jos.close();
            bakJarFile.close();
        }
    
        private static byte[] readStream(InputStream inStream) throws Exception {
            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            outSteam.close();
            inStream.close();
            return outSteam.toByteArray();
        }
    
    }
    
    

    五、自定义模块注解类

    package com.zkc.web.annotation;
    
    import java.lang.annotation.*;
    
    /**
     * @author zkc
     * @version 1.0.0
     * @since 2020-12-21
     */
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Module {
    
        String moduleId();
    
        String moduleName();
    
    }
    
    

    插件运行效果

    [INFO] 
    [INFO] --- pre-maven-plugin:1.0-SNAPSHOT:jwfRepackage (default) @ web ---
    自定义分模块打包插件开始执行:[1,608,560,919,883]
    排除非应用模块类:[BOOT-INF/classes/com/zkc/web/controller/ProductController.class]
    排除非应用模块类:[BOOT-INF/classes/com/zkc/web/controller/RoleController.class]
    自定义分模块打包插件结束执行,供排除[2]个非应用模块Class,耗时:[153]毫秒
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    

    完整代码以上传码云

    码云地址: git地址


    我的专栏

    1. 设计模式
    2. 认证授权框架实战
    3. java进阶知识
    4. maven进阶知
    5. spring进阶知识
    展开全文
  • 自定义Maven插件及Debug

    2021-04-22 11:42:47
    自定义Maven插件 maven本质上就是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven- compiler-plugin完成的。进一步说,每个任务对应了一个插件目标...

    自定义Maven插件

    maven本质上就是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven- compiler-plugin完成的。进一步说,每个任务对应了一个插件目标(goal),每个插件会有一个或者多个目标,例如maven- compiler-plugin的compile目标用来编译位于src/main/java/目录下的主源码,testCompile目标用来编译位于src/test/java/目录下的测试源码。

    用户可以通过两种方式运行maven插件目标。第一种方式是直接运行命令,比如我们自定义插件test-maven-plugin,那么执行mvn test:run(run是插件中自行指定的名称),这种调用方式与生命周期没有关系。第二种方式是将插件目标与生命周期阶段绑定,用户在执行maven生命周期阶段运行我们的自定义插件,例如Maven默认将maven-compiler-plugin的compile目标与 compile生命周期阶段绑定,因此命令mvn compile实际上是先定位到compile这一生命周期阶段,然后再根据绑定关系调用maven-compiler-plugin的compile目标。

    自定义插件

    在项目中新建一个moudle作为插件。勾选Create from archetype,并选择maven-archetype-mojo。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yhoFW49C-1619062943433)(http://images.sunshunkai.com//picimage-20210422103631809.png)]

    填写插件信息,插件名一般取myname-maven-plugin,官方定义的取名为maven-name-plugin。

    在这里插入图片描述

    如果不是使用Idea自带maven的可以自行选择maven。

    在这里插入图片描述

    项目创建完成之后,我们还需要进入插件相关的依赖

    <dependency>
          <groupId>org.apache.maven</groupId>
          <artifactId>maven-plugin-api</artifactId>
          <version>2.0</version>
        </dependency>
    
        <dependency>
          <groupId>org.apache.maven.plugin-tools</groupId>
          <artifactId>maven-plugin-annotations</artifactId>
          <version>3.1</version>
        </dependency>
    
        <dependency>
          <groupId>org.codehaus.gmaven</groupId>
          <artifactId>gmaven-mojo</artifactId>
          <version>1.5-jenkins-3</version>
        </dependency>
    
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.2</version>
          <scope>test</scope>
        </dependency>
    

    接下来我们就可以编写插件代码了,自定义一个类继承AbstractMojo,重写execute方法,execute就是我们插件需要运行的逻辑,最后需要在类上添加@Mojo,其中name就是我们需要运行时指定运行目标的名字。

    @Mojo(name = "hello")
    public class HelloMojo extends AbstractMojo {
    
        public void execute() throws MojoExecutionException, MojoFailureException {
            System.out.println("hello world,my plugin run...");
        }
    
    }
    

    插件编写完成之后,需要执行mvn install进行安装就可以被其他项目引用使用了。

    命令方式运行插件

    在项目中引入自定义插件

    <plugin>
            <groupId>com.ssk</groupId>
            <artifactId>ssk-maven-plugin</artifactId> 
            <version>1.0-SNAPSHOT</version>
     </plugin>
    

    在我们Idea右侧的插件栏中可以看到我们自定义的插件,点击可以直接运行插件命令,也可以通过mvn ssk:name,其中冒号前面的为插件的名,name与@Mojo中指定的goal name保持一致。

    在这里插入图片描述

    运行结果

    在这里插入图片描述

    绑定到Maven生命周期运行插件

    将自定义插件绑定到Maven生命周期上,可以在支持生命周期的命令的时候,执行自定义插件。在引用自定义插件的项目中引入插件,goal为我们需要执行插件的名字,对应@Mojo中的name,phase标签为生命周期阶段,这里我们选择在compile阶段执行自定义插件。

    <plugin>
        <groupId>com.ssk</groupId>
        <artifactId>ssk-maven-plugin</artifactId>
        <version>1.0-SNAPSHOT</version>
        <!-- 自定义插件处理时机 -->
        <executions>
            <execution>
                <goals>
                    <goal>hello</goal>
                </goals>
                <phase>compile</phase>
            </execution>
        </executions>
    </plugin>
    

    执行mvn compile可以看到打印插件信息。

    在这里插入图片描述

    Maven Debug

    我们在执行maven命令的时候出现异常,根据错误日志很难找到问题,这时候通过Debug就可以很清除的看到插件的运行情况。现在我们的插件代码中打上断点。如果是Debug别人的插件,可以根据报错的位置打上断点。

    在这里插入图片描述

    在正常使用mvn命令的后面加上debug就可以以Debug的方式运行了,并显示监听端口是8000,

    在这里插入图片描述

    在Configurations面板输入如下信息,Name自行定义,Port要与上面的端口号一致。

    在这里插入图片描述

    选中刚才选中的组件点击运行。

    在这里插入图片描述

    进入到我们设置断点的位置,接下来就可以按照正常的流程往下Debug了。

    在这里插入图片描述

    展开全文
  • 自定义Maven插件

    2021-03-16 20:33:55
    第一、自定义Maven插件概述Mojo:Maven plain Old Java Object。每一个 Mojo 就是 Maven 中的一个执行目标(executable goal),而插件则是对单个或多个相关的 Mojo 做统一分发。一个 Mojo 包含一个简单的 Java 类。...
  • Maven 自定义Maven插件

    2021-03-16 20:32:51
    1.介绍我们经常在pom的时候,会在build的几点里面配有各式各样的plugin,这些plugin就是maven插件,他们通常叫做Mojo,这些插件的作用就是在构建项目的过程中,执行一些动作,行为,例如使用maven-jar-plugin的...
  • 如果说在整合的时候,你发现哪个哥们他的模块有问题。数据库的整合,订单模块里面的内容需要调用到商品模块的内容。 当你中招了之后,这是好事,犯了错,才能解决嘛。纵观整个软件开发历史,也有几十年的历史了吧...
  • 前面实现了简单自定义 Maven 插件编写和测试,在代码中用到了 @goal 和 @parameter,分别用来标记插件的目标和参数。接下来详细介绍编写 Maven 插件要用到的标记。Mojo 标记自定义 Maven 插件的常用标记如下所示。...
  • 我已经编写了自己的自定义Maven插件并将其上传到我的Archiva服务器.它与指定的全名一起工作正常:mvn com.mjolnirr:maven-plugin:manifest但是当我想通过前缀来做它时,它会失败:mvn mjolnirr:manifest[ERROR] No ...
  • 但是,遗憾的是,老师没有介绍如何去构建这样一个特殊的项目,用于创建项目骨架。于是,本着面向“百度”编程的原则,去网上查了下,不是十多年前的“古董”文章,就是流程不清楚,有的需要部署到私服,有的包含大量...
  • 如何开发自己的插件 1. maven 插件的命名规范 在一个项目之前,第一件事就是确定一个名称。maven 插件也不例外。它有着自己的一套命名规范。但是规范很简单,一句话就可以概括,**官方插件命名的格式为 maven...
  • 前言 在日常的maven项目开发中,我们自己开发maven插件的机会是比较少,因为市面上的maven插件基本上就可以满足我们的日常开发需求。maven官方也提供了很多插件,详情可见如下链接 ...
  • maven进阶插件

    2020-12-18 23:29:40
    通过mvn package指令打包,会在target目录下生成jar包,并将依赖包拷贝到target/lib目录下,目录结构如下: 方案二:使用assembly插件(后面会具体介绍) 可以直接java -jar xx运行,但是在这里我如果自定义assembly...
  • 首先下载源码,导入idea,并且构建成功,如何构建见另一篇https://mp.csdn.net/editor/html/114141447 后边联调先不用管 找到apm-sdk-plugin 在下边新建module 项目 。 也可以单拉项目,这边我没有新建 直接在...
  • Maven高级之插件开发

    2021-09-19 20:41:52
    终于来到了Maven的插件开发,其实Maven的插件并没有想象的那么难,刚开始讲Maven基础的时候就演示了一下JDK是如何打包的,Maven打包只是在JDK打包上封装了一层而已,Maven也支持自定义插件开发 创建 我们先使用...
  • 自定义插件的方法 在Gradle中创建自定义插件,Gradle提供了三种方式: 在build.gradle脚本中直接使用 在buildSrc中使用 在独立Module中使用 开发Gradle插件可以在IDEA中进行开发,也可以在Android Studio中进行开发...
  • Sonar-扫描插件自定义扩展

    千次阅读 2021-06-13 08:27:43
    说的开发插件其实本质就是利用源设计者留下的入口拿到源事件然后进行实现,最终你的实现会在你不知道的时间,不知道的地点被调度执行,这就是设计模式的魅力,保证了开闭原则下进行了功能扩展 那么Sonar的设计...
  • 我有一个类似的问题:this previous question...例如-javaagent:lib/eclipselink.jar我试图让Netbeans启动开发应用程序(我们将编写自定义的启动脚本进行最终部署)由于我使用Maven管理Eclipselink依赖项,我可能不知道...
  • jenkins自定义插件开发

    2021-08-31 20:27:14
    在按照提示创建项目时,如果apche-maven的settings.xml配置的远程仓库是aliyun,创建直接成功,目录下无文件。切换成http://repo.maven.apache.org/maven2就可以了 mvn -U archetype:generate -Dfilter="io....
  • 来源:cnblogs.com/homejim/p/9782403.html1,创建代码生成器1.1,创建Maven项目1.2,配置generator.xml1.3,配置pom.xml1.4...
  • 前言 在日常开发中,不可避免的需要把自己的 library 发布到 maven 仓库中,这样使用起来...maven插件,是 Gradle 1.0 的时候提供的用于发布aar/jar包到 Maven 仓库的插件。在 Gradle 1.3 中,引入了一种新的发布插件
  • 创建自定义 gradle 插件的三种方法

    万次阅读 2021-01-30 16:19:32
    创建自定义 gradle 插件的三种方法 要创建 Gradle 插件,我们需要编写一个实现 Plugin 接口的类。将插件应用于项目时,Gradle 将创建插件类的实例,并调用该实例的 Plugin.apply()方法。项目对象作为参数传递,...
  • Mybatis插件:自定义插件、分页及通用Mapper 1、 插件简介 一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展。这样的好处是显而易见 的,一是增加了框架的灵活性。二是开发者可以结合实际需求...
  • Maven 插件编写 之 Mojo

    2021-02-26 16:14:24
    虽然说大多数情况下,我们可能不太会自己去编写 Maven 插件,但不排除在某些特殊的情况下,我们需要去完成一个自己的插件,来协助我们处理某些比较通用的事情。2.Maven 插件的命名规范一般来说,我们会将自己的插件...
  • 本文内容包括:利用AndroidStudio,编写自定义Gradle pluginMavenDeployer 发布plugin使用Gradle plugin简介之前了一个Android中的AOP框架Cooker.这里总结一下里面用到的两块小知识:1)自定义 Gradle plugin2)发布...
  • Spring Boot Maven Plugin打包解析一. 简介二. Spring Boot Maven Plugin的引用三. Spring Boot Maven Plugin的使用1. 继承 Starter Parent POM2. 在没有 Starter Parent POM 的情况下使用 Spring Boot3. 在命令行上...
  • 如果你刚好把AndroidStudio升级到Android Studio Arctic Fox版本,刚好想新建一个工程来编写自定义Gradle插件,你就会发现你掉坑里了(没错,就是笔者本人了!),噩梦从此开始,一切都是因为你新建的工程中Gradle...
  • java logstash 自定义插件 编译源码 下载gradle 配置gradle-6.6\init.d 为国内镜像地址 allprojects { repositories { maven { url 'file:///C:/Java/maven_repository'} mavenLocal() maven { name ...
  • 老铁昨天下午问我什么时候讲讲Maven插件:于是老田搞到大半夜终于了一篇maven插件,今天分享给大家。想进一步详聊了请加我微信tj20120622,进群和大家一起聊技术。Maven...
  • 大多数框架,都支持插件,用户可通过编写插件来自行扩展功能,Mybatis也不例外。我们从插件配置、插件编写、插件运行原理、插件注册与执行拦截的时机、初始化插件、分页插件的原理等六个方面展...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,817
精华内容 10,326
关键字:

maven自定义插件编写