自由标记是一个模板引擎,用于处理服务器端数据并生成动态 HTML 内容。
在本文中,我们将学习如何创建一个弹簧MVC Web应用程序,该应用程序使用弹簧启动,JPA,H2数据库和自由标记模板执行CRUD操作。
本文中使用的技术包括:
弹簧启动版本:2.7.4
Java 版本 1.8
创建弹簧启动应用程序
创建具有所需依赖项的弹簧启动应用程序。
我们将添加弹簧启动 Web、弹簧启动数据 jpa、弹簧启动自由标记启动器依赖项、龙目岛(以减少样板代码)以及 H2(嵌入式 H2 数据库)maven 依赖项。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.asbnotebook</groupId>
<artifactId>spring-boot-freemarker-crud-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-freemarker-crud-example</name>
<description>spring boot freemarker crud example</description>
<properties>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置 H2 数据库和实体类
将以下配置属性添加到弹簧启动应用程序的“应用程序属性”文件中。
此配置属性配置应用程序的数据源 URL。
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
创建学生 JPA 实体类。此类将 H2 数据库的学生表与实体类进行映射。
实体类还包含自动生成的 ID、名称和成绩字段。
package com.asbnotebook.student;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Data;
@Entity
@Data
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
private String grade;
}
创建存储库、服务和控制器层
对于 Student 实体类,让我们创建一个存储库层、服务和控制器层。
创建 JPA 存储库
创建名为“学生存储库”的界面
弹簧启动的 JPA 启动器为实体类的基本操作提供了内置支持。
此外,我们需要扩展 Jpa存储库接口来获取这些功能。
package com.asbnotebook.student;
import org.springframework.data.jpa.repository.JpaRepository;
public interface StudentRepository extends JpaRepository<Student, Integer> {
}
创建服务类
创建学生服务类并添加以下内容。
package com.asbnotebook.student;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class StudentService {
@Autowired
private StudentRepository studentRepository;
public List<Student> getAllStudents() {
return studentRepository.findAll();
}
public void createStudent(Student student) {
studentRepository.save(student);
}
public void updateStudent(Student student, Integer id) {
Student std = studentRepository.getOne(id);
std.setName(student.getName());
std.setGrade(student.getGrade());
studentRepository.save(std);
}
public void deleteStudent(Integer id) {
studentRepository.deleteById(id);
}
public Student getStudent(Integer id) {
return studentRepository.getOne(id);
}
}
创建控制器类
通过创建学生控制器类来创建弹簧控制器类。
此控制器类还包含学生实体的 CRUD 操作所需的 URL 映射。
package com.asbnotebook.student;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class StudentController {
@Autowired
private StudentService studentService;
@GetMapping("/")
public String getAllStudents(Model model) {
List<Student> students = studentService.getAllStudents();
model.addAttribute("students", students);
return "home";
}
@GetMapping("/create")
public String createStudentPage(Model model) {
Student student = new Student();
model.addAttribute("student", student);
model.addAttribute("isUpdate", false);
return "create-update";
}
@GetMapping("/update/{id}")
public String updateStudentPage(Model model, @PathVariable("id") Integer id) {
Student student = studentService.getStudent(id);
model.addAttribute("student", student);
model.addAttribute("isUpdate", true);
return "create-update";
}
@PostMapping("/update/{id}")
public String createStudent(@ModelAttribute("student") Student student, @PathVariable("id") Integer id) {
studentService.updateStudent(student, id);
return "redirect:/";
}
@PostMapping("/create")
public String createStudent(@ModelAttribute("student") Student student) {
studentService.createStudent(student);
return "redirect:/";
}
@GetMapping("/delete/{id}")
public String deleteStudent(@PathVariable("id") Integer id) {
studentService.deleteStudent(id);
return "redirect:/";
}
}
一些要点是:
- URL路径“/”将呈现主免费标记模板文件并显示所有可用的学生。此外,学生模型属性包含所有可用的学生。
- 路径为“/创建”的 GET URL 映射将返回创建学生页面。此路径还会将新的 Student 实体对象添加到模型属性,并呈现创建-更新模板文件。
- URL 路径“/更新/{id}”GET 映射将呈现现有学生详细信息,并允许更新学生姓名和成绩。
- 模型属性“更新”确定操作类型。
- 路径为“/创建”和“/更新/{id}”的 POST URL 映射分别用于创建和更新学生详细信息。
- 获取 URL 路径“/删除/{id}”将删除特定的学生实体。
- 此外,在创建、更新和删除操作之后,应用程序会通过重定向到主页 URL 路径来显示更新的学生列表。
创建自由标记模板
自由标记模板文件的扩展名为 .ftl 或 .ftlh。这些是包含自由标记标记和指令的普通HTML文件。
在 /src/主/资源/模板文件夹下创建一个名为 home 的模板文件。应用程序在应用程序启动时呈现此模板文件。
此外,自由标记模板的默认文件路径是 /src/主/资源/模板文件夹。
最后,弹簧引导自由标记起始模板依赖项自动配置自由标记模板路径。
<!doctype html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h1>Student CRUD operation with Freemarker Template</h1>
<a href="/create">Create New Student</a>
<table class="table">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Name</th>
<th scope="col">Grade</th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<#list students as student>
<tr>
<th scope="row">${student.id}</th>
<td>${student.name}</td>
<td>${student.grade}</td>
<td><a href="/update/${student.id}">Update</a></td>
<td><a href="/delete/${student.id}">Delete</a></td>
</tr>
</#list>
</tbody>
</table>
</div>
</body>
</html>
需要注意的几点是:
- 我们已经使用引导为应用程序提供了一些样式。
- FreeMarker 的<#list学生作为学生></列表>指令通过 Spring 模型属性学生进行迭代。此外,每次迭代都会在自由标记指令中重复 HTML 块。
- 我们还在表格中打印每个学生对象的 ID、名称和成绩属性。
创建一个名为“创建-更新.ftlh”的自由标记模板文件。
要创建或更新学生实体,我们使用此免费标记模板文件。
<!doctype html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h1>
<#if !isUpdate>Create</#if>
<#if isUpdate>Update</#if>
Student
</h1>
<div>
<form action="<#if isUpdate>/update/${student.id}</#if><#if !isUpdate>/create</#if>" name="student" method="post">
<table class="table">
<tbody>
<thead>
<tr>
<th>Field</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<#if isUpdate>
<tr>
<th>ID</th>
<td><div name="id">${student.id}</div></td>
</tr>
</#if>
<tr>
<th>Name</th>
<td><input type="text" name="name" value="<#if student.name??>${student.name}</#if>" /></td>
</tr>
<tr>
<th>Grade</th>
<td><input type="text" name="grade" value="<#if student.grade??>${student.grade}</#if>" /></td>
</tr>
</tbody>
</table>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>
</body>
</html>
这里需要注意的一些要点是:
- <#if是更新>检查布尔模型属性是否为更新,并确定操作是创建还是更新。<#if更新>自由标记指令是反转版本。
- ID 字段将由 JPA 在创建学生操作期间自动生成。
- 对于更新操作,将填充现有的学生 ID、姓名和成绩字段。id 字段无法更新。
- 免费标记的标记 ${学生.name} 将输入字段名称的值映射到学生模型属性。标记 ${student.grade} 将输入字段成绩的值映射到学生模型属性。
测试应用程序
启动弹簧启动应用程序。
我们应该能够在学生实体上执行 CRUD 操作,如下所示。
结论
在本文中,我们学习了如何使用弹簧引导和自由标记模板语言对 JPA 实体执行 CRUD 操作。
我们还了解了弹簧引导自由标记初学者依赖项如何自动配置基本配置,以解析应用程序类路径上可用的 FreeMarker 模板文件。
完整的示例代码可在 GitHub 上找到。