以前用jsp和原生的JDBC实现过分页,现在一看,不仅代码冗余,而且可读性差,今天分享一种简洁的实现方式,我用起来是很方便的。
一.概述
主要思想就是建一个Page类,所有跟分页有关的参数都放在这个类里,这个类里放一个集合用来装返回的数据,前端用JSTL提供的标签进行展示。这里需要注意的是,Oracle与mysql不同,没有提供类似limit这样的函数,稍微麻烦一点,我们用rownum做分页。
我们举个例子,在数据库(Oracle)里有名为Game的一张表,字段有no,name,company,type,现在要做的是在前端用jsp展示,看代码
二.结构
1. model包中有两个类: AnyPage和Game类
public class AnyPage<T> {
private int currentPage; //画面接收到的当前页数。
private int dataCountOnePage = 5; //每页要显示的数据量。
private int indexRowNum; //当前页要显示的第一条记录的行号。
private int lastRowNum; //当前页要显示的最后一条记录的行号。
private int dataCount; //数据库记录总数
private int pageCount; //页码数
private List<T> games; //每页要显示的数据集合。
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public List<T> getGames() {
return games;
}
public void setGames(List<T> games) {
this.games = games;
}
public int getDataCount() {
return dataCount;
}
//根据数据库总数据量算出总页数
public void setDataCount(int dataCount) {
this.dataCount = dataCount;
pageCount = dataCount / dataCountOnePage;
if (dataCount % dataCountOnePage != 0) {
pageCount = pageCount + 1;
}
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public int getCurrentPage() {
return currentPage;
}
//根据当前的页数算出开始和结束的rownum
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
this.lastRowNum = currentPage * dataCountOnePage;
this.indexRowNum = this.lastRowNum - (dataCountOnePage - 1);
}
public int getDataCountOnePage() {
return dataCountOnePage;
}
public void setDataCountOnePage(int dataCountOnePage) {
this.dataCountOnePage = dataCountOnePage;
}
public int getIndexRowNum() {
return indexRowNum;
}
public void setIndexRowNum(int indexRowNum) {
this.indexRowNum = indexRowNum;
}
public int getLastRowNum() {
return lastRowNum;
}
public void setLastRowNum(int lastRowNum) {
this.lastRowNum = lastRowNum;
}
}
//Game类
public class Game {
//对应数据库的字段
private int no;
private String name;
private String company;
private String type;
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
在这里AnyPage采用泛型,也是一个小技巧。
2.mapper包:GameMapper的接口和XML配置文件
//mapper接口
public interface GameMapper {
//分页查询
List<Game> selectByPage(AnyPage anyPage);
//统计总数量
AnyPage selectDataCount();
}
//XML配置
<mapper namespace="com.easy.mapper.GameMapper">
<select id="selectByPage" parameterType="com.easy.model.AnyPage" resultType="com.easy.model.Game">
select no, name, company, type
from
(select rownum r, no, name, company, type
from game where no > #{no})
where r between #{indexRowNum} and #{lastRowNum}
</select>
<select id="selectDataCount" resultType="com.easy.model.AnyPage">
select count(no) dataCount from game
</select>
</mapper>
3.service包:GameService接口
//定义分页查询的接口
public interface GameService {
public AnyPage selectByPage(AnyPage anyPage);
}
**4.serviceImpl包**
//具体实现类,这里用的是spring整合
@Service
public class GameServiceImpl implements GameService{
@Autowired
GameMapper gameMapper;
@Override
public AnyPage selectByPage(AnyPage anyPage) {
//根据参数查询到分页后的game
List<Game> list = gameMapper.selectByPage(anyPage);
//查询总数量
AnyPage anyPage2 = gameMapper.selectDataCount();
anyPage2.setGames(list);
//以AnyPage的形式返回
return anyPage2;
}
}
5.Controller包
```
//这里使用的是SpringMVC作为控制器
public class GameController {
@Autowired
GameService gameService;
@RequestMapping("sp")
public String selectByPage(AnyPage anyPage, Map<String, Object> map) {
//在服务层将分页代码处理好
AnyPage anyPage2 = gameService.selectByPage(anyPage);
anyPage2.setCurrentPage(anyPage.getCurrentPage());
///以map作为数据模型
map.put("anyPage", anyPage2);
return "games";
}
}
6.前端:jsp
<h1>分页展示</h1>
<table border="1" cellspacing="0">
<tr>
<td>#</td>
<td>游戏名</td>
<td>公司</td>
<td>类型</td>
</tr>
<c:forEach items="${requestScope.anyPage.games}" var="game" varStatus="b1">
<tr>
<td>${b1.count}</td>
<td>${game.name }</td>
<td>${game.company }</td>
<td>${game.type }</td>
</tr>
</c:forEach>
</table>
<c:forEach begin="1" end="${requestScope.anyPage.pageCount }" var="page">
<c:if test="${not page eq requestScope.anyPage.currentPage }">
<a href="${pageContext.request.contextPath }/gc/sp?currentPage=${page}">
${page}
</a>
</c:if>
<c:if test="${not page eq requestScope.anyPage.currentPage }">
${page}
</c:if>
</c:forEach>
“`
这里面我截取了其中重要的部分,JSTL提供的标签真的很方便,省去了大量的java代码,可读性性也比较高,还有需要注意的是,最后ye页面编码角标的判断,循环判断的方式也是很好的想法。怎么样,很简单吧。