Unable to load freemarker template using multipart

2019-09-06 09:47发布

问题:

I am using MultipartFile configured in my Spring MVC app via the classpath:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="1000000"/>
    </bean>

<bean id="MyController" class="myController">
        <property name="myTemplate" value="classpath:myTemplate.txt"/>

    </bean>

And I am trying to use freemarker in order to load this templete:

    public class MyController
    {
        private Resource myTemplate;

        ....

        Configuration cfg = new Configuration();
        Template tpl = cfg.getTemplate(myTemplate.getFilename());

But when I run it I am getting an error: Template classpath:myTemplate.txt not found

I tried using: cfg.setDirectoryForTemplateLoading(myTemplate.getFile().getParentFile()) to determine the directory but that didn't help either.

Any ideas...?

回答1:

From the quoted error message I suppose myTemplate.getFilename() returns classpath:myTemplate.txt, not myTemplate.txt. That would exaplain why it doesn't work even if you set the template directory to myTemplate.getFile().getParentFile().

But the more fundamental problem here is that you seem to misuse the FreeMarker API. The Configuration object should be created once in the application life cycle, normally. That's among others because it contains the template cache. If you don't use the template cache anyway, then you might as well load the template into a String, and create the Template with the Template class constructor. (However, if it #include-s or #import-s other templates, then for that FreeMarker will call cfg.getTemplate internally.) If you want to use cfg.getTemplate (and thus the cache too), then probably you should use a TemplateLoader that understands those Spring resource names, then configure FreeMarker to use that (cfg.setTemplateLoader(yourTemplateLoader)). I don't know if Spring already contains such thing or not, but in general it's not difficult to wrap a storage API into the TemplateLoader interface. (It's certainly easier and more robust on the long run than trying to "trick" FreeMarker into loading a template with an ad-hoc setDirectoryForTemplateLoading and such.)