前言

如题,今天介绍 Thymeleaf ,并整合 Thymeleaf 开发一个简陋版的学生信息管理系统。

SpringBoot 提供了大量模板引擎,包含 Freemarker、Groovy、Thymeleaf、Velocity 以及 Mustache,SpringBoot 中推荐使用 Thymeleaf 作为模板引擎,因为 Thymeleaf 提供了完美的 SpringMVC 支持。Thymeleaf 是新一代 Java 模板引擎,在 Spring 4 后推荐使用。

什么是模板引擎?

Thymeleaf 是一种模板语言。那模板语言或模板引擎是什么?常见的模板语言都包含以下几个概念:数据(Data)、模板(Template)、模板引擎(Template Engine)和结果文档(Result Documents)。

  • 数据

    数据是信息的表现形式和载体,可以是符号、文字、数字、语音、图像、视频等。数据和信息是不可分离的,数据是信息的表达,信息是数据的内涵。数据本身没有意义,数据只有对实体行为产生影响时才成为信息。
  • 模板

    模板,是一个蓝图,即一个与类型无关的类。编译器在使用模板时,会根据模板实参对模板进行实例化,得到一个与类型相关的类。
  • 模板引擎

    模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。
  • 结果文档

    一种特定格式的文档,比如用于网站的模板引擎就会生成一个标准的HTML文档。

模板语言用途广泛,常见的用途如下:

  • 页面渲染
  • 文档生成
  • 代码生成
  • 所有 “数据+模板=文本” 的应用场景

Thymeleaf 简介

Thymeleaf 是一个 Java 类库,它是一个 xml/xhtml/html5 的模板引擎,可以作为 MVC 的 web 应用的 View 层。

Thymeleaf 还提供了额外的模块与 SpringMVC 集成,所以我们可以使用 Thymeleaf 完全替代 JSP 。

Thymeleaf 语法

博客资料:http://www.cnblogs.com/nuoyiamy/p/5591559.html

官方文档:http://www.thymeleaf.org/documentation.html

SpringBoot 整合 Thymeleaf

下面使用 SpringBoot 整合 Thymeleaf 开发一个简陋版的学生信息管理系统。

1、准备工作

  • IDEA
  • JDK1.8
  • SpringBoot2.1.3

2、pom.xml 主要依赖

<dependencies>
<!-- JPA 数据访问 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- thymeleaf 模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- web 启动类 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mysql 数据库连接类 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>

3、application.yaml 文件配置

spring:
# 数据库相关
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=true
username: root
password: 123456
# jpa 相关
jpa:
hibernate:
ddl-auto: update # ddl-auto: 第一次启动项目设为 create 表示每次都重新建表,之后设置为 update
show-sql: true

4、实体类

@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class Student { @Id
@GeneratedValue
/**
* 主键
*/
private Long id; /**
* 主键
*/
private Long studentId; /**
* 姓名
*/
private String name; /**
* 年龄
*/
private Integer age; /**
* 专业
*/
private String major; /**
* 宿舍
*/
private String dormitory; /**
* 籍贯
*/
private String city; /*@Temporal(TemporalType.TIMESTAMP)//将时间戳,转换成年月日时分秒的日期格式
@Column(name = "create_time",insertable = false, updatable=false, columnDefinition = "timestamp default current_timestamp comment '注册时间'")
private Date createDate; @Temporal(TemporalType.TIMESTAMP)//将时间戳,转换成年月日时分秒的日期格式
@Column(name = "update_time",insertable = false, updatable=true, columnDefinition = "timestamp default current_timestamp comment '修改时间'")
private Date updateDate;*/ }

5、dao 层

@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
}

6、service 层

public interface StudentService {

    List<Student> findStudentList();

    Student findStudentById(Long id);

    Student saveStudent(Student student);

    Student updateStudent(Student student);

    void deleteStudentById(Long id);

}

实现类:

