SpringBoot 实战 (十二) | 整合 thymeleaf

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 如题,今天介绍 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>


页面效果


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


640.png


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


640.png


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


640.jpg


源码下载


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


后语


如果本文对你哪怕有一丁点帮助,请帮忙点好看。你的好看是我坚持写作的动力。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
缓存 编解码 移动开发
SpringBoot 整合 Thymeleaf|学习笔记
快速学习 SpringBoot 整合 Thymeleaf
191 0
SpringBoot 整合 Thymeleaf|学习笔记
|
安全 Java 关系型数据库
Mall电商实战项目全面升级!支持最新版SpringBoot,干掉循环依赖
技术栈升级 mall项目采用现阶主流技术实现,这些主流技术基本都升级了目前最新稳定版,具体升级内容大家可以参考下表。 技术版本说明
|
Java Docker Python
docker部署项目 dockerfile 实战 SpringBoot、flask
作者主页:https://www.couragesteak.com/
docker部署项目 dockerfile 实战 SpringBoot、flask
|
负载均衡 Java API
SpringBoot整合elasticsearch-rest-client实战
SpringBoot整合elasticsearch-rest-client实战
1396 0
SpringBoot整合elasticsearch-rest-client实战
|
JSON Java 测试技术
SpringBoot业务开发 01、Springboot实战:实现Gitee图床上传及删除(含完整代码)
SpringBoot业务开发 01、Springboot实战:实现Gitee图床上传及删除(含完整代码)
SpringBoot业务开发 01、Springboot实战:实现Gitee图床上传及删除(含完整代码)
|
安全 前端开发 Java
狂神说SpringBoot:SpringSecurity笔记及thymeleaf静态资源(三)
狂神说SpringBoot:SpringSecurity笔记及thymeleaf静态资源(三)
202 0
狂神说SpringBoot:SpringSecurity笔记及thymeleaf静态资源(三)
|
移动开发 安全 前端开发
狂神说SpringBoot:SpringSecurity笔记及thymeleaf静态资源(二)
狂神说SpringBoot:SpringSecurity笔记及thymeleaf静态资源(二)
318 0
狂神说SpringBoot:SpringSecurity笔记及thymeleaf静态资源(二)
|
Java 应用服务中间件 容器
springboot原理实战(15)--springboot优化和定制tomcat
springboot原理实战(15)--springboot优化和定制tomcat
586 0
springboot原理实战(15)--springboot优化和定制tomcat
|
Java Spring
springboot原理实战(12)--扫描包,banner,配置属性默认值的3种方式
springboot原理实战(12)--扫描包,banner,配置属性默认值的3种方式
814 0
springboot原理实战(12)--扫描包,banner,配置属性默认值的3种方式
|
Java 容器 Spring
springboot原理实战(11) -- springboot扩展分析CommandLineRunner
springboot原理实战(11) -- springboot扩展分析CommandLineRunner
177 0
springboot原理实战(11) -- springboot扩展分析CommandLineRunner