Day08論壇3---分頁

  1. 實現主題列表的分頁:

步驟:default.properties(放到src目錄下)àConfiguration.java(放到cn.itcast.cfg包下)àPageBeanàActionàServicejavascript

default.properties:css

pageSize=10html

Configuration.java:java

package cn.itcast.cfg; spring

/** sql

* 管理配置信息(讀取配置文件)數據庫

* @author Tan 數組

* session

*/ app

public class Configuration {

 

    private static int pageSize = 10;

    

    static{

        //加載default.properties配置文件

        //...

    }

 

    public static int getPageSize() {

        return pageSize;

    }

    public static void setPageSize(int pageSize) {

        Configuration.pageSize = pageSize;

    }

}

  • PageBean.java:

package cn.itcast.oa.domain;

import java.util.List;

 

/**

* 分頁用的一頁的信息對象

* @author Tan

*

*/

public class PageBean {

    //傳遞的參數或配置的值

    private int currentPage;    //當前頁

    private int pageSize;    //每頁顯示的記錄數

    //詢數據庫

    private int recordCount;    //總記錄數

    private List recordList;    //本頁的數據列表

    //計算出來的

    private int pageCount;    //總頁數

    private int beginPageIndex;    //頁面列表的開始索引

    private int endPageIndex;    //頁面列表的結束索引

    

    /**

     * 只接受前四個屬性的值,會自動計算後四個屬性的值

     * @param currentPage

     * @param pageSize

     * @param recordCount

     * @param recordList

     */

    public PageBean(int currentPage, int pageSize, int recordCount, List recordList) {

        this.currentPage = currentPage;

        this.pageSize = pageSize;

        this.recordCount = recordCount;

        this.recordList = recordList;

        

        //計算pageCount總頁數

        pageCount = (recordCount + pageSize - 1)/ pageSize;

        

        //計算beginPageIndexendPageIndex

        //a.若是總頁數不超過十頁,就所有顯示

        if(pageCount <= 10){

            beginPageIndex = 1;

            endPageIndex = pageCount;

        //b.若是總頁數超過十頁,就顯示當前頁附近的共10個頁碼,(4+當前頁+5)

        }else{

            //就顯示當前頁附近的共10個頁碼,(4+當前頁+5)

            beginPageIndex = currentPage - 4;

            endPageIndex = currentPage + 5;

            

            //若是前面不足4個頁碼,就顯示前10

            if(beginPageIndex < 1){

                beginPageIndex = 1;

                endPageIndex = 10;

                

            //若是後面不足5個頁碼,就顯示後10

            }else if(endPageIndex > pageCount){

                endPageIndex = pageCount;

                beginPageIndex = pageCount - 10 + 1;    //注意:在顯示的時候是包含兩個邊界的

            }

        }

    }

(此處省略他們的get/set方法)

}

修改FroumAction:

@Controller

@Scope("prototype")

public class ForumAction extends BaseAction<Forum>{

 

    private int pageNum = 1;    //當前頁,默認爲第一頁

    

    /** 版塊列表 */

    public String list() throws Exception {

        List<Forum> forumList = forumService.findAll();

        ActionContext.getContext().put("forumList", forumList);

        return "list";

    }

    

    /** 顯示單個版塊(主題列表) */

    public String show() throws Exception {

        //準備數據:forum

        Forum forum = forumService.getById(model.getId());

        ActionContext.getContext().put("forum", forum);

        

        /*//準備數據:topicList

        List<Topic> topicList = topicService.findByForum(forum);

        ActionContext.getContext().put("topicList", topicList);*/

        

        //準備分頁的數據

        PageBean pageBean = topicService.getPageBeanByForum(pageNum, forum);

        ActionContext.getContext().getValueStack().push(pageBean);

        

        return "show";

    }    

    //------------

    public int getPageNum() {

        return pageNum;

    }

    

    public void setPageNum(int pageNum) {

        this.pageNum = pageNum;

    }

Tips:由於pageSize已經在配置文件中指出,而配置文件中的數據在哪都能被取出來,在業務層取出pageSize比較好,因此在action中只接收當前頁.

TopicServiceImpl:

@Service

@Transactional

@SuppressWarnings("unchecked")

public class TopicServiceImpl extends DaoSupportImpl<Topic> implements TopicService{

 

    /**

     * 查詢指定版塊的主題列表,最新狀態的排到前面,置頂帖排到最前面

     */

    public List<Topic> findByForum(Forum forum) {

        return getSession().createQuery(//

                "from Topic t where t.forum = ? order by (case t.type when 2 then 2 else 0 end) desc, t.lastUpdateTime desc")//

                .setParameter(0, forum)//

                .list();

    }

    

    /**

     * 重寫save()

     */

    public void save(Topic topic) {

        //設置屬性並保存

        topic.setType(topic.TYPE_NORMAL);    //普通帖

        topic.setReplyCount(0);

        topic.setLastReply(null);

        topic.setPostTime(new Date());    //當前時間

        topic.setLastUpdateTime(topic.getPostTime());    //默認爲主題的發表時間

        

        getSession().save(topic);

            

        //更新相關信息

        Forum forum = topic.getForum();    

        forum.setTopicCount(forum.getTopicCount()+1);    //主題數量

        forum.setArticleCount(forum.getArticleCount()+1);    //回覆數量(主題+回覆)

        forum.setLastTopic(topic);    //最後發表主題

        

        getSession().update(forum);

    }

 

    /**

     * 查詢分頁的主題列表數據

     */

    public PageBean getPageBeanByForum(int pageNum, Forum forum) {

        //獲取pageSize信息

        int pageSize = Configuration.getPageSize();

        

        //查詢一頁的數據信息

        List list = getSession().createQuery(//

                "from Topic t where t.forum = ? order by (case t.type when 2 then 2 else 0 end) desc, t.lastUpdateTime desc")//

                .setParameter(0, forum)//

                .setFirstResult((pageNum - 1) * pageSize) //(當前頁pageNum - 1) * 每頁顯示的條數pageSize 意思是:從數據庫中的第幾條記錄開始查詢,下標是從0開始的,因此要先-1

                .setMaxResults(pageSize) //每頁顯示的條數,即查詢數據庫中的多少條記錄

                .list();

        

        //查詢總記錄數

        Long count = (Long)getSession().createQuery(//

                "select count(*) from Topic t where t.forum=?")//

                .setParameter(0, forum)//

                .uniqueResult();

        

        return new PageBean(pageNum, pageSize, count.intValue(), list);

    }

ForumAction對應的show.jsp:

……

<!-- 標題顯示 -->

<div id="Title_bar">

<div id="Title_bar_Head">

<div id="Title_Head"></div>

<div id="Title"><!--頁面標題-->

<img border="0" width="13" height="13" src="${pageContext.request.contextPath}/style/images/title_arrow.gif"/>${forum.name }】中的主題列表

</div>

<div id="Title_End"></div>

</div>

</div>

 

<div id="MainArea">

    <div id="PageHead"></div>

    <center>

        <div class="ItemBlock_Title1" style="width: 98%;">

            <font class="MenuPoint"> &gt; </font>

            <s:a action="forum_list">論壇</s:a>

            <font class="MenuPoint"> &gt; </font>

            ${forum.name }

            <span style="margin-left:30px;"><s:a action="topic_addUI?forumId=%{#forum.id }">

                <img align="absmiddle" src="${pageContext.request.contextPath}/style/blue/images/button/publishNewTopic.png"/></s:a>

            </span>

        </div>

        

        <div class="ForumPageTableBorder">

            <table width="100%" border="0" cellspacing="0" cellpadding="0">

                <!--表頭-->

                <tr align="center" valign="middle">

                    <td width="3" class="ForumPageTableTitleLeft">

                        <img border="0" width="1" height="1" src="${pageContext.request.contextPath}/style/images/blank.gif" />

