thymeleaf springboot CRUD (新手向)
前言
我是以我原来mybatis+druid+mysql做CRUD为基础https://www.jianshu.com/p/4b285b5b34f8,主要借鉴了https://blog.csdn.net/zhuyu19911016520/article/details/81537154。这个网址的没做分页,我的做了能在我的程序上运行的分页处理以及一些优化。其中,包括显示上一页与下一页(如果有的话),当前是第几页以及总共有多少页。在删除时不会删了最后一页的最后一个,直接跳到首页(这是不知为何的机制所致),而是对使用者友好的删除后还在当前页面(如果当前页面仍然有数据)。由于刚接触,所以在对于工具所提供的接口只会使用,背后的机制是不了解的。总之,网上找的代码大概意思能看懂,具体代码层面的工作流程需要通过修复一个一个bug,以及加些新功能或者优化一起学习。
放一下thymeleaf官网 https://www.thymeleaf.org/。如果英语差,可以看菜鸟教程。
项目目的
前后端共同实现mysql分页增删改查
文件结构
上代码
pom.xml
<?xmlversion="1.0"encoding="UTF-8"?>
<projectxmlns="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>1.5.1.RELEASE</version>
<relativePath/><!--lookupparentfromrepository-->
</parent>
<groupId>com.vue</groupId>
<artifactId>mybatis_druid_mysql</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis_druid_mysql</name>
<description>mybatis_druid_mysql</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--web依赖,包含servlet,内置tomcat等-->
<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>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!--druid依赖包,配合springBoot项目使用-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.14</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<!--<version>2.3.4.RELEASE</version>-->
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Controller
importcom.mybatis_druid_mysql.demo.Entity.Customer;
importcom.mybatis_druid_mysql.demo.Service.Service;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.data.domain.Page;
importorg.springframework.ui.ModelMap;
importorg.springframework.web.bind.annotation.ModelAttribute;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RequestParam;
importjava.util.Iterator;
@org.springframework.stereotype.Controller
@RequestMapping("customers")
publicclassController{
@Autowired
privateServiceservice;
@RequestMapping("edit")
publicStringedit(ModelMapmap,@RequestParam(value="pageNum",defaultValue="0")intpageNum,@RequestParam(value="pageSize",defaultValue="2")intpageSize,@RequestParam(defaultValue="0")intid){
//isAdd : 向前端页面返回一个是新增与编辑的标识
if(id>0){
map.addAttribute("isAdd",0);
map.addAttribute("customer",service.getById(id));
map.addAttribute("pageNum",pageNum);
}else{
map.addAttribute("isAdd",1);
map.addAttribute("customer",newCustomer());
map.addAttribute("pageNum",pageNum);
}
return"customer/edit";
}
@RequestMapping("goingToDel")
publicStringgoingToDel(ModelMapmap,@RequestParam(value="pageNum",defaultValue="0")intpageNum,@RequestParam(value="pageSize",defaultValue="2")intpageSize,@RequestParam(value="id")intid){
map.addAttribute("customer",service.getById(id));
map.addAttribute("pageNum",pageNum);
return"customer/goingToDel";
}
@RequestMapping("list")
publicStringlist(ModelMapmap,@RequestParam(value="pageNum",defaultValue="0")intpageNum,@RequestParam(value="pageSize",defaultValue="2")intpageSize) {
System.out.println("============================");
Page<Customer>customers=service.getUserList(pageNum,pageSize);
System.out.println("总页数"+customers.getTotalPages());
System.out.println("当前页是:"+pageNum);
System.out.println("分页数据:");
Iterator<Customer>u=customers.iterator();
while(u.hasNext()){
System.out.println(u.next().toString());
}
map.addAttribute("customers",customers);
map.addAttribute("pageNum",pageNum);
return"customer/list";
}
//新增和编辑
@RequestMapping("save")
publicStringsave(ModelMapmap,@RequestParam(value="pageNum",defaultValue="0")intpageNum,@RequestParam(value="pageSize",defaultValue="2")intpageSize,@ModelAttributeCustomercustomer){
if(customer==null){
return"customer/list";
}
if(customer.getId()!=null&&customer.getId()>0){
service.edit(customer);
}else{
service.add(customer);
}
Page<Customer>customers=service.getUserList(pageNum,pageSize);
map.addAttribute("customers",customers);
map.addAttribute("pageNum",pageNum);
return"customer/list";
}
@RequestMapping("del")
publicStringdel(ModelMapmap,@RequestParam(value="pageNum",defaultValue="0")intpageNum,@RequestParam(value="pageSize",defaultValue="2")intpageSize,@ModelAttributeCustomercustomer){
if(customer==null){
return"customer/list";
}
service.delete(customer.getId());
Page<Customer>customers=service.getUserList(pageNum,pageSize);
Iterator<Customer>u=customers.iterator();
map.addAttribute("customers",customers);
map.addAttribute("pageNum",pageNum);
System.out.println(pageNum);
if(u.hasNext()){
System.out.println("1");
return"redirect:list?pageNum="+pageNum;
}
elseif(customers.getTotalPages()!=0) {
pageNum--;
System.out.println("2");
return"redirect:list?pageNum="+pageNum;
}
else{
System.out.println("3");
return"redirect:list?pageNum=0";
}
}
}
ModelMap对象主要用于传递控制方法处理数据到结果页面,也就是说我们把结果页面上需要的数据放到ModelMap对象中即可。通过以下方法向页面传递参数:
publicModelMapaddAttribute(StringattributeName,ObjectattributeValue){...}
publicModelMapaddAttribute(ObjectattributeValue){...}
publicModelMapaddAllAttributes(Collection<?>attributeValues) {...}
publicModelMapaddAllAttributes(Map<String,?>attributes){...}
thymeleaf配置
###ThymeLeaf??
spring.thymeleaf.mode=HTML5
#????????HTML,XMLTEXTJAVASCRIPT
spring.thymeleaf.encoding=UTF-8
#???????
spring.thymeleaf.content-type=text/html
#????,?????
spring.thymeleaf.cache=false
#?????false,?????????????
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.prefix= classpath:/templates/spring.thymeleaf.suffix= .html
设置了thymeleaf的寻址地址以及文件格式。
Controller中return "customer/list";就是在thymeleaf的寻址地址基础上再寻址找到相应的页面。
至于return "redirect:list?pageNum=0"; 这是个重定位。相当于调用Controller方法 http://127.0.0.1:8080/customers/list?pageNum=0
edit.html
<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="UTF-8"/>
<title>新增、编辑客户</title>
</head>
<body>
<formth:action="@{/customers/save}"method="post">
<!--//新增时不存在-->
<divth:if="${isAdd} == 0">
<labelstyle="color: red">id</label>
<inputtype="text"name="id"readonly="readonly"th:field="${customer.id}"style="background-color: red"/>
</div>
<div>
<label>name</label>
<inputtype="text"name="name"th:field="${customer.name}"/>
</div>
<div>
<label>age</label>
<inputtype="text"name="age"th:field="${customer.age}"/>
</div>
<div>
<label>used</label>
<inputtype="text"name="used"th:field="${customer.used}"/>
</div>
<div>
<inputtype="submit"value="提交"/>
</div>
<div>
<inputtype="button"value="返回"onclick="JavaScript:history.go(-1)"/>
</div>
<!--<div>-->
<!--<inputtype="button"value="删除"onclick='remove(this)'/>-->
<!--</div>-->
</form>
</body>
</html>
goingToDel.html
<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="UTF-8"/>
<title>删除客户</title>
</head>
<body>
<formth:action="@{/customers/del(pageNum=${pageNum},id=${customer.id})}"method="post">
<div>
<label>id</label>
<inputtype="text"name="id"readonly="readonly"th:field="${customer.id}"/>
</div>
<div>
<label>name</label>
<inputtype="text"name="name"readonly="readonly"th:field="${customer.name}"/>
</div>
<div>
<label>age</label>
<inputtype="text"name="age"readonly="readonly"th:field="${customer.age}"/>
</div>
<div>
<label>used</label>
<inputtype="text"name="used"readonly="readonly"th:field="${customer.used}"/>
</div>
<div>
<inputtype="submit"value="确定删除"/>
</div>
<div>
<inputtype="button"value="返回"onclick="JavaScript:history.go(-1)"/>
</div>
</form>
</body>
</html>
list.html
<!DOCTYPEhtml>
<htmllang="en"xmlns:th="http://www.thymeleaf.org">
<head>
<metacharset="UTF-8"/>
<title>客户列表</title>
<style>
table{border-collapse:collapse;}
table,th,td{border:1pxsolidblack;padding:5px;text-align:center;}
</style>
<linkrel="stylesheet"th:href="@{/css/bootstrap.css}"/>
</head>
<bodyclass="container">
<br/>
<br/>
<ath:href="edit">新增用户</a>
<br/>
<br/>
<table>
<thead>
<thwidth="20%">id</th>
<thwidth="20%">name</th>
<thwidth="20%">age</th>
<thwidth="20%">used</th>
<thwidth="20%">操作</th>
</thead>
<tbody>
<trth:each="customer : ${customers}">
<tdth:text="${customer.id}"></td>
<tdth:text="${customer.name}"></td>
<tdth:text="${customer.age}"></td>
<tdth:text="${customer.used}"></td>
<td>
<ath:href="@{/customers/edit(id=${customer.id})}">编辑</a>
<ath:href="@{/customers/goingToDel(pageNum=${pageNum},id=${customer.id})}">删除</a>
</td>
</tr>
</tbody>
</table>
<divth:text="当前页数"></div>
<divth:text="${pageNum}"></div>
<divclass="modal-footer no-margin-top">
<ulclass="pagination pull-right no-margin">
<!--首页-->
<li>
<ath:href="'/customers/list?pageNum=0'">首页</a>
</li>
<!--上一页-->
<lith:if="${customers.hasPrevious()}">
<ath:href="'/customers/list?pageNum=' + ${customers.previousPageable().getPageNumber()}"th:text="上一页"></a>
</li>
<!--中间页-->
<lith:each="pageNum:${#numbers.sequence(0, customers.getTotalPages()-1)}">
<ath:href="'/customers/list?pageNum=' + ${pageNum}"th:text="${pageNum + 1}"th:style="'font-weight:bold;background: #6faed9;'"></a>
</li>
<!--下一页-->
<lith:if="${customers.hasNext()}">
<ath:href="'/customers/list?pageNum=' + ${customers.nextPageable().getPageNumber()}"th:text="下一页"></a>
</li>
<!--尾页-->
<li>
<ath:href="'/customers/list?pageNum=' + ${customers.getTotalPages() - 1}">尾页</a>
</li>
</ul>
</div>
</body>
</html>
UserRepositrory
publicinterfaceUserRepositoryextendsJpaRepository<Customer,Long>{
}
Service
@org.springframework.stereotype.Service
publicinterfaceService{
//新增
voidadd(Customercustomer);
//编辑
voidedit(Customercustomer);
//删除
voiddelete(intid);
//获取单个
CustomergetById(intid);
//获取所有
List<Customer>listByAll();
Page<Customer>getUserList(intpageNum,intpageSize);
}
ServiceImpl
import com.mybatis_druid_mysql.demo.Entity.Customer;
import com.mybatis_druid_mysql.demo.Mapper.Mapper;
import com.mybatis_druid_mysql.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import java.util.List;
@org.springframework.stereotype.Service
public class ServiceImpl implements Service {
@Autowired
private Mapper mapper;
@Autowired
private UserRepository userRepository;
@Override
public void add(Customer customer) {
mapper.insert(customer);
}
@Override
public void edit(Customer customer) {
mapper.updateByPrimaryKey(customer);
}
@Override
public void delete(int id) {
mapper.deleteByPrimaryKey(id);
}
@Override
public Customer getById(int id) {
return mapper.selectByPrimaryKey(id);
}
@Override
public List listByAll() {
return mapper.listByAll();
}
@Override
public Page getUserList(int pageNum, int pageSize) {
Pageable pageable = new PageRequest(pageNum, pageSize);
Page customers = userRepository.findAll(pageable);
return customers;
}
}