@Service
public class StudentServiceImpl implements StudentService { @Autowired
private StudentRepository studentRepository; /**
* 查询所有学生信息列表
* @return
*/
@Override
public List<Student> findStudentList() {
Sort sort = new Sort(Direction.ASC,"id");
return studentRepository.findAll(sort);
} /**
* 根据 id 查询单个学生信息
* @param id
* @return
*/
@Override
public Student findStudentById(Long id) {
return studentRepository.findById(id).get();
} /**
* 保存学生信息
* @param student
* @return
*/
@Override
public Student saveStudent(Student student) {
return studentRepository.save(student);
} /**
* 更新学生信息
* @param student
* @return
*/
@Override
public Student updateStudent(Student student) {
return studentRepository.save(student);
} /**
* 根据 id 删除学生信息
* @param id
* @return
*/
@Override
public void deleteStudentById(Long id) {
studentRepository.deleteById(id);
}
}

7、controller 层 (Thymeleaf) 使用

controller 层将 view 指向 Thymeleaf:

@Controller
@RequestMapping("/student")
public class StudentController { @Autowired
private StudentService studentService; /**
* 获取学生信息列表
* @param map
* @return
*/
@GetMapping("/list")
public String findStudentList(ModelMap map) {
map.addAttribute("studentList",studentService.findStudentList());
return "studentList";
} /**
* 获取保存 student 表单
*/
@GetMapping(value = "/create")
public String createStudentForm(ModelMap map) {
map.addAttribute("student", new Student());
map.addAttribute("action", "create");
return "studentForm";
} /**
* 保存学生信息
* @param student
* @return
*/
@PostMapping(value = "/create")
public String saveStudent(@ModelAttribute Student student) {
studentService.saveStudent(student);
return "redirect:/student/list";
} /**
* 根据 id 获取 student 表单,编辑后提交更新
* @param id
* @param map
* @return
*/
@GetMapping(value = "/update/{id}")
public String edit(@PathVariable Long id, ModelMap map) {
map.addAttribute("student", studentService.findStudentById(id));
map.addAttribute("action", "update");
return "studentForm";
} /**
* 更新学生信息
* @param student
* @return
*/
@PostMapping(value = "/update")
public String updateStudent(@ModelAttribute Student student) {
studentService.updateStudent(student);
return "redirect:/student/list";
} /**
* 删除学生信息
* @param id
* @return
*/
@GetMapping(value = "/delete/{id}")
public String deleteStudentById(@PathVariable Long id) {
studentService.deleteStudentById(id);
return "redirect:/student/list";
}
}

简单说下,ModelMap 对象来进行数据绑定到视图。return 字符串,该字符串对应的目录在 resources/templates 下的模板名字。 @ModelAttribute 注解是用来获取页面 Form 表单提交的数据,并绑定到 Student 数据对象。

8、studentForm 表单

定义了一个 Form 表单用于注册或修改学生信息。

<form th:action="@{/student/{action}(action=${action})}" method="post" class="form-horizontal">

        <div class="form-group">