                    </td>

                    <td width="50" class="ForumPageTableTitle"><!--狀態/圖標-->&nbsp;</td>

                    <td class="ForumPageTableTitle">主題</td>

                    <td width="130" class="ForumPageTableTitle">做者</td>

                    <td width="100" class="ForumPageTableTitle">回覆數</td>

                    <td width="130" class="ForumPageTableTitle">最後回覆</td>

                    <td width="3" class="ForumPageTableTitleRight">

                        <img border="0" width="1" height="1" src="${pageContext.request.contextPath}/style/images/blank.gif" />

                    </td>

                </tr>

                <tr height="1" class="ForumPageTableTitleLine"><td colspan="8"></td></tr>

                <tr height=3><td colspan=8></td></tr>

                    

                <!--主題列表-->

                <tbody class="dataContainer" datakey="topicList">

                <s:iterator value="recordList">

                    <tr height="35" id="d0" class="template">

                        <td></td>

                        <td class="ForumTopicPageDataLine" align="center"><img src="${pageContext.request.contextPath}/style/images/topicType_${type}.gif" /></td>

                        <td class="Topic"><s:a cssClass="Default" action="topic_show?id=%{id}">${title}</s:a></td>

                        <td class="ForumTopicPageDataLine">

                            <ul class="ForumPageTopicUl">

                                <li class="Author">${author.name}</li>

                                <li class="CreateTime"><s:date name="postTime" format="yyyyMMdd HH:mm:ss"/> </li>

                            </ul>

                        </td>

                        <td class="ForumTopicPageDataLine Reply" align="center"><b>${replyCount}</b></td>

                        <td class="ForumTopicPageDataLine">

                            <ul class="ForumPageTopicUl">

                                <li class="Author">${lastReply.author.name }</li>

                                <li class="CreateTime"><s:date name="lastReply.postTime" format="yyyyMMdd HH:mm:ss"/></li>

                            </ul>

                        </td>

                        <td></td>

                    </tr>

                </s:iterator>

                </tbody>

                    <!--主題列表結束-->    

                        

                    <tr height="3"><td colspan="9"></td></tr>

                

            </table>

            ……

        </div>

    </center>

</div>

 

<!--分頁信息-->

<div id=PageSelectorBar>

    <div id=PageSelectorMemo><!-- 由於actionpageBean push進了棧頂,因此前面不用加pageBean. -->

        頁次:${currentPage}/${pageCount} &nbsp;

        每頁顯示:${pageSize} &nbsp;

        總記錄數:${recordCount}

    </div>

    <div id=PageSelectorSelectorArea>

        <a href="javascript: gotoPage(1)" title="首頁" style="cursor: hand;">

            <img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/firstPage.png"/></a>

        

        <!-- 頁碼列表 --><!--%{beginPageIndex}這是ognl表達式,pageBean在棧頂, var="num",numvar放到了map,因此取出num要加# -->

        <s:iterator begin="%{beginPageIndex}" end="%{endPageIndex}" var="num">

            <s:if test="#num != currentPage"><!-- 非當前頁,有連接 -->

                <span class="PageSelectorNum" style="cursor: hand;" onClick="gotoPage(${num});">${num }</span>

            </s:if>

            <s:else><!-- 當前頁,沒有連接 -->

                <span class="PageSelectorNum PageSelectorSelected">${num }</span>

            </s:else>

        </s:iterator>

        

        <a href="javascript: gotoPage(${pageCount})" title="尾頁" style="cursor: hand;">

            <img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/lastPage.png"/></a>

        

        轉到:

        <select id="pn" onchange="gotoPage(this.value)">

            <s:iterator begin="1" end="%{pageCount}" var="num">

                <option value="${num }">${num }</option>

            </s:iterator>

        </select>

        

        <!-- select默認選中當前頁 -->

        <script type="text/javascript">

            $("#pn").val("${currentPage}");            

        </script>

 

        <script type="text/javascript">

            <!-- 轉到指定的頁碼 -->

            function gotoPage(pageNum){

                window.location.href = "forum_show.do?id=${id}&pageNum="+pageNum;

<!—-這裏將當前頁pageNum傳給了Action,action中用屬性驅動的方式接收-->

            }

        </script>

    </div>

</div>

…….

%{}這是OGNL表達式,${}這是EL表達式.傻傻分不清…

難道說,在配合s:iterator,s:select等struts2標籤使用的時候,一般用%{},普通標籤就用${}??????????

頁面效果:

轉到:如下拉選的形式展現全部頁碼,點擊頁碼,頁面就會立刻跳轉到相應頁碼.

  1. 實現回覆列表的分頁:

順序依舊是:pageBeanèActionèserviceèjsp

這裏先把重複代碼抽取出來(暫時先抽取action中的少許代碼和jsp中的分頁代碼,service中的代碼後面再抽取)

將以前寫在ForumAction中的pageNum和其get,set方法抽取到BaseAction中:

    //-----------對分頁的支持----------------

    protected int pageNum = 1;    //當前頁,默認爲第一頁

    public int getPageNum() {

        return pageNum;

    }

    

    public void setPageNum(int pageNum) {

        this.pageNum = pageNum;

    }

再將jsp中的分頁代碼抽取到新建到public文件夾中新建的pageView.jspf:

<%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding="UTF-8"%>

<%@taglib prefix="s" uri="/struts-tags" %>

<!--分頁信息-->

<div id=PageSelectorBar>

    <div id=PageSelectorMemo>

        頁次:${currentPage}/${pageCount} &nbsp;

        每頁顯示:${pageSize} &nbsp;

        總記錄數:${recordCount}

    </div>

    <div id=PageSelectorSelectorArea>

        <a href="javascript: gotoPage(1)" title="首頁" style="cursor: hand;">

            <img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/firstPage.png"/></a>

        

        <!-- 頁碼列表 -->

        <s:iterator begin="%{beginPageIndex}" end="%{endPageIndex}" var="num">

            <s:if test="#num != currentPage"><!-- 非當前頁,有連接 -->

                <span class="PageSelectorNum" style="cursor: hand;" onClick="gotoPage(${num});">${num }</span>

            </s:if>

            <s:else><!-- 當前頁,沒有連接 -->

                <span class="PageSelectorNum PageSelectorSelected">${num }</span>

            </s:else>

        </s:iterator>

        

        <a href="javascript: gotoPage(${pageCount})" title="尾頁" style="cursor: hand;">

            <img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/lastPage.png"/></a>

        

        轉到:

        <select id="pn" onchange="gotoPage(this.value)">

            <s:iterator begin="1" end="%{pageCount}" var="num">

                <option value="${num }">${num }</option>

            </s:iterator>

        </select>

        

        <!-- select默認選中當前頁 -->

        <script type="text/javascript">

            $("#pn").val("${currentPage}");            

        </script>

 

        <!-- <script type="text/javascript">

            <!-- 轉到指定的頁碼 -->

            <%-- function gotoPage(pageNum){

                window.location.href = "forum_show.do?id=${id}&pageNum="+pageNum;

            }

         </script> --%>

    </div>

</div>

其中,最後一段代碼由於不一樣頁面要傳遞的id值也不一樣,因此不能做爲公共代碼.

TopicAction:

@Controller

@Scope("prototype")

public class TopicAction extends BaseAction<Topic>{

 

    private Long forumId;

    

    /** 顯示單個主題 */

    public String show() throws Exception {

        //準備數據:topic

        Topic topic = topicService.getById(model.getId());

        ActionContext.getContext().put("topic", topic);

        

        /*//準備數據:replyList

        List<Reply> replyList = replyService.findByTopic(topic);

        ActionContext.getContext().put("replyList", replyList);*/

        

        //準備數據

        PageBean pageBean = replyService.getPageBeanByTopic(pageNum, topic);

        ActionContext.getContext().getValueStack().push(pageBean);

        

        return "show";

    }

    

