Spring Boot动态生成、加载模板文件
背景
bpm表单设计器在线生成html模板文件,需要保存到项目中,对表单进行查看、编辑。
方法一
直接生成文件保存到 Spring Boot 默认的模板文件目录下,即classpath:template
。
此方法简单粗暴,开发环境运行有效。但是使用JAR包部署到线上环境后存在问题:由于classpath的资源目录存在于JAR包下,而在Java程序运行时,不能直接将文件写入已经打包好的JAR文件中,并期望通过classpath:template
这样的方式来访问。这是因为JAR文件是一个压缩文件,用于分发和部署Java应用程序,而它的内容在构建时是固定的。一旦JAR文件被创建,它的内容就不能在运行时被修改。
需求是在线生成表单后,立即可以对表单进行查看、编辑,很显然这个方法是不可行的。
方法二
自定义模板路径。
spring.thymeleaf.prefix=classpath:/mytemplates/
spring.thymeleaf.suffix=.html
或
spring:
thymeleaf:
prefix: classpath:/mytemplates/
suffix: .html
可以把路径写在配置文件中,使模板引擎每次都读取自定义目录下的模板文件。此方法也不能解决问题,因为自定义的路径还是在项目中,并没有办法满足上述的需求。
最终解决方法
方法二中的自定义模板路径,其实是对Spring Boot 默认的模板解析器进行修改。我们完全可以自定义一个新的模板解析器,并从文件系统的目录中读取并解析模板文件。以下是详细的步骤:
添加依赖
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf-spring5 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
自定义模板解析器
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.templateresolver.FileSystemTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@Configuration
public class ThymeleafConfig {
// 模板引擎的配置
@Bean
public SpringTemplateEngine templateEngine(ITemplateResolver... templateResolvers) {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
Set<ITemplateResolver> templateResolverSet = new HashSet<>(Arrays.asList(templateResolvers));
templateEngine.setTemplateResolvers(templateResolverSet);
return templateEngine;
}
// 默认模板解析器
@Bean
public ITemplateResolver classpathTemplateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setPrefix("classpath:/templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setCharacterEncoding("UTF-8");
resolver.setOrder(2);
return resolver;
}
// 自定义一个额外的文件系统模板解析器
@Bean
public ITemplateResolver fileSystemTemplateResolver() {
FileSystemTemplateResolver resolver = new FileSystemTemplateResolver();
resolver.setPrefix("/path/to/your/templates/"); // 指定文件系统的模板路径
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setCharacterEncoding("UTF-8");
resolver.setCheckExistence(true);
resolver.setOrder(1); //优先使用此解析器
resolver.setCacheable(false); //解析器级别的缓存
return resolver;
}
}
以上代码做到了既要去解析项目中自带的模板文件,又要对系统运行过程中新生成的模板文件进行解析。
值得注意的点:
-
解析器的优先级使用setOrder定义。
-
使用setCacheable可以定义解析器级别的缓存禁用,这既满足了修改历史表单的需求,也不影响系统性能。
-
模板解析器的实现类不止以上两种,有兴趣可以去了解。