1 概述
如今使用Spring boot+thymeleaf开发Web应用程序,开发周期更短,学习周期也短。本节课程技术采用Spring Boot+thymeleaf+ArrayList组合,可以在学员位不了解Spring Data或不使用数据库访问对象的情况仍然学习好 Spring Boot+thymeleaf 开发CURD程序。
2 依赖
在这种情况下,我们将依赖spring-boot-starter-parent进行简单的依赖关系管理,版本控制和插件配置。
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.6.RELEASE
com.wangshenghua
spring-mvc-curd
0.0.1-SNAPSHOT
spring-mvc-curd
Demo project for Spring Boot
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3 数据模型层 为避免过多的细节,这里还是使用POJO作为数据模型层。学员可以更专注于thymeleaf。
package com.wangshenghua.model;
public class User {
private long id;
private String name;
private String email;
public User() {
}
public User(long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
4 控制器层
在这一层使用一个类UserController.java却包含数据访问对象(DAO)的功能。
package com.wangshenghua.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import com.wangshenghua.model.User;
@Controller
public class UserController {
private static List<User> users = new ArrayList<User>();
// 使用List当容器保存数据,来代替数据库
static {
users.add(new User(1, "黄志燕", "ssss@qq.com"));
users.add(new User(2, "侯慧聪", "hhhh@qq.com"));
users.add(new User(3, "王广宏", "gggg@qq.com"));
}
private long getMaxId() {
long id = 0;
for (User user : users) {
if (user.getId() > id)
id = user.getId();
}
return id + 1;
}
private User getUser(long id) {
User user = null ;
for (User u : users) {
if (u.getId() == id) {
user = u;
break;
}
}
return user;
}
private void update(User user,long id) {
for (User u : users) {
if (u.getId() == id) {
u.setName(user.getName());
u.setEmail(user.getEmail());
break;
}
}
}
private void delete(long id) {
for (User u : users) {
if (u.getId() == id) {
users.remove(u);
break;
}
}
}
@GetMapping("/allUser")
public String allUser(Model model) {
model.addAttribute("users", users);
return "list-user";
}
@GetMapping("/adduser")
public String showAddUserForm(Model model) {
User user = new User();
user.setId(getMaxId());
model.addAttribute("user", user);
return "add-user";
}
@PostMapping("/adduser")
public String addUser(User user, Model model) {
users.add(user);
return "redirect:/allUser";
}
@GetMapping("/edit/{id}") //{id}是占位符
public String showUpdateForm(@PathVariable("id") long id, Model model) { //@PathVariable 路径变量
User user = getUser(id);
model.addAttribute("user", user);
return "update-user";
}
@PostMapping("/update/{id}")
public String updateUser(@PathVariable("id") long id, User user, Model model) {
update(user,id);
return "redirect:/allUser";
}
@GetMapping("/delete/{id}")
public String deleteUser(@PathVariable("id") long id, Model model) {
delete(id);
return "redirect:/allUser";
}
}
@Controller注释表明UserController.java类是一个控制器。
Spring的控制器默认是单实例,因此List users被设计成静态的,使得它在全生命周期可以使用。而且添加一个静态块用于初始部分数据,这里初始了3条用户信息。
接下来的几个方法代替了DAO层的查找、保存、删除方法。
@GetMapping和@PostMapping分别表示get请求和post请求,相当于Servlet中doGet()方法和doPost()方法。这意味着 @GetMapping和@PostMapping 中的值可以一样。
在方法showUpdateForm()上传的注释中出现了{id},它表示一个占位符,表示路径变量的占位符,其中的id可以是别的字符。而紧跟是注释@PathVariable(“id”) long id,用于获取占位符 {id} 实际传递过来的值。
@PathVariable注释用途非常广泛,在查找、修改、删除等方法中都需要用到。
重定向,通过redirect指示重定向到另一个URL。如”redirect:/allUser” 重定向到请求 /allUser
在showAddUserForm方法中,实例化一个User,并设置好id,然后通过Model的实例传递实例User到视图层add-user.html
5 视图层
视图层在使用thymeleaf模板时,视图层的文件都是.html文件。这对前后端分工合作开发非常好友,前端开发人员不需要懂java编程也能参与到Java开发中来。
thymeleaf模板文件在spring boot工程中统一放置在src/main/resources/templates目录里。这个规则很重要,不遵循会出现404的错误。
list-user.html
list-user.html 视图用于遍历所有的用户信息。
th:each="user : ${users}"用于遍历集合里的数据,user是变量,users是控制传递过来的数据。
显示数据使用th:text="${user.name}",user是变量或实例,name是实例的属性。
属性th:href相当于HTML中的a元素的属性href。@{/edit/} 用于指定个相对的URL路径。而 {id}表示路径变量的一个占位符,(id=${user.id}) 用于设置这个id的实际值。
add-user.html
add-user.html视图提供一个表单,用于添加user。
th:object用于与控制器交互,它的值是控制器传递过来的一个数据模型。这个数据模型可以收集表单的字段。
th:field是HTML中input元素的name属性和value属性的结合体,th:field=”*{name}不仅有属性name,还有属性value。属性name的值是name,value的值是表单中输入的值,或控制器传递过来的数据模型的值。
update-user.html
视图update-user.html提供一个修改数据的表单,它同添加用户的视图一样。
package com.wangshenghua.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = {“com.wangshenghua.*”})
public class SpringMvcCurdApplication {
public static void main(String[] args) {
SpringApplication.run(SpringMvcCurdApplication.class, args);
}
}
这个类在使用STS创建Spring Starter Project时自动生成。
@SpringBootApplication用于指示容器,这是入口处,要运行程序先到这里来。
参数scanBasePackages用于扫描包,它的值是各包名,可以使用能配符*。在多个包的情况下,未指定包扫描的包不会被实例化,不被实例化也就不能在内存里,不能在CPU里执行。
右击工程,在弹出的菜单中选择【Run as】【Spring Boot App】启动工程,在浏览器地址栏输入http://localhost:8080即可访问本程序。
7 总结
本节课程使用Spring Boot和thymeleaf技术实现一个增、删、改、查的小程序。程序虽小,用到的技术却是以后复杂应用的基石。学员位重点掌握控制层各方法的写及视图如何遍历数据、表单的使用。
本节课程源码已经上传到github,可以前往下载。