    /** 發新帖頁面*/

    public String addUI() throws Exception {

        //準備數據:forum

        Forum forum = forumService.getById(forumId);

        ActionContext.getContext().put("forum", forum);

        return "addUI";

    }

    

    /** 發新帖 */

    public String add() throws Exception {

        //封裝對象

        Topic topic = new Topic();

        //須要在action中封裝的數據:

        //>>a.表單中的參數

        topic.setTitle(model.getTitle());

        topic.setContent(model.getContent());

        topic.setForum(forumService.getById(forumId));

        //>>b.在顯示層才能得到的數據

        topic.setAuthor(getCurrentUser());    //當前登陸的用戶

        topic.setIpAddr(getRequestIp());    //客戶端的IP地址

        

        //調用業務方法

        topicService.save(topic);

        

        ActionContext.getContext().put("topicId", topic.getId());

        return "toShow";    //轉到當前這個新主題的頁面

    }

 

    //-----------------------------------

    public Long getForumId() {

        return forumId;

    }

 

    public void setForumId(Long forumId) {

        this.forumId = forumId;

    }

}

ReplyServiceImpl:

@Service

@Transactional

public class ReplyServiceImpl extends DaoSupportImpl<Reply> implements ReplyService{

 

    /**

     * 重寫save(),處理特殊屬性

     */

    public void save(Reply reply) {

        reply.setPostTime(new Date());    //發表時間爲當前時間

        reply.setDeleted(false);    //默認爲未刪除

        

        getSession().save(reply);

        //處理Forum和Topic中的特殊屬性

        Topic topic = reply.getTopic();

        Forum forum = topic.getForum();

        

        forum.setArticleCount(forum.getArticleCount()+1);    //版塊的文章數量(主題+回覆)

        

        topic.setReplyCount(topic.getReplyCount()+1);    //主題回覆數量

        topic.setLastReply(reply);    //主題的最後回覆

        topic.setLastUpdateTime(reply.getPostTime());    //主題的最後更新時間 默認爲最後回覆時間

        

        getSession().update(forum);

        getSession().update(topic);

    }

    

    /**

     * 查詢指定主題的回覆,最新回覆排到最後

     */

    public List<Reply> findByTopic(Topic topic) {

        return getSession().createQuery(//

                "from Reply r where r.topic = ? order by r.postTime")//

                .setParameter(0, topic)//

                .list();

    }

 

    /**

     * 分頁查詢指定主題的回覆,最新回覆排到最後

     */

    public PageBean getPageBeanByTopic(int pageNum, Topic topic) {

        //獲取pageSize信息

        int pageSize = Configuration.getPageSize();

        

        //查詢一頁的數據信息

        List list = getSession().createQuery(//

                "from Reply r where r.topic=? order by r.postTime desc")//

                .setParameter(0, topic)//

                .setFirstResult((pageNum - 1) * pageSize)//

                .setMaxResults(pageSize)//

                .list();

        

        //查詢總記錄數

        Long count = (Long) getSession().createQuery(//

                "select count(*) from Reply r where r.topic=?")//

                .setParameter(0, topic)//

                .uniqueResult();

        

        

        return new PageBean(pageNum, pageSize, count.intValue(), list);

    }    

}

TopicAction對應的show.jsp:

……

                <!-- ~~~~~~~~~~~~~~~ 顯示主帖 ~~~~~~~~~~~~~~~ -->

                <s:if test="currentPage == 1"><!—不寫這個判斷語句的話,不管跳到哪一頁,最上面的位置都會顯示主貼信息-->

                <div class="ListArea">

                    <table border="0" cellpadding="0" cellspacing="1" width="100%">

                        <tr>

                            <td rowspan="3" width="130" class="PhotoArea" align="center"

                                valign="top">

                                <!--做者頭像-->

                                <div class="AuthorPhoto">

                                    <img border="0" width="110" height="110"

                                        src="${pageContext.request.contextPath}/style/images/defaultAvatar.gif"

                                        onerror="this.onerror=null; this.src='${pageContext.request.contextPath}/style/images/defaultAvatar.gif';" />

                                </div> <!--做者名稱-->

                                <div class="AuthorName">${topic.author.name }</div>

                            </td>

                            <td align="center">

                                <ul class="TopicFunc">

                                    <!--操做列表-->

                                    <li class="TopicFuncLi"><a class="detail"

                                        href="${pageContext.request.contextPath}/BBS_Topic/saveUI.html"><img

                                            border="0"

                                            src="${pageContext.request.contextPath}/style/images/edit.gif" />編輯</a>

                                        <a class="detail" href="#"

                                        onClick="return confirm('肯定要刪除本帖嗎?')"><img border="0"

                                            src="${pageContext.request.contextPath}/style/images/delete.gif" />刪除</a>

                                    </li>

                                    <!-- 文章標題 -->

                                    <li class="TopicSubject"><s:property value="#topic.title"

                                            escape="true" /></li>

                                </ul>

                            </td>

                        </tr>

                        <tr>

                            <!-- 文章內容 -->

                            <td valign="top" align="center">

                                <div class="Content">${topic.content }</div>

                            </td>

                        </tr>

                        <tr>

                            <!--顯示樓層等信息-->

                            <td class="Footer" height="28" align="center" valign="bottom">

                                <ul style="margin: 0px; width: 98%;">

                                    <li style="float: left; line-height: 18px;"><font

                                        color=#C30000>[樓主]</font> <s:date name="#topic.postTime"

                                            format="yyyy-MM-dd HH:mm:ss" /></li>

                                    <li style="float: right;"><a href="javascript:scroll(0,0)">

                                            <img border="0"

                                            src="${pageContext.request.contextPath}/style/images/top.gif" />

                                    </a></li>

                                </ul>

                            </td>

                        </tr>

                    </table>

                </div>

                </s:if>

                <!-- ~~~~~~~~~~~~~~~ 顯示主帖結束 ~~~~~~~~~~~~~~~ -->

 

 

                <!-- ~~~~~~~~~~~~~~~ 顯示回覆列表 ~~~~~~~~~~~~~~~ -->

                <s:iterator value="recordList" status="status">

……

                                <!--顯示樓層等信息-->

                                <td class="Footer" height="28" align="center" valign="bottom">

                                    <ul style="margin: 0px; width: 98%;">

                                        <li style="float: left; line-height: 18px;"><font

                                            color=#C30000>[${(currentPage - 1) * pageSize + status.count}]</font> <s:date

……

                </s:iterator>

                <!-- ~~~~~~~~~~~~~~~ 顯示回覆列表結束 ~~~~~~~~~~~~~~~ -->

            </div>

 

            <%@include file="/WEB-INF/jsp/public/pageView.jspf" %>

            <script type="text/javascript">

                function gotoPage(pageNum){

                    window.location.href("topic_show.do?id=${id}&pageNum="+pageNum);

                }

 

            </script>

……

完善Configuration.java(其做用是讀取配置文件):

package cn.itcast.cfg;

import java.io.IOException;

import java.io.InputStream;

import java.util.Properties;

/**

* 管理配置信息(讀取配置文件)

* @author Tan

*

*/

public class Configuration {

    private static int pageSize = 10;

    

