可放置在参数中,为Pageable对象指定默认值和排序方式
@GetMapping("/")
public String index(
// size: 每一页显示的数据数量
// sort: 排序的依据
// direction: 排序的方式
@PageableDefault(size = 5,sort = {"updateTime"},direction = Sort.Direction.DESC) Pageable pageable,
Model model
){
// 返回前端的分页对象Page
Page<Blog> listBlog = blogService.listBlog(pageable);
toIndex(model,listBlog);
return "index";
}
多用来和SpringDataJPA结合,进行分页查询,返回结果就是一个Page分页对象
前端根据搜索条件进行分页查询,后端用一个对象来封装前端的查询条件,进行分页条件查询
封装的前端查询条件对象
// 博客查询的封装对象
public class BlogQuery {
private String title; // 根据博客标题查询
private Long typeId; // 根据博客的分类id查询
private boolean recommend; // 根据是否推荐查询
// ......
}
controller层
@PostMapping("/blogs/search")
public String search(
// 指定默认的分页方式
@PageableDefault(size = 10,sort = {"updateTime"},direction = Sort.Direction.DESC) Pageable pageable,
BlogQuery blog, // 前端的查询条件对象
Model model
){
model.addAttribute("page",blogService.listBlog(pageable, blog));
// 定义一个片段,实现局部的渲染
return "admin/blogs :: blogList";
}
service层
@Override
public Page<Blog> listBlog(Pageable pageable, BlogQuery blog) {
Specification<Blog> blogSpecification = new Specification<Blog>() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery cq, CriteriaBuilder cb) {
ArrayList<Predicate> predicateList = new ArrayList<>();
// 判断是否有标题的条件传输过来(标题不等于空或者null的时候才会拼接条件)
if (!"".equals(blog.getTitle()) && blog.getTitle() != null ){
predicateList.add(cb.like(root.<String>get("title"), "%" + blog.getTitle() + "%"));
}
// 根据Blog对象中的Type对象的id值进行查询
// 因为id是Long类型的,所以不存在空格字符串的情况
if (blog.getTypeId() != null){
predicateList.add(cb.equal(root<Type>get("type").get("id"),
blog.getTypeId()));
}
// 判断是否是推荐的文章,是true的情况就进行查询
if (blog.isRecommend()){
predicateList.add(cb.equal(root.<Boolean>get("recommend"),
blog.isRecommend()));
}
// 把条件列表转换成数组
Predicate[] predicates = predicateList.toArray(
new Predicate[predicateList.size()]
);
// 通过条件数据进行查询
cq.where(predicates);
return null;
}
};
// 进行分页条件查询
Page<Blog> all = repository.findAll(blogSpecification, pageable);
return all;
}
前端使用Page分页对象获取数据分页数据
// 获取博客的总的条数
<h2 class="ui orange header" th:text="${page.totalElements}">14</h2>
// 获取分页对象中的每一个blog对象
<div class="ui padded vertical segment" th:each="blog : ${page.content}">
// 如果页数大于1页的话,就进行显示
<div class="ui bottom attached segment" th:if="${page.totalPages}>1">
// 点击上一页的时候当前页数-1 只有存在上一页的情况下,上一页的按钮才会显示
<a href="#" th:href="@{/(page=${page.number}-1)}" th:unless="${page.first}">上一页</a>
// 点击下一页的时候当前页数+1 只有存在下一页的情况下,下一页的按钮才会显示
<a href="#" th:href="@{/(page=${page.number}+1)}" th:unless="${page.last}">下一页</a>
PageImpl extends Chunk implements Page
PageImpl 是 Page接口的一个实现类
/*
参数一: 通过分页查询查询到的对象
参数二: 分页对象
参数三: 对象(不是分页对象)的总的数量
*/
new PageImpl<>(arrayList, pageable, count);
示例
private Page<CommentAndBlog> returnResult (Page<Comment> commentList,Pageable pageable){
ArrayList<CommentAndBlog> arrayList = new ArrayList<>();
for (Comment comment : commentList) {
CommentAndBlog commentAndBlog = new CommentAndBlog();
commentAndBlog.setNickname(comment.getNickname());
commentAndBlog.setContent(comment.getContent());
commentAndBlog.setCreateTime(comment.getCreateTime());
// 封装评论的id(为删除或者编辑id的时候使用)
commentAndBlog.setId(comment.getId());
// 封装评论所对应的文章
Long blogId = comment.getBlog().getId();
// 根据文章id查找文章的标题
String blogTitle = blogService.getBlog(blogId).getTitle();
commentAndBlog.setTitle(blogTitle);
// 把构造好的对象添加到集合中
arrayList.add(commentAndBlog);
}
// 获取查询对象的总的数量(非分页查询对象)
long count = commentRepository.count();
// 通过PageImpl<> 构造分页对象
/*
* 参数一: 查询到的对象
* 参数二: 分页对象
* 参数三: 数据的总的数量
* */
Page<CommentAndBlog> commentAndBlogs = new PageImpl<>(arrayList, pageable, count);
return commentAndBlogs;
}
参数一: 从第几页开始查询,当前为从第一页开始查询(写作0)
参数二: 每页显示的条数
参数三: 排序方式
PageRequest.of(0, size, sort);
@Override
public List<Blog> listRecommendBlogTop(Integer size) {
// 构造排序对象
Sort sort = new Sort(Sort.Direction.DESC, "updateTime");
Pageable pageable = PageRequest.of(0, size, sort);
// 根据分页对象,进行分页查询
return repository.findTop(pageable);
}