和Thymeleaf一樣,FreeMarker也是一款前端模板,該模板用純Java語言編寫,能很好地同Spring Boot后端框架整合。在該模板中,不僅可以包含HTML等前端元素,也可以從Spring Boot等后端獲取元素,以實現數據的動態展示。本文我們就來看看如何實現這個功能,希望小伙伴們看后有什么問題給我留言。
1. Spring Boot整合FreeMarker的簡單范例
FreeMarker和Thymeleaf模板一樣,都可以從后端接收參數並展示,在如下的FreeMarkerDemo項目中將展示該模板的基本用法,具體的步驟如下:
步驟一:在pom.xml中引入FreeMarker模板的依賴包,關鍵代碼如下:
01 <dependency>
02 <groupId>org.springframework.boot</groupId>
03 <artifactId>spring-boot-starter-freemarker</artifactId>
04 </dependency>
步驟二:編寫啟動類SpringBootApp.java和控制器類Controller.java,這兩個Java文件的代碼和ModelAndViewDemo項目中的基本一致,所以不再講解,讀者可以自行查看相關源碼。
步驟三:在application.properties文件中編寫FreeMarker模板的相關配置,具體代碼如下:
01 #指定模板文件的位置
02 spring.freemarker.tempalte-loader-path=classpath:/templates
03 #指定是否開啟緩存
04 spring.freemarker.cache=false
05 #指定模板中采用的編碼,用了UTF-8以后,就可以展示中文
06 spring.freemarker.charset=UTF-8
07 #指定在使用前需要檢查模板的位置
08 spring.freemarker.check-template-location=true
09 #指定模板中頁面的格式
10 spring.freemarker.content-type=text/html
11 #指定需要使用HttpServletRequest中的值
12 spring.freemarker.expose-request-attributes=true
13 #指定需要使用Session中的值
14 spring.freemarker.expose-session-attributes=true
15 #指定RequestContext attribute的值
16 spring.freemarker.request-context-attribute=request
17 #指定模板文件的后綴名
18 spring.freemarker.suffix=.ftl
相關的配置值都已經通過注釋說明,根據這里的配置,控制器中返回的list將被加上.ftl后綴,形成list.ftl,然后FreeMarker解析器會據此到第2行指定的resources/templates目錄下找這個模板文件,並展示數據。
步驟四:在resources/templates目錄下編寫list.ftl文件,在其中通過FreeMarker模板動態展示數據。注意該模板的前端文件擴展名是.ftl,該文件的具體代碼如下:
01 <!DOCTYPE html>
02 <html lang="en">
03 <head>
04 <meta charset="UTF-8">
05 <title>庫存列表</title>
06 </head>
07 <body>
08 <tableborder="2">
09 <tr>
10 <td>庫存編號</td>
11 <td>庫存貨物</td>
12 <td>數量</td>
13 <td>描述</td>
14 </tr>
15 <#list stocks as stock>
16 <tr>
17 <td>${stock.ID}</td>
18 <td>${stock.name}</td>
19 <td>${stock.num}</td>
20 <td>${stock.description}</td>
21 </tr>
22 </#list>
23 </table>
24 </body>
25 </html>
這里請注意,是通過第15行的#list標簽循環地展示數據的,展示的數據同樣來自Spring Boot控制器中的stocks參數,展示時同樣會用第17~20行的形式,以參數.屬性的方式具體展示參數的每條數據的每個屬性元素。
編寫完成后啟動該項目,並在瀏覽器中輸入
http://localhost:8080/showList,就能看到如圖所示的效果,其中庫存數據使用FreeMarker模板中的循環語句動態展示。

