Spring 4 MVC + Freemarker Template Annotation Integration Example with FreeMarkerConfigurer
October 12, 2015
This page will walk through Spring 4 MVC and Freemarker template annotation integration example with FreeMarkerConfigurer. Spring provides FreeMarkerConfigurer that is used to set template loader path. It is internally used by FreeMarkerView. The values for Freemarker template is assigned in ModelAndView or Model and we set values using addObject() and addAttribute() in spring controller class. In our example, our template generates a HTML page for blogging.
Software Used in Demo
Find the software used in demo.1. Java 8
2. Tomcat 8
3. Spring 4.1
4. Freemarker 2.3
5. Eclipse
6. Gradle
Project Structure in Eclipse
Find the project structure in eclipse.Gradle to Resolve Dependency for Spring and Freemarker
Find the build.gradle file to resolve dependency for Spring and Freemarker.build.gradle
apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'war' archivesBaseName = 'Spring4' version = '1' repositories { mavenCentral() } dependencies { compile 'org.springframework.boot:spring-boot-starter-web:1.2.3.RELEASE' compile 'org.springframework:spring-context-support:4.1.6.RELEASE' compile 'org.freemarker:freemarker:2.3.23' providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat:1.2.3.RELEASE' }
Create Freemarker Template (FTL)
Find the Freemarker template which are being used in our demo. This will generate HTML file for a blog.blog-template.ftl
<html> <head><title> ${blogTitle} </title> <body> <h1> ${blogTitle} </h1> <p> ${message} </p> <h3>References</h3> <#list references as reference> ${reference_index + 1}. <a href="${reference.url}"> ${reference.title} </a> <br/> </#list> </body> </html>
JavaConfig with FreeMarkerConfigurer and ViewResolverRegistry.freeMarker()
Find the JavaConfig used in our demo.AppConfiguration.java
package com.concretepage.config; import java.util.HashMap; import java.util.Map; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; import freemarker.template.utility.XmlEscape; @Configuration @ComponentScan("com.concretepage") @EnableWebMvc public class AppConfiguration extends WebMvcConfigurerAdapter { @Bean(name ="freemarkerConfig") public FreeMarkerConfigurer freemarkerConfig() { FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); configurer.setTemplateLoaderPath("/WEB-INF/views/"); Map<String, Object> map = new HashMap<>(); map.put("xml_escape", new XmlEscape()); configurer.setFreemarkerVariables(map); return configurer; } @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.ignoreUnknownPathExtensions(false).defaultContentType(MediaType.TEXT_HTML); } @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.freeMarker(); } }
FreeMarkerConfigurer : We need to create a bean with name freemarkerConfig that will configure templateLoaderPath. FreeMarkerConfigurer is used internally by
FreeMarkerView
.
ViewResolverRegistry.freeMarker() :
freeMarker()
method configures view resolver with empty default view name prefix and default suffix as .ftl
Now find
WebApplicationInitializer
implementation class.
Initializer.java
package com.concretepage.config; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration.Dynamic; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; public class Initializer implements WebApplicationInitializer { public void onStartup(ServletContext servletContext) throws ServletException { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(AppConfiguration.class); ctx.setServletContext(servletContext); Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx)); dynamic.addMapping("/"); dynamic.setLoadOnStartup(1); } }
Controller and Bean Class
Freemarker template variables get value from springModelAndView
or Model
and we set values using addObject()
and addAttribute()
.
BlogController.java
package com.concretepage.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.concretepage.bean.URL; @Controller public class BlogController { @Autowired private URL url; @RequestMapping(value = "/blog") public ModelAndView getBlog(ModelAndView mv) { mv.addObject("blogTitle", "Freemarker Template Demo using Spring"); mv.addObject("message", "Getting started with Freemarker.<br/>Find a Freemarker template demo using Spring."); mv.addObject("references", url.getUrlList()); mv.setViewName("blog-template"); return mv; } }
URL.java
package com.concretepage.bean; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Service; @Service public class URL { private String url; private String title; public URL(){} public URL(String url, String title) { this.url = url; this.title = title; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public List<URL> getUrlList() { List<URL> list = new ArrayList<>(); list.add(new URL("http://url1.com","URL One")); list.add(new URL("http://url2.com","URL Two")); list.add(new URL("http://url3.com","URL Three")); return list; } }