Spring Data JPA使用Pageable 参数Thymeleaf 视图进行分页

news2024/11/19 2:32:26

在上一个教程中,我们看到了如何在Spring MVC控制器方法中使用参数。以下示例显示了如何将 Spring 数据分页与 Thymeleaf 视图一起使用。我们还将使用注释来更改默认页面大小。Pageable@PageableDefault

实体

package com.example;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.envers.Audited;

@Data
@Entity
@DynamicUpdate

@Audited
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String dept;
    private Integer salary;

    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 getDept() {
        return dept;
    }

    public void setDept(String dept) {
        this.dept = dept;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public static Employee create(String name, String dept, int salary) {
        Employee e = new Employee();
        e.setName(name);
        e.setDept(dept);
        e.setSalary(salary);
        return e;
    }

    @Override
    public String toString() {
        return "Employee{"
                + "id=" + id
                + ", name='" + name + '\''
                + ", dept='" + dept + '\''
                + ", salary=" + salary
                + '}';
    }
}

存储 库

package com.example;

import org.springframework.data.jpa.repository.JpaRepository;

public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}

弹簧MVC控制器

package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class EmployeeController {

    @Autowired
    private EmployeeRepository repository;

    @GetMapping("/employees")
    public String getEmployees(@PageableDefault(size = 10) Pageable pageable,
            Model model) {
        Page<Employee> page = repository.findAll(pageable);
        model.addAttribute("page", page);
        return "employee-page";
    }
}

百里香叶视图

src/main/webapp/WEB-INF/views/employee-page.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <style>
            table{
                width:100%;
            }
            table td, table th {
                border: 1px solid grey;
            }
            table th {
                background: #eee;
            }
            .pagination-div{
                user-select: none;
            }
            .pagination-div span{
                border-radius:3px;
                border:1px solid #999;
                padding:5px;
                margin:10px 0px 0px 10px;
                display:inline-block
            }
            span.selected{
                background:#ccf;
            }
        </style>
    </head>
    <body>
        <h2>Employees</h2>
        <table>
            <tr><th>Id</th>
                <th>Name</th>
                <th>Department</th>
                <th>Salary</th>
            </tr>
            <tr th:each="employee : ${page.content}">
                <td th:text="${employee.id}"></td>
                <td th:text="${employee.name}"></td>
                <td th:text="${employee.dept}"></td>
                <td th:text="${employee.salary}"></td>
            </tr>
        </table>

        <div class="pagination-div">
            <span th:if="${page.hasPrevious()}">
                <a th:href="@{/employees(page=${page.number-1},size=${page.size})}">Previous</a>
            </span>
            <th:block th:each="i: ${#numbers.sequence(0, page.totalPages - 1)}">
                <span th:if="${page.number == i}" class="selected">[[${i}+1]]</span>
                <span th:unless="${page.number == i}">
                    <a th:href="@{/employees(page=${i},size=${page.size})}">[[${i}+1]]</a>
                </span>
            </th:block>
            <span th:if="${page.hasNext()}">
                <a th:href="@{/employees(page=${page.number+1},size=${page.size})}">Next</a>
            </span>
        </div>
    </body>
</html>

运行

要尝试示例,请运行以下示例项目的嵌入式tomcat(在pom中配置.xml):

mvn tomcat7:run-war

输出

本地主机:8080/员工

