今天开发个人开源框架,完善了系统模块后,集成工作流功能模块,在新的resources下面新建freemarker前端页面(ftl页面),然后正常开发到展示流程表的时候,后台报错情景重新:Could not resolve view with name '/actList' in servlet with name 'dispatcherServlet'
当时我就想是不是映射地址出错了,检查多次后发现也没错,怎么spring mvc就映射不到呢,而且是相同的的地址路径(模块不一样),和其他模块resources一致的路径,然后我系统模块是完全没问题的,我感觉应该是freemarker配置的问题,然后各种尝试,各种检查,各种查阅资料,发现,的确是freemarker的问题,我少配置了一项freemarker配置:FreeMarkerConfigurationFactory类下的属性:preferFileSystemAccess,<---对就是它,我们来看源码发现默认是true
public class FreeMarkerConfigurationFactory {
protected final Log logger = LogFactory.getLog(getClass());
private Resource configLocation;
private Properties freemarkerSettings;
private Map<String, Object> freemarkerVariables;
private String defaultEncoding;
private final List<TemplateLoader> templateLoaders = new ArrayList<TemplateLoader>();
private List<TemplateLoader> preTemplateLoaders;
private List<TemplateLoader> postTemplateLoaders;
private String[] templateLoaderPaths;
private ResourceLoader resourceLoader = new DefaultResourceLoader();
private boolean preferFileSystemAccess = true;
那么他是干嘛用的呢,我们看官方介绍是介绍:
Set whether to prefer file system access for template loading. File system access enables hot detection of template changes.
If this is enabled, FreeMarkerConfigurationFactory will try to resolve the specified "templateLoaderPath" as file system resource (which will work for expanded class path resources and ServletContext resources too).
Default is "true". Turn this off to always load via SpringTemplateLoader (i.e. as stream, without hot detection of template changes), which might be necessary if some of your templates reside in an expanded classes directory while others reside in jar files.
我们随便翻一下:第一句的意思是是否以更喜欢方式来访问模板
如果启用就以templateLoaderPath设置的路径来加载,默认为true,设置为false的话就以SpringTemplateLoader方式访问,那么就是流的方式访问,这可能是必要的,如果你的一些模板驻留在一个扩展的类而其他人驻留在jar文件的目录。
意思就是 如果你的文件在jar包文件目录下,就有必要设置为false,我们是多模块的,最终只运行一个模块,其他模块都是以jar包来加载的,我们要加载jar包里面的文件目录,必须要把这个属性设置为false才行,debug源码看看,先上配置文件:
@Bean
public FreeMarkerConfigurer freemarkerConfig() throws IOException, TemplateException {
FreeMarkerConfigurationFactory factory = new FreeMarkerConfigurationFactory();
factory.setTemplateLoaderPath("classpath:/ftl/");
factory.setDefaultEncoding("UTF-8");
factory.setPreferFileSystemAccess(true);
FreeMarkerConfigurer result = new FreeMarkerConfigurer();
freemarker.template.Configuration configuration = factory.createConfiguration();
configuration.setClassicCompatible(true);
result.setConfiguration(configuration);
Properties settings = new Properties();
settings.put("template_update_delay", "0");
settings.put("default_encoding", "UTF-8");
settings.put("number_format", "0.######");
settings.put("classic_compatible", true);
settings.put("template_exception_handler", "ignore");
result.setFreemarkerSettings(settings);
return result;
}
FreeMarkerConfigurationFactory
返回
最终返回:
看到没,是单个模块的绝对路径ftl文件夹。
看图我们可以明确知道为true的话,加载的是设置的setTemplateLoaderPath的路径 也就是我其中一个模块下的ftl路径,所以其他模块下ftl路径是加载不出来的,也就是spring mvc 映射不到的原因。
我们试试 将isPreferFileSystemAccess设置为false:
最终我们跟到这里:
发现路径是/ftl/而不是之前的绝对路径,然后set进spring对freemarker的配置对象中。
好的,我们通过分析源码我们可以知道,多模块下,我们设置为false,spring才能以相对路径来访问我们的模板文件夹,问题解决。