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

https://imgur.com/qOTgYZW

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 InternalResourceViewResolverfor 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;
    }
}

Use JSP and Thymeleaf views in Spring Boot app

Leave a Reply

Your email address will not be published. Required fields are marked *