前后端如何进行分工?
jsp已经没落了,基本不再建议使用,而且在SpringBoot中已经不再建议使用jsp编写页面。SpringBoot针对同步应用开发建议使用Thymeleaf模板引擎
Thymeleaf的基本思路:
前后端使用同一个html页面,只是前端使用浏览器直接打开,后端是通过特定的解析器打开
<h1 bbb="ccc"> 由于html的h1标签上并没有bbb这个属性,则浏览器直接跳过;如果使用特定的解析器打开则会对应的处理,例如读取bbb属性,获取配置的数据,用于替代标签体的原始内容,再进行显示
原始内容
h1>
模板引擎其实就是根据这种方式,使用户界面与业务数据分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档在原有的HTML页面中来填充数据。最终达到渲染页面的目的
Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎,能够处理HTML,XML,JavaScript,CSS甚至纯文本
Thymeleaf的主要目标是提供一种优雅且高度可维护的模板创建方式。它以自然模板的概念为基础,以不影响模板用作设计原型的方式将其逻辑注入模板文件。这样可以改善设计沟通,并缩小设计团队与开发团队之间的差距
1、添加依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>3.0.1version>
<relativePath/>
parent>
<groupId>com.yangroupId>
<artifactId>demo3artifactId>
<version>0.0.1-SNAPSHOTversion>
<name>demo3name>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>17java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
惯例优于配置
全局配置 application.properties
spring.thymeleaf.cache=false # 关闭thymeleaf缓存,避免修改后一直不生效的问题;如果产品环境建议打开缓存
2、定义控制器
接收客户端请求参数username,生成问候语,跳转页面显示
@Controller
public class HelloController {
@RequestMapping(value="hello",params = "username")
public String sayHello(String username, Model model){
if(username.trim().length()<1)
username="Thymeleaf";
String msg="Hello "+username+"!";
model.addAttribute("msg",msg);
return "hello";
}
}
3、定义thymeleaf模板文件 hello.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h2>欢迎您访问当前页面h2>
body>
html>
在html页面中添加Thymeleaf相关的语法
,这个名空间用于标识Thymeleaf相关的属性,同时使浏览器不能直接识别DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h2 th:text="${msg}">欢迎您访问当前页面h2>
body>
html>
4、启动应用,然后再浏览器中通过URL地址[Title](http://localhost:8080/hello?username=zhangsan)
访问,可以看到对应的页面
特点
另外还有片段表达式,后面结合片段模板语法再说。
变量表达式用于访问容器上下文环境中的变量
1、首先是控制器,在控制器中使用model.addAttribute准备数据
@Controller
public class HelloController {
@GetMapping("/hello")
public String sayHello(String name, Model model){
if(!StringUtils.hasText(name))
name="Thymeleaf";
String msg="Hello "+name+"!";
model.addAttribute("msg",msg);//request.setAttribute
return "hello";
}
}
2、在页面中使用变量表达式获取controller中准备的数据 ${msg}
<h2 th:text="${msg}">原始显示内容h2>
选择变量表达式计算的是选定的对象(th:object属性绑定的对象)
首先在控制器中准备数据
@RequestMapping("/hello2")
public String hello2(Model model){
User user=new User();
user.setId(99L);
user.setUsername("name_"+99);
user.setPassword("pwd_"+99);
model.addAttribute("user",user);
return "input";
}
使用选择变量表达式实现数据的显示回填
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<form action="hello" method="post" th:object="${user}"> 在form表单上绑定一个对象
<input type="text" name="id" th:value="*{id}"/> 子标签中可以使用*{}获取该对象的
属性值
<input type="text" name="username" th:value="*{username}"/> 注意这里实际上还可
以使用${user.username}
<input type="password" name="password" th:value="*{password}"/>
form>
信息表达式一般用于显示静态文本,也可能需要根据需求而整体变动的静态文本放在properties文件以便维护,通过与th:text属性一起使用。信息表达式主要是用于对国际化功能的支持。所谓的国际化功能就是指,根据浏览器的编码,返回对应编码的内容的支持。
1、国际化配置文件名称命名规范:
默认名:xxx.properties
指定国家编码的名称: xxx_语言编码_国家编号.properties
2、配置SpringBoot 配置文件application.properties
注意:配置的besename就是国际化文件名字名,不需要写语言国家编号以及后缀。
## 配置国际化支持
spring.messages.basename=message
一般在properties文件中不允许出现多字节编码的内容,例如中文字符。如果出现多字节编码内容
需要通过JDK提供的命令行工具native2ascii进行转换,将【中国人民】之类的中文字符转换为
UTF-8编码的字符串【\u4e2d\u56fd\u4eba\u6c11】
3、Thymeleaf 对国际化的支持,信息表达式
标签消息表达式取值:
Thymeleaf模板通过@{…}表达式引入URL
<script src="../static/jslib/hello.js" th:src="@{/jslib/hello.js}">script>
<img src="../static/images/mv02.jpg" th:src="@{${imagePath}}"> 这里使用控制器传
递的参数作为路径
服务器相关配置 application.properties
spring.application.name=demo 应用名称
server.port=9000 配置服务器的端口号,默认8080
server.servlet.context-path=/test 配置上下文路径,默认/
Thymeleaf模板表达式中可以使用各种算术运算符和逻辑运算符。
123
,如果属性要求是表达式,不写${}
则当作字符串处理;如果属性不要求表达式,则必须写${}Product Description
控制器准备数据–数据可以来源于数据库
@GetMapping("/hello5") public String testExp4(Model model){ List<User> userList=new ArrayList<>(); for(int i=0;i<10;i++){ User tmp=new User(); tmp.setId(i+1L); tmp.setUsername("name_"+i); tmp.setPassword("pwd_"+i); userList.add(tmp); } model.addAttribute("userList",userList); return "hello4"; }
页面显示
<table> <tr> <td th:text="${userList[1].id}">001td> <td th:text="${userList[0].username}">yanjuntd> <td th:text="${userList[3].password}">123456td> tr> table>
对象实例化 22-Jun-2023
事实上这种写法不建议,因为准备显示数据应该是控制器的职责,不应该转嫁给页面控制。如果非用不可,可以考虑使用Thymeleaf中的默认工具对象
```html
原始内容
123456
基本运算规则和Java一致
<p th:text="7>5?'7大':'5大'">三元运算符p>
<p th:text="${age}!=null?${age}:'age等于null'">p>
<p th:text="${age2}!=null?${age2}:'age2等于null'">p>
Thymeleaf模板通过一些专门的表达式从模板的WebContext获取请求参数,请求,会话和应用中的属性
控制器存储数据
@GetMapping("/hello6") public String testServlet(Model model, >HttpServletRequest request, HttpSession session){ model.addAttribute("msg1",new Date()); request.setAttribute("msg1",9999L); return "hello5"; }
页面显示
Model:<b th:text="${msg1}">Model中的数据b> <hr/> request:<b th:text="${msg1}">request中的数据b> 如>果名称不一致,则可以使用${key}的方式访问>request.setAttribute的数据
结果显示的是model中存储的数据,
request.setAttribute的数据不能显示
目前版本中已经不允许使用#request、#session和#servletContext Caused by:
java.lang.IllegalArgumentException: The
‘request’,‘session’,‘servletContext’ and ‘response’ expression utility objects are no longer available by default for template expressions and their use is not recommended. In cases where they are really needed, they should be manually added as context variables
与EL表达式一样,使用${xxx}获取变量值,使用 ${对象变量名.属性名}获取JavaBean属性值。
只有在th:if标签条件成立才会显示标签内容,th:unless只有在条件不成立才显示标签内容,可以理解为else。
控制器传递一个数据,也可以使用表达式表示条件
@GetMapping("/hello6")
public String testIf(Model model){
model.addAttribute("msg",true);
return "hello6";
}
显示页面
<b th:if="${true}">原始显示内容b>
<b th:unless="${false}">不显示内容b>
也可以使用表达式进行判断,表达式中可以使用and or not
<b th:if="${msg > 10}">原始显示内容b>
<b th:unless="${msg <= 10}">不显示内容b>
但是>和<容易和标签混淆,所以可以使用实体字符替代。用>表示>、$lt;表示<、$ge;表示>=、
$le;表示<=、$eq;表示==、not表示非!、$neq;/$ne;表示不等于!=
<b th:if="${msg > 10}">原始显示内容b>
<b th:unless="${msg > 10}">不显示内容b>
Thymeleaf模板也支持多路选择的switch语句结构,默认属性default可用 * 表示。
<div th:switch="${msg}"> 获取控制器传递的数据
<span th:case="18">我18岁了!span> 等值判断
<span th:case="14">我14岁了!span>
<span th:case="*">我其他岁了!span> 其他默认情形
div>
Thymeleaf模板使用 th:each=“obj,iterStat:${objList}” 标签进行迭代循环,迭代对象可以是List、Set、Map或者数组等。
控制器获取数据
@GetMapping("/hello9")
public String testExp9(Model model){
List<User> userList=new ArrayList<>();
for(int i=0;i<10;i++){
User tmp=new User();
tmp.setId(i+1L);
tmp.setUsername("name_"+i);
tmp.setPassword("pwd_"+i);
userList.add(tmp);
}
model.addAttribute("userList",userList);
return "hello8";
}
页面显示
<table border="1" width="60%">
<thead>
<tr><th>用户编号th><th>用户名称th><th>用户口令th>tr>
thead>
<tbody>
<tr th:each="tmp:${userList}"> 需要哪个标签循环出现则将th:each添加在哪个标
签上,tmp是循环控制变量,${userList}获取一个集合数据
<td th:text="${tmp.id}">001td>
<td th:text="${tmp.username}">Usernametd>
<td th:text="${tmp.password}">Passwordtd>
tr>
tbody>
table>
在th:each标签中可以使用循环状态变量,该变量有如下属性:
<table border="1" width="60%">
<thead>
<tr><td>索引变量的使用td><th>用户编号th><th>用户名称th><th>用户口令th>
tr>
thead>
<tbody>
<tr th:each="tmp,stat:${userList}"
th:bgcolor="${stat.odd?'red':'blue'}">
<td th:text="${stat.index}+' '+${stat.count}">Indextd>
<td th:text="${tmp.id}">001td>
<td th:text="${tmp.username}">Usernametd>
<td th:text="${tmp.password}">Passwordtd>
tr>
tbody>
table>
在实际Web项目开发中,经常传递列表,日期等数据,所以Thymeleaf模板提供了很多内置对象,通过#
直接访问,这些内置对象一般都通过s结尾,如dates、lists、numbers、strings等。
其实Thymeleaf语法的使用都是通过在html页面的标签中添加th:xxx关键字首先模板套用,其属性与
html标签基本相似。
Thymeleaf属性只有当Thymeleaf模板引擎启动的情况下,才会生效,即取代对应的HTML5属性,相反,Thymeleaf属性仅仅只是一个无用的自定义属性,因为浏览器内核不认识,因此使用Thymeleaf模板引擎可以使得前端代码和后端代码分离,当出现显示问题时,可以立即定位问题所在,是前端页面还是后台返回数据有错,这也是Thymeleaf相对于JSP的一个优势
常用属性有以下几种:
标签的href属性th:text是在页面中输出值 th:value 可以将一个值放入到 input 标签的 value 中