SpringBoot深入实践Thymeleaf
上一篇大致介绍了Thymeleaf的简单语法规则,这一篇就来对Thymeleaf进行使用。下边都是我通过实战测试后写出来的。
Thymeleaf是一个很强大的模板引擎,它基本可以替换所有的HTML标签的属性,因此我们可以在HTML的基础上进行修改,下边就说一说我在一次简单整合中遇到的一些常用的属性。
Thymeleaf的属性是覆盖在HTML上的
- 超链接(th:href),链接使用@{},可以看出在Thymeleaf中 / 就可以表示当前项目
<a class="nav-link" href="/crud/emps" th:href="@{/emps}"
- class属性(th:class),使用${}的原因是activeUri是自定义在Context中的需要用 ${} 取出来,并且在下面例子可以看出使用了三元运算
<a class="nav-link active"
th:class="${activeUri=='main.html'?'nav-link active':'nav-link'}"
th:href="@{/main.html}" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
- name属性(th:name)
<input th:name="gender" class="form-check-input" type="radio" name="gender" value="1">
- select标签的name,值得注意的是,option的value和使用模板引擎来遍历,depts是我们在后台在Model中放的属性,dep是遍历depts的单个并且指定dep的id为value。
<select class="form-control" th:name="department.id">
<!--注意:显示的是部门名称,打但是请求的是部门id-->
<option th:value="${dep.id}" th:each="dep:${depts}" th:text="${dep.departmentName}">1</option>
</select>
//来到员工添加的页面
@GetMapping(value = "/emp")
public String addPage(Model model) {
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("depts", departments);
return "emp/add";
}
- 单行显示,取出session的userKey属性
<a class="navbar-brand col-sm-3 col-md-2 mr-0" th:href="@{/main.html}">[[${session.userKey}]]</a>
package com.wrial.demo.controller;
@Controller
@RequestMapping(value = "/user")
public class UserController {
@PostMapping(value = "/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Map<String, Object> map, HttpSession session) {
if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password) &&
username.equals("wrial") && password.equals("123")) {
map.put("msg", "登陆成功!");
//配置拦截器进行安全检测
session.setAttribute("userKey", username);
//为了防止重复提交请求,使用重定向
return "redirect:/main.html";
} else {
map.put("msg", "登陆失败,请重试");
return "login";
}
}
}
- 公共模块抽取
(1)使用feagment实现公共模块抽取
<!--使用feagment抽取公共部分-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" th:href="@{/main.html}">[[${session.userKey}]]</a>
<input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
</li>
</ul>
</nav>
使用公共抽取页面,必须使用div包裹,第一种是插入因此外层还是div包裹,第二个是替代,外层就没有这个div包裹了(一般会使用第二种)
引入的格式~{},然后commons/bar(template目录下)是我的html页面的目录(Thymeleaf会自动解析为指定的HTMl),然后topbar也就是我上边feagment的值。
<div th:insert="~{commons/bar::topbar}"></div>
<div th:replace="~{commons/bar::topbar}"></div>
(2)使用id选择器实现公共模块抽取
<nav class="col-md-2 d-none d-md-block bg-light sidebar" id="sidebar">
<div class="sidebar-sticky">
<ul class="nav flex-column">
....
....
</nav>
使用id选择器,格式也是~{},commons/bar是template下的指定html文件,使用#选择在bar中的id为sidebar的模块,并且可以在小括号中传入属性。
<div th:replace="~{commons/bar::#sidebar(activeUri='emps')}"></div>
- 使用put方式修改员工数据,必须是post请求然后根据指定的命名规则SpringBoot自动识别为是put请求。
<!--发送put请求修改员工数据-->
<!--
1、SpringMVC中配置HiddenHttpMethodFilter;(SpringBoot自动配置好的)
2、页面创建一个post表单
3、创建一个input项,name="_method";值就是我们指定的请求方式
-->
<form action="/crud/addemp" method="post" th:value="${employee!=null}">
<input type="hidden" name="_method" value="put" th:if="${employee!=null}"/>
<input type="hidden" name="id" th:if="${employee!=null}" th:value="${employee.id}">
<div class="form-group">
<label>LastName</label>
<!--可以用作添加修改二合一页面-->
<input th:name="lastName" type="text" class="form-control"
th:value="${employee.lastName!=null}?${employee.lastName}" placeholder="wrail">
</div>
<div class="form-group">
<label>Email</label>
<input th:name="email" type="email" class="form-control"
th:value="${employee.email!=null}?${employee.email}" placeholder="wrial.qq.com">
</div>
<div class="form-group">
<label>Gender</label><br/>
<div class="form-check form-check-inline">
<!--如果要让多选回显的化,那就使用判断-->
<input th:name="gender" class="form-check-input" type="radio" name="gender" value="1"
th:checked="${employee.gender!=null}?${employee.gender==1}">
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input th:name="gender" class="form-check-input" type="radio" name="gender" value="0"
th:checked="${employee.gender!=null}?${employee.gender==0}">
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label>department</label>
<select class="form-control" th:name="department.id">
<!--注意:显示的是部门名称,打但是请求的是部门id-->
<option th:selected="${employee.department.id!=null}?${dep.id==employee.department.id}"
th:value="${dep.id}" th:each="dep:${depts}" th:text="${dep.departmentName}">1
</option>
</select>
</div>
<div class="form-group">
<label>Birth</label>
<input th:name="birth" th:type="date" class="form-control"
th:value="${employee.birth!=null}?${#dates.format(employee.birth,'yyyy-mm-dd ')}"
placeholder="zhangsan">
</div>
<!--action不可用,使用formaction绑定-->
<button type="submit" class="btn btn-primary" formaction="/crud/emp" formmethod="post">添加</button>
<button type="reset" class="btn btn-primary">重置</button>
</form>
//信息修改
@PutMapping("/emp")
public String updateEmp(Employee employee) {
//修改方法(是一个懒方法,在内部进行id判断,如果有id就是修改,没id就是增加)
employeeDao.save(employee);
System.out.println("update:" + employee);
return "redirect:/emps";
}
- 自定义属性,使用attr自定义属性
<button th:attr="del_uri=@{/emp/}+${emp.id}" class="btn btn-sm btn-danger deleteBtn">删除 </button>
- 使用delete请求,必须为post请求,然后创建hidden属性,value是delete
<form id="deleteEmp" method="post">
<input name="_method" type="hidden" value="delete">
</form>
<!--自定义属性del_uri-->
<button th:attr="del_uri=@{/emp/}+${emp.id}" class="btn btn-sm btn-danger deleteBtn">删除 </button>
使用Jquery删除
<script type="text/javascript">
$(".deleteBtn").click(function () {
//删除当前员工的
$("#deleteEmp").attr("action", $(this).attr("del_uri")).submit();
return false;
});
</script>
@DeleteMapping("/emp/{id}")
public String deleteEmp(@PathVariable("id") Integer id) {
employeeDao.delete(id);
return "redirect:emps";
}
- 读取配置文件,${name}是读的是Model中的name属性,#{success.mes}读的是配置文件中的属性(properties),因此一般可使用配置文件来做国际化页面。
<h1 th:text="${name}">你好!</h1>
<h1 th:text="#{success.mes}">123</h1>
- if标签判断,not 是否定,使用#可以调用strings库来对msg进行判空判断
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
- 国际化
下面是使用国际化进行登陆操作使用前面说过的#{}来取出国际化的值,也可以在请求的时候加上l属性标示是那个地区。
配置文件
server.port=8081
spring.thymeleaf.cache=false
server.servlet.context-path=/crud
spring.messages.basename=i18n.login
#指定日期格式化,也可以加上分和秒
spring.mvc.date-format=yyyy-MM-dd
<form class="form-signin" action="/crud/user/login" method="post">
<img class="mb-4" th:src="@{/asserts/img/bootstrap-solid.svg}" src="../static/asserts/img/bootstrap-solid.svg" alt="" width="72" height="72">
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<!--进行判断生效,如果mes空的话,那就不显示-->
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
<label class="sr-only" th:text="#{login.username}">Username</label>
<input type="text" name="username" class="form-control" th:placeholder="#{login.username}" placeholder="Username" required="" autofocus="">
<label class="sr-only" th:text="#{login.password}">Password</label>
<input type="password" name="password" class="form-control" th:placeholder="#{login.password}" placeholder="Password" required="">
<div class="checkbox mb-3">
<label>
<!--<input type="checkbox" value="remember-me" /> Remember Me-->
<input type="checkbox" value="remember-me" /> [[#{login.remember}]]
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" th:text="#{login.btn}" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-muted">©2019</p>
<!--实现多国语言切换-->
<a class="btn btn-sm" th:href="@{/(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/(l='en_US')}">English</a>
</form>
这就是一些常用的标签,还有一些没说是因为用法都一样,就不多重复了!