Maven插件(Maven plugin)开发

126 阅读2分钟

背景介绍 上家公司中,对业务开发的安全极为重视,需要对Java代码和pom引用的jar组件做安全性扫描。安全部门提供的渠道是,对业务的src和lib压缩winrar后,通过winscp上传到指定的服务器,效率较为低下,我这里开发了一个Maven插件,实现了自动化上传。

1、自定义maven的步骤

1、修改pom中标签的值为maven-plugin

     <groupId>com.xxx</groupId>
  <artifactId>security-plugin</artifactId>
  <packaging>maven-plugin</packaging>

2、引入依赖

 <dependency>
          <groupId>org.apache.maven</groupId>
          <artifactId>maven-plugin-api</artifactId>
          <version>3.8.3</version>
      </dependency>
      <dependency>
          <groupId>org.apache.maven.plugin-tools</groupId>
          <artifactId>maven-plugin-annotations</artifactId>
          <version>3.6.1</version>
      </dependency>

3、使用注释或者注解方式(推荐使用注解)

注解:@mojo-name表示goal名字(id),default-value-默认调用阶段

4、部分代码

 ​
 @Mojo(name = "upload-check",
         defaultPhase = LifecyclePhase.PACKAGE)
 @Execute(phase = LifecyclePhase.PACKAGE)
 public class MainMojo extends AbstractMojo {
 ​
 ​
     @Parameter(property = "checkComponentUploadFileName")
     private String checkComponentUploadFileName;
 ​
     @Parameter(property = "checkComponentHost", defaultValue = "xxx")
     private String checkComponentHost;
     @Parameter(property = "checkComponentPort", defaultValue = "xx")
     private Integer checkComponentPort;
 ​
     @Parameter(property = "checkComponentUserName",defaultValue = "xxxxx")
     private String checkComponentUserName;
 ​
     @Parameter(property = "checkComponentPassword",defaultValue = "xxxxx")
     private String checkComponentPassword;
 ​
     //===================================代码检查====================================================
     @Parameter(property = "checkCodeUploadFileName" )
     private String checkCodeUploadFileName;
 ​
     @Parameter( property ="checkCodeHost", defaultValue = "xxxxx")
     private String checkCodeHost;
     @Parameter( property = "checkCodePort", defaultValue = "xx")
     private Integer checkCodePort;
 ​
     @Parameter( property = "checkCodeUserName",defaultValue = "xxxxxx")
     private String checkCodeUserName;
 ​
     @Parameter(property = "checkCodePassword",defaultValue = "xxxxx")
     private String checkCodePassword;
 ​
 ​
     @Parameter(property = "enableCheckCode",defaultValue = "true")
     private Boolean enableCheckCode;
 ​
     @Parameter(property = "enableCheckComponent",defaultValue = "true")
     private Boolean enableCheckComponent;
 ​
 ​
 ​
     @Parameter(defaultValue = "${project}")
     MavenProject mavenProject;
 ​
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
 ​
         getLog().info("开启代码扫描:"+enableCheckCode);
         getLog().info("开启组件扫描:"+enableCheckComponent);
         if(enableCheckCode){
             Log log =getLog();
             log.info("\n");
             log.info("----------代码安全扫描上传开始------------------");
             if(StringUtils.isBlank(checkCodeUploadFileName)){
                 log.error("checkCodeUploadFileName参数为空!");
                 return;
             }
             String path = mavenProject.getBasedir().getAbsolutePath();
             String  sourcePath = path+ File.separator+"src";
             String targetFile= path+File.separator+checkCodeUploadFileName;
             log.info("扫描路径:"+sourcePath);
             log.info("上传目标文件="+targetFile);
 ​
             try {
 //                ZipUtil.zip(sourcePath,targetFile,true);
 //                String destPath ="";
                 String outRst = TarUtil.tarFiles(targetFile,new File(sourcePath));
                 System.out.println("outRst = " + outRst);
                 log.info("--------------启动上传到Fortify扫描服务器-------------");
                 uploadToServer(checkCodeHost,checkCodePort,checkCodeUserName,checkCodePassword,"/uploads",
                         targetFile,checkCodeUploadFileName);
                 log.info("--------------上传到Fortify扫描服务器结束-------------");
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
             log.info("----------代码安全扫描上传完成------------------");
 ​
         }
         if(enableCheckComponent){
             Log log  =getLog();
             log.info("\n");
             log.info("---启动组件安全扫描上传-----");
             // mvnExcute();
             String packaging = mavenProject.getPackaging();
             String uploadFileName = checkComponentUploadFileName+"."+packaging;//xx.jar\xx.war
             renameTargetJarFile(uploadFileName);
             String buildOutputDir =mavenProject.getBuild().getDirectory();
 ​
             String targetFile =  buildOutputDir+File.separator+uploadFileName;
             //2、 upload file
             uploadToServer(checkComponentHost,checkComponentPort,checkComponentUserName,checkComponentPassword,"/upload",
                     targetFile,uploadFileName);
             log.info("---组件安全扫描上传文件完成-----");
         }
 ​
 ​
     }

image.png

5、如何使用?

<finalName>PluginTestDemo</finalName>  
<plugins>  
<plugin>  
<groupId>com.xxx</groupId>  
<artifactId>xxx-securitycheck-maven-plugin</artifactId>  
<version>1.1</version>  
<configuration>  
    <!-- 这里是需要指定上传安全服务器的文件名-->
<checkCodeUploadFileName>测试_my-test.0_xxx-jdk1.8.tar</checkCodeUploadFileName>  
<checkComponentUploadFileName>  
测试_xx-test2.0_user  
</checkComponentUploadFileName>  
<enableCheckCode>true</enableCheckCode>  
<enableCheckComponent>true</enableCheckComponent>  
</configuration>
  
<executions>  
<execution>  
<id>upload-check</id>  
<phase>package</phase>  
<goals>  
<goal>upload-check</goal>  
</goals>  
</execution>  
</executions>  
</plugin>  
</plugins>  
</build>

6、说明

由于安全扫描服务器部署在公司内网,使用涉及到公司的服务器地址、端口和账号密码,为严格遵守公司的安全规定,生成的maven组件不能上传到apache maven仓库里,给大家使用。我上传到了公司内网的Maven 仓库,使用时候只需要pom做引用(前提是,在maven的/conf/setting.xml中设置好了公司仓库) 上面的pom引用中,如果从公司的maven仓库中拉取不到(有同事在使用过程,确实出现奇怪的现象),可以将maven 插件直接放到本地仓库中。

上述的引用例子和代码中,我去掉了部分和公司相关信息。