通过单击页面链接导航到页面:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <link rel="icon" th:href="@{/assets/img/favicon.png}"  />
        <link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap/css/bootstrap.min.css}" />
        <link rel="stylesheet" type="text/css" th:href="@{/webjars/font-awesome/css/all.min.css}"/>
        <link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap-icons/font/bootstrap-icons.css}"/>
        <link rel="stylesheet" type="text/css" th:href="@{/assets/css/style.css}" />
        <link rel="stylesheet" type="text/css" th:href="@{/css/style.css}" />
        <style>
            table{
                width:100%;
            }
            table td, table th {
                border: 1px solid grey;
            }
            table th {
                background: #eee;
            }
            .pagination-div{
                user-select: none;
            }
            .pagination-div span{
                border-radius:3px;
                border:1px solid #999;
                padding:5px;
                margin:10px 0px 0px 10px;
                display:inline-block
            }
            span.selected{
                background:#ccf;
            }
        </style>
    </head>
    <body>
        <h2>Employees</h2>
        <div class="my-3 ">

            <div class="row d-flex flex-row">
                <form th:action="@{/employees}" id="searchForm" >
                    <div class="row">
                        <div class="col-sm-8">
                            <div class="col-md-12 mt-2">
                                <div class="search">
                                    <i class="fa fa-search"></i>
                                    <input id="keyword" type="search" name="keyword" th:value="${keyword}" required class="form-control"
                                           placeholder="Enter keyword">
                                    <button type="submit" class="btn btn-secondary">搜索</button>
                                </div>
                            </div>
                        </div>
                        <div class="col-sm-3">
                            <div class="col-md-12 input-group mt-2">
                                <div class="input-group-prepend">
                                    <label class="input-group-text" for="pageSize">每页显示行数:</label>
                                </div>
                                <select form="searchForm" name="size" th:value="${pageSize}" onchange="changePageSize()" class="size-select"
                                        id="pageSize">
                                    <option th:each="s : ${ {10, 25, 50} }" th:value="${s}" th:text="${s}" th:selected="${s == pageSize}"></option>
                                </select>
                            </div>
                        </div>
                        <div class="col-sm-1">
                            <div class="col-md-12 mt-2">
                                <button id="btnClear" class="btn btn-info">重置</button>
                            </div>
                        </div>
                    </div>
                </form>
            </div>

        </div>
        <table>
            <tr><th>Id</th>
                <th>Name</th>
                <th>Department</th>
                <th>Salary</th>
            </tr>
            <tr th:each="employee : ${page.content}">
                <td th:text="${employee.id}"></td>
                <td th:text="${employee.name}"></td>
                <td th:text="${employee.dept}"></td>
                <td th:text="${employee.salary}"></td>
            </tr>
        </table>

        <div class="pagination-div">
            <span th:if="${page.hasPrevious()}">
                <a th:href="@{/employees(page=${page.number-1},size=${page.size})}">Previous</a>
            </span>
            <th:block th:each="i: ${#numbers.sequence(0, page.totalPages - 1)}">
                <span th:if="${page.number == i}" class="selected">[[${i}+1]]</span>
                <span th:unless="${page.number == i}">
                    <a th:href="@{/employees(page=${i},size=${page.size})}">[[${i}+1]]</a>
                </span>
            </th:block>
            <span th:if="${page.hasNext()}">
                <a th:href="@{/employees(page=${page.number+1},size=${page.size})}">Next</a>
            </span>
        </div>

        <div class="row">
            <div class="col-sm-6">
                <div th:if="${page.totalPages > 0}">
                    总计<span th:text="${page.totalElements}">99</span>行,当前显示<span th:text="(${page.number} )*${page.size} +1">1</span> -
                    <span th:text="(${page.number} )*${page.size} +${page.numberOfElements}">5</span>行&nbsp; &nbsp;总计<span th:text="${page.totalPages}">99</span>页
                </div>
            </div>
            <div class="col-sm-6">
                <nav aria-label="Pagination" th:if="${page.totalPages > 0}">
                    <ul class="pagination justify-content-center">
                        <li class="page-item" th:classappend="${page.number == 0} ? 'disabled'">
                            <a class="page-link"
                               th:href="@{'/employees?' + ${keyword!=null && keyword!=''? 'keyword=' + keyword + '&' : ''} + 'page=' +'0'+ '&size=' + ${page.size}}"
                               title="First Page" rel="First Page">
                                最前页
                            </a>
                        </li>
                        <li class="page-item font-weight-bold" th:classappend="${page.number == 0} ? 'disabled'">
                            <a class="page-link"
                               th:href="@{'/employees?' + ${keyword!=null && keyword!=''? 'keyword=' + keyword + '&' : ''} + 'page=' + ${page.number - 1} + '&size=' + ${page.size}}"
                               title="Previous Page" rel="Previous Page">
                                前一页
                            </a>
                        </li>
                        <li class="page-item disabled" th:if="${page.number - 2 > 0}">
                            <a class="page-link" href="#">...</a>
                        </li>
                        <li
                            th:each="i : ${#numbers.sequence(page.number > 2 ? page.number - 2 : 0, page.number + 2 < page.totalPages ? page.number + 2 : page.totalPages-1)}"
                            class="page-item" th:classappend="${i == page.number} ? 'active'">
                            <a class="page-link"
                               th:href="@{'/employees?' + ${keyword!=null && keyword!=''? 'keyword=' + keyword + '&' : ''} + 'page=' + ${i} + '&size=' + ${page.size}}"
                               th:title=${i+1} th:rel=${i+1}>
                                [[${i+1} ]]
                            </a>
                        </li>
                        <li class="page-item disabled" th:if="${page.number + 2 < page.totalPages}">
                            <a class="page-link" href="#">...</a>
                        </li>
                        <li class="page-item font-weight-bold" th:classappend="${page.number == page.totalPages-1} ? 'disabled'">
                            <a class="page-link"
                               th:href="@{'/employees?' + ${keyword!=null && keyword!=''? 'keyword=' + keyword + '&' : ''} + 'page=' + ${page.number + 1} + '&size=' + ${page.size}}"
                               title="Next Page" rel="Next Page">
                                后一页
                            </a>
                        </li>
                        <li class="page-item" th:classappend="${page.number == page.totalPages-1} ? 'disabled'">
                            <a class="page-link"
                               th:href="@{'/employees?' + ${keyword!=null && keyword!=''? 'keyword=' + keyword + '&' : ''} + 'page=' +${page.totalPages-1}+ '&size=' + ${page.size}}"
                               title="Last Page" rel="Last Page">
                                最后页
                            </a>
                        </li>
                    </ul>
                </nav>
            </div>
        </div>
        <a href="#" class="back-to-top d-flex align-items-center justify-content-center"><i
                class="bi bi-arrow-up-short"></i></a>
        <script type="text/javascript" th:src="@{/webjars/jquery/jquery.min.js}"></script>
        <script type="text/javascript" th:src="@{/webjars/bootstrap/js/bootstrap.bundle.min.js}"></script>
        <script type="text/javascript" th:src="@{/assets/js/main.js}" ></script>
        <script type="text/javascript">
            $(document).ready(function () {
                $(".btn-delete").on("click", function (e) {
                    e.preventDefault();
                    link = $(this);

                    tutorialTitle = link.attr("tutorialTitle");
                    $("#yesBtn").attr("href", link.attr("href"));
                    $("#confirmText").html("Do you want to delete the Tutorial \<strong\>" + tutorialTitle + "\<\/strong\>?");
                    var myModal = new bootstrap.Modal(document.getElementById('confirmModal'), {
                        keyboard: false
                    });
                    myModal.toggle();
                });

                $("#btnClear").on("click", function (e) {
                    e.preventDefault();
                    $("#keyword").text("");
                    window.location = "[[@{/employees}]]";
                });
            });

            function changePageSize() {
                $("#searchForm").submit();
            }
        </script>
    </body>
