Spring Boot MVC ---前後臺互動
我對Spring Boot MVC一直存在一個誤解,那就是所有的頁面都要通過
@Controller
來實現對映,因此也導致後面出了一個大bug.後來查閱資料才發現真是錯到姥姥家了
之前的誤解是這樣的:
再控制器中加入一個對映/hello
,然後返回檢視的名字hello
,希望它能對映到/static/hello.html
,假如使用Ajax作為互動的話,可以讓前臺獲得返回的hello.html
後,通過傳送HTTP請求和其他@Controller
對映互動JSON
資料。
我一開始做這樣合理的假設是因為我一直都是這麼幹的,而且因為官網上說:
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" };
以下路徑會通過Spring Boot的自動配置加入到搜尋路徑中。
因此,不應該返回錯誤頁,因為我能檢測到確實請求能夠到達方法,但是返回的字串卻不能合理的解析成檢視名hello.html
這就是癥結所在了,那麼問題處在那裡呢?
看下maven構建的目錄:
可以看到hello.html
的確在搜尋路徑下,因為classes
目錄就是classpath
根路徑
訪問以下路徑,靜態頁面是可以在瀏覽器訪問到的。
http://localhost:8080/hello.html
那麼,問題就來了,Spring Boot本身就不支援這樣的頁面模型。靜態頁面應該就是通過連結直接訪問。
可我明明原來做專案就是這麼幹的啊,為什麼現在卻不行了呢?
我突然想到Thymeleaf
原來在路徑中用的是這樣的模型,我大概是記混了…
因此我嘗試了下配置Themeleaf:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
把這個放入Maven POM檔案中。
在/static/templates
路徑下放入一個html頁面,這是從官網上覆制的一個樣本Themeleaf檔案
加入像原來出錯程式碼一樣的對映,輸入localhost:8080/test
,成了!
我了個去,大烏龍,然後看看原來出錯的頁面/hello
,結果錯誤出現變化,不是錯誤頁,而是出現以下異常:
可見/hello
被嘗試解析為Thymeleaf模板。
總結
因此總結如下:
Spring Boot在環境中沒有Themeleaf時,將@Controller的所有返回字串解析為重定向對映:
比如/hello
返回的是“hello”
,因此會被解析為/hello
,因此這就會產生無限迴圈,
Spring boot報錯Circular Mapping.....
但是如果Maven配置中Themeleaf,這樣子符串會被解析為Thymeleaf模板名hello.html。
但是普通的hello.html
,要想被訪問,不要通過@Controller
,直接訪問,假如在路徑下,比如/static/hello.html
,直接輸入localhost:8080/hello.html
訪問。
互動模型
-
模型一:Ajax +JSON+RESTful API
通過訪問靜態頁面比如localhost:8080/hello.html
,然後使用Ajax向Restful API傳送JSON資料,來和後臺互動資料。 -
模型二 Thymeleaf +Spring MVC
這個模型是利用傳統的Spring MVC,可以參見:
https://spring.io/guides/gs/serving-web-content/
來學習前後臺傳至以下是擷取的程式碼片段。
@Controller
public class GreetingController {
@GetMapping("/greeting")
public String greeting(@RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {
model.addAttribute("name", name);
return "greeting";
}
}
將資料<name,"">
放入Model物件中,前臺Thymeleaf這樣獲取:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
//這裡獲取資料
<p th:text="'Hello, ' + ${name} + '!'" />
</head>
<body>
</body>
</html>