keyword:分页 缓存 eXtremeTable oscache
引子:这几天在弄一个关于页面的分页,查了一下网上的资料,大都不合要求,要么就是说怎么在数据库这个层面上如何实现,晕,有了hibernate我用那么费劲翻身么.看到一个用的比较多的方案是做了一个Page工具类,实现诸如getBooks(),getNextPage(),看了一下底层实现居然是"select * from book",吓死偶了,要是有1千万条记录那不是要吐血啊,这哪叫分页啊,这该叫杀人不见血啊. 一气之下在jbuilder下建了一个项目就叫Page :)
好了,言归正传,本文主要说的是关于在展示层一些常用的方案和实现,目录如下:
本分页实现概览:Struts + hibernate
PageBean负责两部分内容,一是要在页面显示的业务信息,是一个ArrayList;另一个是逻辑控制信息,诸如是否有下一页,上一页等等.
PageBean代码如下:
注意,我没有在PageBean里放具体的业务逻辑,诸如getBooks()等,目的很简单,具有通用性,业务逻辑由另一个业务类实现BookService,BookService获得的业务数据都放在了PageBean的ArrayList里.
BookService代码如下:
在Struts的Action中调用service,返回一个PageBean给展示页面
Action代码如下:
在本Action中判断了可能出现的三种情况:
好了,到了我们呼之欲出的展示页面了 :)
show.jsp代码如下
引子:这几天在弄一个关于页面的分页,查了一下网上的资料,大都不合要求,要么就是说怎么在数据库这个层面上如何实现,晕,有了hibernate我用那么费劲翻身么.看到一个用的比较多的方案是做了一个Page工具类,实现诸如getBooks(),getNextPage(),看了一下底层实现居然是"select * from book",吓死偶了,要是有1千万条记录那不是要吐血啊,这哪叫分页啊,这该叫杀人不见血啊. 一气之下在jbuilder下建了一个项目就叫Page :)
好了,言归正传,本文主要说的是关于在展示层一些常用的方案和实现,目录如下:
- 手工实现分页
- 用eXtremeTable标签实现自动分页
- 用oscache缓存jsp,提高性能
本分页实现概览:Struts + hibernate
PageBean负责两部分内容,一是要在页面显示的业务信息,是一个ArrayList;另一个是逻辑控制信息,诸如是否有下一页,上一页等等.
PageBean代码如下:
public
class
PageBean {
int currentPage = 1 ; // 当前页:Action控制
int totalPages = 0 ; // 总页数 :自己运算
int pageRecorders = 5 ; // 每页记录数,默认为5,可以在初始化的时候修改 // 总数据数
int pageStartRow = 0 ; // 每页的起始数
int pageEndRow = 0 ; // 每页显示数据的终止数
boolean hasNextPage = false ; // 是否有下一页:自己运算
boolean hasPreviousPage = false ; // 是否有前一页 :自己运算
List objList = new ArrayList(); // 存放欲展示的对象列表
int totalRows; // 总记录数,由底层service提供
// 是否有上一页
public boolean isHasPreviousPage() {
return (currentPage > 1 ? true : false );
}
// 共有多少页,service只提供有多少条记录,多少页数由PageBean自己运算
public int getTotalPages() {
return (totalRows / pageRecorders == 0 ? totalRows / pageRecorders:totalRows / pageRecorders + 1 );
}
public int getCurrentPage() {
return currentPage;
}
public int getPageEndRow() {
return pageEndRow;
}
// 是否有下一页
public boolean isHasNextPage() {
return (currentPage < this .getTotalPages() ? true : false );
}
public int getTotalRows() {
return totalRows;
}
public int getPageStartRow() {
return pageStartRow;
}
public int getPageRecorders() {
return pageRecorders;
}
public void setObjList(List objList) {
this .objList = objList;
}
public void setHasPreviousPage( boolean hasPreviousPage) {
this .hasPreviousPage = hasPreviousPage;
}
public void setTotalPages( int totalPages) {
this .totalPages = totalPages;
}
public void setCurrentPage( int currentPage) {
this .currentPage = currentPage;
}
public void setPageEndRow( int pageEndRow) {
this .pageEndRow = pageEndRow;
}
public void setHasNextPage( boolean hasNextPage) {
this .hasNextPage = hasNextPage;
}
public void setTotalRows( int totalRows) {
this .totalRows = totalRows;
}
public void setPageStartRow( int pageStartRow) {
this .pageStartRow = pageStartRow;
}
public void setPageRecorders( int pageRecorders) {
this .pageRecorders = pageRecorders;
}
public List getObjList() {
return objList;
}
public PageBean() {}
public void description() {
String description = " 共有数据数: " + this .getTotalRows() +
" 共有页数: " + this .getTotalPages() +
" 当前页数为: " + this .getCurrentPage() +
" 是否有前一页: " + this .isHasPreviousPage() +
" 是否有下一页: " + this .isHasNextPage() +
" 开始行数: " + this .getPageStartRow() +
" 终止行数: " + this .getPageEndRow();
System.out.println(description);
}
}
int currentPage = 1 ; // 当前页:Action控制
int totalPages = 0 ; // 总页数 :自己运算
int pageRecorders = 5 ; // 每页记录数,默认为5,可以在初始化的时候修改 // 总数据数
int pageStartRow = 0 ; // 每页的起始数
int pageEndRow = 0 ; // 每页显示数据的终止数
boolean hasNextPage = false ; // 是否有下一页:自己运算
boolean hasPreviousPage = false ; // 是否有前一页 :自己运算
List objList = new ArrayList(); // 存放欲展示的对象列表
int totalRows; // 总记录数,由底层service提供
// 是否有上一页
public boolean isHasPreviousPage() {
return (currentPage > 1 ? true : false );
}
// 共有多少页,service只提供有多少条记录,多少页数由PageBean自己运算
public int getTotalPages() {
return (totalRows / pageRecorders == 0 ? totalRows / pageRecorders:totalRows / pageRecorders + 1 );
}
public int getCurrentPage() {
return currentPage;
}
public int getPageEndRow() {
return pageEndRow;
}
// 是否有下一页
public boolean isHasNextPage() {
return (currentPage < this .getTotalPages() ? true : false );
}
public int getTotalRows() {
return totalRows;
}
public int getPageStartRow() {
return pageStartRow;
}
public int getPageRecorders() {
return pageRecorders;
}
public void setObjList(List objList) {
this .objList = objList;
}
public void setHasPreviousPage( boolean hasPreviousPage) {
this .hasPreviousPage = hasPreviousPage;
}
public void setTotalPages( int totalPages) {
this .totalPages = totalPages;
}
public void setCurrentPage( int currentPage) {
this .currentPage = currentPage;
}
public void setPageEndRow( int pageEndRow) {
this .pageEndRow = pageEndRow;
}
public void setHasNextPage( boolean hasNextPage) {
this .hasNextPage = hasNextPage;
}
public void setTotalRows( int totalRows) {
this .totalRows = totalRows;
}
public void setPageStartRow( int pageStartRow) {
this .pageStartRow = pageStartRow;
}
public void setPageRecorders( int pageRecorders) {
this .pageRecorders = pageRecorders;
}
public List getObjList() {
return objList;
}
public PageBean() {}
public void description() {
String description = " 共有数据数: " + this .getTotalRows() +
" 共有页数: " + this .getTotalPages() +
" 当前页数为: " + this .getCurrentPage() +
" 是否有前一页: " + this .isHasPreviousPage() +
" 是否有下一页: " + this .isHasNextPage() +
" 开始行数: " + this .getPageStartRow() +
" 终止行数: " + this .getPageEndRow();
System.out.println(description);
}
}
注意,我没有在PageBean里放具体的业务逻辑,诸如getBooks()等,目的很简单,具有通用性,业务逻辑由另一个业务类实现BookService,BookService获得的业务数据都放在了PageBean的ArrayList里.
BookService代码如下:
public
class
BookService {
private static Logger log = Logger.getLogger(BookService. class .getName());
public BookService() {
}
/**
* 获得book列表
* @param pageBean PageBean:返回的对象存在pageBean里
*/
public static void getBooks(PageBean pageBean) {
String infoSql = " from Book " ; // 获得业务信息
String countSql = " select count(*) from Book " ; // 获得控制信息
Session session = null ;
try {
session = DBUtil.currentSession();
Query query = session.createQuery(infoSql);
query.setFirstResult((pageBean.getCurrentPage() - 1 ) * pageBean.getPageRecorders()); // 起始页
query.setMaxResults(pageBean.getPageRecorders()); // 每页记录数
pageBean.getObjList().clear();
for (Iterator it = query.iterate(); it.hasNext(); ) {
Book po = (Book)it.next();
BookVo vo = new BookVo();
BeanUtils.copyProperties(vo,po);
pageBean.getObjList().add(vo);
}
session = DBUtil.currentSession();
query = session.createQuery(countSql);
int totalRecords = ((Integer)query.list().get( 0 )).intValue();
pageBean.setTotalRows(totalRecords);
}
catch (Exception e) {
e.printStackTrace();
System.out.println( " 数据库异常 " + e.toString());
}
finally {
try {
if ( null != session) {
session.close();
}
}
catch (HibernateException ex) {
ex.printStackTrace();
}
}
}
}
private static Logger log = Logger.getLogger(BookService. class .getName());
public BookService() {
}
/**
* 获得book列表
* @param pageBean PageBean:返回的对象存在pageBean里
*/
public static void getBooks(PageBean pageBean) {
String infoSql = " from Book " ; // 获得业务信息
String countSql = " select count(*) from Book " ; // 获得控制信息
Session session = null ;
try {
session = DBUtil.currentSession();
Query query = session.createQuery(infoSql);
query.setFirstResult((pageBean.getCurrentPage() - 1 ) * pageBean.getPageRecorders()); // 起始页
query.setMaxResults(pageBean.getPageRecorders()); // 每页记录数
pageBean.getObjList().clear();
for (Iterator it = query.iterate(); it.hasNext(); ) {
Book po = (Book)it.next();
BookVo vo = new BookVo();
BeanUtils.copyProperties(vo,po);
pageBean.getObjList().add(vo);
}
session = DBUtil.currentSession();
query = session.createQuery(countSql);
int totalRecords = ((Integer)query.list().get( 0 )).intValue();
pageBean.setTotalRows(totalRecords);
}
catch (Exception e) {
e.printStackTrace();
System.out.println( " 数据库异常 " + e.toString());
}
finally {
try {
if ( null != session) {
session.close();
}
}
catch (HibernateException ex) {
ex.printStackTrace();
}
}
}
}
在Struts的Action中调用service,返回一个PageBean给展示页面
Action代码如下:
1
public
class
PageListAction
extends
Action {
2
3 public PageListAction() {}
4
5 ArrayList arrayList = new ArrayList();
6
7 public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) throws Exception {
8 String action;
9 PageBean pageBean = null ;
10 action = request.getParameter( " action " );
11 if (action == null || action.equals( " null " )) { // 第一次读取数据
12 pageBean = new PageBean();
13 } else { // 用户选择上一页或者下一页
14 if (action == " nextPage " || action.equals( " nextPage " )) {
15 pageBean = (PageBean)request.getSession().getAttribute( " pageBean " );
16 pageBean.setCurrentPage(pageBean.getCurrentPage() + 1 );
17 } else if (action == " previousPage " || action.equals( " previousPage " )) {
18 pageBean = (PageBean)request.getSession().getAttribute( " pageBean " );
19 pageBean.setCurrentPage(pageBean.getCurrentPage() - 1 );
20 } else if (action == " targetPage " || action.equals( " targetPage " )){ // 指定页
21 pageBean = (PageBean)request.getSession().getAttribute( " pageBean " );
22 System.out.println( " targetPage= " + request.getParameter( " targetPage " ));
23 // 这里根据需要可以对填写的目标页进行判断,不要大于最大页数[此处省略]
24 pageBean.setCurrentPage(Integer.parseInt(request.getParameter( " targetPage " )));
25 }
26 }
27 if ( null == pageBean) throw new Exception( " 获得PageBean异常 " );
28 BookService service = new BookService();
29 service.getBooks(pageBean);
30 pageBean.description();
31 request.getSession().setAttribute( " pageBean " ,pageBean);
32 request.setAttribute( " result " ,pageBean.getObjList());
33 return (mapping.findForward( " success " ));
34 }
35 }
2
3 public PageListAction() {}
4
5 ArrayList arrayList = new ArrayList();
6
7 public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) throws Exception {
8 String action;
9 PageBean pageBean = null ;
10 action = request.getParameter( " action " );
11 if (action == null || action.equals( " null " )) { // 第一次读取数据
12 pageBean = new PageBean();
13 } else { // 用户选择上一页或者下一页
14 if (action == " nextPage " || action.equals( " nextPage " )) {
15 pageBean = (PageBean)request.getSession().getAttribute( " pageBean " );
16 pageBean.setCurrentPage(pageBean.getCurrentPage() + 1 );
17 } else if (action == " previousPage " || action.equals( " previousPage " )) {
18 pageBean = (PageBean)request.getSession().getAttribute( " pageBean " );
19 pageBean.setCurrentPage(pageBean.getCurrentPage() - 1 );
20 } else if (action == " targetPage " || action.equals( " targetPage " )){ // 指定页
21 pageBean = (PageBean)request.getSession().getAttribute( " pageBean " );
22 System.out.println( " targetPage= " + request.getParameter( " targetPage " ));
23 // 这里根据需要可以对填写的目标页进行判断,不要大于最大页数[此处省略]
24 pageBean.setCurrentPage(Integer.parseInt(request.getParameter( " targetPage " )));
25 }
26 }
27 if ( null == pageBean) throw new Exception( " 获得PageBean异常 " );
28 BookService service = new BookService();
29 service.getBooks(pageBean);
30 pageBean.description();
31 request.getSession().setAttribute( " pageBean " ,pageBean);
32 request.setAttribute( " result " ,pageBean.getObjList());
33 return (mapping.findForward( " success " ));
34 }
35 }
在本Action中判断了可能出现的三种情况:
- 用户选择了"上一页"
- 用户选择了"下一页"
- 用户手工输入了指定的某一页
好了,到了我们呼之欲出的展示页面了 :)
show.jsp代码如下
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ page contentType="text/html; charset=gb2312" language="java"%>
<html:html locale="true">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<script language="javaScript">
function go(){
try{
var targetValue = document.getElementById("targetPage").value;
parseInt(targetValue);
alert(targetValue);
}catch(e){
alert("请正确填写目标页");
return;
}
if(targetValue == null || targetValue == ''){
alert("请填写目标页");
return;
}
window.location = "//pageList.do?action=targetPage&targetPage="+targetValue;
}
</script>
</head>
<body>
<logic:present name="pageBean">
共有数据总数<bean:write name="pageBean" property="totalRows"/>;
共分<bean:write name="pageBean" property="totalPages"/>页,
当前是第<bean:write name="pageBean" property="currentPage"/>页
</logic:present>
<table border="1">
<tr><th>书名</th><th>作者</th><th>价格</th></tr>
<logic:present name="result">
<logic:iterate id="book" name="result">
<logic:present name="book">
<tr>
<td><bean:write name="book" property="name" /></td>
<td> <bean:write name="book" property="author" /></td>
<td><bean:write name="book" property="price" /></td>
/tr>
</logic:present>
</logic:iterate>
</logic:present>
</table>
<logic:present name="pageBean">
<logic:equal name="pageBean" property="hasNextPage" value="true">
<html:link page="/pageList.do?action=nextPage">nextPage</html:link>
</logic:equal>
<logic:equal name="pageBean" property="hasPreviousPage" value="true">
<html:link page="/pageList.do?action=previousPage">PreviousPage</html:link>
</logic:equal>
<input type="text" name
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ page contentType="text/html; charset=gb2312" language="java"%>
<html:html locale="true">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<script language="javaScript">
function go(){
try{
var targetValue = document.getElementById("targetPage").value;
parseInt(targetValue);
alert(targetValue);
}catch(e){
alert("请正确填写目标页");
return;
}
if(targetValue == null || targetValue == ''){
alert("请填写目标页");
return;
}
window.location = "//pageList.do?action=targetPage&targetPage="+targetValue;
}
</script>
</head>
<body>
<logic:present name="pageBean">
共有数据总数<bean:write name="pageBean" property="totalRows"/>;
共分<bean:write name="pageBean" property="totalPages"/>页,
当前是第<bean:write name="pageBean" property="currentPage"/>页
</logic:present>
<table border="1">
<tr><th>书名</th><th>作者</th><th>价格</th></tr>
<logic:present name="result">
<logic:iterate id="book" name="result">
<logic:present name="book">
<tr>
<td><bean:write name="book" property="name" /></td>
<td> <bean:write name="book" property="author" /></td>
<td><bean:write name="book" property="price" /></td>
/tr>
</logic:present>
</logic:iterate>
</logic:present>
</table>
<logic:present name="pageBean">
<logic:equal name="pageBean" property="hasNextPage" value="true">
<html:link page="/pageList.do?action=nextPage">nextPage</html:link>
</logic:equal>
<logic:equal name="pageBean" property="hasPreviousPage" value="true">
<html:link page="/pageList.do?action=previousPage">PreviousPage</html:link>
</logic:equal>
<input type="text" name