一、账单

1.导入依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>com.ts</groupId>
  7. <artifactId>billmappers</artifactId>
  8. <version>1.0-SNAPSHOT</version>
  9. <parent>
  10. <artifactId>spring-boot-starter-parent</artifactId>
  11. <groupId>org.springframework.boot</groupId>
  12. <version>2.0.0.RELEASE</version>
  13. </parent>
  14. <properties>
  15. <java.version>1.8</java.version>
  16. </properties>
  17. <dependencies>
  18. <dependency>
  19. <groupId>org.springframework.boot</groupId>
  20. <artifactId>spring-boot-starter-web</artifactId>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-test</artifactId>
  25. </dependency>
  26. <dependency>
  27. <groupId>mysql</groupId>
  28. <artifactId>mysql-connector-java</artifactId>
  29. <version>5.1.46</version>
  30. </dependency>
  31. <dependency>
  32. <groupId>tk.mybatis</groupId>
  33. <artifactId>mapper-spring-boot-starter</artifactId>
  34. <version>2.0.2</version>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  39. </dependency>
  40. </dependencies>
  41. </project>

2.spring boot 启动器

  1. package com.ts;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import tk.mybatis.spring.annotation.MapperScan;
  5. /**
  6. * @author 森哥
  7. */
  8. @SpringBootApplication
  9. @MapperScan("com.ts.dao")
  10. public class Application {
  11. public static void main(String[] args) {
  12. SpringApplication.run(Application.class, args);
  13. }
  14. }

3.application.properties:springboot全局配置文件

  1. #连接池
  2. spring:
  3. datasource:
  4. driver-class-name: com.mysql.jdbc.Driver
  5. username: root
  6. password: root
  7. url: jdbc:mysql://localhost:3306/bill-mapper
  8. thymeleaf:
  9. cache: false #关闭thymeleaf的缓存
  10. #整合mybatis
  11. mybatis:
  12. type-aliases-package: com.ts.entity #别名
  13. mapper-locations: classpath:/mappers/*.xml

4.实体类

4.1账单类型

  1. package com.ts.entity;
  2. /**
  3. * @Author: 森哥
  4. * @Description:
  5. * @Date Created in 2021-09-15 11:20
  6. * @Modified By:
  7. */
  8. import javax.persistence.*;
  9. @Table(name = "bill_type_")
  10. public class BillType {
  11. @Id
  12. @GeneratedValue(strategy = GenerationType.IDENTITY)
  13. @Column(name = "id_")
  14. private Long id;
  15. @Column(name = "name_")
  16. private String name;
  17. public Long getId() {
  18. return id;
  19. }
  20. public void setId(Long id) {
  21. this.id = id;
  22. }
  23. public String getName() {
  24. return name;
  25. }
  26. public void setName(String name) {
  27. this.name = name;
  28. }
  29. }

4.2账单

  1. package com.ts.entity;
  2. import javax.persistence.*;
  3. import java.util.Date;
  4. /**
  5. * @Author: 森哥
  6. * @Description:
  7. * @Date Created in 2021-09-15 11:28
  8. * @Modified By:
  9. */
  10. @Table(name = "bill_")
  11. public class Bill {
  12. @Id
  13. @GeneratedValue(strategy = GenerationType.IDENTITY)
  14. @Column(name = "id_")
  15. private long id;
  16. @Column(name = "title_")
  17. private String title;
  18. @Column(name = "bill_time_")
  19. private Date billTime;
  20. @Column(name = "type_id_")
  21. private long typeId;
  22. @Column(name = "price_")
  23. private Double price;
  24. @Column(name = "explain_")
  25. private String explain;
  26. @Transient
  27. private String date1;
  28. /**
  29. * 开始时间
  30. */
  31. @Transient
  32. private Date date2;
  33. /**
  34. * 结束时间
  35. */
  36. @Transient
  37. private Date endTime;
  38. public long getId() {
  39. return id;
  40. }
  41. public void setId(long id) {
  42. this.id = id;
  43. }
  44. public String getTitle() {
  45. return title;
  46. }
  47. public void setTitle(String title) {
  48. this.title = title;
  49. }
  50. public Date getBillTime() {
  51. return billTime;
  52. }
  53. public void setBillTime(Date billTime) {
  54. this.billTime = billTime;
  55. }
  56. public long getTypeId() {
  57. return typeId;
  58. }
  59. public void setTypeId(long typeId) {
  60. this.typeId = typeId;
  61. }
  62. public Double getPrice() {
  63. return price;
  64. }
  65. public void setPrice(Double price) {
  66. this.price = price;
  67. }
  68. public String getExplain() {
  69. return explain;
  70. }
  71. public void setExplain(String explain) {
  72. this.explain = explain;
  73. }
  74. public String getDate1() {
  75. return date1;
  76. }
  77. public void setDate1(String date1) {
  78. this.date1 = date1;
  79. }
  80. public Date getDate2() {
  81. return date2;
  82. }
  83. public void setDate2(Date date2) {
  84. this.date2 = date2;
  85. }
  86. public Date getEndTime() {
  87. return endTime;
  88. }
  89. public void setEndTime(Date endTime) {
  90. this.endTime = endTime;
  91. }
  92. @Override
  93. public String toString() {
  94. return "Bill{" +
  95. "id=" + id +
  96. ", title='" + title + '\'' +
  97. ", billTime=" + billTime +
  98. ", typeId=" + typeId +
  99. ", price=" + price +
  100. ", explain='" + explain + '\'' +
  101. ", date1='" + date1 + '\'' +
  102. ", date2=" + date2 +
  103. ", endTime=" + endTime +
  104. '}';
  105. }
  106. }

