<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    分頁通用技術

    首先聲明以下是轉載的,感謝原作者

    通用分頁實現(xiàn)及其OO設計探討

    本來是打算拿到it168投稿的!!那邊的速度太慢了!先貼出來先!!

    分頁是一種常用的頁面數據顯示技術,分頁能夠通過減少頁面數據處理量從而提高了系統(tǒng)的性能。分頁應該是做WEB開發(fā)必須掌握的一個小技術。而分頁卻是復雜的,倒不是它的技術有多復雜;而是有太多的重復代碼,這些代碼都難以重用。能不能實現(xiàn)一個通用的分頁框架?每次只需要去覆寫一兩個方法,通過少量的代碼就能實現(xiàn)分頁的功能?

    一般分頁應該要具有的功能有
    1. 靈活的設置分頁大小。可以動態(tài)的設置分頁大小,而不是寫死到代碼中。
    2. 自動計算總頁數。根據分頁大小和總記錄數自動計算總頁數。
    3. 獲得當前頁的頁號。
    4. 獲得當前頁的總記錄數。一般是最后一頁的時候可能會小于分頁大小。
    5. 判斷當前頁是否為第一頁。
    6. 判斷當前頁是否為最后一頁。
    7. 判斷當前頁是否有上一頁。
    8. 判斷當前頁是否有下一頁。
    9. 獲得當前頁的數據列表。
    10. 獲得當前頁的第一條記錄的索引號
    11. 獲得當前頁的最后一條記錄的索引號。
    二、常用的分頁技術
    目前常用的分頁技術有兩種:
    1. 第一次訪問是讀取所有記錄,放入session中,然后每次從session對象中讀取當前頁的數據
    2. 每次都訪問數據庫,從數據庫中讀取當前頁的記錄。
    這兩種方法都各有優(yōu)缺點,當數據量比較少時,第一種方法無疑是要快一些,因為減少與數據庫的連接訪問。而當數據量比較大時,比如查詢結果可能會是上萬條,那么內存的開銷是十分大的,放到session中還有一個問題是能不能及時的清除無用的對象。而且這么大數據量在網絡中傳輸也會使系統(tǒng)變得很慢。
    第二種方法就是專門解決這個問題的,它每次訪問數據庫,只讀取當前頁所需的記錄,大大的減少網絡傳輸量;它不會把頁數據放到session中,大大提高服務器的性能。
    所以第二種方式要優(yōu)于第一種方法。Session不要亂用,要用也僅僅是存放一些公共變量,相對于占用空間比較少的對象。不適合存放大量的數據,否則在很多個用戶同時訪問時那么系統(tǒng)會很慢,因為服務器內存被銷耗的很厲害

    三、通用分頁框架需要解決的問題
    作為一個通用分頁框架,
    1. 應該不依賴于任何其它框架
    2. 應該支持多種數據庫
    3. 應該可以應用于任何web框架中,如:struts,spring等。
    4. 應該把數據訪問的具體實現(xiàn)留給用戶去實現(xiàn)。
    5. 應該實現(xiàn)關鍵的算法和過程,如:計算總頁數,所需的實始化動作。
    6. 應該減化Contrller控制器的代碼,以往的分頁技術在Contrller中存在太多的if…else代碼。十分難懂,應該由一個輔助類來實現(xiàn)。
    7. 應該減化jsp頁面的代碼,頁面應該沒有任何與分頁相關的計算。應該由分頁對象來實現(xiàn)。
    8. 應該支持兩種分頁方式,采用session或不采用session由用戶控制。

    四、具體實現(xiàn)
    1.通用分頁接口。定義接口可以有更多不同的實現(xiàn),接口只聲明了分頁應該具有的公共行為。
    ViewPage.java
    /**
    * 分頁接口
    * @author ex_yuanguangdong
    *
    */
    public interface ViewPage {



    /**
    * 獲取總頁數
    * @return 總頁數
    */
    public int getPageCount();


    /**
    * 獲得頁面大小
    * @return 頁面大小
    */
    public int getPageSize();


    /**
    * 設置頁面大小
    * @param size
    */
    public void setPageSize(int size);
    /**
    * 獲得當前頁數據
    * @return 數據列表
    */
    public List getPageData();


    /**
    * 獲得當前頁索引號
    * @return 當前頁索引號
    */
    public int getPageIndex();

    /**
    * 獲得當前頁記錄總數
    * @return 當前頁記錄總數
    */
    public int getPageRows();

    /**
    * 是否有下一頁
    * @return
    */
    public boolean getHashNextPage();


    /**
    * 是否有上一頁
    * @return
    */
    public boolean getHashPreviousPage();

    /**
    * 轉到尾頁
    *
    */
    public void gotoLastPage();
    /**
    * 轉到首頁
    *
    */
    public void gotoFirstPage();

    /**
    * 是否首頁
    * @return
    */
    public boolean isFirstPage();

    /**
    * 是否尾頁
    * @return
    */
    public boolean isLastPage();

    /**
    * 轉到上一頁
    *
    */
    public void gotoPreviousPage();

    /**
    * 轉到下一頁
    *
    */
    public void gotoNextPage();

    /**
    * 轉到指定頁面,pageIndex小于1時,轉到第一頁;pageIndex大于總頁數時,轉到最尾頁
    * @param pageIndex 指定的頁號
    */
    public void gotoPage(int pageIndex);

    /**
    * 獲取當前頁第一條記錄的記錄號
    * @return int 當前頁第一條記錄的記錄號
    */
    public int getPageFirstRecord();

    /**
    * 獲取當前頁最后一條記錄的記錄號
    * @return int 當前頁最后一條記錄的記錄號
    */
    public int getPageLastRecord();

    }

    2. 分頁抽像實現(xiàn)類,實現(xiàn)關鍵的算法
    AbstractViewPage.java
    /**
    * 分頁默認抽象實現(xiàn)
    * 初始時,分頁類有下列默認值:
    * 分頁大小為-1,為不分頁;
    * 總頁數為1頁
    * 當前頁為第一頁
    * 總記錄數為0條
    * 當前頁數據列表為沒有任何記錄的列表
    * @author ex_yuanguangdong
    *
    */
    public abstract class AbstractViewPage implements ViewPage {

    //-----------------------------------------
    //私有靜態(tài)常量
    //-----------------------------------------

    private static final int DEFAULT_PAGE_INDEX = 1;

    private static final int DEFALT_PAGE_COUNT = 1;

    private static final int DEFAULT_PAGE_SIZE = -1;

    private static final int DEFAULT_ROWS = 0;

    //-----------------------------------------
    //私有成員變量
    //-----------------------------------------

    /**當前頁索引號**/
    private int pageIndex = DEFAULT_PAGE_INDEX;
    /**總頁數**/
    private int pageCount =DEFALT_PAGE_COUNT;

    /**分頁大小**/
    private int pageSize = DEFAULT_PAGE_SIZE ;

    /**數據總記錄數**/
    private int rows = DEFAULT_ROWS;


    //------------------------------------------
    //本地成員變量getter,setter方法
    //------------------------------------------


    /**
    * 設置新頁號,只有大于等于1而且小于等于總頁數并且不為當前頁時,才允許設置
    * @param pageIndex The pageIndex to set.
    */
    private void setPageIndex(int newPageIndex) {

    if( newPageIndex >= this.DEFAULT_PAGE_INDEX && newPageIndex <= this.getPageCount() && newPageIndex != this.pageIndex) {
    this.pageIndex = newPageIndex;
    }

    }

    /**
    * @return Returns the rows.
    */
    private int getRows() {
    return rows;
    }

    /**
    * @param rows The rows to set.
    */
    private void setRows(int rows) {
    this.rows = rows;
    }
    /**
    * @param pageCount The pageCount to set.
    */
    private void setPageCount(int pageCount) {
    this.pageCount = pageCount;
    }



    //--------------------------------------
    //實現(xiàn)Page接口方法
    //--------------------------------------


    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageData()
    */
    public List getPageData() {
    List pageList =null;

    //獲得當前頁數據
    pageList = this.pageList(this.getPageFirstRecord(), this.getPageRows());
    //保證不返回null
    if(pageList == null) {
    pageList =new ArrayList();
    }
    return pageList;

    }

    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageIndex()
    */
    public int getPageIndex() {
    return this.pageIndex;
    }
    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#isFirstPage()
    */
    public boolean isFirstPage() {

    return this.DEFAULT_PAGE_INDEX ==this.pageIndex;
    }
    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#isLastPage()
    */
    public boolean isLastPage() {
    //當前頁索引為總頁數時為最后一頁
    return this.pageIndex == this.pageCount;
    }

    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getHashNextPage()
    */
    public boolean getHashNextPage() {
    //當前頁索引號小于總頁數
    return this.pageIndex < this.pageCount ;
    }

    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getHashPreviousPage()
    */
    public boolean getHashPreviousPage() {
    //當前頁索引號大于默認的初始頁號,這里為1
    return this.pageIndex > this.DEFAULT_PAGE_INDEX ;
    }



    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageCount()
    */
    public int getPageCount() {

    return this.pageCount;
    }



    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageSize()
    */
    public int getPageSize() {

    return this.pageSize;
    }

    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageRows()
    */
    public int getPageRows() {
    //當頁面大小為-1 時,返回總記錄數
    if(this.DEFAULT_PAGE_SIZE == this.pageSize ) {
    return this.rows;
    }

    //不為最后一頁時,返回pageSize
    if(!this.isLastPage()) {
    return this.pageSize;
    }
    //最后一頁時
    return this.rows - (this.pageSize * (this.pageCount -1));
    }



    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageFirstRecord()
    */
    public int getPageFirstRecord() {

    //頁大小為-1 時
    if(this.DEFAULT_PAGE_SIZE== this.pageSize ) {
    return 0;
    }
    return (this.pageIndex -1)* this.pageSize;
    }

    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#getPageLastRecord()
    */
    public int getPageLastRecord() {
    //頁大小為-1時,返回總記錄數
    if(this.DEFAULT_PAGE_SIZE == this.pageSize) {
    return this.rows;
    }
    return this.getPageFirstRecord() + this.getPageRows() ;
    }
    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#gotoFirstPage()
    */
    public void gotoFirstPage() {
    this.gotoPage(this.DEFAULT_PAGE_INDEX);

    }

    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#gotoLastPage()
    */
    public void gotoLastPage() {
    this.gotoPage(this.getPageCount());

    }

    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#gotoPreviousPage()
    */
    public void gotoPreviousPage() {
    this.gotoPage(this.getPageIndex() -1);

    }

    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#gotoNextPage()
    */
    public void gotoNextPage() {
    this.gotoPage(this.getPageIndex() + 1);

    }

    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#gotoPage(int)
    */
    public void gotoPage(int newPageIndex) {
    if( newPageIndex >= this.DEFAULT_PAGE_INDEX && newPageIndex <= this.getPageCount() ) {
    this.setPageIndex(newPageIndex);
    }

    }
    /**
    * @see com.palic.elis.pos.junit.counter.web.mvc.ViewPage#setPageSize(int)
    */
    public void setPageSize(int size) {
    if(size < 1) {
    size = 1;
    }

    this.pageSize = size;

    //進行初始化
    this.doInit();
    }

    //-----------------------------------
    //輔助方法
    //-----------------------------------


    /**
    * 分頁初始化方法,為了保證總是能正確的初始化,所以聲明為final ,為了讓子類可以調用聲明為protected
    *
    */
    protected final void doInit() {
    int rows = 0;

    //獲得總記錄數
    rows= totalRows();

    //設置總記錄數
    this.setRows(rows);
    //設置新的總頁數

    //計算并設置總頁數
    int pages = calculatePageCount();
    this.setPageCount(pages);

    //轉到第一頁
    this.gotoPage(this.DEFAULT_PAGE_INDEX);

    onInit();
    }
    /**
    * 記算總頁數
    * @return 總頁數
    */
    private int calculatePageCount() {

    //總記錄數為0條,則返回的總頁數為1
    if(this.getRows() == 0) {
    return this.DEFALT_PAGE_COUNT;
    }

    //如果頁面大小為-1,則返回的總頁數為1
    if(this.DEFAULT_PAGE_SIZE == this.getPageSize() ) {
    return this.DEFALT_PAGE_COUNT;
    }

    return this.getRows() / this.getPageSize() + ( this.getRows() % this.getPageSize() ==0 ? 0 :1);
    }


    /**
    * 獲得總記錄數,調用queryTotalRows(),將異常封裝為non-checked 異常
    * @return 總記錄數
    * @throws ApplicationRuntimeException
    */
    private int totalRows() throws ApplicationRuntimeException{
    try{
    return queryTotalRows();
    }
    catch(Exception ex){
    throw new ApplicationRuntimeException(ex);
    }
    }
    /**
    * 獲得當前頁數據,調用queryPageList()方法,將異常封裝為non-checked異常
    * @param startRow 開始記錄號
    * @param rowCount 記錄總數
    * @return 當前頁數據
    * @throws ApplicationRuntimeException
    */
    private List pageList(int startRow, int rowCount) throws ApplicationRuntimeException{
    try{
    return queryPageList(startRow, rowCount);
    }catch(Exception ex){
    throw new ApplicationRuntimeException(ex);
    }
    }


    //-----------------------------------------
    //子類實現(xiàn)的方法
    //-----------------------------------------

    /**
    * 初始化附加方法,由子類擴展
    */
    protected void onInit() {

    }


    /**
    * 查詢獲得總記錄數,由子類具體實現(xiàn)
    * @return 總記錄數
    * @throws Exception
    */
    protected abstract int queryTotalRows() throws Exception;

    /**
    * 查詢當前頁數據,從startRow 開始的rowCount條記錄
    * @param startRow 開始記錄號
    * @param rowCount 記錄總數
    * @return 當前頁數據
    * @throws Exception
    */
    protected abstract List queryPageList(int startRow, int rowCount) throws Exception;

    }

    3. 分頁輔助類
    ViewPageHelper.java/**
    * 分頁輔助類,用于減化Controller中的代碼
    * @author yuanguangdong
    * date: Oct 22, 2006
    */
    public class ViewPageHelper {
    private static final int FIRST_PAGE_VALUE = 1;

    private static final int PREVIOUS_PAGE_VALUE = 2;

    private static final int NEXT_PAGE_VALUE = 3;

    private static final int LAST_PAGE_VALUE = 4;

    private static final int SPECIAL_PAGE_VALUE = 5;

    public static final String FIRST_PAGE = "FIRST_PAGE";

    public static final String PREVIOUS_PAGE = "PREVIOUS_PAGE";

    public static final String NEXT_PAGE = "NEXT_PAGE";

    public static final String LAST_PAGE = "LAST_PAGE";

    public static final String SPECIAL_PAGE = "SPECIAL_PAGE";

    /**分頁動作參數名**/
    public static final String PAGE_ACTION = "page_action";

    /**分頁對象屬性名**/
    public static final String SESSION_PAGE = "session_page";

    /**頁號參數名**/
    public static final String PAGE_NO = "page_no";

    private static Map actionMap = new HashMap();
    static {
    actionMap.put(FIRST_PAGE, new Integer(FIRST_PAGE_VALUE));
    actionMap.put(PREVIOUS_PAGE, new Integer(PREVIOUS_PAGE_VALUE));
    actionMap.put(NEXT_PAGE, new Integer(NEXT_PAGE_VALUE));
    actionMap.put(LAST_PAGE, new Integer(LAST_PAGE_VALUE));
    actionMap.put(SPECIAL_PAGE, new Integer(SPECIAL_PAGE_VALUE));
    }
    /**
    * 執(zhí)行分頁動作
    * @param page 分頁對象
    * @param action 分頁動作參數
    * @param pageIndex 頁號
    */
    public static void doAction(ViewPage page, String action, int pageIndex) {
    int actionIndex = 0;
    if (page == null) {
    throw new NullPointerException("Page對象null");
    }
    if (action == null || "".equals(action)) {
    throw new IllegalArgumentException("無效的分頁動作參數null");
    }
    action = action.toUpperCase();
    if (!actionMap.containsKey(action)) {
    throw new UnsupportedOperationException("不支持的分頁動作參數:" + action);
    }
    Integer index = (Integer) actionMap.get(action);
    actionIndex = index.intValue();
    switch (actionIndex) {
    case FIRST_PAGE_VALUE:
    page.gotoFirstPage();
    break;
    case PREVIOUS_PAGE_VALUE:
    page.gotoPreviousPage();
    break;
    case NEXT_PAGE_VALUE:
    page.gotoNextPage();
    break;
    case LAST_PAGE_VALUE:
    page.gotoLastPage();
    break;
    case SPECIAL_PAGE_VALUE:
    page.gotoPage(pageIndex);
    }
    }

    public static void doAction(ViewPage page, String action){
    doAction(page, action, 1);
    }
    }

    五、應用通用分頁框架
    1.繼承AbstractViewPage類,實現(xiàn)queryPageList(int startRow, int endRow)和
    queryTotalRows()方法。

    protected int queryTotalRows() throws Exception
    獲得查詢條件的總記錄數

    protected List queryPageList(int startRow, int rowCount)
    用于查詢指定范圍的數據。startRow為開始記錄號, rowCount為查詢的記錄數

    queryPageList(0,20)為查詢從第一條開始的20條記錄。

    使用Ibatis可以由queryPageList調用queryForList()方法。

    /**
    * 用戶信息分頁內部類
    * @author yuanguangdong
    * date: Oct 22, 2006
    */
    class UserInfoPage extends AbstractViewPage{

    //------------------------------------------------
    //實現(xiàn)AbstractViewPage抽象類的抽象方法
    //------------------------------------------------

    /**
    * @see com.prs.application.ehld.web.mvc.AbstractViewPage#getPageDate(int, int)
    */
    protected List queryPageList(int startRow, int endRow) throws Exception {
    return sampleAction.getUserInfoList(startRow, endRow);
    }

    /**
    * @see com.prs.application.ehld.web.mvc.AbstractViewPage#getRows()
    */
    protected int queryTotalRows() throws Exception {
    return sampleAction.getUserCount();
    }

    }



    3. 在Contrller中的實現(xiàn)
    public ModelAndView listUser(HttpServletRequest request,
    HttpServletResponse response) throws Exception {
    String pageAction =
    RequestUtils.getStringParameter(request,ViewPageHelper.PAGE_ACTION);
    Integer pageIndex =
    RequestUtils.getIntParameter(request,ViewPageHelper.PAGE_NO);
    //聲明分頁對象
    ViewPage userPage =
    (ViewPage) request.getSession().getAttribute(ViewPageHelper.SESSION_PAGE);
    //第一次請求
    if(pageAction == null || userPage == null){
    //構建一個新的分頁對象
    userPage = new UserInfoPage();
    //設置分頁大小
    userPage.setPageSize(2);
    }else{

    if(ViewPageHelper.SPECIAL_PAGE.equals(pageAction)){
    //如果頁數為空,則默認為1
    if (pageIndex == null)
    pageIndex = new Integer(1);
    ViewPageHelper.doAction(userPage,pageAction,pageIndex.intValue());
    }else{
    ViewPageHelper.doAction(userPage,pageAction);
    }
    }

    //從分頁對象中獲得當前頁數據
    List userInfoList = userPage.getPageData();

    ModelAndView mav = new ModelAndView(userInfoListView);
    mav.addObject(this.userInfoListKey,userInfoList);
    request.getSession().setAttribute(ViewPageHelper.SESSION_PAGE,userPage);
    return mav;
    }

    4. jsp頁面實現(xiàn)

    <%@ page contentType="text/html;charset=utf-8" language="java" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
    <%@ taglib prefix="tiles" uri="http://jakarta.apache.org/struts/tags-tiles" %>
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
    <html>
    <head>
    <title>顯示所有員工</title>

    <SCRIPT language="javaScript">
    function pageNoChange(pageNo){
    location.href= "ehld.sample.getuserinfolist.do?page_action=SPECIAL_PAGE&page_no="+pageNo.value;

    }
    </SCRIPT>
    </head>

    <body>
    <table width="80%" border="0">
    <tr>
    <td bgcolor="#F0FEFF"><div align="left">  用戶列表</div></td>
    </tr>
    </table>
    <br>
    <input name="adduser" type="submit" id="adduser" value="新增用戶" onclick="location.href='ehld.sample.edituserinfo.do'">
    <table width="80%" border="0">
    <tr bgcolor="#58ED64">
    <th width="25%">id</th>
    <th width="34%">姓名</th>
    <th colspan="2">操作</th>
    </tr>
    <c:forEach items="${userInfoList}" var="userInfoDTO">
    <tr bgcolor="#D6EBF8">
    <td><c:out value="${userInfoDTO.userID}"/></td>
    <td><c:out value="${userInfoDTO.userName}"/></td>
    <td width="21%"><a href="ehld.sample.edituserinfo.do?id=<c:out value='${userInfoDTO.userID}'/>">編輯</a></td>
    <td width="20%"><a href="#">刪除</a></td>
    </tr>
    </c:forEach>
    </table>
    <c:if test="${session_page.firstPage}">
    首頁
    </c:if>
    <c:if test="${! session_page.firstPage}">
    <a href="ehld.sample.getuserinfolist.do?page_action=FIRST_PAGE">首頁</a>
    </c:if>
    <c:if test="${! session_page.hashPreviousPage}">
    上一頁
    </c:if>
    <c:if test="${session_page.hashPreviousPage}">
    <a href="ehld.sample.getuserinfolist.do?page_action=PREVIOUS_PAGE">上一頁</a>
    </c:if>

    <c:if test="${!session_page.hashNextPage}">
    下一頁
    </c:if>

    <c:if test="${session_page.hashNextPage}">
    <a href="ehld.sample.getuserinfolist.do?page_action=NEXT_PAGE">下一頁</a>
    </c:if>

    <c:if test="${session_page.lastPage}">
    尾頁
    </c:if>

    <c:if test="${!session_page.lastPage}">
    <a href="ehld.sample.getuserinfolist.do?page_action=LAST_PAGE">尾頁</a>
    </c:if>

    共有<c:out value="${session_page.pageCount}" />頁,第

    <select name = "pageNo" onChange = "java script:pageNoChange(this);">
    <c:forEach begin="1" end = "${session_page.pageCount}" var = "pageIndex">
    <option value="<c:out value='${pageIndex}'/>" <c:if test = "${pageIndex ==session_page.pageIndex }">selected</c:if>>
    <c:out value="${pageIndex}"/>
    </option>
    </c:forEach>
    </select>

    </body>
    </html>

    六、設計探討
    1.通過提供queryTotalRows() 和queryPageList(int startRow, int rowCount)方法,交由用戶具體的去實現(xiàn),所以能夠支持任何數據庫。
    對于Ibatis用戶可以使用queryForList()方法,對于用jdbc實現(xiàn)也可以有多種方法來支持各種數據庫。
    Ms sql 可以使用top 關鍵字,來獲得指定范圍的數據
    ORACEL可以使用rowid 偽列來獲得指定范圍的數據
    具體怎么去讀取數據,完全交由用戶控制
    2.分頁對象與具體的業(yè)務對象分離。分頁對象如果不能與具體的業(yè)務對象分離那么就不可能實現(xiàn)分頁對象的重用,不可以實現(xiàn)代碼的最大的重用。這不符合oo的按職責來設計對象的原則。
    3. ViewPageHelper幫助類的使用有兩個好處,統(tǒng)一為分頁代碼所需的字符參數進行定義,便于contrller和jsp頁面代碼的維護。第二便于代碼重用,減少在contrller中的if分支句語。如果不使用幫助類,則在每個controller中都會產生大量相同的代碼。
    4. final關鍵字的使用,protected final void doInit()用于分頁對象的實始化,它讀取并設置總記錄數,計算總頁數,默認為第一頁等。為什么不在構造函數中來做它呢?如果在構造函數來做它,子類就不可以擴展了。像這樣的初始化方法的位置應該由擴展類來靈活控制。聲明為protected是不讓它由外部對象來進行訪問,但是子類又可以進行調用。聲明為final是為了子類不能重寫它,如果子類重寫不當就會造成分頁對象的執(zhí)行邏輯錯誤。但是如果子類又想擴展它怎么辦?子類重寫protected void onInit()方法就可以了。這樣就能保證父類的邏輯,又能夠讓子類進行擴展。
    5.異常處理的思考,queryTotalRows()和queryPageList方法都是要求由子類實現(xiàn)的抽象類,這兩個類的特點都是可能會調用業(yè)務對象去實現(xiàn)相應的功能,業(yè)務對象可能會訪問業(yè)務數據庫等,可能會拋出任何Exception,但是分頁對象類去調用queryTotalRows()和queryPageList的方法是不應該對這些Exception進行任何處理的,如果進行try…catch那么就會隱藏了異常的細節(jié),這是十分可怕的。如果這些方法拋出異常,分頁對象應該是不能處理的,不能處理的異常應該封裝為運行時異常,所以就有了下面的實現(xiàn)
    private List pageList(int startRow, int rowCount) throws ApplicationRuntimeException{
    try{
    return queryPageList(startRow, rowCount);
    }catch(Exception ex){
    throw new ApplicationRuntimeException(ex);
    }
    }

    private int totalRows() throws ApplicationRuntimeException{
    try{
    return queryTotalRows();
    }
    catch(Exception ex){
    throw new ApplicationRuntimeException(ex);
    }
    }

    分頁對象內部調用pageList和totalRows方法,這樣就很好的解決了異常的問題,把異常交由外部調用者去決定是否處理,而不是強制調用者去處理。

    5. 模板方法模式的使用,這是一個典型的模板方法模式的運用。在父類實現(xiàn)關鍵的算法代碼,實現(xiàn)分頁對象的處理邏輯,而把某些會發(fā)生改變的方法交由子類去實現(xiàn),使得子類完全不用去關心父類的實現(xiàn)細節(jié),子類只需要重寫兩個簡單的方法就可以實現(xiàn)父類的功能。這就是模板方法帶來的最大好處。模板方法模式在各種開源框架中有著廣泛的運用,看看spring的源碼就知道。子類只需要去實現(xiàn)自己最關心的細節(jié),而父類實現(xiàn)那些不變的邏輯或算法。
    6. 針對接口編程,而不是針對類編程。接口可以實現(xiàn)多重繼承,而類卻不能。接口有比類獲得更多的好處,更利于擴展。比如說分頁接口,它可以讓用戶有更多不同的實現(xiàn),完全不依賴于任何類。只需要為它定制了共同的行為就可以了。在使用委托的時候接口比抽像類更好用。比如在裝飾模式的使用中,可能需要實現(xiàn)一個接口,而其中還要有一個本接口的引用。 如果是抽象類,則不可以實現(xiàn)。
    7. 通用框架應該具有靈活性,不應該依懶于任何具體的框架。如果通用框架依懶于某一技術細節(jié),某一框架,那么它就有一定的局限性。所以通用分頁不應該依懶于ibatis或hibernate 或spring的某一特點。更不應該依懶于sql或oralce某種數據庫。

    posted on 2007-09-17 16:41 劉錚 閱讀(258) 評論(0)  編輯  收藏 所屬分類: JAVA General

    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導航

    統(tǒng)計

    留言簿(1)

    文章分類(141)

    文章檔案(147)

    搜索

    最新評論

    主站蜘蛛池模板: 又粗又硬免费毛片| 国产91免费视频| 337p日本欧洲亚洲大胆人人| 亚洲高清一区二区三区电影| 亚洲丁香婷婷综合久久| 成年男女免费视频网站| 免费成人午夜视频| 免费国产a理论片| 国产精品久久久久久久久免费| 人人狠狠综合久久亚洲高清| 国产亚洲精品精华液| 亚洲日本国产精华液| 国产免费A∨在线播放| 中文字幕视频免费| 国产av无码专区亚洲国产精品| 亚洲电影在线免费观看| 免费夜色污私人影院网站| 久久青青草原亚洲av无码| 亚洲中文字幕无码av| 亚洲一级片免费看| 精品免费国产一区二区| 亚洲成A∨人片在线观看不卡| 亚洲大尺度无码无码专线一区| 国产国产人免费人成免费视频| 亚洲一区二区三区高清视频| 亚洲精品偷拍视频免费观看| 亚洲国产精品无码久久久秋霞2| 午夜视频在线免费观看| 久久亚洲精品无码播放| 日韩免费电影网址| 相泽亚洲一区中文字幕| 久99久精品免费视频热77| 亚洲色偷偷色噜噜狠狠99| 亚洲精品视频免费| 国产免费播放一区二区| 亚洲国产人成网站在线电影动漫| 一级特黄录像免费播放中文版| 亚洲AV日韩精品一区二区三区| 久久精品国产免费一区| 亚洲日韩精品无码一区二区三区 | 日韩成人在线免费视频|