1. 程式人生 > >Spring Boot MVC ---前後臺互動

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>