    static{

 

        InputStream in = null;

 

        try {

 

        //加載default.properties配置文件

        Properties props = new Properties();

        in = Configuration.class.getClassLoader().getResourceAsStream("default.properties");

        props.load(in);

 

        //獲取配置的值

        pageSize = Integer.parseInt(props.getProperty("pageSize"));

 

        } catch (Exception e) {

            throw new RuntimeException(e);

        }finally{

            if(in != null){

                try {

                    in.close();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        }

        

    }

 

    public static int getPageSize() {

        return pageSize;

    }

    public static void setPageSize(int pageSize) {

        Configuration.pageSize = pageSize;

    }    

}

測試是否能拿到pageSize.方法:

鼠標對着(左側包下的)Configuration.java右鍵,Newà

Nextà

Nextà

Finish後,得出一個在test包下的ConfigurationTest.java文件:

package cn.itcast.oa.test;

import static org.junit.Assert.*;

import org.junit.Test;

public class ConfigurationTest {

    @Test

    public void testGetPageSize() {

        fail("Not yet implemented");

    }

改爲這樣:

package cn.itcast.oa.test;

import org.junit.Test;

import cn.itcast.cfg.Configuration;

public class ConfigurationTest {

    @Test

    public void testGetPageSize() {

        int pageSize = Configuration.getPageSize();

        System.out.println("pageSize = "+pageSize);

    }

}

  1. 抽取Service:

由於TopicServiceImpl和ReplyServiceImpl中有不少共同的分頁代碼,因此將他們抽取到DaoSupportImpl中.

DaoSupport:

    /**

     * 公共的查詢分頁信息的方法

     * @param pageNum

     * @param hql    查詢數據列表的hql語句    在方法內部會自動生成查詢總數量的hql語句

     * @param args

     * @return

     */

    PageBean getPageBean(int pageNum, String hql, Object[] args);

在TopicService和ReplyService的分頁方法上加上@Deprecated,表明此方法已過期.

DaoSupportImpl:

    /**

     * 公共的查詢分頁信息的方法

     */

    public PageBean getPageBean(int pageNum, String hql, Object[] args) {

        System.out.println("------------------->DaoSupportImpl.getPageBean()");

        

        //獲取pageSize信息

        int pageSize = Configuration.getPageSize();

        

        //查詢一頁的數據信息

        Query query = getSession().createQuery(hql);

        if(args != null && args.length > 0){

            for(int i=0; i<args.length; i++){

                query.setParameter(i, args[i]);        //設置參數

            }

        }

        

        query.setFirstResult((pageNum - 1) * pageSize).setMaxResults(pageSize);

        List list = query.list();    //查詢

        

        //查詢總記錄數

        query = getSession().createQuery("select count(*) "+hql);    //注意空格!!

        if(args != null && args.length>0){

            for(int i=0; i<args.length; i++){

                query.setParameter(i, args[i]);

            }

        }

        

        Long count = (Long) query.uniqueResult();    //查詢

        

        return new PageBean(pageNum, pageSize, count.intValue(), list);

    }

TopicAction:

    /** 顯示單個主題 */

    public String show() throws Exception {

        //準備數據:topic

        Topic topic = topicService.getById(model.getId());

        ActionContext.getContext().put("topic", topic);

        

        /*//準備數據:replyList

        List<Reply> replyList = replyService.findByTopic(topic);

        ActionContext.getContext().put("replyList", replyList);*/

        

        /*//準備數據    V1

        PageBean pageBean = replyService.getPageBeanByTopic(pageNum, topic);

        ActionContext.getContext().getValueStack().push(pageBean);*/

        

        //準備數據    V2

        String hql = "from Reply r where r.topic=? order by r.postTime desc";

        Object[] args = { topic };

        PageBean pageBean = replyService.getPageBean(pageNum, hql, args);

        ActionContext.getContext().getValueStack().push(pageBean);

        

        return "show";

    }

ForumAction:

    /** 顯示單個版塊(主題列表) */

    public String show() throws Exception {

        //準備數據:forum

        Forum forum = forumService.getById(model.getId());

        ActionContext.getContext().put("forum", forum);

        

        /*//準備數據:topicList

        List<Topic> topicList = topicService.findByForum(forum);

        ActionContext.getContext().put("topicList", topicList);*/

        

        /*//準備分頁的數據    V1

        PageBean pageBean = topicService.getPageBeanByForum(pageNum, forum);

        ActionContext.getContext().getValueStack().push(pageBean);*/

        

        //準備數據    V2

        String hql = "from Topic t where t.forum = ? order by (case t.type when 2 then 2 else 0 end) desc, t.lastUpdateTime desc";

        Object[] args = { forum };

        PageBean pageBean = topicService.getPageBean(pageNum, hql, args);

        ActionContext.getContext().getValueStack().push(pageBean);

        

        return "show";

    }

抽取出JSP和Service分頁代碼的好處:

實現分頁的正常步驟:PageBeanàActionàServiceàJSP

抽取後的步驟:PageBeanàAction(在action中須要寫好hql語句和傳遞參數) à(Service中再也不須要寫分頁代碼) àJSP(只須要導入公共的分頁代碼和傳遞id)

但到此爲止,實現的分頁效果還存在兩個缺點:1.不支持自定義檢索(過濾條件)2.把hql語句寫在了action中,耦合性變高了.

頁面中使用提交表單的方式跳轉頁面:

Pageview.jspf:

<%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding="UTF-8"%>

<%@taglib prefix="s" uri="/struts-tags" %>

<!--分頁信息-->

<div id=PageSelectorBar>

    <div id=PageSelectorMemo>

        頁次:${currentPage}/${pageCount} &nbsp;

        每頁顯示:${pageSize} &nbsp;

        總記錄數:${recordCount}

    </div>

    <div id=PageSelectorSelectorArea>

        <a href="javascript: gotoPage(1)" title="首頁" style="cursor: hand;">

            <img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/firstPage.png"/></a>

        

        <!-- 頁碼列表 -->

        <s:iterator begin="%{beginPageIndex}" end="%{endPageIndex}" var="num">

            <s:if test="#num != currentPage"><!-- 非當前頁,有連接 -->

                <span class="PageSelectorNum" style="cursor: hand;" onClick="gotoPage(${num});">${num }</span>

            </s:if>

            <s:else><!-- 當前頁,沒有連接 -->

                <span class="PageSelectorNum PageSelectorSelected">${num }</span>

            </s:else>

        </s:iterator>

        

        <a href="javascript: gotoPage(${pageCount})" title="尾頁" style="cursor: hand;">

            <img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/lastPage.png"/></a>

        

        轉到:

        <select id="pn" onchange="gotoPage(this.value)">

            <s:iterator begin="1" end="%{pageCount}" var="num">

                <option value="${num }">${num }</option>

            </s:iterator>

        </select>

        

        <!-- select默認選中當前頁 -->

        <script type="text/javascript">

            $("#pn").val("${currentPage}");            

        </script>

 

        <!-- 轉到指定的頁碼 -->

        <script type="text/javascript">

            function gotoPage(pageNum){

                //方式一

                /*window.location.href = "forum_show.do?id=${id}&pageNum="+pageNum; */

                //方式二

                $("#pageForm").append("<input type='hidden' name='pageNum' value='"+pageNum+"'>");//添加pageNum表單字段

                $("#pageForm").submit();//提交表單

            }

         </script>

        

    </div>

</div>

ForumAction對應的show.jsp:

<%@include file="/WEB-INF/jsp/public/pageView.jspf" %>

<s:form id="pageForm" action="forum_show?id=%{id}"></s:form>

TopicAction對應的show.jsp:

<%@include file="/WEB-INF/jsp/public/pageView.jspf" %>

<s:form id="pageForm" action="topic_show?id=%{id}"></s:form>

  1. 支持過濾條件與排序條件:

頁面需求是這樣的:

ForumAction對應的show.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<html>

<head>

<title>【常見問題】中的主題列表</title>

<%@include file="/WEB-INF/jsp/public/header.jspf"%>

<link type="text/css" rel="stylesheet"

    href="${pageContext.request.contextPath}/style/blue/forum.css" />

</head>

<body>

 

    <!-- 標題顯示 -->

    <div id="Title_bar">

        <div id="Title_bar_Head">

            <div id="Title_Head"></div>

            <div id="Title">

                <!--頁面標題-->

                <img border="0" width="13" height="13"

                    src="${pageContext.request.contextPath}/style/images/title_arrow.gif" />

                ${forum.name }】中的主題列表

            </div>

            <div id="Title_End"></div>

        </div>

    </div>

 

<s:form id="pageForm" action="forum_show?id=%{id}">

 

    <div id="MainArea">

        <div id="PageHead"></div>

        <center>

            <div class="ItemBlock_Title1" style="width: 98%;">

                <font class="MenuPoint"> &gt; </font>

                <s:a action="forum_list">論壇</s:a>

                <font class="MenuPoint"> &gt; </font> ${forum.name } <span

                    style="margin-left: 30px;"><s:a

                        action="topic_addUI?forumId=%{#forum.id }">

                        <img align="absmiddle"

                            src="${pageContext.request.contextPath}/style/blue/images/button/publishNewTopic.png" />

                    </s:a> </span>

            </div>

 

            <div class="ForumPageTableBorder">

                <table width="100%" border="0" cellspacing="0" cellpadding="0">

                    <!--表頭-->

                    <tr align="center" valign="middle">

                        <td width="3" class="ForumPageTableTitleLeft"><img border="0"

                            width="1" height="1"

                            src="${pageContext.request.contextPath}/style/images/blank.gif" />

                        </td>

                        <td width="50" class="ForumPageTableTitle">

                            <!--狀態/圖標-->&nbsp;

                        </td>

                        <td class="ForumPageTableTitle">主題</td>

                        <td width="130" class="ForumPageTableTitle">做者</td>

                        <td width="100" class="ForumPageTableTitle">回覆數</td>

                        <td width="130" class="ForumPageTableTitle">最後回覆</td>

                        <td width="3" class="ForumPageTableTitleRight"><img

                            border="0" width="1" height="1"

                            src="${pageContext.request.contextPath}/style/images/blank.gif" />

                        </td>

                    </tr>

                    <tr height="1" class="ForumPageTableTitleLine">

                        <td colspan="8"></td>

                    </tr>

                    <tr height=3>

                        <td colspan=8></td>

                    </tr>

 

                    <!--主題列表-->

                    <tbody class="dataContainer" datakey="topicList">

                        <s:iterator value="recordList">

                            <tr height="35" id="d0" class="template">

                                <td></td>

                                <td class="ForumTopicPageDataLine" align="center"><img

                                    src="${pageContext.request.contextPath}/style/images/topicType_${type}.gif" /></td>

                                <td class="Topic"><s:a cssClass="Default"

                                        action="topic_show?id=%{id}">${title}</s:a></td>

                                <td class="ForumTopicPageDataLine">

                                    <ul class="ForumPageTopicUl">

                                        <li class="Author">${author.name}</li>

                                        <li class="CreateTime"><s:date name="postTime"

                                                format="yyyyMMdd HH:mm:ss" /></li>

                                    </ul>

                                </td>

                                <td class="ForumTopicPageDataLine Reply" align="center"><b>${replyCount}</b></td>

                                <td class="ForumTopicPageDataLine">

                                    <ul class="ForumPageTopicUl">

                                        <li class="Author">${lastReply.author.name }</li>

                                        <li class="CreateTime"><s:date name="lastReply.postTime"

                                                format="yyyyMMdd HH:mm:ss" /></li>

                                    </ul>

                                </td>

                                <td></td>

                            </tr>

                        </s:iterator>

                    </tbody>

                    <!--主題列表結束-->

 

                    <tr height="3">

                        <td colspan="9"></td>

                    </tr>

 

                </table>

 

                <!--其餘操做-->

                <div id="TableTail">

                    <div id="TableTail_inside">

                        <table border="0" cellspacing="0" cellpadding="0" height="100%"

                            align="left">

                            <tr valign=bottom>

                                <td></td>

                                <td>

                                

                                <!-- 使用自定義標籤,以便於回顯數據 -->

                                <s:select name="viewType" list="%{ #{0:'所有主題', 1:'所有精華貼' } }" />

                                <s:select name="orderBy" list="%{ #{0:'默認排序(按最後更新時間排序,但全部置頂帖都在前面)',

                                    1:'按最後更新時間排序', 2:'按主題發表時間排序', 3:'按回複數量排序' } }" />

