完成问题发布功能后就可以开始着手进行首页的开发了,首页开发的最大难题就是对内容进行分页。现在的思路是在后端处理完分页的功能,前端直接对后端提供的内容进行展示。处理分页主要由sql语句的limit进行处理。最终的展示如下:
# (一)分页的处理逻辑 {#一-分页的处理逻辑}
我的打算是在一个页面上显示五条内容,所以为了实现这个功能首先需要创建超过5条数据库信息,为了方便我复制了12条问题信息。整体sql语句处理逻辑如下:
当需要显示1-5条时
select * from question limit 0,5;
当需要显示6-10条数据时
select * from question limit 5,5;
基于此,设置一个变量offset,offset = size * (page - 1),使用下述sql完成分页的查找
select * from question limit #{offset},#{size};
# (二)把需要展示的数据封装起来 {#二-把需要展示的数据封装起来}
需要展示问题的时候,我们不仅需要展示问题本身,还需要用户的信息。question属性中包含一个createid属性,如果是单纯的数据库操作,只需要把两个表联合查询就行。在Spring项目中,通过创建一个DTO来实现,DTO用来处理一个同时需要处理多张表的情况。新建DTO文件夹,创建QuestionDto,在question的实体类基础上新增User属性:
public class Questiondto {
private int id;
private String title;
private String description;
private int createid;
private int comment_count;
private int view_count;
private int like_count;
private String tag;
private long createtime;
//增加一个user对象
private User user;
//省略getter and setter方法
}
因为还需要展示页面信息,于是再新建一个PageDto,包含questionDto属性和页面属性,比如当前页面,是否展示前一页,是否展示首页等等信息。对于page的处理逻辑,我打算最多显示七个页码:
当前页码是1时,显示1,2,3,4
当前页码是2时,显示1,2,3,4,5
。。。
当前页码是4时,显示1,2,3,4,5,6,7
PageDto中新增setPagination方法,处理页码展示逻辑
public class PageDto {
//问题内容
private List<Questiondto> questions;
//是否展示前一页
private boolean showPre;
//是否展示后一页
private boolean shownext;
//是否展示第一页
private boolean showfirst;
//是否展示最后一页
private boolean showlast;
//当前页码
private int page;
//当前展示的页码集合
private List<Integer> pages = new ArrayList<>();
//所有页数
private int totalpage;
public void setPagination(int totalcount, int page, int size) {
this.page = page;
if (totalcount % size == 0) {
totalpage = totalcount / size;
} else {
totalpage = totalcount / size + 1;
}
//page<1就显示1,page>最大页数就显示最大页数
if (page<1){
this.page=1;
}
if (page>totalpage){
this.page=totalpage;
}
//将需要展示的页码插入到pages中
pages.add(page);
for (int i = 1; i <= 3; i++) {
if (page - i > 0) {
pages.add(0, page - i);
}
if (page + i <= totalpage) {
pages.add(page + i);
}
}
//是否展示上一页
if (page == 1) {
showPre = false;
} else {
showPre = true;
}
//是否展示后一页
if (page == totalpage) {
shownext = false;
} else {
shownext = true;
}
//是否展示第一页
if (pages.contains(1)) {
showfirst = false;
} else {
showfirst = true;
}
//是否展示最后一页
if (pages.contains(totalpage)) {
showlast = false;
} else {
showlast = true;
}
}
//省略getter and setter方法
}
接下来要做的事情就是把问题(question)、用户信息(User)、页码(page)全部整合到一起返回给indexController,再由indexController把数据通过model传递给前端。
# (三)Service层处理数据整合业务 {#三-service层处理数据整合业务}
service层从名字上就能看出来是处理服务和业务的,数据的整合就放在service层进行处理。新建一个QuestionService,注意加上@Service标签:
@Service
public class QuestionService {
//注入QuestionMapper和UserMapper
@Resource
private QuestionMapper questionMapper;
@Resource
private UserMapper userMapper;
//将question、user、page整合后返回
public PageDto list(int page, int size) {
PageDto pageDto = new PageDto();
int totalcount = questionMapper.count();
pageDto.setPagination(totalcount,page,size);
//size*{page-1}
int offset = size * (page - 1);
//每页只展示5条
List<Question> questions = questionMapper.list(offset, size);
List<Questiondto> questiondtoList = new ArrayList<>();
for (Question question : questions) {
User user = userMapper.findById(question.getCreateid());
Questiondto questiondto = new Questiondto();
//把第一个对象的所有属性拷贝到第二个对象中
BeanUtils.copyProperties(question, questiondto);
questiondto.setUser(user);
questiondtoList.add(questiondto);
}
pageDto.setQuestions(questiondtoList);
return pageDto;
}
}
# (四)前端处理和展示 {#四-前端处理和展示}
只需要在indexController中加上下面两句代码:
PageDto pagination = questionService.list(page,size);
model.addAttribute("pagination", pagination);
就可以实现把返回过来的pagination对象传递给model,在html页面中,用Thymeleaf操作model数据,实现首页展示和分页功能,index.html代码请看下面的源码部分。