我对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>