如何实现Spring Boot项目动态跨工程互用FreeMarker模板?
我之前遇到过几乎一模一样的问题,核心原因是默认的模板加载器配置没有正确覆盖本地和依赖包的templates路径,而且模板加载器的路径映射有问题。下面是我验证过的可行解决方案:
1. 替换默认配置,手动构建多源模板加载器
原来的FreeMarkerConfigurationFactoryBean可能因为本地templates目录的存在,优先使用了FileTemplateLoader——这个加载器只能读取本地文件系统的资源,根本访问不到依赖jar包里的templates。同时自动生成的ClassTemplateLoader路径设置不对,导致找不到jar里的模板。我们需要手动配置加载器,确保同时扫描本地和jar包中的classpath:/templates/目录:
@Bean public FreeMarkerConfigurer freeMarkerConfigurer() { FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); // 替换为你项目实际使用的Freemarker版本 Configuration freemarkerConfig = new Configuration(Configuration.VERSION_2_3_32); // 配置两个ClassTemplateLoader: // 1. 从当前类的上下文加载本地项目的templates // 2. 从系统类加载器根目录加载所有依赖jar中的templates ClassTemplateLoader localTemplateLoader = new ClassTemplateLoader(this.getClass(), "/templates/"); ClassTemplateLoader jarTemplateLoader = new ClassTemplateLoader(ClassLoader.getSystemClassLoader(), "/templates/"); // 组合成多源加载器,顺序可以根据需求调整(优先本地还是jar包) MultiTemplateLoader multiLoader = new MultiTemplateLoader(new TemplateLoader[]{localTemplateLoader, jarTemplateLoader}); freemarkerConfig.setTemplateLoader(multiLoader); freemarkerConfig.setDefaultEncoding("UTF-8"); freemarkerConfig.setObjectWrapper(new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_32).build()); // 可选:添加其他Freemarker配置,比如自动导入、日期格式等 configurer.setConfiguration(freemarkerConfig); return configurer; }
2. 确认模板导入路径的正确性
你的模板里用的<#import "/feature3/f3page.ftl" as f3>这个写法是对的——绝对路径/会从模板加载器的根目录(也就是我们配置的/templates/)开始查找,不管是本地Project A还是依赖Project B里的/templates/feature3/f3page.ftl都能匹配到。
3. 验证依赖包的模板是否正确打包
确保Project B的src/main/resources/templates目录被正确打包到jar中。Maven默认会打包这个目录,但如果Project B的pom.xml有自定义的<resources>配置,一定要检查是否包含了该目录:
<build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> </resource> </resources> </build>
4. 清理并重新构建项目
有时候target目录里的旧资源会干扰加载,先清理Project A的target目录,再执行mvn clean install,确保依赖的Project B jar是最新的,并且包含了所有模板文件。
补充说明为什么原来的配置不行
当你设置setTemplateLoaderPath("classpath:/templates/")并开启setPreferFileSystemAccess(false)时,Spring的FreeMarkerConfigurationFactoryBean可能仍然因为本地templates目录存在(在target/classes下),优先使用了FileTemplateLoader,而这个加载器无法读取jar中的资源。同时从报错信息能看到,自动配置的ClassTemplateLoader的basePackagePath是空的,导致它会去类路径根目录找/feature3/f3page.ftl,而不是正确的/templates/feature3/f3page.ftl,自然找不到目标模板。
内容的提问来源于stack exchange,提问作者CtrlAltMe

