Reputation: 1567
I'm trying to create a Spring MVC application using Freemarker and Java configuration.
I'm used to using JSPs, but thought I'd give Freemarker a spin in this project.
I've added Freemarker as a dependancy and the jar is being downloaded by Maven:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.20</version>
</dependency>
I'm trying to use 3.2.3.RELEASE version of Spring.
My MVC configuration, assembled from reading similar question:
@ComponentScan(basePackages="yhj.*")
@EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter{
@Bean
public ViewResolver viewResolver() {
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
resolver.setCache(true);
resolver.setPrefix("");
resolver.setSuffix(".ftl");
return resolver;
}
@Bean
public FreeMarkerConfigurer freemarkerConfig() {
FreeMarkerConfigurer result = new FreeMarkerConfigurer();
result.setTemplateLoaderPath("/WEB-INF/views/");
return result;
}
}
When I try run this up I get a compilation error, my IDE is telling me the method 'setTemplateLoaderPath(String)' cannot be resolved.
So... does look like the right way of going about configuring Spring MVC with Freemarker? What dependency do I need to add to my POM if that is the issue?
Upvotes: 13
Views: 13906
Reputation: 12625
This is my custom configuration for an MVC project using Boot
/**
* Otras configuraciones de la aplicaciones web, incluyendo algunas definidas en
* xml. Usar @ImportResource("classpath:/extra-config.xml") en caso de quererse
* importar configuracion en xml
*/
@Configuration
@PropertySource("classpath:application.properties")
public class WebAppConfig
{
@Autowired
private ServletContext context;
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer placeHolderConfigurer = new PropertySourcesPlaceholderConfigurer();
return placeHolderConfigurer;
}
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() throws IOException, TemplateException
{
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer()
{
@Override
protected void postProcessConfiguration(freemarker.template.Configuration config) throws IOException, TemplateException
{
WebappTemplateLoader WebAppTplLoader = new WebappTemplateLoader(context, "/WEB-INF/ftl");
ClassTemplateLoader classTplLoader = new ClassTemplateLoader(context.getClassLoader(), "/templates");
ClassTemplateLoader baseMvcTplLoader = new ClassTemplateLoader(FreeMarkerConfigurer.class, "");
MultiTemplateLoader mtl = new MultiTemplateLoader(new TemplateLoader[]
{
WebAppTplLoader,
classTplLoader,
baseMvcTplLoader
});
config.setTemplateLoader(mtl);
}
};
configurer.setDefaultEncoding("UTF-8");
configurer.setPreferFileSystemAccess(false);
return configurer;
}
@Bean
public FreeMarkerViewResolver viewResolver()
{
FreeMarkerViewResolver viewResolver = new FreeMarkerViewResolver();
viewResolver.setExposeSpringMacroHelpers(true);
viewResolver.setExposeRequestAttributes(true);
viewResolver.setPrefix("");
viewResolver.setSuffix(".ftl");
viewResolver.setContentType("text/html;charset=UTF-8");
return viewResolver;
}
}
The first 2 loaders allow to load .ftl
templates in war
files from "/WEB-INF/ftl" and from regular jar
files from src/resources/templates
.
If you want to use security tags in freemarker the escense are this two lines:
viewResolver.setExposeSpringMacroHelpers(true);
viewResolver.setExposeRequestAttributes(true);
And the baseMvcTplLoader
loader to get the spring.ftl
from org.springframework.web.servlet.view.freemarker
. I suggest to explore ftl templates in some example project or documentation to have a clue of how spring.ftl
works.
The configuration of the placeholder is not related to the freemarker configuration, yet its very useful for injecting values in variables from
src/resources/application.properties
by using the@Value
annotation.
With this you can use all the spring power within freemarker templates.
Upvotes: 4
Reputation: 6280
@Bean(name = "freeMarkerViewResolver")
public FreeMarkerViewResolver getFreeMarkerViewResolver() {
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
resolver.setPrefix("/WEB-INF/views/json/");
resolver.setSuffix(".json");
resolver.setOrder(2);
resolver.setContentType("application/json");
resolver.setCache(true);
return resolver;
}
@Bean(name = "freemarkerConfig")
public FreeMarkerConfigurer getFreemarkerConfig() throws IOException, TemplateException {
FreeMarkerConfigurer result = new FreeMarkerConfigurer();
result.setTemplateLoaderPaths("/"); // prevents FreeMarkerConfigurer from using its default path allowing setPrefix to work as expected
return result;
}
Upvotes: 5
Reputation: 2720
My solution for Spring Boot 1.0.2, Spring 4.0.3, and FreeMarker 2.3.20 was the following class:
@Configuration
public class MvcConfigurer extends WebMvcConfigurerAdapter {
@Bean
public ViewResolver viewResolver() {
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
resolver.setCache(true);
resolver.setPrefix("");
resolver.setSuffix(".ftl");
resolver.setContentType("text/html; charset=UTF-8");
return resolver;
}
@Bean
public FreeMarkerConfigurer freemarkerConfig() throws IOException, TemplateException {
FreeMarkerConfigurationFactory factory = new FreeMarkerConfigurationFactory();
factory.setTemplateLoaderPath("classpath:templates");
factory.setDefaultEncoding("UTF-8");
FreeMarkerConfigurer result = new FreeMarkerConfigurer();
result.setConfiguration(factory.createConfiguration());
return result;
}
}
In addition you need the same pom.xml
changes as in the question and DaFoot's own answer.
Upvotes: 14
Reputation: 1567
Well I've sorted the compilation issue, added a dependency to my pom...
<dependency><!-- needed for freemarker FreeMarkerConfigurer stuff -->
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
Upvotes: 12