springboot thymeleaf

Spring Boot前端Jsp與thymeleaf共存

顏俊吉 2020/07/07 20:26:57
5742

 

簡介  
   

 

一、前言

不久前才接觸SpringBoot,並嘗試使用thymeleaf做為視圖解析器,就在想是否能同時使用jspthymeleaf,網路上有不少人提供解決方法,但是依照其所提供的解決方法做卻一直無法實現兩者共存,後來終於找到原因,重點就是那麼簡單。

二、專案設定

1. 建立Spring Started Project

File->New->Spring Starter Project

輸入專案資訊

選擇配置dependency,「spring web」、「thymeleaf

2. 設定pom.xml

 

使用thymeleaf則需要有以下的dependency

 

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

要用Jsp則需要有以下的dependency

<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>  
<groupId>javax.servlet</groupId>  
<artifactId>jstl</artifactId>
</dependency>          
<dependency>  
<groupId>javax.servlet</groupId>  
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>  
</dependency>

3. 設定application.properties

設定網頁開啟的網址路徑及通訊埠,其餘參數在ViewResolver中設定。

server.servlet.context-path=/thjsp
server.port=8083

三、解決方法與實作

1. 建立網頁檔案存放資料目錄

網頁檔案應放置於「src/main/webapp/ WEB-INF」下,若無此目錄,請新增目錄「WEB-INF」。

在「src/main/webapp/WEB-INF/」建立資料夾「jsp」以放置jsp網頁檔案;

在「src/main/webapp/WEB-INF/」建立資料夾「th」以放置thymeleafhtml檔案。

2. 增加解析器類別

InternalResourceViewResolverjsp的視圖解析器

ThymeleafViewResolverthymeleaf的視圖解析器

viewResolver.setPrefix:只設定為web的預設目錄「/WEB-INF/」,不加上網頁檔案所存在的資料目錄,而在controller回傳值才加上檔案所在目錄路徑。

viewResolver.setViewNames:未設定時預設都會解析jsp網頁,但有設定只會依設定值解析該目錄中的網頁。

 

viewResolver. setOrder()jsp 解析器與thymeleaf解析器有設定到相同的目錄,則以order為判斷,數字越小優先權越高。

import org.springframework.context.annotation.Bean;
...
@Configuration 
@EnableWebMvc
@ComponentScan
public class ViewResolverConfiguration  extends WebMvcConfigurationSupport {
        @Bean
        public InternalResourceViewResolver viewResolver() {         
            InternalResourceViewResolver resolver = new InternalResourceViewResolver();
//不在此加上jsp檔案所在資料目錄,而在controller回傳值才加上檔案所在目錄
            resolver.setPrefix("/WEB-INF/"); 
            resolver.setSuffix(".jsp");
resolver.setViewNames("jsp/*");
            resolver.setOrder(1);
            return resolver;
        }       
        @Bean
        public ITemplateResolver templateResolver() {
            SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
            templateResolver.setTemplateMode("HTML");
//不在此加上jsp檔案所在資料目錄,而在controller回傳值才加上檔案所在目錄
            templateResolver.setPrefix("/WEB-INF/");
            templateResolver.setSuffix(".html");
            templateResolver.setCharacterEncoding("utf-8");
            templateResolver.setCacheable(false);
            return templateResolver;
        }
        @Bean
        public SpringTemplateEngine templateEngine() {
            SpringTemplateEngine templateEngine = new SpringTemplateEngine();
            templateEngine.setTemplateResolver(templateResolver());          
            return templateEngine;
        }
        @Bean
        public ThymeleafViewResolver viewResolverThymeLeaf() {
            ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
            viewResolver.setTemplateEngine(templateEngine());
            viewResolver.setCharacterEncoding("utf-8");
            viewResolver.setOrder(2); 
            viewResolver.setViewNames(new String[]{"html/*", "vue/*","templates/*","th/*"});
//網頁檔案存放目錄需符合viewNames中的值才可被成功解析顯示
            return viewResolver;
        }
        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }
}

增加Controller

網址列輸入localhost:8083:thjsp/jsp,則應該開啟jsp/jsphome.jsp頁面。

網址列輸入localhost:8083:thjsp/th,則應該開啟th/thhome.html頁面。

@Controller
@RequestMapping("/")
public class indexController {	
	@RequestMapping("/jsp")
	public String toJspHome(Model model) {
model.addAttribute("today", new Date());
model.addAttribute("welcome", "這是jsp頁面"));
		return "jsp/jsphome";
	}
	@RequestMapping("/th")
	public String toVue(Model model) {
	model.addAttribute("today", new Date());
model.addAttribute("today", "這是thymeleaf頁面");
		return "th/thhome";
	}
}

 

jsphome.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> jspHome.jsp </title>
</head>
<body>
<h2>${welcome}</h2>
<p>現在時間: ${today}</p> 
</body>
</html>

thhome.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset=utf-8">
<title>thome.html</title>
</head>
<body>
<h2 th:text="${welcome}"></h2>
<p th:text="'現在時間: ' +${today}"></p>
</body>
</html>

四、執行結果

專案執行(Run As Spring Boot App)後,

於瀏覽器輸入http://localhost:8083/thjsp/th/ 則顯示thymeleaf網頁,

輸入http://localhost:8083/thjsp/jsp/ 則顯示jsp網頁,顯示結果如下圖

以上步驟完成,即可同時使用jspthymeleaf做為view解析器顯示。

 

不過依上述步驟經多次實作,結果發現有更簡單的做法不用建立ViewResolver類別能達成兩者並存。

1.application.properties 設定「spring.mvc.view.prefix=/WEB-INF/」、「spring.thymeleaf.prefix=/WEB-INF/」。

2. 再於controller的返回值加上欲開啟網頁的存放目錄,如「return "th/thhome";」「return "jsp/jsphome";」。

 

3. 執行後於Browser上輸入「http://localhost:8083/thjsp/th/」即可顯示thymeleaf頁面,Browser上輸入「http://localhost:8083/thjsp/jsp/」即可顯示jsp頁面。

application.properties

thjspController.java

瀏覽結果

五、總結

其實能達成jspthymeleaf視圖並存的重點有幾點:

1. application.propertiesthymeleaf.prifix目錄只設定「/WEB-INF/」,而不加上視圖所存放資料夾路徑。

2.controllerreturn返回值加上欲開啟網頁的存放資料夾路徑

3.  設定application.propertiesthymeleaf.view-names或是ViewResolverviewNames屬性,設定的值即為該ViewResolver會存放的路徑與格式,若非在此設定範圍內,controller返回時無法顯示指定的thymeleaf頁面或是只執行指定目錄中的符合名稱的.jsp頁面。

下圖範例為spring.thymeleaf view-names輸入「th/*,vue/*」,

jsp目錄下同時放置「jsphome.jspjsphome.html」,controller中返回jsp/jsphome,執行結果會選擇開啟jsphome.jsp

vue目錄中同時放置「thhome.jsp」「thhome.html」,controller中返回vue/thhome,執行結果會選擇開啟thhome.html。

因接觸不久,或許做法有不完善或是還有其他做法,也請不吝分享,謝謝。

六、分享

 

GitHub: https://github.com/chunchiYen/JspAndThymeleaf

 

 

顏俊吉