注意 @Transient注解表示当前属性为瞬时属性,跟字段没有映射,上面实体类中date1和date2只作为查询条件存
在,跟表中的字段没有关联

5.dao

5.1BillMapeer和TypeMapper

  1. package com.ts.dao;
  2. import com.ts.entity.Bill;
  3. import tk.mybatis.mapper.common.Mapper;
  4. import java.util.List;
  5. /**
  6. * @Author: 森哥
  7. * @Description:
  8. * @Date Created in 2021-09-15 20:14
  9. * @Modified By:
  10. */
  11. public interface BillMapper extends Mapper<Bill> {
  12. /**
  13. * 查询
  14. *
  15. * @param bill
  16. * @return java.util.List<com.ts.entity.Bill>
  17. * @author ts
  18. * @date 2021/9/15 21:05
  19. */
  20. List<Bill> queryBill(Bill bill);
  21. }
  1. package com.ts.dao;
  2. import com.ts.entity.BillType;
  3. import org.springframework.stereotype.Component;
  4. import tk.mybatis.mapper.common.Mapper;
  5. /**
  6. * @Author: 森哥
  7. * @Description:
  8. * @Date Created in 2021-09-15 20:14
  9. * @Modified By:
  10. */
  11. public interface TypeMapper extends Mapper<BillType> {
  12. }

5.2查询修改的映射文件

  1. <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  2. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.ts.dao.BillMapper">
  4. <sql id="selectSql">
  5. SELECT
  6. b.id_ as id,
  7. b.title_ as title,
  8. b.bill_time_ as billTime,
  9. b.type_id_ as typeId,
  10. b.price_ as price,
  11. b.explain_ as `explain`,
  12. t.name_ as typeName
  13. FROM
  14. bill_ as b
  15. left join bill_type_ as t
  16. on b.type_id_ = t.id_
  17. </sql>
  18. <select id="queryBill" resultType="com.ts.entity.Bill">
  19. <include refid="selectSql"/>
  20. <where>
  21. <if test="typeId !=null">b.type_id_ = #{typeId}</if>
  22. <if test="title !=null">and b.title_ like '%${title}%'</if>
  23. <if test="date1 !=null">and b.bill_time_ &gt;= #{date1}</if>
  24. <if test="date2 !=null">and b.bill_time_ &lt;= #{date2}</if>
  25. </where>
  26. </select>
  27. </mapper>

注意:explain字段名在mysql 中是关键词必须使用``包裹

