Use JSP and Thymeleaf views in Spring Boot app
Use JSP and Thymeleaf views in Spring Boot app
Just adding one more view resolver for jsp wont do,
we also need to add one more template resolver for jsp and connect it to spring template engine.
The code below works in Spring Boot 2.
package org.jwebshop.webshop.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import javax.annotation.Resource;
@Configuration
@EnableWebMvc
public class ViewConfiguration implements WebMvcConfigurer {
@Resource
protected ApplicationContext applicationContext;
@Resource
protected SpringTemplateEngine springTemplateEngine;
@Bean
public ThymeleafViewResolver thymeleafViewResolver(){
final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setViewNames(new String[] {thyme/*});
viewResolver.setExcludedViewNames(new String[] {jsp/*});
viewResolver.setTemplateEngine(springTemplateEngine);
viewResolver.setCharacterEncoding(UTF-8);
return viewResolver;
}
@Bean
public InternalResourceViewResolver jspViewResolver(){
final InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix(/WEB-INF/views/);
viewResolver.setSuffix(.jsp);
viewResolver.setViewNames(jsp/*);
return viewResolver;
}
@Bean
public SpringResourceTemplateResolver thymeleafTemplateResolver(){
final SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix(/WEB-INF/views/);
templateResolver.setSuffix(.html);
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCacheable(false);
templateResolver.setOrder(0);
return templateResolver;
}
@Bean
public SpringResourceTemplateResolver jspTemplateResolver(){
final SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix(/WEB-INF/views/);
templateResolver.setSuffix(.jsp);
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCacheable(false);
templateResolver.setOrder(1);
templateResolver.setCharacterEncoding(UTF-8);
return templateResolver;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(/webjars/**).addResourceLocations(/webjars/);
registry.addResourceHandler(/images/**).addResourceLocations(/images/);
registry.addResourceHandler(/css/**).addResourceLocations(/css/);
registry.addResourceHandler(/js/**).addResourceLocations(/js/);
}
}
package org.jwebshop.webshop.controller.web.thymeleaf;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class RootController {
@Secured(ROLE_CUSTOMER)
@GetMapping({/, /index})
public String root() {
return thyme/index;
}
}
package org.jwebshop.webshop.controller.web.jsp;
import org.jwebshop.webshop.dto.converter.impl.UserDataConverter;
import org.jwebshop.webshop.dto.data.UserData;
import org.jwebshop.webshop.entity.User;
import org.jwebshop.webshop.service.UserService;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import javax.annotation.Resource;
@Controller
public class LuckyController {
@Resource
protected UserService userService;
@Resource
protected UserDataConverter userDataConverter;
@Secured(ROLE_CUSTOMER)
@GetMapping(/lucky)
public String hello(final Model model, final Authentication auth) {
final User user = userService.findByEmail(auth.getName());
final UserData userData = userDataConverter.convertFrom(user);
model.addAttribute(userData, userData);
return jsp/lucky;
}
}
Folder structure:
webapp
|
WEB-INF
|
views
| |
jsp thyme
I havent actually tried it yet, as I used jsp
and thymeleaf
on totally different project. And also converted jsp
into thymeleaf
, but not use it together. I just want to help, as I bump into this question and I find it interesting.
I assume you already checked this thread? Using both Thymeleaf and JSP
According to this blog, you can leave as is the default configuration of thymeleaf. You just need to add InternalResourceViewResolver
for the jsp configuration.
Full example here:
Add below dependencies to your pom.xml file
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
In your application.properties set thymeleaf view names and JSP
configuration for internal view resolution
spring.view.prefix:/WEB-INF/
spring.view.suffix:.jsp
spring.view.view-names:jsp/*
spring.thymeleaf.view-names:thymeleaf/*
create a configuration class for view resolution for JSP pages
package com.example.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
@Configuration
public class JspConfig {
@Value(${spring.view.prefix})
private String prefix;
@Value(${spring.view.suffix})
private String suffix;
@Value(${spring.view.view-names})
private String viewNames;
@Bean
InternalResourceViewResolver jspViewResolver() {
final InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix(prefix);
viewResolver.setSuffix(suffix);
viewResolver.setViewClass(JstlView.class);
viewResolver.setViewNames(viewNames);
return viewResolver;
}
}