You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Gradle Java插件及Java任务类中运行GMetrics Ant任务

在Java Gradle插件中实现GMetrics Ant任务

我来帮你搞定这个问题!你遇到的闭包编译错误是因为Java并不支持Groovy的Closure类型——Gradle的Groovy DSL里的闭包语法是Groovy特有的,Java里得换用更适合的方式实现。下面给你两种可行的方案,从类型安全的角度推荐第二种:

方案1:使用Gradle的AntBuilder API(反射式调用)

getProject().getAnt()返回的是Gradle的AntBuilder实例,它允许你在Java中通过反射式的方法调用构建Ant任务逻辑,对应你原来的Groovy代码:

import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.TaskExecutionException;
import org.gradle.api.AntBuilder;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

public class GmetricsTask extends DefaultTask {

    @TaskAction
    public void gmetrics() throws TaskExecutionException {
        AntBuilder ant = getProject().getAnt();

        // 1. 定义GMetrics Ant任务
        Map<String, Object> taskdefParams = new HashMap<>();
        taskdefParams.put("name", "gmetrics");
        taskdefParams.put("classname", "org.gmetrics.ant.GMetricsTask");
        taskdefParams.put("classpath", getProject().getConfigurations().getByName("gmetrics").getAsPath());
        ant.invokeMethod("taskdef", taskdefParams);

        // 2. 确保报告目录存在
        File reportsDir = new File(getProject().getBuildDir(), "reports/gmetrics");
        if (!reportsDir.exists()) {
            reportsDir.mkdirs();
        }

        // 3. 配置并执行GMetrics任务
        try {
            ant.invokeMethod("gmetrics", new org.gradle.api.Action<AntBuilder>() {
                @Override
                public void execute(AntBuilder gmetricsBuilder) {
                    // 配置XML报告
                    Map<String, Object> reportParams = new HashMap<>();
                    reportParams.put("type", "org.gmetrics.report.XmlReportWriter");
                    gmetricsBuilder.invokeMethod("report", reportParams, new org.gradle.api.Action<AntBuilder>() {
                        @Override
                        public void execute(AntBuilder reportBuilder) {
                            Map<String, Object> optionParams = new HashMap<>();
                            optionParams.put("name", "outputFile");
                            optionParams.put("value", new File(reportsDir, "gmetrics.xml").getAbsolutePath());
                            reportBuilder.invokeMethod("option", optionParams);
                        }
                    });

                    // 配置文件集
                    Map<String, Object> filesetParams = new HashMap<>();
                    filesetParams.put("dir", new File(getProject().getProjectDir(), "src").getAbsolutePath());
                    gmetricsBuilder.invokeMethod("fileset", filesetParams, new org.gradle.api.Action<AntBuilder>() {
                        @Override
                        public void execute(AntBuilder filesetBuilder) {
                            // 添加包含规则
                            Map<String, Object> includeParams = new HashMap<>();
                            includeParams.put("name", "**/*.java");
                            filesetBuilder.invokeMethod("include", includeParams);

                            // 添加排除规则
                            Map<String, Object> excludeParams = new HashMap<>();
                            excludeParams.put("name", "**/*Config*");
                            filesetBuilder.invokeMethod("exclude", excludeParams);
                        }
                    });
                }
            });
        } catch (Exception e) {
            throw new TaskExecutionException(this, e);
        }
    }
}

方案2:直接实例化GMetrics Ant任务类(类型安全推荐)

这种方式不需要反射调用,直接使用GMetrics的Java API,代码更清晰且类型安全:

import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.TaskExecutionException;
import org.apache.tools.ant.types.FileSet;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

public class GmetricsTask extends DefaultTask {

    @TaskAction
    public void gmetrics() throws TaskExecutionException {
        try {
            // 获取GMetrics配置的类加载器
            URLClassLoader classLoader = new URLClassLoader(
                    getProject().getConfigurations().getByName("gmetrics").getFiles().stream()
                            .map(file -> {
                                try {
                                    return file.toURI().toURL();
                                } catch (Exception e) {
                                    throw new RuntimeException(e);
                                }
                            })
                            .toArray(URL[]::new),
                    getClass().getClassLoader()
            );

            // 1. 实例化GMetrics Ant任务
            Class<?> gmetricsTaskClass = Class.forName("org.gmetrics.ant.GMetricsTask", true, classLoader);
            Object gmetricsAntTask = gmetricsTaskClass.newInstance();
            // 关联Ant项目上下文
            gmetricsTaskClass.getMethod("setProject", org.apache.tools.ant.Project.class)
                    .invoke(gmetricsAntTask, getProject().getAnt().getAntProject());

            // 2. 配置XML报告
            Class<?> reportWriterClass = Class.forName("org.gmetrics.report.XmlReportWriter", true, classLoader);
            Object reportWriter = reportWriterClass.newInstance();
            File reportFile = new File(getProject().getBuildDir(), "reports/gmetrics/gmetrics.xml");
            reportFile.getParentFile().mkdirs(); // 确保父目录存在
            reportWriterClass.getMethod("setOutputFile", String.class)
                    .invoke(reportWriter, reportFile.getAbsolutePath());
            gmetricsTaskClass.getMethod("addReportWriter", Class.forName("org.gmetrics.report.ReportWriter", true, classLoader))
                    .invoke(gmetricsAntTask, reportWriter);

            // 3. 配置文件集
            FileSet fileSet = new FileSet();
            fileSet.setDir(new File(getProject().getProjectDir(), "src"));
            fileSet.createInclude().setName("**/*.java");
            fileSet.createExclude().setName("**/*Config*");
            gmetricsTaskClass.getMethod("addFileset", FileSet.class)
                    .invoke(gmetricsAntTask, fileSet);

            // 4. 执行GMetrics任务
            gmetricsTaskClass.getMethod("execute").invoke(gmetricsAntTask);

        } catch (Exception e) {
            throw new TaskExecutionException(this, e);
        }
    }
}

前置准备:添加GMetrics配置

别忘了在你的插件类中先创建gmetrics配置,确保依赖能被正确拉取:

import org.gradle.api.Plugin;
import org.gradle.api.Project;

public class MyCodeQualityPlugin implements Plugin<Project> {
    @Override
    public void apply(Project project) {
        // 创建gmetrics配置
        project.getConfigurations().create("gmetrics", config -> {
            config.setTransitive(true);
            config.setVisible(false);
            // 添加GMetrics依赖
            config.defaultDependencies(deps -> {
                deps.add(project.getDependencies().create("org.gmetrics:gmetrics:1.10"));
            });
        });

        // 创建GMetrics任务
        project.getTasks().create("gmetrics", GmetricsTask.class);
    }
}

关键注意点

  • 确保你的插件能访问到GMetrics的依赖,通过gmetrics配置引入是最优方式
  • 所有异常都要包装成Gradle的TaskExecutionException,符合Gradle的任务异常处理规范
  • 方案2虽然代码稍长,但避免了反射调用,更易维护和调试

内容的提问来源于stack exchange,提问作者Shehabic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:34:50