6.service

  1. package com.ts.service;
  2. import com.ts.dao.BillMapper;
  3. import com.ts.entity.Bill;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Service;
  6. import javax.annotation.Resource;
  7. import java.util.List;
  8. /**
  9. * @Author: 森哥
  10. * @Description:
  11. * @Date Created in 2021-09-15 21:10
  12. * @Modified By:
  13. */
  14. @Service
  15. public class BillService {
  16. @Resource
  17. private BillMapper billMapper;
  18. /**
  19. * 根据开始时间和结束时间查询
  20. *
  21. * @param bill
  22. * @return java.util.List<com.ts.entity.Bill>
  23. * @author ts
  24. * @date 2021/9/15 21:18
  25. */
  26. public List<Bill> queryBill(Bill bill) {
  27. return billMapper.queryBill(bill);
  28. }
  29. /**
  30. * 添加
  31. *
  32. * @param bill
  33. * @return int
  34. * @author ts
  35. * @date 2021/9/15 21:23
  36. */
  37. public int add(Bill bill) {
  38. return billMapper.insert(bill);
  39. }
  40. /**
  41. * 根据id查询
  42. *
  43. * @param id
  44. * @return com.ts.entity.Bill
  45. * @author ts
  46. * @date 2021/9/15 21:25
  47. */
  48. public Bill selectBillById(Long id) {
  49. return billMapper.selectByPrimaryKey(id);
  50. }
  51. /**
  52. * @param bill
  53. * @return int
  54. * @author ts
  55. * @date 2021/9/15 21:29
  56. */
  57. public int updateBillById(Bill bill) {
  58. return billMapper.updateByPrimaryKey(bill);
  59. }
  60. /**
  61. * @param id
  62. * @return int
  63. * @author ts
  64. * @date 2021/9/15 21:30
  65. */
  66. public int deleteBillById(Long id) {
  67. return billMapper.deleteByPrimaryKey(id);
  68. }
  69. }
  1. package com.ts.service;
  2. import com.ts.dao.TypeMapper;
  3. import com.ts.entity.BillType;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Service;
  6. import javax.annotation.Resource;
  7. import java.util.List;
  8. /**
  9. * @Author: 森哥
  10. * @Description:
  11. * @Date Created in 2021-09-15 21:11
  12. * @Modified By:
  13. */
  14. @Service
  15. public class TypeService {
  16. @Resource
  17. private TypeMapper typeMapper;
  18. /**
  19. * @return java.util.List<com.ts.entity.BillType>
  20. * @author ts
  21. * @date 2021/9/15 21:44
  22. */
  23. public List<BillType> getAll() {
  24. return typeMapper.selectAll();
  25. }
  26. }

7.controller

  1. package com.ts.controller;
  2. import com.ts.entity.Bill;
  3. import com.ts.entity.BillType;
  4. import com.ts.service.BillService;
  5. import com.ts.service.TypeService;
  6. import org.springframework.stereotype.Controller;
  7. import org.springframework.ui.Model;
  8. import org.springframework.web.bind.annotation.PathVariable;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import javax.annotation.Resource;
  11. import java.util.List;
  12. /**
  13. * @Author: 森哥
  14. * @Description:
  15. * @Date Created in 2021-09-16 21:10
  16. * @Modified By:
  17. */
  18. @Controller
  19. @RequestMapping("/bill")
  20. public class BillController {
  21. @Resource
  22. private BillService billService;
  23. @Resource
  24. private TypeService typeService;
  25. /**
  26. * 查询类别
  27. *
  28. * @return java.util.List<com.ts.entity.BillType>
  29. * @author ts
  30. * @date 2021/9/16 21:14
  31. */
  32. public List<BillType> queryTypes() {
  33. return typeService.getAll();
  34. }
  35. /**
  36. * 查询
  37. *
  38. * @param bill
  39. * @param model
  40. * @return java.lang.String
  41. * @author ts
  42. * @date 2021/9/16 21:24
  43. */
  44. @RequestMapping("/list")
  45. public String query(Bill bill, Model model) {
  46. List<BillType> types = queryTypes();
  47. model.addAttribute("types", types);
  48. List<Bill> list = billService.queryBill(bill);
  49. model.addAttribute("lsit", list);
  50. model.addAttribute("b", bill);
  51. return "/bill/list";
  52. }
  53. /**
  54. * 调到添加页面
  55. *
  56. * @param model
  57. * @return java.lang.String
  58. * @author ts
  59. * @date 2021/9/16 21:26
  60. */
  61. @RequestMapping("/toAdd")
  62. public String toAdd(Model model) {
  63. List<BillType> types = queryTypes();
  64. model.addAttribute("types", types);
  65. return "/bill/add";
  66. }
  67. /**
  68. * 添加
  69. *
  70. * @param bill
  71. * @return java.lang.String
  72. * @author ts
  73. * @date 2021/9/16 21:27
  74. */
  75. @RequestMapping("/add")
  76. public String add(Bill bill) {
  77. billService.add(bill);
  78. return "redirect:/bill/list";
  79. }
  80. /**
  81. * 删除操作
  82. *
  83. * @param id
  84. * @return java.lang.String
  85. * @author ts
  86. * @date 2021/9/16 21:31
  87. */
  88. @RequestMapping("/delete/{id}")
  89. public String deleteById(@PathVariable("id") Long id) {
  90. billService.deleteBillById(id);
  91. return "redirect:/bill/list";
  92. }
  93. /**
  94. * 跳转到修改界面
  95. *
  96. * @param id
  97. * @param model
  98. * @return java.lang.String
  99. * @author ts
  100. * @date 2021/9/16 21:36
  101. */
  102. @RequestMapping("/toUpdate/{id}")
  103. public String toUpdate(@PathVariable("id") Long id, Model model) {
  104. List<BillType> types = queryTypes();
  105. model.addAttribute("types", types);
  106. Bill bill = billService.selectBillById(id);
  107. model.addAttribute("b", bill);
  108. return "/bill/update";
  109. }
  110. /**
  111. * @param bill
  112. * @return java.lang.String
  113. * @author ts
  114. * @date 2021/9/16 21:38
  115. */
  116. @RequestMapping("/update")
  117. public String update(Bill bill) {
  118. billService.updateBillById(bill);
  119. return "redirect:/bill/list";
  120. }
  121. }

