Spring Boot 3中使用JTE预编译模板抛出ClassNotFoundException问题求助
问题
在Spring Boot 3.2中使用JTE生成非HTML文件,未采用jte-spring-boot-starter-3。本地测试时配置正常,但Docker容器运行应用时抛出ClassNotFoundException。打包后的JAR结构中存在gg.jte.generated.precompiled目录,但调用生成方法时仍报错。
Maven插件配置
<plugin> <groupId>gg.jte</groupId> <artifactId>jte-maven-plugin</artifactId> <version>${jte.version}</version> <configuration> <sourceDirectory>${project.basedir}/src/main/jte</sourceDirectory> <targetDirectory>${project.build.directory}/jte-classes</targetDirectory> <contentType>Plain</contentType> </configuration> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>generate</goal> </goals> </execution> </executions> </plugin>
TemplateEngine使用代码
@Service public class GenerateUseCase { private final TemplateEngine jteTemplateEngine; public GenerateUseCase() throws IOException { this.jteTemplateEngine = TemplateEngine.createPrecompiled(ContentType.Plain); } private void generateFileByTemplate(final Path dir, final Map<String, Object> params, final String fileName) throws IOException { final File file = dir.resolve(fileName).toFile(); file.createNewFile(); try (FileOutput output = new FileOutput(file.getAbsoluteFile().toPath(), StandardCharsets.UTF_8)) { jteTemplateEngine.render(fileName + ".jte", params, output); } } }
报错堆栈
Servlet.service() for servlet [dispatcherServlet] in context with path [/] threw exception [Request processing failed: java.lang.RuntimeException: gg.jte.TemplateNotFoundException: Failed to load ingress.yml.jte] with root cause java.lang.ClassNotFoundException: gg.jte.generated.precompiled.JteingressymlGenerated at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:593) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) at gg.jte.runtime.TemplateLoader.load(TemplateLoader.java:25) at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708) at gg.jte.TemplateEngine.resolveTemplate(TemplateEngine.java:339) at gg.jte.TemplateEngine.render(TemplateEngine.java:228) at org.service.GenerateUseCase.generateFileByTemplate(GenerateUseCase.java:151)
解决方案
1. 确保预编译JTE类被打包进JAR
当前JTE插件将生成的类输出到target/jte-classes,但Spring Boot Maven插件默认不会把该目录下的类打包进最终JAR,可通过以下三种方式解决:
方案A:调整JTE插件输出目录到源码目录
修改jte-maven-plugin的targetDirectory为src/main/java(建议将生成的类添加到.gitignore,避免提交):
<configuration> <sourceDirectory>${project.basedir}/src/main/jte</sourceDirectory> <targetDirectory>${project.basedir}/src/main/java</targetDirectory> <contentType>Plain</contentType> </configuration>
方案B:配置Spring Boot插件包含jte-classes目录
在spring-boot-maven-plugin中添加配置,将jte-classes作为额外类目录:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <additionalClasspathElements> <additionalClasspathElement>${project.build.directory}/jte-classes</additionalClasspathElement> </additionalClasspathElements> </configuration> </plugin>
方案C:用资源插件复制生成类到classes目录
添加maven-resources-plugin,在构建阶段将jte-classes下的类复制到target/classes:
<plugin> <artifactId>maven-resources-plugin</artifactId> <executions> <execution> <id>copy-jte-classes</id> <phase>process-classes</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/classes</outputDirectory> <resources> <resource> <directory>${project.build.directory}/jte-classes</directory> <includes> <include>**/*.class</include> </includes> </resource> </resources> </configuration> </execution> </executions> </plugin>
2. 检查Docker构建流程
确保Dockerfile执行完整的Maven构建,包含generate-sources和package阶段,避免直接复制本地JAR:
FROM maven:3.8.6-openjdk-17 AS build WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn clean package -DskipTests FROM openjdk:17-jdk-slim WORKDIR /app COPY --from=build /app/target/your-app.jar app.jar ENTRYPOINT ["java", "-jar", "app.jar"]
3. 显式指定类加载器(可选)
若类加载器存在问题,创建TemplateEngine时传入当前类的类加载器:
public GenerateUseCase() throws IOException { this.jteTemplateEngine = TemplateEngine.createPrecompiled(ContentType.Plain, getClass().getClassLoader()); }
内容的提问来源于stack exchange,提问作者Alina Didenko
相关产品推荐
相关产品推荐