</html>

 

示例项目

https://www.logicbig.com/tutorials/spring-framework/spring-data/pagination-with-thymeleaf/spring-data-jpa-pagination-with-thymeleaf.zip

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/54799.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VS系列多通道振弦温度采发仪的选型与开机操作

VS A B C D E VS&#xff1a;无线型振弦传感器采发仪 A&#xff1a;内嵌核心测量模块数量&#xff08;1~4 个&#xff09; B&#xff1a;两位数字表示的振弦通道数量&#xff08;02、04、08、16&#xff09; C&#xff1a;T 表示带有温度测量通道 D&#xff1a;是否有…

【能效管理】电力监控系统在移动某分公司配电系统中的应用分析

安科瑞 李亚俊 壹捌柒贰壹零玖捌柒伍柒 概述 在社会科技发展越来越快捷和便利的现在&#xff0c;对用电设施的管理和实时监视越来越重要。在用电过程中经常发生漏电、过流等现象。甚至照成断电现象&#xff0c;而及时查询故障并解决问题恢复用电也越发重要。 中国移动通信集…

LeetCode 278. 第一个错误的版本

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓本LeetCode 278. 第一个错误的版本&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434; 一、题目名称 LeetC…

Python基础(十):列表的详细讲解

文章目录 列表的详细讲解 一、列表的应用场景 二、列表的格式 三、列表的常用操作 1、查找 2、增加 3、删除 4、修改 5、复制 四、列表的循环遍历 1、while 2、for 五、列表嵌套 六、总结 列表的详细讲解 一、列表的应用场景 思考&#xff1a;有⼀个⼈的姓名(TO…

菜狗杯Misc迅疾响应wp

一、原题 之前没接触过这种题型&#xff0c;所以记录一下 打开题目附件压缩包是一个图片&#xff0c;一看就不是常见的那种二维码&#xff08;甚至看起来有点不适……呜呜&#xff09;果然微信扫一扫也扫不出来。 二、工具和解题步骤 后来去看了官方wp&#xff0c;知道了一…

【Matplotlib绘制图像大全】(十七):散点图

前言 大家好,我是阿光。 本专栏整理了《Matplotlib绘制图像大全》,内包含了各种常见的绘图方法,以及Matplotlib各种内置函数的使用方法,帮助我们快速便捷的绘制出数据图像。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmMatp…

防火墙dmz实验

♥️作者&#xff1a;小刘在C站 ♥️每天分享云计算网络运维课堂笔记&#xff0c;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的&#xff0c;绽放。 ciscoasa> en Password: ciscoasa# conf t ciscoasa(config)# int e0/0 ciscoasa(co…

线程的概念+线程函数API

C线程 有关线程的简单实现 #include<stdio.h> #include<stdlib.h> #include<unistd.h> //定义线程函数&#xff08;固定&#xff09;--void * void *pth_fun(void *pth_arg){while(1){printf("pthread\n");sleep(1);}return NULL; } int main(){…

k8s学习笔记-完整版