2 用FreeMarker模板展示分頁效果
這里將通過FreeMarker模板分頁展示數據的效果,進一步給出該模板的具體用法。這里要用到的項目FreeMarkerWithDB是根據ThymeleafWithDB項目改寫而成的。
項目對應的啟動類是StringBootApp.java,業務邏輯類是StockService.java,訪問數據庫所用到的StockRepo.java和業務模型Stock.java完全一致,而控制器類Controller.java和配置文件application.yml以及前端文件listByPage.ftl需要修改。
相同的類文件之前已經分析過,讀者可自行閱讀本書附帶的源碼,需要修改的文件具體描述如下:
步驟一:需要修改的Controller.java關鍵代碼如下:
01 @RequestMapping("/listByPage")
02 public ModelAndViewlistByPage(@RequestParam(value = "pageNum", defaultValue ="0") int pageNum, @RequestParam(value = "pageSize",defaultValue = "3") int pageSize) {
03 Page<Stock>stocks=stockService.getStockListByPage(pageNum, pageSize);
04 ModelAndView modelAndView = newModelAndView("listByPage");
05 //傳遞參數
06 modelAndView.addObject("stocks",stocks.getContent());
07 modelAndView.addObject("currentPage",pageNum);
08 modelAndView.addObject("totalPage",stocks.getTotalPages());
09 return modelAndView;
10 }
這里在第4行創建ModelAndView對象時,指定了該對象將要向listByPage視圖返回Stock數據,結合后文提到的配置文件,這里具體會向listByPage.ftl前端文件傳輸數據。
為了實現分頁效果,這里需要通過第7行和第8行代碼傳輸表示當前頁的currentPage參數和表示一共多少頁的totalPage參數,而包含庫存數據的stocks參數則是在第6行設置的,由於ftl文件在循環時只能接收List等類型的集合類數據,因此這里需要調用stocks.getContent方法把數據轉換成List<Stock>類型的數據。
步驟二:在application.yml文件中加入JPA和FreeMarker的參數,這里注意配置文件的格式,具體每個參數的含義之前都已經講過了。
01 spring:
02 jpa:
03 show-sql: true
04 hibernate:
05 dll-auto: validate
06 datasource:
07 url: jdbc:mysql://localhost:3306/stock?serverTimezone=GMT
08 username: root
09 password: 123456
10 driver-class-name: com.mysql.jdbc.Driver
11 freemarker:
12 tempalte-loader-path: classpath:/templates
13 cache: false
14 charset: UTF-8
15 check-template-location: true
16 content-type: text/html
17 expose-request-attributes: true
18 expose-session-attributes: true
19 request-context-attribute: request
20 suffix: .ftl
步驟三:在listByPage.ftl文件中,用FreeMarker模板實現分頁的效果,具體代碼如下:
01 <!DOCTYPE html>
02 <html lang="en">
03 <head>
04 <meta charset="UTF-8">
05 <title>庫存列表</title>
06 </head>
07 <body>
08 <tableborder="2">
09 <tr>
10 <td>庫存編號</td>
11 <td>庫存貨物</td>
12 <td>數量</td>
13 <td>描述</td>
14 </tr>
15 <#list stocks as stock>
16 <tr>
17 <td>${stock.ID}</td>
18 <td>${stock.name}</td>
19 <td>${stock.num}</td>
20 <td>${stock.description}</td>
21 </tr>
22 </#list>
23 </table>
24 <div>
25 <ul>
26 <li>
27 <ahref="/listByPage?pageNum=0">首頁</a>
28 </li>
29 <#if (currentPage>0)>
30 <li>
31 <ahref="/listByPage?pageNum=${currentPage-1}">上一頁</a>
32 </li>
33 </#if>
34 <#if(currentPage<totalPage-1)>
35 <li>
36 <ahref="/listByPage?pageNum=${currentPage+1}">下一頁</a>
37 </li>
38 </#if>
39 <li>
40 <ahref="/listByPage?pageNum=${totalPage - 1}">尾頁</a>
41 </li>
42 </ul>
43 </div>
44 </body>
45 </html>
這里在第15~22行代碼中用<#list>的形式循環展示了當前頁的數據,而在24~43行的<div>標簽中用<#if>的形式動態展示了分頁的效果。
在分頁相關的代碼中,在第29行中,先通過<#if>語句用currentPage參數判斷當前是不是第1頁,如果不是,則通過第30~32行代碼展示“上一頁”的鏈接,同樣,在第34行的<#if>語句中,通過currentPage<totalPage-1的形式判斷當前是不是最后一頁,如果不是,則通過第35~37行代碼展示“下一頁”的效果。
本范例運行后,如果在瀏覽器中輸入
http://localhost:8080/listByPage,就能看到如圖所示的分頁效果,和之前的范例不同,這里的分頁效果是用FreeMarker模板實現的。

(本文是在學習Spring Boot+Vue.js+分布式組件全棧開發訓練營一書獲得的知識,想了解更多內容可以參考該書)