                                <s:select name="asc" list="%{ #{true:'升序', false:'降序' } }" />

                                <input type="IMAGE"

                                    src="${pageContext.request.contextPath}/style/blue/images/button/submit.PNG"

                                    align="ABSMIDDLE" /></td>

                            </tr>

                        </table>

                    </div>

                </div>

 

            </div>

        </center>

    </div>

</s:form>//這個表單能包住viewType,orderByasc就行了.只不過在這裏包的範圍過小的話,會阻擋頁面效果的顯示.

    <%@include file="/WEB-INF/jsp/public/pageView.jspf" %>

    

    <div class="Description">

        說明:<br /> 1,主題默認按最後更新的時間降序排列。最後更新時間是指主題最後回覆的時間,若是沒有回覆,就是主題發表的時間。<br />

        2,帖子有普通、置頂、精華之分。置頂貼始終顯示在最上面,精華貼用不一樣的圖標標示。<br />

    </div>

 

</body>

</html>

Tips:這裏的回顯是指,當用戶點擊其餘頁碼的時候,它還能記住用戶選擇的過濾條件和排序條件.

ForumAction:

package cn.itcast.oa.view.action;

 

import java.util.ArrayList;

import java.util.List;

 

import org.springframework.context.annotation.Scope;

import org.springframework.stereotype.Controller;

 

import cn.itcast.oa.base.BaseAction;

import cn.itcast.oa.domain.Forum;

import cn.itcast.oa.domain.PageBean;

import cn.itcast.oa.domain.Topic;

 

import com.opensymphony.xwork2.ActionContext;

@Controller

@Scope("prototype")

public class ForumAction extends BaseAction<Forum>{

    /**

     * 0 表示所有主題<br>

     * 1 表示所有精華貼

     */

    private int viewType;

 

    /**

     * 0 表示默認排序(全部置頂帖在前面,並按最後更新時間降序排列)<br>

     * 1 表示只按最後更新時間排序<br>

     * 2 表示只按主題發表時間排序<br>

     * 3 表示只按回複數量排序

     */

    private int orderBy;

 

    /**

     * true表示升序<br>

     * false表示降序

     */

    private boolean asc;

    

    /** 版塊列表 */

    public String list() throws Exception {

        List<Forum> forumList = forumService.findAll();

        ActionContext.getContext().put("forumList", forumList);

        return "list";

    }

    

    /** 顯示單個版塊(主題列表) */

    public String show() throws Exception {

        //準備數據:forum

        Forum forum = forumService.getById(model.getId());

        ActionContext.getContext().put("forum", forum);

        

        /*//準備數據:topicList

        List<Topic> topicList = topicService.findByForum(forum);

        ActionContext.getContext().put("topicList", topicList);*/

        

        /*//準備分頁的數據    V1

        PageBean pageBean = topicService.getPageBeanByForum(pageNum, forum);

        ActionContext.getContext().getValueStack().push(pageBean);*/

        

        /*//準備數據    V2

        String hql = "from Topic t where t.forum = ? order by (case t.type when 2 then 2 else 0 end) desc, t.lastUpdateTime desc";

        Object[] args = { forum };

        PageBean pageBean = topicService.getPageBean(pageNum, hql, args);

        ActionContext.getContext().getValueStack().push(pageBean);*/

        

        // 準備分頁的數據     V3     帶過濾條件與排序條件的 注意空格!!!

        List<Object> argsList = new ArrayList<Object>();

        String hql = "FROM Topic t WHERE t.forum=? ";

        argsList.add(forum);

 

        if (viewType == 1) { // 1 表示只看精華帖

            hql += "AND t.type=? ";

            argsList.add(Topic.TYPE_BEST);

        }

 

        if (orderBy == 1) {

            // 1 表示只按最後更新時間排序

            hql += " ORDER BY t.lastUpdateTime " + (asc ? "ASC" : "DESC");

        } else if (orderBy == 2) {

            // 表示只按主題發表時間排序

            hql += " ORDER BY t.postTime " + (asc ? "ASC" : "DESC");

        } else if (orderBy == 3) {

            // 表示只按回複數量排序

            hql += " ORDER BY t.replyCount " + (asc ? "ASC" : "DESC");

        } else {

            // 0 表示默認排序(全部置頂帖在前面,並按最後更新時間降序排列)

            hql += " ORDER BY (CASE t.type WHEN 2 THEN 2 ELSE 0 END) DESC, t.lastUpdateTime DESC";

        }

 

        Object[] args = argsList.toArray();

        PageBean pageBean = topicService.getPageBean(pageNum, hql, args);

        ActionContext.getContext().getValueStack().push(pageBean); // 放到棧頂

        

        return "show";

    }

