拜讀了 bibiye 的《一個高效簡潔的 Struts 分頁方法 ( 原創 ) 》后,根據 bibiye 的方法,自己修改了一下,也弄了一個 struts 下的分頁,大家見笑了!
我的方法是,根據用戶點擊導航條上的頁號 (offset) ,到 DB 中讀取該頁的數據 ( 不是一次全部讀出 ) ,點到哪頁讀哪頁的數據, JBX + tomcat + oracle 下測試通過,數據庫用的表是 oracle 的 emp 表。
******** 分頁類 Pager.java ,負責生成分頁導航條 ********
package page;
/**
?* 分頁代碼
?* <p>Title: 分頁 </p>
?* <p>Description: </p>
?* <p>Copyright: Copyright (c) 2005</p>
?* <p>Company: BCS</p>
?* @author Alex
?* @version 1.0
?*/
public class Pager {
? private int offset;
? private int size;
? private int length;
? private String url;
? private String pageHeader;
? public Pager(int offset, int size, int length, String url, String pageHeader) {
??? this.offset = offset;
??? this.size = size;
??? this.length = length;
??? this.url = url;
??? this.pageHeader = pageHeader;
? }
? /**
?? * 返回分頁導航條
?? * @param offset int 起始記錄的位置
?? * @param size int 總記錄數
?? * @param length int 步長
?? * @param url String .do 的 url
?? * @param pageHeader String 導航條的前綴文字提示
?? * @return String
?? */
? public String getPageNavigation() {
??? String pageNavigation = ""; // 最終返回的分頁導航條
??? // 記錄數超過一頁 , 需要分頁
??? if (size > length) {
????? String pref; // 前綴
????? if (url.indexOf("?") > -1) {
??????? // 如果 url 中已經包含了其他的參數 , 就把 offset 參數接在后面
??????? pref = "&";
????? }
????? else {
??????? // 如果 url 中沒有別的參數
??????? pref = "?";
????? }
????? // 如果導航條包含 header
????? if (pageHeader != null && pageHeader.length() > 0) {
??????? pageNavigation = pageHeader + " : ";
????? }
????? // 如果不是第一頁 , 導航條將包含“ << ” ( 第一頁 ) 和“ < ” ( 前一頁 )
????? if (offset > 0) {
??????? pageNavigation += "<a href='" + url + pref + "offset=0'>[<<]</a>\n" +
??????????? "<a href='" + url + pref + "offset=" + (offset - length) +
??????????? "'>[<]</a>\n";
????? }
????? // 導航條中 , 排頭的那一頁的 offset 值
????? int startOffset;
????? // 位于導航條中間的那一頁的 offset 值 ( 半徑 )
????? int radius = constants.MAX_PAGE_INDEX / 2 * length;
????? // 如果當前的 offset 值小于半徑
????? if (offset < radius || this.pageCount() <= constants.MAX_PAGE_INDEX) {
??????? // 那么第一頁排頭
??????? startOffset = 0;
????? }
????? else if (offset < size - radius) {
??????? startOffset = offset - radius;
????? }
????? else {
??????? startOffset = (size / length - constants.MAX_PAGE_INDEX) * length;
????? }
????? for (int i = startOffset;
?????????? i < size && i < startOffset + constants.MAX_PAGE_INDEX * length;
?????????? i += length) {
??????? if (i == offset) {
????????? // 當前頁號 , 加粗顯示
????????? pageNavigation += "<b>" + (i / length + 1) + "</b>\n";
??????? }
??????? else {
????????? // 其他頁號 , 包含超鏈接
????????? pageNavigation += "<a href='" + url + pref + "offset=" + i + "'>" +
????????????? (i / length + 1) + "</a>\n";
??????? }
? ????}
????? // 如果不是最后一頁 , 導航條將包含“ > ” ( 下一頁 ) 和“ >> ” ( 最后一頁 )
????? if (offset < size - length) {
??????? pageNavigation += "<a href='" + url + pref + "offset=" +
??????????? (offset + length) + "'>[>]</a>\n" +
??????????? "<a href='" + url + pref + "offset=" + lastPageOffset() +
??????????? "'>[>>]</a>\n";
????? }
//????? System.out.println("radius : " + radius);
//????? System.out.println("start offset : " + startOffset);
????? return pageNavigation;
??? }
??? // 記錄不超過一頁 , 不需要分頁
??? else {
????? return "";
??? }
? }
? /**
?? * 返回分頁后的總頁數
?? * @param size int 總記錄數
?? * @param length int 每頁的記錄數
?? * @return int
?? */
? public int pageCount() {
??? int pagecount = 0;
??? if (size % length == 0) {
????? pagecount = size / length;
??? }
??? else {
????? pagecount = size / length + 1;
??? }
??? return pagecount;
? }
? /**
?? * 返回最后一頁的記錄數
?? * @param size int 總記錄數
?? * @param length int 每頁的記錄數
?? * @return int
?? */
? public int lastPageSize() {
??? int lastpagesize = 0;
??? if (size % length == 0) {
????? lastpagesize = length;
??? }
??? else {
????? lastpagesize = size % length;
??? }
??? return lastpagesize;
? }
? /**
?? * 返回最后一頁的起始記錄位置
?? * @param size int 總記錄數
?? * @param length int 每頁的記錄數
?? * @return int
?? */
? public int lastPageOffset() {
??? return size - lastPageSize();
? }
? public int getOffset() {
??? return offset;
? }
? public void setOffset(int offset) {
??? this.offset = offset;
? }
? public int getSize() {
??? return size;
? }
? public void setSize(int size) {
??? this.size = size;
? }
? public int getLength() {
??? return length;
? }
? public void setLength(int length) {
??? this.length = length;
? }
? public String getUrl() {
??? return url;
? }
? public void setUrl(String url) {
??? this.url = url;
? }
? public String getPageHeader() {
??? return pageHeader;
? }
? public void setPageHeader(String pageHeader) {
??? this.pageHeader = pageHeader;
? }
}
******** 數據處理類 empDAO.java ,負責訪問 DB ,獲取當前頁面需要顯示的記錄 ********
package page;
import java.sql.*;
import java.util.*;
public class empDAO {
? public empDAO() {
? }
? /**
?? * 從 offset 位置起始 , 返回 length 條記錄
?? * @param offset int 起始的記錄位置
?? * @param length int 步長
?? * @param conn Connection 數據庫連接
?? * @return ArrayList
?? */
? public ArrayList findAllEmp(int offset, int length, Connection conn) throws
????? SQLException {
??? PreparedStatement ps = null;
??? ResultSet rs = null;
??? ArrayList emps = new ArrayList();
??? empVO empvo = null;
??? String strSql = "select empno, ename from emp where rowid not in (select rowid from emp where rownum <= ?) and rownum <= ?";
?? ?try {
????? ps = conn.prepareStatement(strSql);
????? ps.setInt(1, offset); // 起始記錄的位置
????? ps.setInt(2, length); // 步長
????? rs = ps.executeQuery();
????? while (rs != null && rs.next()) {
??????? empvo = new empVO();
??????? empvo.setEmpno(rs.getInt("empno"));
??????? empvo.setEname(rs.getString("ename"));
??????? emps.add(empvo);
????? }
??? }
??? catch (SQLException ex) {
????? ex.printStackTrace();
????? throw ex;
??? }
??? return emps;
? }
? /**
?? * 返回總的記錄數
?? * @param conn Connection
?? * @throws SQLException
?? * @return int
?? */
? public int getRsTotalCount(Connection conn) throws SQLException {
??? PreparedStatement ps = null;
??? ResultSet rs = null;
??? int rsCount = 0;
??? String strSql = "select count(empno) as empCount from emp";
??? try {
????? ps = conn.prepareStatement(strSql);
????? rs = ps.executeQuery();
????? if (rs != null && rs.next()) {
??????? rsCount = rs.getInt("empCount");
????? }
??? }
??? catch (SQLException ex) {
????? ex.printStackTrace();
????? throw ex;
??? }
??? return rsCount;
? }
}
******** 業務類 empBO.java ,調用 empDAO 類 ********
package page;
import java.util.*;
/**
?* BO 類
?* <p>Title: 分頁 </p>
?* <p>Description: </p>
?* <p>Copyright: Copyright (c) 2005</p>
?* <p>Company: BCS</p>
?* @author Alex
?* @version 1.0
?*/
public class empBO {
? private DBPool db = DBPool.newInstance();
? private empDAO empdao = new empDAO();
? public empBO() {
? }
? /**
?? * 從 offset 位置起始 , 返回 length 條記錄
?? * @param offset int 起始
?? * @param length int 步長
?? * @throws Exception
?? * @return ArrayList
?? */
? public ArrayList findAllEmp(int offset, int length) throws Exception {
??? ArrayList emps = new ArrayList();
??? try {
????? emps = empdao.findAllEmp(offset, length, db.getConnection());
??? }
??? catch (Exception ex) {
????? throw ex;
??? }
??? finally {
????? db.release();
??? }
??? return emps;
? }
? /**
?? * 返回總的記錄數
?? * @throws Exception
?? * @return int
?? */
? public int getRsTotalCount() throws Exception {
??? int rsCount = 0;
??? try {
????? rsCount = empdao.getRsTotalCount(db.getConnection());
??? }
??? catch (Exception ex) {
????? throw ex;
??? }
??? finally {
????? db.release();
??? }
??? return rsCount;
? }
}
********ActionForm 類 empForm.java********
package page;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class empForm
??? extends ActionForm {
? private int offset; // 起始記錄的位置 // 每頁顯示的記錄數
? public ActionErrors validate(ActionMapping actionMapping,
?????????????????????????????? HttpServletRequest httpServletRequest) {
??? /**@todo: finish this method, this is just the skeleton.*/
??? return null;
? }
? public void reset(ActionMapping actionMapping,
??????????????????? HttpServletRequest httpServletRequest) {
??? this.offset = 0; // 記錄默認從第一條開始顯示
? }
? public int getOffset() {
??? return offset;
? }
? public void setOffset(int offset) {
??? this.offset = offset;
? }
}
********Action 類 empAction.java ,控制器,調用 BO 類, Pager 類 ********
package page;
import java.util.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;
/**
?* 分頁測試的 Action
?* <p>Title: 分頁 </p>
?* <p>Description: </p>
?* <p>Copyright: Copyright (c) 2005</p>
?* <p>Company: BCS</p>
?* @author Alex
?* @version 1.0
?*/
public class empAction
??? extends Action {
? public ActionForward execute(ActionMapping actionMapping,
?????????????????????????????? ActionForm actionForm,
?????????????????????????????? HttpServletRequest httpServletRequest,
?????????????????????????????? HttpServletResponse httpServletResponse) {
??? empForm empform = (empForm) actionForm;
??? return performList(actionMapping, actionForm, httpServletRequest,
?????????????????????? httpServletResponse);
? }
? private ActionForward performList(ActionMapping actionMapping,
??????????????????????????????????? ActionForm actionForm,
??????????????????????????????????? HttpServletRequest request,
??????????????????????????????????? HttpServletResponse response) {
??? try {
????? empBO empbo = new empBO();
????? // 獲取外部傳進來的起始記錄號
????? int offset = ( (empForm) actionForm).getOffset();
????? // 獲取每頁的記錄數
????? int pagesize = constants.PAGE_SIZE;
????? // 獲取記錄集合 , 從 offset 開始 , 取 length 條記錄
????? ArrayList emps = empbo.findAllEmp(offset, pagesize);
????? // 計算所有記錄的條數 ( 總記錄數 )
????? int size = empbo.getRsTotalCount();
????? // 外部 url 地址 , 得到形如 : http://localhost:8088/bugMIS/showlist.do 的 String
????? String url = request.getContextPath() + actionMapping.getPath() + ".do";
????? // 實例化分頁類
????? Pager p = new Pager(offset, size, pagesize, url, "Page Navigation");
????? // 獲取分頁導航條
????? //String pageNavigation = p.getPageNavigation();
????? // 將 url 字符串和記錄集合 , 存入 request 中
????? request.setAttribute("pager", p);
????? request.setAttribute("emps", emps);
??? }
??? catch (Exception e) {
????? e.printStackTrace();
????? return actionMapping.findForward("failure");
??? }
??? return actionMapping.findForward("success");
? }
}
******** 數據庫連接池類 DBPool.java ,可以使用 tomcat 的連接池,也可以不用,這里關閉了 ********
package page;
import java.sql.*;
import javax.naming.*;
import javax.sql.*;
import org.apache.commons.logging.*;
/**
?* 系統連接池類
?* <p>Title: Gantoo@91.com</p>
?* <p>Description: </p>
?* <p>Copyright: Copyright (c) 2005</p>
?* <p>Company: BCS</p>
?* @author Alex
?* @version 1.0
?*/
public class DBPool {
? Log log = LogFactory.getLog("DBPool"); // 日志機
? private DBPool() {
? }
? private Connection conn = null;
? /* true: 使用連接池
???? false: 不使用連接池 , 采用 JDBC 直接連接 */
? private final static boolean USE_DB_POOL = false;
? private final static String jndi_DataSource = "jdbc/BugMIS_ora";
? private final static String jdbcdriver =
????? "oracle.jdbc.driver.OracleDriver";
? private final static String url =
????? "jdbc:oracle:thin:@localhost:1521:myo9";
? private final static String user = "scott";
? private final static String pass = "tiger";
? public static DBPool newInstance() {
??? return new DBPool();
? }
? /**
?? * 切換是否使用連接池
?? * */
? public Connection getConnection() {
??? if (USE_DB_POOL) {
????? conn = getConnectionByDBPool();
??? }
??? else {
????? conn = getConnectionDirect();
??? }
??? return conn;
? }
? /**
?? * 直接采用 JDBC 連接數據庫
?? * */
? private Connection getConnectionDirect() {
??? try {
????? Class.forName(jdbcdriver).newInstance();
????? conn = DriverManager.getConnection(url, user, pass);
??? }
??? catch (SQLException ex) {
????? log.error("Error Connection! " + ex.getMessage());
??? }
??? catch (ClassNotFoundException ex) {
????? log.error("Driver Not Found! " + ex.getMessage());
??? }
??? catch (IllegalAccessException ex) {
????? log.error(ex.getMessage());
??? }
??? catch (InstantiationException ex) {
????? log.error(ex.getMessage());
??? }
??? return conn;
? }
? /**
?? * 采用連接池
?? * */
? private Connection getConnectionByDBPool() {
??? try {
????? Context initCtx = new InitialContext();
????? Context ctx = (Context) initCtx.lookup("java:/comp/env");
????? DataSource ds = (DataSource) ctx.lookup(jndi_DataSource);
????? conn = ds.getConnection();
??? }
??? catch (NamingException ex) {
????? log.error("Data Source Not Found! " + ex.getMessage());
????? //System.out.println(" 未找到數據源 " + ex.getMessage());
??? }
??? catch (SQLException ex1) {
????? log.error("Error Connection! " + ex1.getMessage());
????? //System.out.println(" 錯誤的數據連接 " + ex1.getMessage());
??? }
??? return conn;
? }
? /**
?? * 釋放連接
?? * */
? public void release() {
??? try {
????? if (!conn.isClosed()) {
??????? conn.close();
????? }
??? }
??? catch (SQLException ex) {
????? log.error("Connection Closing Error! " + ex.getMessage());
????? //System.out.println(" 連接關閉失敗 " + ex.getMessage());
??? }
? }
}
******** 包含常量的類 constants.java ,常量 ********
package page;
/**
?* 定義工程中公用的常量
?* <p>Title: 分頁 </p>
?* <p>Description: </p>
?* <p>Copyright: Copyright (c) 2005</p>
?* <p>Company: BCS</p>
?* @author Alex
?* @version 1.0
?*/
public final class constants {
? public static final int MAX_PAGE_INDEX = 5; // 頁腳顯示多少頁
? public static final int PAGE_SIZE = 2; // 每頁的記錄數
}
******** 測試 jsp 頁面 index.jsp ,為了方便測試,嵌入了 java 代碼,能顯示就行 ********
<%@ 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=GBK" import="java.util.*,page.*"%>
<html:html>
<head>
<title></title>
<style type="text/css">
.pt9 {? font: 10pt " 宋體 "}
body { font: 10pt " 宋體 " ; margin: 15px}
td {? font-size: 10pt}
a:hover {? font-size: 10pt; color: red; text-decoration: underline}
a:link {? font-size: 10pt; color: blue; text-decoration: underline}
a:active {? font-size: 10pt; color: blue; text-decoration: underline}
a:visited { font-size: 10pt; color: blue; text-decoration: underline }
</style>
</head>
<body bgcolor="#ffffff">
<p><a href="Show">http://localhost:8088/page/showEmp.do?offset=0">Show Me All Of The Emps</a></p>
<logic:present name="emps">
? <%
? ArrayList emps = (ArrayList)request.getAttribute("emps");
? Iterator it = emps.iterator();
? empVO empvo;
? while(it!=null && it.hasNext()){
??? empvo = (empVO)it.next();
??? out.print(empvo.getEmpno() + "? ");
??? out.print(empvo.getEname() + "<br>");
? }
??? out.print(" 當前頁有 " + emps.size() + " 條記錄 <br>");
??? out.print("<p>");
? %>
</logic:present>
<logic:present name="pager">
? <%
? Pager pager = (Pager)request.getAttribute("pager");
? out.print(pager.getPageNavigation() + "<p>");
? out.print(" 共有記錄 " + pager.getSize() + " 條 <br>");
? out.print(" 每頁有 " + pager.getLength() + " 條記錄 <br>");
? out.print(" 共分 " + pager.pageCount() + " 頁 <br>");
? %>
</logic:present>
</body>
</html:html>
******** 配置文件 struts-config.xml********
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
? <form-beans>
??? <form-bean name="empForm" type="page.empForm" />
? </form-beans>
? <action-mappings>
??? <action input="/index.jsp" name="empForm" path="/showEmp" scope="request" type="page.empAction" validate="false">
????? <forward name="faiure" path="/index.jsp" />
????? <forward name="success" path="/index.jsp" />
??? </action>
? </action-mappings>
</struts-config>