精华内容
下载资源
问答
  • 这里介绍一种通过Maven中的插件,基于命令行实现依赖树查看的方法。 基本命令如下: mvn dependency:tree 在项目工程中使用该命令可以查看当前工程依赖包所产生的依赖树。 当然,在我们使用多模块编程时,会遇到...

    Maven 是当前最普及的包管理工具,在我们的项目变大后会时不时的遇到需要解决依赖冲突的场景。这里介绍一种通过Maven中的插件,基于命令行实现依赖树查看的方法。


    基本命令如下:

    mvn dependency:tree
    

    在项目工程中使用该命令可以查看当前工程依赖包所产生的依赖树。
    在这里插入图片描述
    当然,在我们使用多模块编程时,会遇到由于找不到对应的依赖包而报错。这时你需检查报错的依赖包是否是你当前工程中的子模块,如果是这样的话则需要先将工程打包到本地Maven仓库后再执行依赖树查看命令:

    mvn clean install dependency:tree
    

    当我们想要查看当前依赖树的冲突情况时,则需要添加选项 -Dverbose 则可以看到依赖冲突的详细情况。

    mvn dependency:tree -Dverbose
    

    在这里插入图片描述

    处理 Maven 依赖冲突

    如果发生依赖冲突,首先,对于多个jar包都引用同一jar包的情况。
    在这里插入图片描述
    最好是在程序中显式定义被共同引用的jar包的依赖,来统一版本号,方便维护。
    在这里插入图片描述
    如果模块A模块B都统一依赖包C,可能会出现两种情况

    1. AB 引用的 C 版本相同
      这时按照pom.xml定义顺序选择第一个即可,没有冲突问题,如果在项目的 Maven 中显示定义了C 依赖,那么用选择项目定义的依赖,反正版本都一样,没有影响。
      在这里插入图片描述
    2. AB依赖的C版本不同,选择版本高的那个,这时会出现两种结果

    在这里插入图片描述
    2.1 高版本兼容低版本,所以不会出现问题
    2.2 高版本不兼容低版本

    假如A依赖C2版本,B依赖C3版本,C3不兼容C2,Maven选择了高版本C3,对A来说会出现问题

    解决方法

    1. 提升A版本,找到依赖C3A版本
    2. 如果B版本也可依赖C2,在项目的Maven中显示定义对C2的依赖,这样所有都使用C2版本
    3. 如果B版本不支持C2版本,只能降低B版本,找到依赖C2B版本

    从功能性和可维护性考虑,优先使用高版本的依赖,因为理论上来说高版本的依赖会有更少的 bug和更好的性能。只有极少数情况下需要考虑低版本的兼容问题,但是这样会产生技术债务,建议作为应急方案使用,并尽早升级高版本的依赖。

    参考资料

    Resolving conflictss using the dependency tree
    maven 依赖jar包时版本冲突的解决

    展开全文
  • 开发完成后在命令行执行mvn clean test 想执行一下全部的单元测试 发现编译失败, 提示符号找不到。但在intellij idea中明明没有任何编译错误啊。 折腾了半天 发现原来父pom中的maven-compiler插件版本太低导致 <...
        

    开发完成后在命令行执行mvn clean test 想执行一下全部的单元测试 发现编译失败, 提示符号找不到。
    但在intellij idea中明明没有任何编译错误啊。

    折腾了半天 发现原来父pom中的maven-compiler插件版本太低导致

    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>

    改用最新的版本即可

    <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin -->
    <dependency>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.5.1</version>
    </dependency>
    
    展开全文
  • Maven插件命令行执行

    千次阅读 2015-07-26 06:24:25
    用了一段时间的maven,但是只是简单的...最近好好接触了一下maven的生命周期和插件机制,被其强大的可配置性所折服。此处简要记录自己所感并分享。 简单接触 maven中所有的插件都是配置在标签<build>-->&l...
        

    用了一段时间的maven,但是只是简单的使用它来解决依赖问题以及打包而已,配置文件只是使用了<dependency>这么一个配置。最近好好接触了一下maven的生命周期和插件机制,被其强大的可配置性所折服。此处简要记录自己所感并分享。

    简单接触

    maven中所有的插件都是配置在标签<build>--><plugins>下面,其下每一个<plugin>标签对应一个插件。官方自带的插件五花八门,用的最多的无非是maven-compiler-pluginmaven-dependency-pluginmaven-surefire-plugin等。官方网址
    每一个插件可以定义插件的groupIdartifactId,以及要执行的<executions>executions下可以定义一大堆的execution用来定义具体的任务,其中又包括目标、绑定的阶段、配置等参数。大致上配置文件如下:

    xml<build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.3</version>
                    <executions>
                        <execution>
                            <id>compile</id>
                            <goals>
                                <goal>compile</goal>
                            </goals>
                            <configuration>
                                <source>1.7</source>
                                <target>1.7</target>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <version>2.10</version>
                    <executions>
                        <execution>
                            <id>get_source</id>
                            <goals>
                                <goal>get</goal>
                                <goal>unpack</goal>
                            </goals>
                            <phase>process-resources</phase>
                            <configuration>
                                <artifact>com.alibaba.middleware.race:rpc-api:1.0:jar:sources</artifact>
                                <artifactItems>
                                    <artifactItem>
                                        <groupId>com.alibaba.middleware.race</groupId>
                                        <artifactId>rpc-api</artifactId>
                                        <version>1.0</version>
                                        <classifier>sources</classifier>
                                    </artifactItem>
                                </artifactItems>
                                <outputDirectory>${project.build.sourceDirectory}</outputDirectory>
                                <excludes>META-INF\/**</excludes>
                            </configuration>
                        </execution>
                    </executions>
    
                    <!--<configuration>-->
                        <!--<artifact>com.alibaba.middleware.race:rpc-api:1.0:jar:sources</artifact>-->
                    <!--</configuration>-->
                </plugin>
            </plugins>
        </build>
    

    其中maven-dependency-plugin插件下的任务先从中央库下载com.alibaba.middleware.race:rpc-api:1.0:jar:sources的jar包,再解压到指定的目录并排除META-INF文件夹。(由于本人刚接触,这种写法可能不是最佳实践,如果有人有更好的写法的话恳请告知。)这个id为get_source的任务绑定到了阶段process-resources,在执行到default生命周期的该阶段时会执行这个任务。运行mvn compile,成功执行,感觉良好。

    命令行执行

    现在想要在命令行下不是执行某个阶段,而是直接执行某个插件的任务。命令

    mvn org.apache.maven.plugins:maven-dependency-plugin:get -Dartifact=com.alibaba.middleware.race:rpc-api:1.0:jar:sources
    

    或者其缩写

    mvn dependency:get -Dartifact=com.alibaba.middleware.race:rpc-api:1.0:jar:sources
    

    成功下载了指定的源文件。看来命令行执行插件也很容易,但是有一个小问题:我没办法不指定artifact,也就是直接执行

    mvn dependency:get
    

    会有错误。但是我想使用配置文件中的artifact配置,而不想每次运行都敲那么一大串(不使用周期绑定的情况下)。

    我尝试了在上面的配置文件中加入了注释掉的那部分内容,直接运行mvn dependency:get,没出错,似乎可行。

    想要更灵活的命令行执行

    注释部分的内容虽然可行,dependency插件的get任务虽然找到了该配置,但是缺点也很明显:

    1. 我没办法针对不同的任务使用不同的配置;
    2. 我没办法一条命令运行两个任务。

    对于1,假如现在我有另一个id为get_sources2的任务,它是把com.alibaba.middleware.race:rpcapi:2.0:jar:sources这么一个版本的包下载并拷贝到相同目录下,而且和get_sources只能运行一个。这样的话明显的不能使用“全局的配置”,这样会有冲突;而在每个execution中定义的参数,是没办法被mvn dependency:get这样识别的。

    对于2,我要想执行“下载并解压到指定目录”这个操作,必须执行:

    mvn dependency:get
    mvn dependency:unpack ##(当然,需要先向get那样配置参数)
    

    两条语句虽然不多,但是当任务中又有copy等其他goal时,也是相当麻烦的。

    最为理想的状态是:有这么一条命令,能够让我指定运行时的某个插件具体的任务,而不是仅仅运行某个目标。比如类似如下的命令:

    mvn dependency:get_sources ##(get_sources为某个execution的id)
    

    这样的话,这两个问题都完美解决了(不绑定生命周期的阶段情况下)。但是很遗憾,maven不支持这种操作

    不过倒是有一种办法可以解决问题1:使用默认的execution id名:default-cli。凡是execution iddefault-cli的任务,命令行运行时如果goalgoals中有定义,则goal与其参数会被执行。这其实是将“全局配置”放在了“默认配置”中。好处在于可以定义几个任务,然后需要执行哪个任务,只需要把<id>改为default-cli就行了。虽然要修改pom.xml,但是也不算麻烦。

    对于问题2,如果存在任务之间的依赖定义的话,倒是可以把目标getunpack分别定义在不同的任务中,然后任务中指定依赖关系:unpack依赖get,这样只需要执行unpack即可自动执行get,就像ant中<target>depends那样。但是我没有找到如何定义这种“任务间的依赖”。

    更深入的学习

    当然,并非没有可能简化:如果能自己写一个插件的话,一切问题都不在话下。但是现在自己的水平还远远没有到那种程度。学习之路依旧遥远。

    PS:Maven相比于ant的很大的进步之处在于其周期和阶段的概念。除了极少数不适合绑定阶段的任务外还是多使用阶段和任务的绑定比较好,能省很多麻烦。

    PPS:本人学习maven未深,理解可能出现偏差,如果有人发现文中的疏漏或者错误,恳请指正以免误导他人。

    展开全文
  • 我们知道Maven具体构建动作都是由插件执行的,maven本身只是提供一个框架,这样就提供了高度可定制化的功能,我们用maven命令执行比如mvn clean package这样的命令时maven会将package这个阶段(phase)绑定到相应的...

    maven的插件

    我们知道Maven具体构建动作都是由插件执行的,maven本身只是提供一个框架,这样就提供了高度可定制化的功能,我们用maven命令执行比如mvn clean package这样的命令时maven会将package这个阶段(phase)绑定到相应的生命周期(lifecycle),再寻找项目(project)里配置的plugin,执行具体的plugin完成持续构建

    maven绑定插件(plugin)

    maven在读取命令行之后会根据命令行参数是系统默认的phase还是其他的自定义插件(goal)来解析成task参数,继而根据这些task参数来生成插件执行列表。

    for ( Object task : tasks ) { if ( task instanceof GoalTask ) { String pluginGoal = ( (GoalTask) task ).pluginGoal;
    
                    MojoDescriptor mojoDescriptor = mojoDescriptorCreator.getMojoDescriptor( pluginGoal, session, project );
    
                    MojoExecution mojoExecution =
                        new MojoExecution( mojoDescriptor, "default-cli", MojoExecution.Source.CLI );
    
                    mojoExecutions.add( mojoExecution );
                }
                else if ( task instanceof LifecycleTask )
                {
                    String lifecyclePhase = ( (LifecycleTask) task ).getLifecyclePhase();
    
                    Map<String, List<MojoExecution>> phaseToMojoMapping =
                        calculateLifecycleMappings( session, project, lifecyclePhase );
    
                    for ( List<MojoExecution> mojoExecutionsFromLifecycle : phaseToMojoMapping.values() )
                    {
                        mojoExecutions.addAll( mojoExecutionsFromLifecycle );
                    }
                }
                else
                {
                    throw new IllegalStateException( "unexpected task " + task );
                }
            }
    

      

    代码里先判断task的类型,如果是GoalTask就说明参数是clean:clean这一种带goal的格式,这种情况可能是maven内置插件也可能是开发者自己开发的插件,这种情况下maven就会先根据插件的goal去找到具体的插件,找的方法是先从项目定义的插件里找,找不到的话再去仓库里找,这里把核心部分代码贴出来:

       PluginDescriptor pluginDescriptor =
                        pluginManager.loadPlugin( plugin, request.getRepositories(), request.getRepositorySession() );
    
              if ( request.getPrefix().equals( pluginDescriptor.getGoalPrefix() ) )
                    {
                        return new DefaultPluginPrefixResult( plugin );
                    }

    这个这部分比较简单,就是遍历项目里的插件一个个加载,然后比较这个插件的goal前缀是否和命令行的请求相同,如果相同的话直接封装下该插件返回。其他用groupId:artifactId:version:goal格式的命令行解析也是差不多的方法,根据这些信息加载响应的plugin插件。接下来要重点说的是比较复杂的情况,即clean package这种比较内置的phase,下面代码一一解读: 先根据lifecyclephase来决定是哪个lifecycle,比如package这个phase就是在default生命周期里,maven内置定义了clean、default、site三个生命周期,maven采用plexus作为IOC容器,这个defaultLifeCycles的依赖是在maven-core的component.xml中定义的,与此同时定义了各个生命周期里的phase,这个读者感兴趣可以去看相应的代码,此处略去不表。回到这里的代码,maven根据phase去默认找生命周期,这里通过package找到了default生命周期。

    /*
             * Determine the lifecycle that corresponds to the given phase.
             */
    
            Lifecycle lifecycle = defaultLifeCycles.get( lifecyclePhase );
    
            if ( lifecycle == null )
            {
                throw new LifecyclePhaseNotFoundException(
                    "Unknown lifecycle phase \"" + lifecyclePhase + "\". You must specify a valid lifecycle phase" +
                        " or a goal in the format <plugin-prefix>:<goal> or" +
                        " <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: " +
                        defaultLifeCycles.getLifecyclePhaseList() + ".", lifecyclePhase );
            }

     

    接下来遍历default lifecycle下所有的phase直到package这个phase就退出遍历循环,这里体现了maven的一个特性,就是如果你指定了某个生命周期中某个phase,那这个phase之前的phase都会被执行,这里主要是初始化mappings包含哪些phase,每个phase的插件列表之所以是TreeMap是因为后面要根据优先级,也就是Key来排序遍历确定插件执行顺序,每个phase具体要执行的插件到下一段代码再写入。

        /*
             * Initialize mapping from lifecycle phase to bound mojos. The key set of this map denotes the phases the caller
             * is interested in, i.e. all phases up to and including the specified phase.
             */
    
            Map<String, Map<Integer, List<MojoExecution>>> mappings =
                new LinkedHashMap<String, Map<Integer, List<MojoExecution>>>();
    
            for ( String phase : lifecycle.getPhases() )
            {
                Map<Integer, List<MojoExecution>> phaseBindings = new TreeMap<Integer, List<MojoExecution>>();
    
                mappings.put( phase, phaseBindings );
    
                if ( phase.equals( lifecyclePhase ) )
                {
                    break;
                }
            }
    

    接下来遍历本项目中所有插件,每个插件在遍历所有执行配置,如果execution配置里已经指定了phase,则将这个execution下所有goal对应的Mojo加到对应phase的执行map里,如果execution配置里没有指定phase的话,那就要去遍历这个execution下所有goal,依次获取该goal的Mojo描述信息,根据每个Mojo绑定的phase来将该Mojo加到对应phase的执行map里。
            /*
             * Grab plugin executions that are bound to the selected lifecycle phases from project. The effective model of
             * the project already contains the plugin executions induced by the project's packaging type. Remember, all
             * phases of interest and only those are in the lifecyle mapping, if a phase has no value in the map, we are not
             * interested in any of the executions bound to it.
             */
    
            for ( Plugin plugin : project.getBuild().getPlugins() )
            {
                for ( PluginExecution execution : plugin.getExecutions() )
                {
                    // if the phase is specified then I don't have to go fetch the plugin yet and pull it down
                    // to examine the phase it is associated to.
                    if ( execution.getPhase() != null )
                    {
                        Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( execution.getPhase() );
                        if ( phaseBindings != null )
                        {
                            for ( String goal : execution.getGoals() )
                            {
                                MojoExecution mojoExecution = new MojoExecution( plugin, goal, execution.getId() );
                                mojoExecution.setLifecyclePhase( execution.getPhase() );
                                addMojoExecution( phaseBindings, mojoExecution, execution.getPriority() );
                            }
                        }
                    }
                    // if not then i need to grab the mojo descriptor and look at the phase that is specified
                    else
                    {
                        for ( String goal : execution.getGoals() )
                        {
                            MojoDescriptor mojoDescriptor =
                                pluginManager.getMojoDescriptor( plugin, goal, project.getRemotePluginRepositories(),
                                                                 session.getRepositorySession() );
    
                            Map<Integer, List<MojoExecution>> phaseBindings = mappings.get( mojoDescriptor.getPhase() );
                            if ( phaseBindings != null )
                            {
                                MojoExecution mojoExecution = new MojoExecution( mojoDescriptor, execution.getId() );
                                mojoExecution.setLifecyclePhase( mojoDescriptor.getPhase() );
                                addMojoExecution( phaseBindings, mojoExecution, execution.getPriority() );
                            }
                        }
                    }
                }
            }
    
    
    

      

    经过前面几个步骤之后,已经拿到了所有phase对应的Mojo执行列表,接下来需要将所有phase的Mojo串起来到一个总的列表里,这里注意mappings是一个LinkedHashMap,所以遍历的时候是有顺序的,而每个phase的execution map是TreeMap,根据优先级排序,这样最后总体的顺序是先按照总体的phase顺序,再按照phase内的优先级进行排序。

     Map<String, List<MojoExecution>> lifecycleMappings = new LinkedHashMap<String, List<MojoExecution>>();
    
            for ( Map.Entry<String, Map<Integer, List<MojoExecution>>> entry : mappings.entrySet() )
            {
                List<MojoExecution> mojoExecutions = new ArrayList<MojoExecution>();
    
                for ( List<MojoExecution> executions : entry.getValue().values() )
                {
                    mojoExecutions.addAll( executions );
                }
    
                lifecycleMappings.put( entry.getKey(), mojoExecutions );
            }
    

      

    转载于:https://www.cnblogs.com/developerY/p/maven_bind_command_line_plugin.html

    展开全文
  • maven使用命令行打包

    千次阅读 2019-12-18 23:02:39
    1,首先将控制台执行切换到项目的根目录 如下图: 2,然后就是直接执行mvn clean ...1、使用清理插件maven-clean-plugin:2.5执行清理删除已有target目录(版本2.5); 2、使用资源插件maven-resources-plugin...
  • Maven打包Package执行插件的顺序

    千次阅读 2019-11-20 09:29:35
    先把命令行切换到Maven项目的根目录,比如:/d/xxxwork/java/maven-test,然后执行命令: mvn clean package 执行结果如下: [INFO] Scanning for projects... [INFO] [INFO] -----------------------------------...
  • SoapUI提供了一个命令行运行程序和maven插件执行此操作。 该运行程序在您的SoapUI \ bin文件夹中可用,并适当地命名为loadtestrunner.bat / .sh。它需要一些与报告,属性等有关的参数,这些参数可以使始参数...
  • maven使用exec插件运行java main方法以下是3种不同的操作方式。从命令行运行1、运行前先编译代码,exec:java不会自动编译代码,你需要手动执行mvn compile来完成编译。mvn compile2、编译完成后,执行exec运行main...
  • maven使用exec插件运行java main方法 以下是3种不同的操作方式。 从命令行运行 1、运行前先编译代码,exec:java不会自动编译代码,你需要手动执行mvn compile来完成编译。 mvn compile 2、编译完成后,执行exec...
  • Spring Boot Maven插件

    2020-03-23 15:53:19
    使用maven命令创建SpringBoot项目,请参考《使用maven命令行方式创建springBoot工程》 SpringBoot Maven插件在Maven中提供了对SpringBoot的支持,允许打包可执行jar或war并直接运行应用程序。 在~/.m2/repository/...
  • Maven插件

    2020-05-31 10:25:08
    方法一:Maven插件 可以使用maven插件,点击IDEA最右边的菜单栏maven,点击项目的Lifecyce,双击构建的阶段即可。 方法二:命令行方式: 可以在Terminal终端进入要打包项目的目录,输入以下命令: 清除上一次...
  • maven 常用插件

    2015-07-28 09:51:03
    maven插件是用来完成构建任务的。用户可以通过两种方式调用Maven插件。...第二种方式是直接在命令行指定要执行插件,如mvn archetype:generate 就表示调用maven-archetype-plugin。 maven-assembly-plug
  • Maven插件配置。

    2018-11-13 10:15:25
    在日常的Maven使用中,我们会经常从命令行输入并执行Maven命令。在这种情况下,如果能够方便的更改某些插件的行为,无疑会十分方便。很多插件目标的参数都支持从命令行配置,用户可以在Maven命令中使用-D参数,并...
  • Maven插件开发引导--第一个maven插件项目前言重要官方提示:插件命名规范和Apache Maven商标你的第一个插件命令行创建你的第一个mojoA Simple mojopom配置:构建一个插件执行你的第一个Mojoidea创建生成插件项目引用...
  • 在使用Java开发中,会使用到将工程打包成可...在pom.xml中添加一下插件maven-assembly-pluginfalsejar-with-dependenciescom.dms.serv.tcp.VertxTcpServermake-assemblypackageassembly在命令行执行mvn assem...
  • Maven插件配置与解析

    2015-03-22 14:28:40
    插件配置就是绑定插件,指定其预定义的参数值,来进一步调整插件目标所...如maven-surefire-plugin插件提供一个maven.test.skip参数、当值为true时会跳过执行测试、命令行执行方式: mvn install –Dmaven.test...
  • [Maven Essentials] 生命周期和插件

    千次阅读 2013-01-22 11:30:50
    maven命令行的输入往往就对应了生命周期,如mvn package就表示执行默认生命周期阶段package。Maven的生命周期是抽象的,其实际行为都由插件来完成,如package阶段的任务可能就会由maven-jar-plugin来完成。   ...
  • maven插件使用

    2015-03-19 16:33:18
    maven命令中,带冒号的方式是指定要执行插件目标。不带冒号的方式是执行生命周期。   第一种方式是将插件目标与生命周期阶段(lifecycle phase)绑定 这样用户在命令行只是输入生命周期阶段而已。 例如:...
  • 一、从命令行运行 1、运行前先编译代码,exec:Java不会自动编译代码,你需要手动执行mvn compile来完成编译。 [plain] view plain copy mvn compile  2、编译完成后,执行exec运行...
  • maven生命周期和插件

    2017-12-09 11:42:35
    在有关Maven的日常使用中,命令行的输入往往就对应了生命周期,如mvn package就表示执行默认生命周期阶段package。Maven生命周期是抽象的,其实际行为都由插件来完成,如package阶段的任务可能就会有maven-jar-...
  • maven拥有三套相互独立的生命周期,它们分别是... 命令行与生命周期:从命令行执行maven任务的最主要方式就是调用maven的生命周期阶段。 mvn clean:该命令调用clean生命周期的clean阶段。实际执行的阶段为clean生命...
  • 在有关Maven的日常使用中,命令行的输入往往就对应了生命周期,如mvn package就表示执行默认生命周期阶段package。Maven的生命周期是抽象的,其实际行为都由插件来完成,如package阶段的任务可能就会由maven-jar-...
  • 要通过命令行执行插件的最新版本,请将其更改为maven项目。 “检查-延后” Maven目标 mvn com.vegardit.maven:depcheck-maven-plugin:check-deps 这将运行check-deps目标,该目标将扫描项目并报告依赖关系问题。 ...
  • maven插件说明

    2012-09-04 18:04:14
    Maven的核心概念除了坐标、依赖及仓库之外还有两个核心的概念即生命周期和插件,对于Maven的生命周期是抽象的概念,其实际行为是由插件完成的,命令行的输入其实对应了插件执行,如mvn package就表示执行默认的...
  • maven生命周期和插件详解

    千次阅读 2018-11-24 10:50:54
    生命周期和插件Maven的两个核心概念,命令行的输入往往就对应了生命周期,如mvn package就表示执行默认生命周期阶段package。Maven的生命周期是抽象的,其实际行为都由插件来完成。Maven的生命周期是为了对所有的...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 193
精华内容 77
关键字:

maven命令行执行插件