SpringBoot模板引擎Thymeleaf使用入门示例

1、Thymeleaf简介

Thymeleaf is a modern server-side Java template engine for both web and standalone environments.
Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎。

模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的html文档。从字面上理解模板引擎,最重要的就是模板二字,这个意思就是做好一个模板后套入对应位置的数据,最终以html的格式展示出来,这就是模板引擎的作用。
这里通过一个例子,演示如何使用Thymeleaf模板引擎。

2、前期准备:通过Mybatis访问数据库

这里对于数据的访问,复用了前面一篇例子中的MyBatis的部分代码,为了保证这篇的独立性,这里将前面的步骤附在如下。这部分主要是展示如何通过Mybatis访问数据库中的数据。

2.1依赖配置添加

connnect/pom.xml文件中添加mybatis依赖,如下:



    4.0.0

    com.space.mysql
    connnect
    1.0-SNAPSHOT

    
        org.springframework.boot
        spring-boot-starter-parent
        2.0.0.RELEASE
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-jdbc
        
        
            mysql
            mysql-connector-java
            8.0.11
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.2.0
        
    


2.2 添加在应用配置文件中添加MyBatis相关配置

主要是说明下数据库记录映射的类和mapper配置文件的路径信息。
application.properties

spring.datasource.username=root
spring.datasource.password=lfqylfqy
spring.datasource.url=jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#mybatis相关配置
#数据库记录映射类所在的包和mapper文件存放的位置
mybatis.type-aliases-package=com.space.mysql.connect.domain
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