文章目录第一章 kubernetes介绍应用部署方式演变kubernetes简介kubernetes组件kubernetes概念第二章 集群环境搭建环境规划集群类型安装方式主机规划环境搭建主机安装环境初始化安装docker安装kubernetes组件准备集群镜像集群初始化安装网络插件服务部署第三章 资源管理资源管理…

docker入门级使用

文章目录dockerdocker概述出现原因官网虚拟化与容器化docker架构图docker安装阿里云镜像加速底层原理Docker常用命令帮助命令镜像命令容器命令常用其他命令安装nginx安装Tomcatdocker 越学习越觉得自己的无知 谦卑,不傲慢,厚积而薄发 docker概述 出现原因 一次编译,到处报错开…

跨境电商如何减少客户流失率:成功的5种保留策略

关键词&#xff1a;跨境电商、客户流失率 经营一家跨境电商企业常常感觉就像一个漏水的容器。无论您在顶部倾注了多少客户&#xff0c;这始终是一个不断耗尽底部的百分比。 这被称为客户流失——它使可持续增长成为品牌面临的主要挑战。 客户流失与客户满意度密切相关。如果您的…

常见七大SMD器件布局基本要求,你掌握了几点?

SMD器件布局的一般要求 细间距器件推荐布置在PCB同一面&#xff0c;也就是引脚间距不大于0.65mm的表面组装器件&#xff1a;也指长X宽不大于1.6mmX0.8mm(尺寸编码为1608)的表面组装元件。 SMD器件的回流焊接器件布局要求 同种贴片器件间距要求≥12mil&#xff08;焊盘间&…

HTML+CSS大作业:旅游网页设计与实现——旅游风景网站6页HTML+CSS+JavaScript实训大作业 HTML+CSS大作业 HTML期末大作业

&#x1f468;‍&#x1f393;静态网站的编写主要是用 HTML DⅣV CSSJS等来完成页面的排版设计&#x1f469;‍&#x1f393;&#xff0c;一般的网页作业需要融入以下知识点&#xff1a;div布局、浮动定位、高级css、表格、表单及验证、js轮播图、音频视频Fash的应用、uli、下拉…

[LINUX]linux基本指令大总结

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【LINUX】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站 文…

塔望3W消费战略全案丨绿力冬瓜茶 三十年饮料老品牌,两年复兴战全国

绿力 冬瓜茶 客户&#xff1a;台湾味丹食品 上海皇品食品有限公司 品牌&#xff1a;绿力 服务&#xff1a;3W消费战略 绿力冬瓜茶品牌全案 &#xff08;2019、2020、2021、2022年度全案&#xff09; 项目背景 1992年台湾味丹食品建立上海味丹食品有限公司&#xff0c;后更…

Cadence Allegro PCB设计88问解析(二十) 之 Allegro中格点设置(一)

一个学习信号完整性仿真的layout工程师 布局是PCB设计中比较重要的一步&#xff0c;一个好的布局&#xff0c;不仅看起来美观而且也方便后期的走线&#xff0c;避免了一些信号完整性问题。在布局时就会涉及到格点设置&#xff0c;一个好的格点设置有利于器件的摆放和走线方便。…

Android—百度地图的简单使用

目录百度地图创建应用获取开发版SHA1获取发布版SHA1设置包名获得一个应用创建模块下载SKDHelloBaiDuMap1.配置AndroidManifest.xml文件2.在布局文件中添加地图容器3.地图初始化4.创建地图Activity&#xff0c;管理MapView生命周期切换地图类型百度地图 百度地图 Android SDK是…

「RocketMQ」消息的刷盘机制

刷盘策略 CommitLog的asyncPutMessage方法中可以看到在写入消息之后&#xff0c;调用了submitFlushRequest方法执行刷盘策略&#xff1a; public class CommitLog {public CompletableFuture<PutMessageResult> asyncPutMessage(final MessageExtBrokerInner msg) {// …

计算机SCI期刊是如何审稿的? - 易智编译EaseEditing

事实上已经有部分国际期刊采用双盲评审模式进行同行评审工作&#xff0c;审稿人看不到作者信息&#xff0c;作者也无法获取审稿人信息。​​​​​​​ 双盲模式或许能保证一定的客观性&#xff0c;但一种观点是&#xff0c;就算是实施双盲评审&#xff0c;一些高水平的科学家…

燃爆一生的拿破仑有多传奇?

拿破仑波拿马&#xff0c;一个凡是学过历史的都知道的名字&#xff0c;他巅峰的时候差点统一整个欧洲&#xff0c;差点就成为欧洲的秦始皇。 他用自己的人生告诉我们一个道理&#xff1a;浓缩的&#xff0c;才是精华&#xff01; 他也向世界证明了&#xff0c;经过几个世纪之…