    //---------------

    public int getViewType() {

        return viewType;

    }

 

    public void setViewType(int viewType) {

        this.viewType = viewType;

    }

 

    public int getOrderBy() {

        return orderBy;

    }

 

    public void setOrderBy(int orderBy) {

        this.orderBy = orderBy;

    }

 

    public boolean isAsc() {

        return asc;

    }

 

    public void setAsc(boolean asc) {

        this.asc = asc;

    }

這樣能實現過濾和排序,但未免太繁瑣,方法還不能重用,下面來個最終版本.

五.設計並實現QueryHelper-----分頁的最終版本(還不很理解,找到工做後再回來研究!!)

在util包下新建一個QueryHelper.java:

package cn.itcast.oa.util;

 

import java.util.ArrayList;

import java.util.List;

 

import cn.itcast.oa.base.DaoSupport;

import cn.itcast.oa.domain.PageBean;

 

import com.opensymphony.xwork2.ActionContext;

 

/**

* 輔助拼接HQL語句的工具類

*

* @author tyg

*

*/

public class QueryHelper {

 

    private String fromClause; // From子句

    private String whereClause = ""; // Where子句

    private String orderByClause = ""; // OrderBy子句

 

    private List<Object> parameters = new ArrayList<Object>(); // 參數列表

 

    /**

     * 生成From子句

     *

     * @param clazz

     * @param alias

     * 別名

     */

    public QueryHelper(Class clazz, String alias) {

        fromClause = "FROM " + clazz.getSimpleName() + " " + alias;

    }

 

    /**

     * 拼接Where子句

     *

     * @param condition

     * @param args

     */

    public QueryHelper addWhereCondition(String condition, Object... args) {

        // 拼接

        if (whereClause.length() == 0) {

            whereClause = " WHERE " + condition;

        } else {

            whereClause += " AND " + condition;

        }

        // 處理參數

        if (args != null && args.length > 0) {

            for (Object arg : args) {

                parameters.add(arg);

            }

        }

        return this;

    }

 

    /**

     * 若是第一個參數的值爲true,就拼接Where子句

     *

     * @param append

     * @param condition

     * @param args

     */

    public QueryHelper addWhereCondition(boolean append, String condition, Object... args) {

        if (append) {

            addWhereCondition(condition, args);

        }

        return this;

    }

 

    /**

     * 拼接OrderBy子句

     *

     * @param propertyName

     * @param asc

     * true表示升序,false表示降序

     */

    public QueryHelper addOrderByProperty(String propertyName, boolean asc) {

        if (orderByClause.length() == 0) {

            orderByClause = " ORDER BY " + propertyName + (asc ? " ASC" : " DESC");

        } else {

            orderByClause += ", " + propertyName + (asc ? " ASC" : " DESC");

        }

        return this;

    }

 

    /**

     * 若是第一個參數的值爲true,就拼接OrderBy子句

     *

     * @param append

     * @param propertyName

     * @param asc

     */

    public QueryHelper addOrderByProperty(boolean append, String propertyName, boolean asc) {

        if (append) {

            addOrderByProperty(propertyName, asc);

        }

        return this;

    }

 

    /**

     * 獲取查詢數據列表的HQL語句

     *

     * @return

     */

    public String getQueryListHql() {

        return fromClause + whereClause + orderByClause;

    }

 

    /**

     * 獲取查詢總記錄數的HQL語句(沒有OrderBy子句)

     *

     * @return

     */

    public String getQueryCountHql() {

        return "SELECT COUNT(*) " + fromClause + whereClause;

    }

 

    /**

     * 獲取參數列表

     *

     * @return

     */

    public List<Object> getParameters() {

        return parameters;

    }

 

    /**

     * 準備PageBean對象到Struts2的棧頂

     * @param service

     * @param pageNum

     */

    public void preparePageBean(DaoSupport<?> service, int pageNum){

        PageBean pageBean = service.getPageBean(pageNum, this);

        ActionContext.getContext().getValueStack().push(pageBean);

    }

} 

DaoSupport.java:

public interface DaoSupport<T> {

 

    /**

     * 保存實體

     */

    void save(T entity);

    

    /**

     * 刪除實體

     */

    void delete(Long id);

    

    /**

     * 更新實體

     */

    void update(T entity);

    

    /**

     * 根據id查詢

     */

    T getById(Long id);

    

    /**

     * 根據id數組查詢多個

     */

    List<T> getByIds(Long[] ids);

    

    /**

     * 查詢全部

     */

    List<T> findAll();

    

    /**

     * 公共的查詢分頁信息的方法

     * @param pageNum

     * @param hql    查詢數據列表的hql語句    在方法內部會自動生成查詢總數量的hql語句

     * @param args

     * @return

     */

    @Deprecated

    PageBean getPageBean(int pageNum, String hql, Object[] args);

    

    /**

     * 公共的查詢分頁信息的方法(最終版)

     *

     * @param pageNum

     * @param queryHelper

     * 查詢語句 + 參數列表

     * @return

     */

    PageBean getPageBean(int pageNum, QueryHelper queryHelper);

DaoSupportImpl.java:

@SuppressWarnings("unchecked")

@Transactional

public abstract class DaoSupportImpl<T> implements DaoSupport<T> {

 

    @Resource

    private SessionFactory sessionFactory;

    protected Class<T> clazz = null;

 

    public DaoSupportImpl() {

        //經過反射獲取T的真實類型 this是子類

        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();

        this.clazz = (Class<T>) pt.getActualTypeArguments()[0];

        

        System.out.println("---> clazz = " + clazz);

    }

 

    /**

     * 獲取session

     */

    protected Session getSession() {

        return sessionFactory.getCurrentSession();

    }

 

    /**

     * 保存實體

     */

    public void save(T entity) {

        getSession().save(entity);

    }

 

    /**

     * 更新實體

     */

    public void update(T entity) {

        getSession().update(entity);

    }

 

    /**

     * 刪除實體

     */

    public void delete(Long id) {

        if (id == null) {

            return;

        }

 

        Object entity = getById(id);

        if (entity != null) {

            getSession().delete(entity);

        }

    }

 

    /**

     * 根據id查詢

     */

    public T getById(Long id) {

        if(id == null){

            return null;

        }

        else{

            return (T) getSession().get(clazz, id);

        }

    }

 

    /**

     * 根據id數組查詢多個

     */

    public List<T> getByIds(Long[] ids) {

        if(ids == null || ids.length == 0){

            return Collections.EMPTY_LIST;

        }

        

        // 注意空格 sql語句:from與類名之間有一空格不能省略 類名與where之間有一空格不能省略

        return getSession().createQuery(//

                "from " + clazz.getSimpleName() + " where id in (:ids)")//

                .setParameterList("ids", ids)//注意:必定要使用setParameterList()方法

                .list();

    }

 

    /**

     * 查詢全部

     */

