MVC 模式
首先简单介绍一下MVC模式,MVC模式是Web应用中最常见的设计模式。MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。其中各自含义为
Model(模型) - 模型代表一个存取数据的对象或 JAVA 普通类。它可以带有逻辑,在数据变化时更新控制器。
View(视图) - 视图代表模型包含的数据的可视化,一般来说我们可以简易理解为用户界面。
Controller(控制器) - 控制器作用于模型和视图上。它控制数据填充到模型对象中,并在数据变化时更新视图。它使视图与模型分离开。
早期开发Web应用中视图通常是静态页面,其主要由HTML、图片、文字等等组成,但随着前端技术的提升当前的Web前端中动态页面技术不断发展,并且出现了一些优秀的前端框架如Angluar、Vue、React等。同样的Spring Boot框架为适应技术发展,简化项目开发,也提供了对视图技术的支持,Spring Boot使用模板引擎技术实现前端页面的动态化。
Spring Boot支持的视图技术
前端模板引擎技术可以实现前后端分离开发,可以使前端开发人员无线关注后端业务的具体实现,只关注前端页面展示效果即可。前后端分离技术降低了系统中前后台的耦合度,提升了开发效率。
Spring Boot对很多模板引擎提供了支持,比如有:
Thymeleaf:它是一种时候Web和独立环境的Java模板引擎,其开发宗旨是将优雅的Java模板贯穿整个开发工作流程中。它强调自然模板化,允许模板成为工作原型(而许多其他模板引擎如FreeMarker不支持 )这可以避免重复造轮子,让团队更容易协作。Thymeleaf能够处理HTML, XML,JavaScript, CSS以及纯文本, Thymeleaf相对其他模板引擎其设计更加优雅,语法更加干净简洁因此是Spring Boot默认推荐的模板引擎。
FreeMarker:即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
Groovy:本质上是一种基于Java虚拟机的敏捷开发语言,它集成了Smalltalk、Ruby和Python等脚本语言中许多强大的特性,能够与Java代码紧密结合。
Spring Boot为什么不支持JSP
SpringMVC是支持JSP的,但是Spring Boot中并不建议我们使用JSP。对此官方文档给出的解释是
大致的含义是
当运行一个内置servlet容器(或者直接打包成一个可执行文件)的SpringBoot应用时,有以下几个对JSP文件的限定条件:
· 在Jetty和Tomcat容器中,SpringBoot应用被打包成war包时可以支持JSP。可以使用java -jar命令或者部署到任何标准容器中都可以让一个可执行war包工程运行。但是当SpringBoot打包成jar包时就不再支持JSP。
·Undertow (一种嵌入式容器)不支持JSP
·创建一个error.jsp不能覆盖掉错误页面的默认视图,Custom error pages 可以实现代替。
官网也给出了一个git地址放了一个支持JSP的SpringBoot工程,可以按照这个工程配置我们自己的工程支持JSP,在遵循上述规则打包成war包放入外置web容器(除Undertow)运行。
有了Vue、 React为什么还要用Thymeleaf
注意模板引擎和前端框架不是一样的东西,模板引擎负责组装数据,以另外一种形式或外观展现数据,是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档。前端框架是一个开发框架,使用框架提供的基础技术、函数、组件等等可以快速开发出想要的业务界面。
由于前端框架和模板引擎都能创建出用于展示的页面,那开发时我们如何选择呢?
在前后端不分离的情况下,springboot推荐用html做页面,然后用Thymeleaf 做模板引擎,做数据渲染,相当于之前的jsp。对于一些小型的项目或者一些比较老旧的项目这是比较常见的做法。
对应偏向简单业务展示的前端页面推荐模板引擎,特别是项目团队里没有专门的前端人员时。
对于大型项目,一般会进行前后端分离设计,然后由不同的团队开发,这种资源充足的情况向前端一般直接使用Vue、react等来渲染页面,前后端采用Restful、JSON通信。
如果项目有SEO要求的话,由于模板引擎对SEO(搜索引擎优化)友好,而Vue、react、Angular等框架开发的页面进行SEO相对困难,此时可以采用模板引擎。
Spring Boot 中使用Thymeleaf
Spring Boot对Thymeleaf提供了非常完整的支持,使得我们使用Thymeleaf非常简单,Spring Boot中使用Thymeleaf模板有两种方法
方法1:新建项目向导时选择Thymeleaf
由于Thymeleaf模板引擎是配合Web应用开发的,因此向导中同时需要选择Web开发
在向导中选择了Thymeleaf模板引擎之后,项目中会看到Thymeleaf相关依赖。
方法2:在pom.xml中添加Thymeleaf相关依赖
如果已经建立好的项目,项目中已经有了Web开发依赖库,即spring-boot-starter-web组件,需要引入Thymeleaf只需要在pom.xml引入spring-boot-starter-thymeleaf依赖库即可
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
首个Thymeleaf页面
Thymeleaf模板后缀为.html,我们现在来创建第一个Thymeleaf页面,在resource\templates模板存放目录下创建index.html页面。
然后添加以下代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<meta charset="UTF-8" />
<title></title>
</head>
<body>
<h3>这是我们第一个模板引擎</h3>
<h1 th:text="${message}">大家好这是修改前的文字</h1>
</body>
</html>
由于Thymeleaf的模板是HTML格式,所以它可以直接用浏览器查看
读者可能已经注意到了前面代码中的 th:text="${message} 和我们印象中的HTML代码不一样,其实这就是Thymeleaf的语法,由于我们代码中添加了 <htmlxmlns:th="http://www.thymeleaf.org">这句话为代码引入了Thymeleaf命名空间,所以我们可以在HTML文件中使用Thymeleaf语法。Thymeleaf语法默认以th:开头,冒号后面接着是具体的命令,前面代码中th:text="${message}命令含义是从上下文中message变量里取出一个文本串,然后放置在该命令所在标签里,这里命令所在的标签就是<p></p>.
下面我们运行验证一下我们的第一个模板页面,运行之前我们先做一下基础配置
Thymeleaf基础配置
#模版文件位置,注意如果配置错误会报500,找不到资源
spring.thymeleaf.prefix=classpath:/templates/
#是否开启缓存,开发时可以设置为 false,默认为 true
spring.thymeleaf.cache=false
#Content-Type配置
spring.thymeleaf.servlet.content-type=text/html
#模版文件后缀
spring.thymeleaf.suffix=.html
#编码
spring.thymeleaf.encoding=UTF-8
配置项:spring.thymeleaf.prefix=classpath:/templates/ 配置模板文件所在的位置,前面这样配置说明模板文件在
resource/templates/目录下,这里注意templates之后需要加"/",如果不加在某些Spring Boot版本下会出现找不到资源错误。
配置项:spring.thymeleaf.cache=false,代表是否启用缓存,一般来说在开发环境中由于要频繁修改代码然后查看效果因此一般配置为false,在生产环境中一般设置为true,启用缓存加快用户访问。
添加controller类
添加一个controller类,取名WellController,并且添加如下代码
@Controller
public class WellController {
@RequestMapping("/well")
public String well(ModelMap map) {
map.addAttribute("message", "大家好这是修改过的文字");
//注意这里返回的字符串需要和模板的文件名一致
return "well";
}
}
代码中定义了一个well方法,接收一个ModelMap 类型的参数map。然后通过map的addAttribute方法,添加了一个属性message,其值是字符串“大家好这是修改过的文字”。注意这里return的字符串“well”要和模板的名字一样,不然访问时会报无法找到资源。完成代码之后,运行项目然后访问路径 http://localhost:8080/well
可以看到通过设置message属性,我们成功替换了页面的文字,说明Thymeleaf 模板在项目中生效了。
Thymeleaf基本语法
th标签表
Thymeleaf通过th: 前缀提供标签,不同的标签代表不同的功能,下面是常见的th标签表
标签 |
功能 |
---|---|
th:text |
文本替换 |
th:utext |
支持html的文本替换 |
th:id |
替换id |
th:object |
替换对象 |
th:value |
属性赋值 |
th:with |
变量赋值 |
th:onclick |
点击事件 |
th:if |
判断条件 |
th:switch |
多路选择,配合th:case使用 |
th:case |
th:swich的一个分支 |
th:src |
图片类地址引入 |
在介绍标签语法之前先简单介绍一下Thymeleaf中的简单表达式,
简单表达式
Tymeleaf常用的简单表达式有
${...} 取出上下文变量的值
*{...} 取出选择的对象的属性值
#{...} 使文字消息国际化
@{...} 用于表示各种超链接地址
${...} 取出上下文变量的值
public String well(ModelMap map) {
map.put("message", "Wellcome to Thymeleaf");
}
Thymeleaf模板将通过${}表达式取出上下文环境中的message变量,并且替换掉 ${}表达式所在的标签的内容
<p th:text="${message}"></p>
*{...} 取出选择的对象的属性值
${}变量表达式可以从整个上下文环境提取信息,而选择表达式*{...}左右的范围是上下文中父标签(th:object)所选择的对象
<div th:object="${session.person}">
<p th:text="*{name}"></p>
<p th:text="*{home}"></p>
</div>
上面的代码等价于
<div>
<p th:text="${session.person.name}"></p>
<p th:text="${session.person.home}"></p>
</div>
@{...} 链接表达式
在Web中我们经常会遇到URL链接,比如访问图片、静态资源文件、访问跳转链接。在Thymeleaf中通过@{...}语法来处理URL表达式,URL表达式主要和th:href、th:src等标签配合使用
引入静态资源文件
Thymeleaf页面可以使用th:href属性引流资源文件例如CSS,格式为 th:href = “@{文件路径}” 如
<link rel="stylesheet" th:href="@{/css/jquery-ui.min.css}" />
引入js资源需要用 th:src ,格式为 th:src = “@{文件路径}”如
<script th:src="@{/js/jquery.js}"></script>
引入URL链接
Thymeleaf支持在<a>标签中使用th:href来处理URL链接
<a th:href="@{https://www.baidu.com}">绝对地址</a>
<a th:href="@{/order}">相对路径</a>
th:href标签将计算并替换使用href链接的URL值,并放入href属性中。
Thymeleaf标签语法
文本赋值
文本赋值通过${}标签将后台返回的数据替换到标签中,如
<p th:text="${msg}">Wellcome to China</p>
上面的代码将后台返回的数据中的msg里的值替换到<p>标签中。如果msg为空,则显示默认值这里是Wellcome to China,如果msg有值,比如Wellcome to Beijing,则将会替换<p>标签中的文本。
文本拼接
<p th:text="'Wellcome, '+ ${user}"></p>
th:text标签中的文本还可以进行拼接,如上从上下文中取到的user的值将和“Welcome, ”一起拼接,最后Thymeleaf将拼接后的结果如“Wellcome, Xiao Ming”替换到页面的<p>标签中。注意最外层是双引号,内层文本文字可以用单引号来包含,对于特殊字符,需要用“\”转义。这样使用单引号有时会觉得比较繁琐,因此Thymeleaf提供了一种简写的文本拼接语法,就是使用竖线"|"将需要拼接的文本包围起来
<p th:text="|Wellcome, ${user}|"></p>
带HTML标签解析的文本赋值
前面说了th:text进行文本拼接时如果有特殊字符需要用到转义,如果${user}中的字符本身有HTML语法标签那会如何处理呢? 假如上面代码user=<h1>Xiao Ming</h1>,则th:text标签会原封不动的输出标签内容
Wellcome, <h1>Xiao Ming</h1>
那如果我们希望内容中的HTML标签被解析处理应该如何操作内? 这个时候就需要使用th:utext标签,这个标签对对文本里的HTML标签进行语法解析,如
<p th:utext="'Wellcome, '+${user}></p>
当user=<h1>Xiao Ming</h1>则会解析为
Wellcome, Xiao Ming
th:id标签
th:id标签可以进行id替换,具体语法介绍如下,有如下代码块
<div id="id1" th:id="new-id-thymeleaf"></div>
th:id标签将会替代id标签中的值。运行程序,然后在chrome浏览器中按F12,选择元素我们可以看到
这个div中的id被替换成了th:id中的id
th:value标签
改标签将会替换HTML中的value属性。如有如下代码
<input type="text" value="input" th:value="new-thymeleaf-value"/>
然后运行程序,访问页面可以看到value的值被替代了。
th:object标签
在前面介绍表达式的时候我们已经提到了th:object标签,th:object标签在父标签选择对象,在子标签中使用 *{}选择表达式选取值, 若父标签没有选择对象,子标签使用*{}选择表达式或${}变量表达式效果是一样的, 同时父标签选择了对象,子标签仍可用${}变量表达式取值。
<div th:object="${user}">
第一:<span th:text="*{username}"></span>
</div>
<div>
第二:<span th:text="*{user.username}"></span>
</div>
<div th:object="${user}">
第三:<span th:text="${user.username}"></span>
</div>
我们新建一个model目录,并在里面增加一个User.java
再其中添加如下代码
public class User {
private String username;
public User(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
同时修改原有的WellController类
@Controller
public class WellController {
@RequestMapping("/well")
// @ResponseBody 注意这里不使用这个注解
public String well(ModelMap map) {
map.addAttribute("message", "大家好这是修改过的文字");
User user = new User( "xiaoming");
map.addAttribute("user", user);
//注意这里返回的字符串需要和模板的文件名一致
return "well";
}
}
最后运行程序,访问http://localhost:8080/well
th:with标签
该标签是局部变量赋值运算符
<span th:with="a = '再次欢迎'" th:text="${a}"></span>
运行结果是
th:onclick标签
th:onclick会被替换为onclick点击事件,具体如下
<input type="button" value="提交" th:onclick=" 'submit()' " />
运行后的页面中onclick元素值会被th:onclick指定的内容替换。
th:if 和th:unless标签
这两个标签是Thmeleaf中的条件判断标签,其中th:if 根据条件判断为true时展示此标签,th:unless 与th:if判断条件相反,当条件不满足时显示此标签。
<div th:if="'a' == 'b'"> a == b, 当表达式为true时展示</div>
<div th:if="'a' == 'a'"> a == a, 当表达式为true时展示</div>
<div th:if=" 'a' eq 'a'">a eq a, 当表达式为true时展示</div>
<div th:unless=" 1==2 ">th:unless 1==2,当表达式为false时展示</div>
运行结果为
th:switch和th:case标签
这两个标签和常见的编程语言中的switch和case一样,是分支选择标签,通过th:switch标签中选择的值,匹配case对应的代码,代码示例如下
<br>
<div th:with="a = '2'" th:switch="${a}" >
<span th:case="1">case =1</span>
<span th:case="3">case =3</span>
<span th:case="2">case =2</span>
</div>
运行结果为
好了对于Thmeleaf模板先简单介绍到这里,目前大多数项目开发还是会选择Vue.js之类的前端框架开发前端页面当真正需要使用Thmeleaf模板时,我们可以具体查阅官方文档,有了上面的入门相信学习起来会更轻松。
可以访问:GitHub - qwdzq/springboot: spring boot 入门
文章有帮助,还请点个赞啊