如何使用gradle任务中的源代码创建文件,然后用所有这些文件制作jar?

How to use source code inside gradle task for create file and then make jar with all of them?

提问人:Micah 提问时间:11/18/2023 更新时间:11/18/2023 访问量:19

问:

我在projectRoot / buildSrc中有任务

package myapp.gradle;

import myapp.Utils;
import myapp.GoodRecord;
import myapp.GoodRecordFactory;
import org.apache.commons.io.FileUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;

import java.io.File;
import java.io.IOException;

public class SoqTask extends DefaultTask {
    private File saveToDir;

    public void setSaveToDir(File saveToDir) {
        this.saveToDir = saveToDir;
    }
    @TaskAction
    public void run() {
        try {
            GoodRecord instance = GoodRecordFactory.instance();
            byte[] serialize = Utils.serialize(instance);
            FileUtils.writeByteArrayToFile(new File(saveToDir, "goodrecord.bin"), serialize);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

但是 SoqTask 无权访问必要的导入类。

如何使用项目代码创建文件,然后在一个 jar 中一起构建?

Java Gradle

评论

0赞 aled 11/18/2023
目前尚不清楚你在问什么。请阅读如何提问并改进问题。

答:

0赞 Micah 11/27/2023 #1

最后,我找到了仅使用反射的解决方案

public abstract class SoqTask extends DefaultTask {
    @Input
    public abstract Property<File> getOutputDir();
    @Input
    public abstract ListProperty<URL> getInputUrls();
    @Input
    public abstract Property<String> getSerializerFileName();

    @TaskAction
    public void generate() {
        URL[] urls = getInputUrls().get().toArray(new URL[0]);
        try (URLClassLoader urlClassLoader = new URLClassLoader(urls)) {
            Class<?> factoryClass =
                    urlClassLoader.loadClass("my.org.GoodRecordFactory");
            Method getInstanceMethod = factoryClass.getMethod("instance");
            Object recordSerializer = getInstanceMethod.invoke(factoryClass);
            Objects.requireNonNull(recordSerializer);

            Class<?> serializerUtils =
                    urlClassLoader.loadClass("my.org.Util");
            Method serializeMethod = Arrays.stream(serializerUtils.getMethods())
                    .filter(e -> "serialize".equals(e.getName()))
                    .findFirst().orElseThrow(RuntimeException::new);
            byte[] serializedBytes = (byte[]) serializeMethod.invoke(serializerUtils, recordSerializer);
            
            File outputFile = new File(getOutputDir().get(), getSerializerFileName().get());
            try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
                outputStream.write(serializedBytes);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

在 Gradle 中使用:

import one.ids.gradle.SoqTask
tasks.register("oqTask", SoqTask) {
    dependsOn(serverJava)
    inputUrls = (sourceSets.server.output.getClassesDirs() + sourceSets.server.runtimeClasspath.files)
            .collect(f -> f.toURI().toURL() as URL)
    outputDir = sourceSets.server.java.destinationDirectory.get().asFile
    serializerFileName = "serializer.bin"
}