    public List<T> findAll() {

        // 注意空格

        return getSession().createQuery("from " + clazz.getSimpleName()).list();

    }

 

    /**

     * 公共的查詢分頁信息的方法

     */

    public PageBean getPageBean(int pageNum, String hql, Object[] args) {

        System.out.println("------------------->DaoSupportImpl.getPageBean()");

        

        //獲取pageSize信息

        int pageSize = Configuration.getPageSize();

        

        //查詢一頁的數據信息

        Query query = getSession().createQuery(hql);

        if(args != null && args.length > 0){

            for(int i=0; i<args.length; i++){

                query.setParameter(i, args[i]);        //設置參數

            }

        }

        

        query.setFirstResult((pageNum - 1) * pageSize).setMaxResults(pageSize);

        List list = query.list();    //查詢

        

        //查詢總記錄數

        query = getSession().createQuery("select count(*) "+hql);    //注意空格!!

        if(args != null && args.length>0){

            for(int i=0; i<args.length; i++){

                query.setParameter(i, args[i]);

            }

        }

        

        Long count = (Long) query.uniqueResult();    //查詢

        

        return new PageBean(pageNum, pageSize, count.intValue(), list);

    }

    

    /**

     * 公共的查詢分頁信息的方法(最終版)

     *

     * @param pageNum

     * @param queryHelper

     * 查詢語句 + 參數列表

     * @return

     */

    public PageBean getPageBean(int pageNum, QueryHelper queryHelper) {

        System.out.println("------------> DaoSupportImpl.getPageBean( int pageNum, QueryHelper queryHelper )");

 

        // 獲取pageSize等信息

        int pageSize = Configuration.getPageSize();

        List<Object> parameters = queryHelper.getParameters();

 

        // 查詢一頁的數據列表

        Query query = getSession().createQuery(queryHelper.getQueryListHql());

        if (parameters != null && parameters.size() > 0) { // 設置參數

            for (int i = 0; i < parameters.size(); i++) {

                query.setParameter(i, parameters.get(i));

            }

        }

        query.setFirstResult((pageNum - 1) * pageSize);

        query.setMaxResults(pageSize);

        List list = query.list(); // 查詢

 

        // 查詢總記錄數

        query = getSession().createQuery(queryHelper.getQueryCountHql()); // 注意空格!

        if (parameters != null && parameters.size() > 0) { // 設置參數

            for (int i = 0; i < parameters.size(); i++) {

                query.setParameter(i, parameters.get(i));

            }

        }

        Long count = (Long) query.uniqueResult(); // 查詢

 

        return new PageBean(pageNum, pageSize, count.intValue(), list);

    }

ForumAction:

@Controller

@Scope("prototype")

public class ForumAction extends BaseAction<Forum>{

    /**

     * 0 表示所有主題<br>

     * 1 表示所有精華貼

     */

    private int viewType;

 

    /**

     * 0 表示默認排序(全部置頂帖在前面,並按最後更新時間降序排列)<br>

     * 1 表示只按最後更新時間排序<br>

     * 2 表示只按主題發表時間排序<br>

     * 3 表示只按回複數量排序

     */

    private int orderBy;

 

    /**

     * true表示升序<br>

     * false表示降序

     */

    private boolean asc;

    

    /** 版塊列表 */

    public String list() throws Exception {

        List<Forum> forumList = forumService.findAll();

        ActionContext.getContext().put("forumList", forumList);

        return "list";

    }

    

    /** 顯示單個版塊(主題列表) */

    public String show() throws Exception {

        //準備數據:forum

        Forum forum = forumService.getById(model.getId());

        ActionContext.getContext().put("forum", forum);

        

        /*//準備數據:topicList

        List<Topic> topicList = topicService.findByForum(forum);

        ActionContext.getContext().put("topicList", topicList);*/

        

        /*//準備分頁的數據    V1

        PageBean pageBean = topicService.getPageBeanByForum(pageNum, forum);

        ActionContext.getContext().getValueStack().push(pageBean);*/

        

//        //準備數據    V2

//        String hql = "from Topic t where t.forum = ? order by (case t.type when 2 then 2 else 0 end) desc, t.lastUpdateTime desc";

//        Object[] args = { forum };

//        PageBean pageBean = topicService.getPageBean(pageNum, hql, args);

//        ActionContext.getContext().getValueStack().push(pageBean);

        

        /*// 準備分頁的數據     V3     帶過濾條件與排序條件的

        List<Object> argsList = new ArrayList<Object>();

        String hql = "FROM Topic t WHERE t.forum=? ";

        argsList.add(forum);

 

        if (viewType == 1) { // 1 表示只看精華帖

            hql += "AND t.type=? ";

            argsList.add(Topic.TYPE_BEST);

        }

 

        if (orderBy == 1) {

            // 1 表示只按最後更新時間排序

            hql += " ORDER BY t.lastUpdateTime " + (asc ? "ASC" : "DESC");

        } else if (orderBy == 2) {

            // 表示只按主題發表時間排序

            hql += " ORDER BY t.postTime " + (asc ? "ASC" : "DESC");

        } else if (orderBy == 3) {

            // 表示只按回複數量排序

            hql += " ORDER BY t.replyCount " + (asc ? "ASC" : "DESC");

        } else {

            // 0 表示默認排序(全部置頂帖在前面,並按最後更新時間降序排列)

            hql += " ORDER BY (CASE t.type WHEN 2 THEN 2 ELSE 0 END) DESC, t.lastUpdateTime DESC";

        }

 

        Object[] args = argsList.toArray();

        PageBean pageBean = topicService.getPageBean(pageNum, hql, args);

        ActionContext.getContext().getValueStack().push(pageBean); // 放到棧頂*/        

        

        // 準備分頁的數據 v4 (最終版)-- 使用QueryHelper

                new QueryHelper(Topic.class, "t")//

                        .addWhereCondition("t.forum=?", forum)//

                        .addWhereCondition((viewType == 1), "t.type=?", Topic.TYPE_BEST) // 1 表示只看精華帖

                        .addOrderByProperty((orderBy == 1), "t.lastUpdateTime", asc) // 1 表示只按最後更新時間排序

                        .addOrderByProperty((orderBy == 2), "t.postTime", asc) // 表示只按主題發表時間排序

                        .addOrderByProperty((orderBy == 3), "t.replyCount", asc) // 表示只按回複數量排序

                        .addOrderByProperty((orderBy == 0), "(CASE t.type WHEN 2 THEN 2 ELSE 0 END)", false)//

                        .addOrderByProperty((orderBy == 0), "t.lastUpdateTime", false) // 0 表示默認排序(全部置頂帖在前面,並按最後更新時間降序排列)

                        .preparePageBean(topicService, pageNum);

        return "show";

    }

    //---------------

    public int getViewType() {

        return viewType;

    }

 

    public void setViewType(int viewType) {

        this.viewType = viewType;

    }

 

    public int getOrderBy() {

        return orderBy;

    }

 

    public void setOrderBy(int orderBy) {

        this.orderBy = orderBy;

    }

 

    public boolean isAsc() {

        return asc;

    }

 

    public void setAsc(boolean asc) {

        this.asc = asc;

    }

TopicAction:

@Controller

@Scope("prototype")

public class TopicAction extends BaseAction<Topic> {

 

    private Long forumId;

 

    /** 顯示單個主題 */