<label for="student_Id" class="col-sm-2 control-label">学号:</label>
<div class="col-xs-4">
<input type="text" class="form-control" id="student_Id" name="name" th:value="${student.studentId}"
th:field="*{student.studentId}"/>
</div>
</div> <div class="form-group">
<label for="student_name" class="col-sm-2 control-label">姓名:</label>
<div class="col-xs-4">
<input type="text" class="form-control" id="student_name" name="name" th:value="${student.name}"
th:field="*{student.name}"/>
</div>
</div> <div class="form-group">
<label for="student_age" class="col-sm-2 control-label">年龄:</label>
<div class="col-xs-4">
<input type="text" class="form-control" id="student_age" name="name" th:value="${student.age}"
th:field="*{student.age}"/>
</div>
</div> <div class="form-group">
<label for="student_major" class="col-sm-2 control-label">专业:</label>
<div class="col-xs-4">
<input type="text" class="form-control" id="student_major" name="name" th:value="${student.major}"
th:field="*{student.major}"/>
</div>
</div> <div class="form-group">
<label for="student_dormitory" class="col-sm-2 control-label">宿舍:</label>
<div class="col-xs-4">
<input type="text" class="form-control" id="student_dormitory" name="name" th:value="${student.dormitory}"
th:field="*{student.dormitory}"/>
</div>
</div> <div class="form-group">
<label for="student_city" class="col-sm-2 control-label">籍贯:</label>
<div class="col-xs-4">
<input type="text" class="form-control" id="student_city" name="writer" th:value="${student.city}"
th:field="*{student.city}"/>
</div>
</div> <div class="form-group">
<div class="col-sm-offset-3 col-sm-10">
<input class="btn btn-primary" type="submit" value="提交"/>&nbsp;&nbsp;
<input class="btn" type="button" value="返回" onclick="history.back()"/>
</div>
</div>
</form>

9、studentList 学生列表

用于展示学生信息:

<table class="table table-hover table-condensed">
<legend>
<strong>学生信息列表</strong>
</legend>
<thead>
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>专业</th>
<th>宿舍</th>
<th>籍贯</th>
<th>管理</th>
</tr>
</thead>
<tbody>
<tr th:each="student : ${studentList}">
<th scope="row" th:text="${student.studentId}"></th>
<td><a th:href="@{/student/update/{studentId}(studentId=${student.id})}" th:text="${student.name}"></a></td>
<td th:text="${student.age}"></td>
<td th:text="${student.major}"></td>
<td th:text="${student.dormitory}"></td>
<td th:text="${student.city}"></td>
<td><a class="btn btn-danger" th:href="@{/student/delete/{studentId}(studentId=${student.id})}">删除</a></td>
</tr>
</tbody>
</table>

页面效果

列表页面:点击按钮可注册学生信息

注册/修改学生信息页面:点提交保存学生信息到数据库并返回列表页面

有数据的列表页面:点击名字跳到注册/修改页面可修改学生信息,点击删除可删除学生信息

源码下载

github 地址 :https://github.com/turoDog/Demo/tree/master/springboot_thymeleaf_demo

最后

如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「一个优秀的废人」,关注后回复「1024」送你一套完整的 java 教程。



Spring Boot2 系列教程 (十二) | 整合 thymeleaf的更多相关文章

  1. Spring Boot2 系列教程 (十八) | 整合 MongoDB

    微信公众号:一个优秀的废人.如有问题,请后台留言,反正我也不会听. 前言 如题,今天介绍下 SpringBoot 是如何整合 MongoDB 的. MongoDB 简介 MongoDB 是由 C++ ...

  2. Spring Boot2 系列教程 (十六) | 整合 WebSocket 实现广播

    前言 如题,今天介绍的是 SpringBoot 整合 WebSocket 实现广播消息. 什么是 WebSocket ? WebSocket 为浏览器和服务器提供了双工异步通信的功能,即浏览器可以向服 ...

  3. Spring Boot2 系列教程(十二)@ControllerAdvice 的三种使用场景

    严格来说,本文并不算是 Spring Boot 中的知识点,但是很多学过 SpringMVC 的小伙伴,对于 @ControllerAdvice 却并不熟悉,Spring Boot 和 SpringM ...

  4. Spring Boot2 系列教程(十)Spring Boot 整合 Freemarker

    今天来聊聊 Spring Boot 整合 Freemarker. Freemarker 简介 这是一个相当老牌的开源的免费的模版引擎.通过 Freemarker 模版,我们可以将数据渲染成 HTML ...

  5. Spring Boot2 系列教程(二十) | SpringBoot 是如何实现日志的?

    微信公众号:一个优秀的废人.如有问题,请后台留言,反正我也不会听. 前言 休息日闲着无聊看了下 SpringBoot 中的日志实现,把我的理解跟大家说下. 门面模式 说到日志框架不得不说门面模式.门面 ...

  6. Spring Boot2 系列教程(十九)Spring Boot 整合 JdbcTemplate

    在 Java 领域,数据持久化有几个常见的方案,有 Spring 自带的 JdbcTemplate .有 MyBatis,还有 JPA,在这些方案中,最简单的就是 Spring 自带的 JdbcTem ...

  7. Spring Boot2 系列教程(二十一) | 自动配置原理

    微信公众号:一个优秀的废人.如有问题,请后台留言,反正我也不会听. 前言 这个月过去两天了,这篇文章才跟大家见面,最近比较累,大家见谅下.下班后闲着无聊看了下 SpringBoot 中的自动配置,把我 ...

  8. Spring Boot2 系列教程 (九) | SpringBoot 整合 Mybatis

    前言 如题,今天介绍 SpringBoot 与 Mybatis 的整合以及 Mybatis 的使用,本文通过注解的形式实现. 什么是 Mybatis MyBatis 是支持定制化 SQL.存储过程以及 ...

  9. Spring Boot2 系列教程(十六)定时任务的两种实现方式

    在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Qua ...

