如何在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
相关产品推荐
相关产品推荐