8.页面

8.1 list.html

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8"/>
  5. <title>userList</title>
  6. <link rel="stylesheet" th:href="@{/css/bootstrap.css}"></link>
  7. <script type="text/javascript" th:src="@{/js/My97DatePicker/WdatePicker.js}"></script>
  8. <script type="text/javascript" src="/js/My97DatePicker/lang/zh-cn.js"></script>
  9. <script type="text/javascript" th:src="@{/js/jquery/jquery-1.10.2.min.js}"></script>
  10. </head>
  11. <body class="container">
  12. <br/>
  13. <h1>账单列表</h1>
  14. <br/><br/>
  15. <div class="with:80%">
  16. <!-- TODO 回显查询数据-->
  17. <form class="form-inline" id="qf" method="post">
  18. <div class="form-group">
  19. <label for="typeId" class="control-label">类型</label>
  20. <select name="typeId" id="typeId" class="form-control">
  21. <option value="">全部</option>
  22. <option th:each="t:${types}" th:value="${t.id}" th:text="${t.name}" th:selected="${t.id}+'' == ${#strings.trim(param.typeId)}"></option>
  23. </select>
  24. </div>
  25. <div class="form-group">
  26. <label for="date1" class="control-label">开始时间</label>
  27. <input type="text" class="form-control" name="date1" id="date1" th:value="${param.date1}" placeholder="开始时间" onclick="WdatePicker()"/>
  28. </div>
  29. <div class="form-group">
  30. <label for="date2" class="control-label">结束时间</label>
  31. <input type="text" class="form-control" name="date2" id="date2" th:value="${param.date2}" placeholder="结束时间" onclick="WdatePicker()"/>
  32. </div>
  33. <div class="form-group">
  34. <input type="submit" value="查询" class="btn btn-info"/>
  35. &nbsp; &nbsp;
  36. <input type="reset" value="重置" class="btn btn-info"/>
  37. &nbsp; &nbsp;
  38. <a href="/bill/toAdd" th:href="@{/bill/toAdd}" class="btn btn-info">添加</a>
  39. </div>
  40. </form>
  41. </div>
  42. <br/>
  43. <div class="with:80%">
  44. <table class="table table-striped table-bordered">
  45. <thead>
  46. <tr>
  47. <th>#</th>
  48. <th>标题</th>
  49. <th>时间</th>
  50. <th>金额</th>
  51. <th>类别</th>
  52. <th>说明</th>
  53. <th>操作</th>
  54. </tr>
  55. </thead>
  56. <tbody>
  57. <!-- TODO 回显查询结果-->
  58. <tr th:each="b, bstatus : ${bills}" th:style="${bstatus.odd} ? 'background-color: #A3C6C8'" th:object="${b}">
  59. <th scope="row" th:text="${b.id}">id</th>
  60. <td th:text="${b.title}">name</td>
  61. <td th:text="${b.billTime} ? ${#dates.format(b.billTime, 'yyyy-MM-dd')}">time</td>
  62. <td th:text="${b.price}">price</td>
  63. <td th:text="${b.typeName}">typeName</td>
  64. <td th:text="${b.explain}">explain</td>
  65. <td>
  66. <a th:href="|/bill/toUpdate/*{id}|">修改</a>
  67. <a th:href="|/bill/delete/*{id}|">删除</a>
  68. </td>
  69. </tr>
  70. </tbody>
  71. </table>
  72. </div>
  73. </body>
  74. </html>

