这一部分的代码是基于大神的代码,只是原本的代码是有错的,只自己记录一下自己更改之后的代码和自己的理解。
最后代码结构如下,我对Spring及其相关之事还是全然陌生的,只按自己理解的话,UserController处定义了浏览器接口,resposity文件夹中的两个文件定义了User类的增删查改,这些增删查改的操作又会被前端通过接口访问,这段代码对于想偷懒的我稍稍有点复杂,但是可以看出比较多的知识点:
使用Thymeleaf的过程:
1、写代码前的配置
在pom.xml中添加依赖
<dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-thymeleafartifactId> dependency>
在application.properties中添加对Thymeleaf的配置
#Thymeleaf #指定编码方式 spring.thymeleaf.encoding=UTF-8 #热部署静态文件。能够在浏览器中及时看到修改后的效果(开发) spring.thymeleaf.cache=false #使用html5标准 spring.thymeleaf.mode=html5
2、编写User类和reponsitory里的代码
User类:这里的成员变量id、name、age都是私有的,但其实我在前端界面直接调用实例的id、name、age好像都可以,并不报错
public class User { private Long id;//唯一标识 private String name; private Integer age; public User() {//无参默认构造器 } public User(Long id, String name, Integer age) { this.id = id; this.name = name; this.age = age; } 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 Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; } }
UserRepository接口
import com.example.demo.domain.User; import java.util.List; public interface UserRepository { User saveOrUpdateUser(User user); //新增或者修改用户 void deleteUsere(Long id); //删除用户 User getUserById(Long id); //根据用户id获取用户 ListuserList (); //获取所有用户的列表 }
UserRepositoryImpl 类:这里增删查改只是模拟保存,没有涉及到真正的保存,重跑就会丢失数据
import com.example.demo.domain.User; import org.springframework.stereotype.Repository; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicLong; @Repository//用于标识UserRepositoryimpl 类是一个可注入的bean 。 public class UserRepositoryImpl implements UserRepository { //用来生成一个递增的id ,作为用户的唯一编号。 private static AtomicLong counterId = new AtomicLong(); //模拟数据的存储, private final ConcurrentMapuserConcurrentMap =new ConcurrentHashMap (); @Override public User saveOrUpdateUser(User user) { Long id =user.getId(); if (id==null){ id=counterId.incrementAndGet(); user.setId(id); } this.userConcurrentMap.put(id,user); return user; } @Override public void deleteUsere(Long id) { this.userConcurrentMap.remove(id); } @Override public User getUserById(Long id) { return this.userConcurrentMap.get(id); } @Override public List userList() { return new ArrayList (this.userConcurrentMap.values()); } }
3、前端界面代码
看这前端的代码数量就知道我为什么嫌弃复杂了,在这里面common文件夹下的明显是可公用的模块(像页眉、页脚这种存在),list是展示所有用户、form界面是新建和编辑用户的可编辑页面,view是进入某个用户的详情页。
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>页脚title>
head>
<body>
<div th:fragment="footer">
<a href="/helloworld">欢迎光临a>
div>
body>
html>
common/footer.html:在这里定义了fragment="footer"的片段
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>页头title>
head>
<body>
<div th:fragment="header">
<h1>DemoThymeleafh1>
<a href="/user" th:href="@{~/user/userlist}">首页a>
div>
body>
html>
common/header.html:在这里定义了fragment="header"的片段
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户列表title>
head>
<body>
<div th:replace="~{common/header::header}">div>
<h4 th:text="${userModel.title}">
渡西湖
h4>
<div>
<a href="/user/form" th:href="@{/user/form}">
新建用户
a>
div>
<table border="2">
<thead>
<tr>
<td>idtd>
<td>名字td>
<td>年龄td>
<td>管理td>
tr>
thead>
<tbody>
<tr th:if="${userModel.userList.size()} eq 0">
<td colspan="3">无数据!td>
tr>
<tr th:each="user:${userModel.userList}">
<td th:text="${user.getId()}">td>
<td><a th:href="@{'/user/'+${user.getId()}}" th:text="${user.getName()}">a>td>
<td th:text="${user.getAge()}">td>
<td><a th:href="@{'/user/delete/'+${user.getId()}}">删除a>td>
tr>
tbody>
table>
<div th:replace="~{common/footer::footer}">div>
body>
html>
user/list.html:
1、使用引用了在commmon/header.html中的片段
2、使用${}获取传入数据
3、使用@{}获取controller中定义的地址
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout= "http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>DemoThymeleaftitle>
head>
<body>
<div th:replace="~{common/header::header}">div>
<h4 th:text="${userModel.title}">h4>
<form action="/user" th:action="@{/user}" method="post" th:object="${userModel.user}">
<input type="hidden" name="id" th:value="*{id}"/>
名字<br/>
<input type="text" name="name" th:value="*{name}"/>
<br/>
<input type="number" name="age" th:value="*{age}"/>
<br/>
<input type="submit" value="提交">
form>
<div th:replace="~{common/footer::footer}">div>
body>
html>
user/form.html:这里包含了对form元素的处理,绑定了object,并使用*{}为输入绑定object里面对应的值,可以直接将数据传到后端
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户详情title>
head>
<body>
<div th:replace="~{common/header::header}">div>
<h4 th:text="${userModel.title}">h4>
<div>
<p><strong>ID:strong><span th:text="${userModel.user.id}">span>p>
<p><strong>名字:strong><span th:text="${userModel.user.name}">span>p>
<p><strong>年龄:strong><span th:text="${userModel.user.age}">span>p>
div>
<div>
<a th:href="@{'/user/delete/'+${userModel.user.id}}">删除a>
<a th:href="@{'/user/edit/'+${userModel.user.id}}">修改a>
div>
<div th:replace="~{common/footer::footer}">div>
body>
html>
4、controller的编写
import com.example.demo.domain.User; import com.example.demo.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; @RestController @RequestMapping("/user") public class UserController { @Autowired private UserRepository userRepository; //查词所有用户 @GetMapping("/userlist") public ModelAndView userList(Model model){ model.addAttribute("userList",userRepository.userList()); model.addAttribute("title","用户管理"); return new ModelAndView("user/list","userModel",model); } //根据id 查询用户 @GetMapping("{id}") public ModelAndView view(@PathVariable("id") Long id, Model model){ User user= userRepository.getUserById(id); model.addAttribute("user",user); model.addAttribute("title","查看用户"); return new ModelAndView("user/view" ,"userModel",model); } //获取创建表单页面 @GetMapping("/form") public ModelAndView createForm(Model model){ model.addAttribute("user",new User()); model.addAttribute("title","创建用户"); return new ModelAndView("user/form","userModel",model); } //保存用户 @PostMapping public ModelAndView saveOrUpdateUser(User user){ user =userRepository.saveOrUpdateUser(user); return new ModelAndView("redirect:/user/userlist"); } //根据id删除用户 @GetMapping(value = "delete/{id}") public ModelAndView delete(@PathVariable("id") Long id){ userRepository.deleteUsere(id); return new ModelAndView("redirect:/user/userlist"); } //修改用户界面 @GetMapping(value = "edit/{id}") public ModelAndView editForm(@PathVariable("id") Long id, Model model){ User user =userRepository.getUserById(id); model.addAttribute("user",user); model.addAttribute("title","编辑用户"); return new ModelAndView("user/form" ,"userModel",model); } }
具体说说,无论是新增用户保存后还是删除用户后都应该跳转回用户列表展示界面,之前代码用的“redirect”,根据别人评论我改成了
"redirect:/user/userlist",但是也没有去验证之前的写法对不对
//保存用户 @PostMapping public ModelAndView saveOrUpdateUser(User user){ user =userRepository.saveOrUpdateUser(user); return new ModelAndView("redirect:/user/userlist"); } //根据id删除用户 @GetMapping(value = "delete/{id}") public ModelAndView delete(@PathVariable("id") Long id){ userRepository.deleteUsere(id); return new ModelAndView("redirect:/user/userlist"); }