随机推荐

  1. java Math和Random和UUID

    Math类 public final class Math extends Object 以下X表示double,float,int, long abs(X x):求绝对值 max(X x1,X x2 ...

  2. 央行下属的上海资信网络金融征信系统(NFCS)签约机构数量突破800家

    央行下属的上海资信网络金融征信系统(NFCS)签约机构数量突破800家 ——已接入NFCS的P2P网贷机构将优先 接入央行征信系统   P2P网贷行业的健康发展依赖于信用体系的支撑和保障,加快完善适应 ...

  3. Python--day46--用户管理设计方案介绍

    1,基于用户权限管理: 2,基于角色的权限管理: 开始一个项目如果要100天的,可能70天都在设计,比如设计数据库表结构,最后30天才是写代码.设计是最难的,写代码是最简单的. 还有一个重要的一点,写 ...

  4. http header详解,HTTP头、请求头、响应头、实体头

    Content-Language,Content-Length,Content-Type,Content-Encoding,mime分析 Accept 指定客户端能够接收的内容类型 Accept:te ...

  5. C# AutoResetEvent 理解

    .. AutoResetEvent在内存中保持着一个bool值值为False,则使线程阻塞:值为True,使线程退出阻塞: 创建AutoResetEvent对象的实例,在函数构造中传递默认的bool值 ...

  6. Vue+node.js实现一个简洁的个人博客系统

    本项目是一个用vue和node以及mysql实现的一个简单的个人博客系统,整体逻辑比较简单.但是可以我们完整的了解一个项目从数据库到后端到前端的实现过程,适合不太懂这一块的朋友们拿来练手. 本项目所用 ...

  7. git常用常用操作指令

    GIT操作 1:git init 初始化空的仓库,会在当前文件夹生成一个隐藏.git的文件夹,相当于一个仓库. 2:提交代码的流程:工作代码区-->暂存区 -->主仓库 -->服务器 ...

  8. E40笔记本无线网卡

    E40笔记本无线网卡详情 网卡名称 Intel(R) Dual Band Wireless-AC 3160 网卡厂商 英特尔 Mac地址 34:E6:AD: 规格 - 基本要素 状态 Launched ...

  9. ABP在MultipleDbContext也就是多库的场景下发布后异常“Could not find content root folder”问题处理

    ABP多库支持 ABP支持多库的方案在abp的案例中aspnetboilerplate-samples中给了现成的demo,其中MultipleDbContextDemo是EF的相关针对dotnet的 ...

  10. vue新增属性响应式更新的问题

    根据官方文档定义: 如果在实例创建之后添加新的属性到实例上,它不会触发视图更新. 受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删 ...