todo:th:selected=”${t.id}+’’ == ${#strings.trim(param.typeId)}”
t.id要与param.typeId比较两边都有成一样的类型
所以${t.id}可以通过+’’来转换为字符串 param.typeId可以通过内置函数strings.trim()来转换为字符串

8.2 add.html

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8"/>
  5. <title>user</title>
  6. <link rel="stylesheet" th:href="@{/css/bootstrap.css}"></link>
  7. <script type="text/javascript" th:src="@{/js/My97DatePicker/WdatePicker.js}"></script>
  8. <script type="text/javascript" src="/js/My97DatePicker/lang/zh-cn.js"></script>
  9. </head>
  10. <body class="container">
  11. <br/>
  12. <h1>添加账单</h1>
  13. <br/><br/>
  14. <div class="with:80%">
  15. <form class="form-horizontal" action="/bill/add" method="post">
  16. <div class="form-group">
  17. <label for="typeId" class="col-sm-2 control-label">类型</label>
  18. <div class="col-sm-10">
  19. <select name="typeId" id="typeId" class="form-control">
  20. <option th:each="t:${types}" th:text="${t.name}" th:value="${t.id}"></option>
  21. <!-- TODO 回显账单类型 -->
  22. </select>
  23. </div>
  24. </div>
  25. <div class="form-group">
  26. <label for="title" class="col-sm-2 control-label" >标题</label>
  27. <div class="col-sm-10">
  28. <input type="text" class="form-control" name="title" id="title" placeholder="标题"/>
  29. </div>
  30. </div>
  31. <div class="form-group">
  32. <label for="billTime" class="col-sm-2 control-label">日期</label>
  33. <div class="col-sm-10">
  34. <input type="text" class="form-control" name="billTime" id="billTime" placeholder="日期" onclick="WdatePicker()"/>
  35. </div>
  36. </div>
  37. <div class="form-group">
  38. <label for="price" class="col-sm-2 control-label">金额</label>
  39. <div class="col-sm-10">
  40. <input type="text" class="form-control" name="price" id="price" placeholder="金额"/>
  41. </div>
  42. </div>
  43. <div class="form-group">
  44. <label for="explain" class="col-sm-2 control-label">说明</label>
  45. <div class="col-sm-10">
  46. <input type="text" class="form-control" name="explain" id="explain" placeholder="说明"/>
  47. </div>
  48. </div>
  49. <div class="form-group">
  50. <div class="col-sm-offset-2 col-sm-10">
  51. <input type="submit" value="保存" class="btn btn-info" />
  52. &nbsp; &nbsp; &nbsp;
  53. <input type="reset" value="重置" class="btn btn-info" />
  54. </div>
  55. </div>
  56. </form>
  57. </div>
  58. </body>
  59. </html>

8.3 update.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>user</title>
    <link rel="stylesheet" th:href="@{/css/bootstrap.css}"></link>
    <script type="text/javascript" th:src="@{/js/My97DatePicker/WdatePicker.js}"></script>
    <script type="text/javascript" src="/js/My97DatePicker/lang/zh-cn.js"></script>
</head>
<body class="container">
<br/>
<h1>修改账单</h1>
<br/><br/>
<div class="with:80%">
    <form class="form-horizontal" action="/bill/update" method="post" th:object="${bill}">
        <input type="hidden" name="id" th:value="*{id}" >
        <div class="form-group">
            <label for="typeId" class="col-sm-2 control-label">类型</label>
            <div class="col-sm-10">
                <select name="typeId" id="typeId" class="form-control">
                    <option value="">全部</option>
                    <option th:each="t:${types}"  th:value="${t.id}" th:text="${t.name}" th:selected="${t.id}+'' == ${typeId}"></option>
                </select>
            </div>
        </div>
        <div class="form-group">
            <label for="title" class="col-sm-2 control-label" >标题</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" name="title" id="title"  th:value="*{title}" placeholder="标题"/>
            </div>
        </div>
        <div class="form-group">
            <label for="billTime" class="col-sm-2 control-label">日期</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" name="billTime"  id="billTime" th:value="*{#dates.format(billTime,'yyyy-MM-dd')}" placeholder="日期" onclick="WdatePicker()"/>
            </div>
        </div>
        <div class="form-group">
            <label for="price" class="col-sm-2 control-label">金额</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" name="price" th:value="*{price}"  id="price" placeholder="金额"/>
            </div>
        </div>
        <div class="form-group">
            <label for="explain" class="col-sm-2 control-label">说明</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" th:value="*{explain}" name="explain" id="explain" placeholder="说明"/>
            </div>
        </div>

        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <input type="submit" value="保存" class="btn btn-info" />
                &nbsp; &nbsp; &nbsp;
                <input type="reset" value="重置" class="btn btn-info" />
            </div>

        </div>
    </form>
</div>
</body>
</html>

8.4 分页

引入pageHelper分页插件的starter,注意:必须引入pagehelper的启动器,不能直接引入pagehelper

8.41 引入依赖

 <!-- 分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.3</version>
        </dependency>

8.4.2分页方法的测试

@Test
    public void findPage() {
        Bill b = new Bill();
        b.setTitle("a");
        PageInfo<Bill> page = PageHelper.startPage(2, 10).doSelectPageInfo(() -> {
            billService.list(b);
        });
        page.getList().forEach(bill -> {
            System.out.println(bill.getId() + " " + bill.getTitle());
        });
        System.out.println("总行数=" + page.getTotal());
        System.out.println("当前页=" + page.getPageNum());
        System.out.println("每页行数=" + page.getPageSize());
        System.out.println("总页数=" + page.getPages());
        System.out.println("起始行数=" + page.getStartRow());
        System.out.println("是第一页=" + page.isIsFirstPage());
        System.out.println("是最后页=" + page.isIsLastPage());
        System.out.println("还有下一页=" + page.isHasNextPage());
        System.out.println("还有上一页=" + page.isHasPreviousPage());
        System.out.println("页码列表" + Arrays.toString(page.getNavigatepageNums()));
    }

8.4.3service中的分页方法

 /**
     * @param bill
     * @param pageNum
     * @param pageSize
     * @return com.github.pagehelper.PageInfo<com.ts.entity.Bill>
     * @author ts
     * @date 2021/9/17 20:35
     */
    public PageInfo<Bill> listPage(Bill bill, int pageNum, int pageSize) {
        return PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(() -> {
            billMapper.queryBill(bill);
        });
    }

8.4.4controller中的方法

 /**
     * @param pageNum
     * @param pageSize
     * @param bill
     * @param model
     * @return java.lang.String
     * @author ts
     * @date 2021/9/17 20:41
     */
    @RequestMapping("/list-page")
    public String pageList(
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize,
            Bill bill, Model model) {
        List<BillType> types = queryTypes();
        model.addAttribute("types", types);

        PageInfo<Bill> page = billService.listPage(bill, pageNum, pageSize);
        model.addAttribute("page", page);

        model.addAttribute("bill", bill);

        return "/bill/list-page";
    }

8.4.5页面部分分页逻辑示意图

image.png

8.4.6 list-page.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>userList</title>
    <link rel="stylesheet" th:href="@{/css/bootstrap.css}"></link>
    <script type="text/javascript" th:src="@{/js/My97DatePicker/WdatePicker.js}"></script>
    <script type="text/javascript" src="/js/My97DatePicker/lang/zh-cn.js"></script>
    <script type="text/javascript" th:src="@{/js/jquery/jquery-1.10.2.min.js}"></script>
</head>
<body class="container">
<br/>
<h1>账单列表</h1>
<br/><br/>
<div class="with:80%">
    <form class="form-inline" id="qf" th:action="@{/bill/list-page}" method="post">
        <!-- TODO 分页相关参数-->
        <input type="hidden" name="pageNum" id="pageNum" th:value="${page.pageNum}">
        <input type="hidden" name="pageSize" id="pageSize" th:value="${page.pageSize}">

        <div class="form-group">
            <label for="typeId" class="control-label">类型</label>
            <select name="typeId" id="typeId" class="form-control">
                <option value="">全部</option>
                <option th:each="t:${types}" th:value="${t.id}" th:text="${t.name}"
                        th:selected="${t.id}+'' == ${#strings.trim(param.typeId)}"></option>
            </select>
        </div>
        <div class="form-group">
            <label for="date1" class="control-label">开始时间</label>
            <input type="text" class="form-control" name="date1" id="date1" placeholder="开始时间" onclick="WdatePicker()"/>
        </div>
        <div class="form-group">
            <label for="date2" class="control-label">结束时间</label>
            <input type="text" class="form-control" name="date2" id="date2" placeholder="结束时间" onclick="WdatePicker()"/>
        </div>
        <div class="form-group">
            <input type="submit" value="查询" class="btn btn-info"/>
            &nbsp; &nbsp;
            <input type="reset" value="重置" class="btn btn-info"/>
            &nbsp; &nbsp;
            <a href="/bill/toAdd" th:href="@{/bill/toAdd}" class="btn btn-info">添加</a>
        </div>
    </form>
</div>
<br/>

<div class="with:80%">
    <table class="table table-striped table-bordered">
        <thead>
        <tr>
            <th>#</th>
            <th>标题</th>
            <th>时间</th>
            <th>金额</th>
            <th>类别</th>
            <th>说明</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        <!-- TODO 页面循环-->
        <tr th:each="b, bstatus : ${page.list}" th:style="${bstatus.odd} ? 'background-color: #A3C6C8'"
            th:object="${b}">
            <th scope="row" th:text="${b.id}">id</th>
            <td th:text="${b.title}">name</td>
            <td th:text="${b.billTime} ? ${#dates.format(b.billTime, 'yyyy-MM-dd')}">time</td>
            <td th:text="${b.price}">price</td>
            <td th:text="${b.typeName}">typeName</td>
            <td th:text="${b.explain}">explain</td>
            <td>
                <a th:href="|/bill/toUpdate/*{id}|">修改</a>
                <a th:href="|/bill/delete/*{id}|">删除</a>
            </td>
        </tr>
        </tbody>
    </table>
</div>

<!-- TODO 分页工具类-->
<ul class="pagination">
    <li>
        <button class="btn btn-default" id="first">第一页</button>
    </li>
    <li>
        <button class="btn btn-default" id="prev">上一页</button>
    </li>
    <li th:each="p:${page.navigatepageNums}">
        <button class="btn btn-default" name="pn" th:text="${p}" th:disabled="(${p} == ${page.pageNum})"></button>
    </li>
    <!--    <li th:each="p:${page.navigatepageNums}">-->
    <!--        <button class="btn btn-default" name="pn" th:text="${p}" th:disabled="(${p} == ${page.pageNum})"></button>-->
    <!--    </li>-->
    <li>
        <button class="btn btn-default" id="next">下一页</button>
    </li>
    <li>
        <button class="btn btn-default" id="last">最后页</button>
    </li>
</ul>

<!-- TODO 分页的js代码-->
<script>
    $(function () {
        //当前页
        let pageNum = [[${page.pageNum}]];
        //最后页
        let pageCount = [[${page.pages}]]
        //还有下一页
        let hasNextPage = [[${page.hasNextPage}]]
        //还有有上一页
        let hasPreviousPage = [[${page.hasPreviousPage}]]
        //按钮事件
        $("#first").click(function () {
            $("#pageNum").val(1);
            $("#qf").submit();
        })
        $("#prev").click(function () {
            $("#pageNum").val(pageNum - 1);
            $("#qf").submit();
        })
        $("#next").click(function () {
            $("#pageNum").val(pageNum + 1);
            $("#qf").submit();
        })
        $("#last").click(function () {
            $("#pageNum").val(pageCount);
            $("#qf").submit();
        })

        //页码跳转
        $("button[name='pn']").click(function () {
            $("#pageNum").val($(this).html());
            $("#qf").submit();
        });
        //没有下一页 下一页和最后一页不可用
        if (!hasNextPage) {
            $("#last").prop("disabled", true);
            $("#next").prop("disabled", true);
        }

        if (!hasPreviousPage) {
            $("#first").prop("disabled", true);
            $("#prev").prop("disabled", true);
        }
    })
</script>

</body>
</html>

bug

1.thymeleaf ${xxx} Cannot resolve

https://blog.csdn.net/engerla/article/details/114891690