springboot2系列教程|整合thymeleaf

一个优秀的废人      2022-05-18     730

关键词:

前言

如题,今天介绍 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 教程。

教程节选
一个优秀的废人

springboot2系列教程(十八)|整合mongodb

微信公众号:一个优秀的废人。如有问题,请后台留言,反正我也不会听。前言如题,今天介绍下SpringBoot是如何整合MongoDB的。MongoDB简介MongoDB是由C++编写的非关系型数据库,是一个基于分布式文件存储的开源数据库系统,它将... 查看详情

springboot2系列教程(十六)|整合websocket实现广播

前言如题,今天介绍的是SpringBoot整合WebSocket实现广播消息。什么是WebSocket?WebSocket为浏览器和服务器提供了双工异步通信的功能,即浏览器可以向服务器发送信息,反之也成立。WebSocket是通过一个socket来实现双工异步通信能力... 查看详情

springboot2系列教程|整合数据缓存cache

如题,今天介绍SpringBoot的数据缓存。做过开发的都知道程序的瓶颈在于数据库,我们也知道内存的速度是大大快于硬盘的,当需要重复获取相同数据时,一次又一次的请求数据库或者远程服务,导致大量时间耗费在数据库查询... 查看详情

springboot2系列教程(十七)|整合websocket实现聊天室

微信公众号:一个优秀的废人。如有问题,请后台留言,反正我也不会听。前言昨天那篇介绍了WebSocket实现广播,也即服务器端有消息时,将消息发送给所有连接了当前endpoint的浏览器。但这无法解决消息由谁发送,又由谁接收... 查看详情

springboot应用系列5--springboot2整合logback

上一篇我们梳理了SpringBoot2整合log4j2的配置过程,其中讲到了SpringBoot2原装适配logback,并且在非异步环境下logback和log4j2的性能差别不大,所以对于那些日志量不算太高的项目来说,选择logback更简单方便。1.pom.xmlpom.xml不需要添加... 查看详情

springboot应用系列6--springboot2整合quartz

Quartz是实现定时任务的利器,Quartz主要有四个组成部分,分别是:1.Job(任务):包含具体的任务逻辑;2.JobDetail(任务详情):是对Job的一种详情描述;3. Trigger(触发器):负责管理触发JobDetail的机制;4. Scheduler(调度器):负... 查看详情

springboot2.0整合同时支持jsp+html跳转(代码片段)

springboot项目创建教程 https://blog.csdn.net/q18771811872/article/details/88126835springboot2.0跳转html教程 https://blog.csdn.net/q18771811872/article/details/88312862springboot2.0跳转jsp教程 https:/ 查看详情

springboot应用系列4--springboot2整合log4j2

一、背景1.log4j2传承于log4j和logback,它是目前性能最好的日志处理工具,有关它们的性能对比请看:2.除了性能好之外,log4j2有这么几个重要的新features:(1)自动热重载配置文件,而且重新加载期间不会丢失日志请求。logback也可以... 查看详情

springboot2系列教程|配置日志

前言如题,今天介绍springboot默认日志的配置。默认日志Logback默认情况下,SpringBoot用Logback来记录日志,并用INFO级别输出到控制台。如果你在平常项目中用过SpringBoot,你应该已经注意到很多INFO级别的日志了。默认日志长这样:20... 查看详情

springboot2系列教程(十四)|统一异常处理

如题,今天介绍SpringBoot是如何统一处理全局异常的。SpringBoot中的全局异常处理主要起作用的两个注解是@ControllerAdvice和@ExceptionHandler,其中@ControllerAdvice是组件注解,添加了这个注解的类能够拦截Controller的请求,而ExceptionHandler... 查看详情

springboot2系列教程|使用jdbctemplates访问mysql

...dbc访问关系型mysql,通过spring的JdbcTemplate去访问。准备工作SpringBoot2.xjdk1.8maven3.0ideamysql构建SpringBoot项目,不会的朋友参考旧文章:如何使用IDEA构建SpringBoot工程项目目录结构pom文件引入依赖<dependencies><!--jdbcTempl 查看详情

springboot2系列教程|实现声明式事务

前言如题,今天介绍SpringBoot的声明式事务。Spring的事务机制所有的数据访问技术都有事务处理机制,这些技术提供了API用于开启事务、提交事务来完成数据操作,或者在发生错误时回滚数据。而Spring的事务机制是用统一的机制... 查看详情

springboot2.x基础教程:springboot整合mybatis附源码(代码片段)

微信号:hzy1014211086,如果你正在学习SpringBoot,可以加入我们的Spring技术交流群,共同成长文章目录一、准备数据表二、添加依赖三、配置数据源四、编写领域对象五、注解配置方式新增修改查询删除六、XML配置... 查看详情

springboot2系列教程理解springboot配置文件application.properties

在SpringBoot中,配置文件有两种不同的格式,一个是properties,另一个是yaml。虽然properties文件比较常见,但是相对于properties而言,yaml更加简洁明了,而且使用的场景也更多,很多开源项目都是使用yaml进行配置(例如Hexo)。除了... 查看详情

springboot2系列教程|使用springdatajpa访问mysql

前言如题,今天介绍SpringDataJPA的使用。什么是SpringDataJPA在介绍SpringDataJPA之前,首先介绍Hibernate。Hibernate使用O/R映射(Object-RelationMapping)技术实现数据访问,O/R映射即将领域模型类与数据库的表进行映射,通过程序操作对象而... 查看详情

springboot2从入门到入坟|基础入门篇:「springboot2从入门到入坟」系列教程介绍(代码片段)

...#xff01;我李阿昀又回来了!嘿嘿😋好久都没更新「SpringBoot2从入门到入坟」这一系列教程了,大家等得着急吗?从今年4月15日起,细细想来已有半载了,时光真如梭啊!昔者,子在川上曰:逝者 查看详情

springboot2从入门到入坟|基础入门篇:「springboot2从入门到入坟」系列教程介绍(代码片段)

...#xff01;我李阿昀又回来了!嘿嘿😋好久都没更新「SpringBoot2从入门到入坟」这一系列教程了,大家等得着急吗?从今年4月15日起,细细想来已有半载了,时光真如梭啊!昔者,子在川上曰:逝者 查看详情

springboot2系列教程(二十一)|自动配置原理

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