    public String show() throws Exception {

        // 準備數據:topic

        Topic topic = topicService.getById(model.getId());

        ActionContext.getContext().put("topic", topic);

 

        /*

         * //準備數據:replyList List<Reply> replyList =

         * replyService.findByTopic(topic);

         * ActionContext.getContext().put("replyList", replyList);

         */

 

        /*

         * //準備數據 V1 PageBean pageBean =

         * replyService.getPageBeanByTopic(pageNum, topic);

         * ActionContext.getContext().getValueStack().push(pageBean);

         */

 

        /*

         * //準備數據 V2 String hql =

         * "from Reply r where r.topic=? order by r.postTime desc"; Object[]

         * args = { topic }; PageBean pageBean =

         * replyService.getPageBean(pageNum, hql, args);

         * ActionContext.getContext().getValueStack().push(pageBean);

         */

 

        // 準備分頁的數據 (最終版)

        new QueryHelper(Reply.class, "r")//

                .addWhereCondition("r.topic=?", topic)//

                .addOrderByProperty("r.postTime", true)//

                .preparePageBean(replyService, pageNum);

 

        return "show";

    }

 

    /** 發新帖頁面 */

    public String addUI() throws Exception {

        // 準備數據:forum

        Forum forum = forumService.getById(forumId);

        ActionContext.getContext().put("forum", forum);

        return "addUI";

    }

 

    /** 發新帖 */

    public String add() throws Exception {

        // 封裝對象

        Topic topic = new Topic();

        // 須要在action中封裝的數據:

        // >>a.表單中的參數

        topic.setTitle(model.getTitle());

        topic.setContent(model.getContent());

        topic.setForum(forumService.getById(forumId));

        // >>b.在顯示層才能得到的數據

        topic.setAuthor(getCurrentUser()); // 當前登陸的用戶

        topic.setIpAddr(getRequestIp()); // 客戶端的IP地址

 

        // 調用業務方法

        topicService.save(topic);

 

        ActionContext.getContext().put("topicId", topic.getId());

        return "toShow"; // 轉到當前這個 新主題的頁面

    }

 

    // -----------------------------------

    public Long getForumId() {

        return forumId;

    }

 

    public void setForumId(Long forumId) {

        this.forumId = forumId;

    }

  • 至此,分頁的最終版本是這樣的:

QueryHelper.javaàDaoSupport,DaoSupportImplàPageView.jspàPageBean

àAction(只須要寫一行長長的代碼) àService(不用寫) àJSP頁面(只須要導入PageView.jsp,寫form表單,將遍歷對象改爲recordList.若是是主題顯示列表的話,還要將過濾和排序那塊改爲用Struts2標籤的形式,便於回顯數據.)

如下圖片僅做參考:

在這裏補上PageBean.java和pageView.jsp:

PageBean:

package cn.itcast.oa.domain;

 

import java.util.List;

 

/**

* 分頁用的一頁的信息對象

* @author Tan

*

*/

public class PageBean {

    //傳遞的參數或配置的值

    private int currentPage;    //當前頁

    private int pageSize;    //每頁顯示的記錄數

    //查詢數據庫

    private int recordCount;    //總記錄數

    private List recordList;    //本頁的數據列表

    //計算出來的

    private int pageCount;    //總頁數

    private int beginPageIndex;    //頁面列表的開始索引

    private int endPageIndex;    //頁面列表的結束索引

    

    /**

     * 只接受前四個屬性的值,會自動計算後四個屬性的值

     * @param currentPage

     * @param pageSize

     * @param recordCount

     * @param recordList

     */

    public PageBean(int currentPage, int pageSize, int recordCount, List recordList) {

        this.currentPage = currentPage;

        this.pageSize = pageSize;

        this.recordCount = recordCount;

        this.recordList = recordList;

        

        //計算pageCount總頁數

        pageCount = (recordCount + pageSize - 1)/ pageSize;

        

        //計算beginPageIndexendPageIndex

        //a.若是總頁數不超過十頁,就所有顯示

        if(pageCount <= 10){

            beginPageIndex = 1;

            endPageIndex = pageCount;

        //b.若是總頁數超過十頁,就顯示當前頁附近的共10個頁碼,(4+當前頁+5)

        }else{

            //就顯示當前頁附近的共10個頁碼,(4+當前頁+5)

            beginPageIndex = currentPage - 4;

            endPageIndex = currentPage + 5;

            

            //若是前面不足4個頁碼,就顯示前10

            if(beginPageIndex < 1){

                beginPageIndex = 1;

                endPageIndex = 10;

                

            //若是後面不足5個頁碼,就顯示後10

            }else if(endPageIndex > pageCount){

                endPageIndex = pageCount;

                beginPageIndex = pageCount - 10 + 1;    //注意:在顯示的時候是包含兩個邊界的

            }

        }

    }

Get,set方法

}

Pageview:

<%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding="UTF-8"%>

<%@taglib prefix="s" uri="/struts-tags" %>

<!--分頁信息-->

<div id=PageSelectorBar>

    <div id=PageSelectorMemo>

        頁次:${currentPage}/${pageCount} &nbsp;

        每頁顯示:${pageSize} &nbsp;

        總記錄數:${recordCount}

    </div>

    <div id=PageSelectorSelectorArea>

        <a href="javascript: gotoPage(1)" title="首頁" style="cursor: hand;">

            <img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/firstPage.png"/></a>

        

        <!-- 頁碼列表 -->

        <s:iterator begin="%{beginPageIndex}" end="%{endPageIndex}" var="num">

            <s:if test="#num != currentPage"><!-- 非當前頁,有連接 -->

                <span class="PageSelectorNum" style="cursor: hand;" onClick="gotoPage(${num});">${num }</span>

            </s:if>

            <s:else><!-- 當前頁,沒有連接 -->

                <span class="PageSelectorNum PageSelectorSelected">${num }</span>

            </s:else>

        </s:iterator>

        

        <a href="javascript: gotoPage(${pageCount})" title="尾頁" style="cursor: hand;">

            <img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/lastPage.png"/></a>

        

        轉到:

        <select id="pn" onchange="gotoPage(this.value)">

            <s:iterator begin="1" end="%{pageCount}" var="num">

                <option value="${num }">${num }</option>

            </s:iterator>

        </select>

        

        <!-- select默認選中當前頁 -->

        <script type="text/javascript">

            $("#pn").val("${currentPage}");            

        </script>

 

        <!-- 轉到指定的頁碼 -->

        <script type="text/javascript">

            function gotoPage(pageNum){

                //方式一

                /*window.location.href = "forum_show.do?id=${id}&pageNum="+pageNum; */

                //方式二

                $("#pageForm").append("<input type='hidden' name='pageNum' value='"+pageNum+"'>");//添加pageNum表單字段

                $("#pageForm").submit();//提交表單

            }

         </script>

        

    </div>

</div>

 

用最終版分頁技術實現用戶的分頁效果:

QueryHelper.java,DaoSupport.java,DaoSupportImpl.java,PageBean.java,pageview.jsp前面已經作好了,接下來再作分頁,只須要在Action和jsp中寫少許代碼便可:

UserAction:

/** 列表 */

    public String list() throws Exception {

 

        /*List<User> userList = userService.findAll();

        ActionContext.getContext().put("userList", userList);*/

        

        new QueryHelper(User.class, "u").preparePageBean(userService, pageNum);

        

        return "list";

    }

UserAction對應的list.jsp:

<s:iterator value="recordList">

<tr class="TableDetail1 template">

<td>${loginName}&nbsp;</td>

<td>${name}&nbsp;</td>

<td>${department.name}&nbsp;</td>

 

<td>

<s:iterator value="roles">

    ${name}

</s:iterator>&nbsp;

</td>

 

<td>${description}&nbsp;</td>

<td><s:a action="user_delete?id=%{id}" onClick="return delConfirm()">刪除</s:a>

<s:a action="user_editUI?id=%{id}" >修改</s:a>

                    <s:a action="user_initPassword?id=%{id}" onClick="return window.confirm('您肯定要初始化密碼爲1234嗎?')">

初始化密碼</s:a>

</td>

</tr>

</s:iterator>

<%@include file="/WEB-INF/jsp/public/pageView.jspf" %>

<s:form id="pageForm" action="user_list"></s:form>

相關文章
相關標籤/搜索