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>

相关文章
相关标签/搜索