新增一个mapper文件,并在其中定义相关的sql语句。
mybatis/mapper/StudentMapper.xml




    
    
    
        insert into Student(id, name, age) VALUES (#{id}, #{name}, #{age})
    
    
        update Student set name = #{name}, age = #{age} where id = #{id}
    
    
        delete from Student where id = #{id}
    

2.3 Java代码编写

2.3.1 新增一个和数据库表中记录对应的java类

这里借用之前的表结构:

$ mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 51
Server version: 8.0.20 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use testdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> describe student;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | NO   | PRI | NULL    |       |
| name  | varchar(30) | YES  |     | NULL    |       |
| age   | varchar(10) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql>

com.space.mysql.connect.domain.Student

package com.space.mysql.connect.domain;

/**
 * Created by chengxia on 2021/12/11.
 */
public class Student {
    private int id;
    private String name;
    private int age;

    public Student(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

2.3.2 新增一个Mapper接口对应mapper配置文件

这个接口可以结合配置文件,对应到sql语句。
com.space.mysql.connect.mapper.StudentMapper

package com.space.mysql.connect.mapper;

import com.space.mysql.connect.domain.Student;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * Created by chengxia on 2021/12/11.
 */
@Mapper
public interface StudentMapper {
    List queryStudentById(int id);
    List queryStudentList();
    void addStudent(Student stu);
    void updateStudent(Student stu);
    void deleteStudent(int id);
}

2.3.3 新增数据库Service类对数据库操作进行包装(调用mapper)

这里将服务多抽象了一层接口。
服务接口类com.space.mysql.connect.service.StudentServiceInterface

package com.space.mysql.connect.service;

import com.space.mysql.connect.domain.Student;

import java.util.List;

/**
 * Created by chengxia on 2021/12/12.
 */
public interface StudentServiceInterface {
    Student queryStudentById(int id);
    List queryStudentList();
    void addStudent(Student stu);
    void updateStudent(Student stu);
    void deleteStudent(int id);
}

服务实现类com.space.mysql.connect.service.StudentService

package com.space.mysql.connect.service;

import com.space.mysql.connect.domain.Student;
import com.space.mysql.connect.mapper.StudentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Created by chengxia on 2021/12/12.
 */
@Service
public class StudentService implements StudentServiceInterface {
    @Autowired
    private StudentMapper stuMapper;
    @Override
    public Student queryStudentById(int id) {
        List studentList = stuMapper.queryStudentById(id);
        if(studentList != null && studentList.size() > 0) {
            System.out.println(studentList.get(0));
            return studentList.get(0);
        }else{
            return null;
        }
    }

    @Override
    public List queryStudentList() {
        List studentList = stuMapper.queryStudentList();
        for (Student stu: studentList){
            System.out.println(stu);
        }
        return studentList;
    }

    @Override
    public void addStudent(Student stu) {
        stuMapper.addStudent(new Student(stu.getId(), stu.getName(), stu.getAge()));
    }

    @Override
    public void updateStudent(Student stu) {
        stuMapper.updateStudent(new Student(stu.getId(),stu.getName(), stu.getAge()));
    }

    @Override
    public void deleteStudent(int id) {
        stuMapper.deleteStudent(id);
    }
}

2.3.4 应用启动类中增加mapper等类的扫描包路径

这一步必不可少,不然会报错mapper类的bean找不到。

Consider defining a bean of type 'com.space.mysql.connect.mapper.StudentMapper' in your configuration.

com.space.mysql.connect.main.Application

package com.space.mysql.connect.main;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * Created by chengxia on 2021/12/7.
 */
@SpringBootApplication
@ComponentScan(basePackages = {"com.space.mysql.connect.controller","com.space.mysql.connect.service"})
@MapperScan(value = "com.space.mysql.connect.mapper")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

到这里,访问数据库相关的代码就完成了。

3、Thymeleaf模板的使用

3.1 依赖配置

connnect/pom.xml文件中添加Thymeleaf相关的依赖配置:



    4.0.0

    com.space.mysql
    connnect
    1.0-SNAPSHOT

    
        org.springframework.boot
        spring-boot-starter-parent
        2.0.0.RELEASE
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-jdbc
        
        
            mysql
            mysql-connector-java
            8.0.11
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.2.0
        
        
            org.thymeleaf
            thymeleaf-spring5
        
        
            org.thymeleaf.extras
            thymeleaf-extras-java8time
        
    


3.2 新建一个使用Thymeleaf模板的Controller

这里单独写一个Controller用来调用Thymeleaf显示页面。
com.space.mysql.connect.controller.ThymeleafTemplateController

package com.space.mysql.connect.controller;

import com.space.mysql.connect.domain.Student;
import com.space.mysql.connect.service.StudentServiceInterface;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;


/**
 * Created by chengxia on 2021/12/12.
 * 这里需要尤为注意,Controller注解 ,必须用Controller,不能用原来的RestController!
 */
@Controller
@RequestMapping("/student")
public class ThymeleafTemplateController {
    @Autowired
    private StudentServiceInterface stuService;

    @RequestMapping("/queryList")
    public String queryStudentList(ModelMap map){
        map.addAttribute("student", stuService.queryStudentList());
        return "StudentsList";
    }
    @RequestMapping("/delete")
    public String deleteStudent(@RequestParam() int id, ModelMap map){
        stuService.deleteStudent(id);
        map.addAttribute("student", stuService.queryStudentList());
        return "StudentsList";
    }
    @RequestMapping("/edit")
    public String editStudent(ModelMap map, @RequestParam(defaultValue = "0") int id){
        if(id >  0){
            //该记录已经存在,就进行更新操作,查询详情并传入map
            map.addAttribute("student", stuService.queryStudentById(id));
        }else{
            //新增一条记录
            map.addAttribute("student",new Student(0,"TmpName", 9));
        }
        return "StudentEdit";
    }

    @RequestMapping(value = "/save", method = {RequestMethod.GET, RequestMethod.POST})
    public String save(ModelMap map, @ModelAttribute Student student){
        if(student == null){
            return "Error Happened when add null...";
        }

        Student stuTmp= stuService.queryStudentById(student.getId());
        if(stuTmp == null){
            //如果没有查到记录,就新增
            stuService.addStudent(student);
        }else{
            stuService.updateStudent(student);
        }
        map.addAttribute("student", stuService.queryStudentList());
        return "StudentsList";
    }
}

3.3 新建模板文件

3.3.1 原理简介

Spring Boot提供了大量模板引擎, 包含括FreeMarker、Groovy、 Thymeleaf、 Velocity和Mustache, Spring Boot中推荐
使用Thymeleaf作为模板引擎, 因为Thymeleaf提供了完美的Spring MVC的支持。
原理上说,Thymeleaf在Spring Boot的org.springframework.boot.autoconfigure.thymeleaf包下实现自动配置,如下所示:


image.png

ThymeleafAutoConfiguration源码:

@Configuration
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
public class ThymeleafAutoConfiguration {

        //配置TemplateResolver
    @Configuration
    @ConditionalOnMissingBean(name = "defaultTemplateResolver")
    static class DefaultTemplateResolverConfiguration {
            ...
    }
    
        //配置TemplateEngine
    @Configuration
    protected static class ThymeleafDefaultConfiguration {
            ...
    }
        //配置SpringWebFluxTemplateEngine
    @Configuration
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
    static class ThymeleafWebMvcConfiguration {
           ...
    }
    
        //配置thymeleafViewResolver
    @Configuration
    @ConditionalOnWebApplication(type = Type.REACTIVE)
    @ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
    static class ThymeleafWebFluxConfiguration {
           ...
    }
    ...
}

ThymeleafAutoConfiguration自动加载Web所需的TemplateResolver、TemplateEngine、SpringWebFluxTemplateEngine以及thymeleafViewResolver,并通过ThymeleafProperties进行Thymeleaf属性配置。详细细节查看官方源码。
ThymeleafProperties源码:

//读取application.properties配置文件的属性
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {

    private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;

    public static final String DEFAULT_PREFIX = "classpath:/templates/";

    public static final String DEFAULT_SUFFIX = ".html";

    /**
     *Web模板文件前缀路径属性,Spring boot默认路径为classpath:/templates/
     */
    private String prefix = DEFAULT_PREFIX;

    /**
     * Web模板文件后缀属性,默认为html
     */
    private String suffix = DEFAULT_SUFFIX;

    /**
     * Web模板模式属性,默认为HTML
     */
    private String mode = "HTML";

    /**
     *  Web模板文件编码属性,默认为UTF_8
     */
    private Charset encoding = DEFAULT_ENCODING;

        ....
}

从上面如下部分的代码:

public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";

可以从ThymeleafProperties中看出,Thymeleaf的默认设置,以及可以通过前缀为spring.thymeleaf属性修改Thymeleaf默认配置。默认地,模板文件的后缀是“.html”放在templates目录下。

3.3.2 新建显示和修改信息的模板文件

显示信息列表的模板文件。
templates/StudentsList.html




    
    Student List
    





New Student


ID Name Age
Edit Delete

修改信息的模板。
templates/StudentEdit.html




    
    Student Edit or New
    



到这里,代码全部完成了,目录结构如下:


image.png

4、运行效果

启动应用之后:
http://localhost:8080/student/queryList

image.png

点击上面的Delete,跳转到链接http://localhost:8080/student/delete?id=0
image.png

点击上面的Edit,跳转到链接http://localhost:8080/student/edit?id=2
image.png

将上面的年龄改成999:
image.png

点击Submit,跳转到http://localhost:8080/student/save
image.png

点击上面的New Student,跳转到http://localhost:8080/student/edit
image.png

修改信息如下:
image.png

点击Submit,跳转到http://localhost:8080/student/save
image.png

到这里示例就结束了。

参考资料

  • Thymeleaf一篇就够了
  • 【SpringBoot2.x】-SpringBoot Web开发中Thymeleaf、Web、Tomcat以及Favicon

你可能感兴趣的:(SpringBoot模板引擎Thymeleaf使用入门示例)