IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> MVC模式下的分页模型处理 -> 正文阅读

[Java知识库]MVC模式下的分页模型处理


前言

在web应用开发中,数据分页是个常见的功能,也是一个极其重要的功能,可以说随处可见。当然对于一个新手来说也是一个难点,下面是我在平常的练习结合一些视频教程,对分页模型的一个拙见。


提示:以下是本篇文章正文内容,下面案例可供参考

一、使用到的开发工具和技术

IDEA ,SQLServer2012/Mysql ,Tomcat,JSP。

二、MVC模式分页处理

1.Web层(应用层,Servlet层)

1)这里,我使用了反射机制,通过反射获取页面的参数,根据获取的参数,寻找对应的Servlet类的相应处理方法。
代码如下(示例):

    public abstract class BaseServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解决post请求中文乱码问题
        // 一定要在获取请求参数之前调用才有效
        req.setCharacterEncoding("UTF-8");
        String action=req.getParameter("action");
        try {
            // 获取action业务鉴别字符串,获取相应的业务 方法反射对象
            Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
//            System.out.println(method);
            // 调用目标业务 方法
            method.invoke(this, req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2)编写对应的处理类,该类继承了上面的BaseServlet,目的就是一个具有相同类型的Servlet,可以使用不同的方法处理不同的业务,进而不用多次写不同的Servlet。(例如:图书的功能:添加图书,修改图书,删除图书… 此时我们至需要写一个BookServlet,在BookServlet编写添加,修改,删除的方法,而怎样确定一个请求是修改图书找到对应的修改方法而不是其他方法呢?这就要用到反射机制,要求我们的方法名必须与请求过来传递的标识参数名称一致。如这儿的page方法,就对应于 String action=req.getParameter(“action”);)
代码如下(示例):

   public class OrderTableServlet extends BaseServlet {
    private OrderTableService orderTableService= new OrderTableServiceImpl();
    /**
     * 处理分页
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    protected void page(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1、获取请求的参数pageNo 和pageSize
        int pageNo= WebUtils.parseInt(request.getParameter("pageNo"), 1);
        int pageSize= WebUtils.parseInt(request.getParameter("pageSize"), Page.PAGE_SIZE);
        //2、OrderTableServlet.page(pageNo,pageSize)
       Page<OrderTable> page= orderTableService.page(pageNo,pageSize);
        page.setUrl("/orderTableServlet.do?action=page");
        //3、保存Page对象到request域中
        request.setAttribute("page",page);
        //4、请求转发
        request.getRequestDispatcher("/back/admin/ordertable_list.jsp").forward(request,response);

    }
}

2.Service层(业务层)

1)这里是分页模型的重点和难点,说它难其实也不至于,无非就是一个公式的计算。以上图片借鉴与尚硅谷王振国老师的课堂笔记。分析可知,难点在于获取总的页码数和每页应该显示的内容。这里需要注意的是:总记录数/每页显示的数量 如果不能整除,则页数要多加1页。即:总记录数%每页数量>0 ,总页数=总记录数/每页数量 + 1,如果总记录数%每页数量 ==0(刚好够均分,总页数=总记录数/每页数量 。 而每页的开始页码是多少,这又是一个困惑的人,下面给出公式:每页开始显示的记录 = (当前页码 - 1) * 每页显示的数量;
以上图片借鉴与尚硅谷王振国老师的课堂笔记。分析可知,难点在于获取总的页码数和每页应该显示的内容。这里需要注意的是:总记录数/每页显示的数量 如果不能整除,则页数要多加1页。即:总记录数%每页数量>0 ,总页数=总记录数/每页数量 + 1,如果总记录数%每页数量 ==0(刚好够均分,总页数=总记录数/每页数量 。 而每页的开始页码是多少,这又是一个困惑的人,下面给出公式:每页开始显示的记录 = (当前页码 - 1) * 每页显示的数量;

分页的业务层代码如下(示例):

   public Page<OrderTable> page(int pageNo, int pageSize) {
        Page<OrderTable> page = new Page<OrderTable>();
        // 设置每页显示的数量
        page.setPageSize(pageSize);
        // 求总记录数
        Integer pageTotalCount = orderTableDao.queryForPageTotalCount();
        // 设置总记录数
        page.setPageTotalCount(pageTotalCount);
        // 求总页码
        Integer pageTotal = pageTotalCount / pageSize;
        if (pageTotalCount % pageSize > 0) {
            pageTotal+=1;
        }
        // 设置总页码
        page.setPageTotal(pageTotal);
        // 设置当前页码
        page.setPageNo(pageNo);

        // 求当前页数据的开始索引
        int begin = (page.getPageNo() - 1) * pageSize;
        // 求当前页数据
        List<OrderTable> items = orderTableDao.queryForPageItems(begin,pageSize);
        // 设置当前页数据
        page.setItems(items);

        return page;
    }

3.Dao层(持久层)

需要指出的是:在SQLServer 和 Mysql 的分页查询他们的语法有点区别;常见的是:
1)SQLServer的分页:

set statistics time on;
-- 分页查询(通用型)
select top pageSize * 
from (select row_number() 
over(order by sno asc) as rownumber,* 
from student) temp_row
where rownumber>((pageIndex-1)*pageSize);

set statistics time on;
-- 分页查询第2页,每页有10条记录
select top 10 * 
from (select row_number() 
over(order by sno asc) as rownumber,* 
from student) temp_row
where rownumber>10;

2)Mysql 的分页:
代码如下(示例):

select * from 表名 order by 属性 desclimit m,n;
select * from dept order by deptno desc limit 3,3;

这里引用别人关于两种分页的多种方法【SQL server分页的四种方法和Mysql数据库分页查询讨论专题】,感兴趣的可以看看:

https://blog.csdn.net/weixin_37610397/article/details/80892426
https://blog.csdn.net/bandaoyu/article/details/89844673

代码如下(示例):这里我封装了数据库,用的是阿里巴巴的【commons-dbutils-1.6.jar】这个包。

public abstract class BaseDao {

    //使用DbUtils操作数据库
    private QueryRunner queryRunner = new QueryRunner();

    /**
     * update() 方法用来执行:Insert\Update\Delete语句
     *
     * @return 如果返回-1,说明执行失败<br/>返回其他表示影响的行数
     */
    public int update(String sql, Object... args) {
        Connection connection = JdbcUtils.getConnection();
        try {
            return queryRunner.update(connection, sql, args);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(connection);
        }
        return -1;
    }

    /**
     * 查询返回一个javaBean的sql语句
     *
     * @param type 返回的对象类型
     * @param sql  执行的sql语句
     * @param args sql对应的参数值
     * @param <T>  返回的类型的泛型
     * @return
     */
    public <T> T queryForOne(Class<T> type, String sql, Object... args) {
        Connection con = JdbcUtils.getConnection();
        try {
            return queryRunner.query(con, sql, new BeanHandler<T>(type), args);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(con);
        }
        return null;
    }

    /**
     * 查询返回多个javaBean的sql语句
     *
     * @param type 返回的对象类型
     * @param sql  执行的sql语句
     * @param args sql对应的参数值
     * @param <T>  返回的类型的泛型
     * @return
     */
    public <T> List<T> queryForList(Class<T> type, String sql, Object... args) {
        Connection con = JdbcUtils.getConnection();
        try {
            return queryRunner.query(con, sql, new BeanListHandler<T>(type), args);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(con);
        }
        return null;
    }

    /**
     * 执行返回一行一列的sql语句
     * @param sql   执行的sql语句
     * @param args  sql对应的参数值
     * @return
     */
    public Object queryForSingleValue(String sql, Object... args){

        Connection conn = JdbcUtils.getConnection();

        try {
            return queryRunner.query(conn, sql, new ScalarHandler(), args);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }
        return null;

    }

}

 public class OrderTableDaoImpl extends  BaseDao implements OrderTableDao {

    /**
     * 查询记录
     * @return
     */
    @Override
    public Integer queryForPageTotalCount() {
        String sql="select count(*) from ordertable";
        Number count=(Number)queryForSingleValue(sql);
        return count.intValue();
    }

    /**
     * 处理每页显示的数据
     * @param begin
     * @param pageSize
     * @return
     */
    @Override
    public List<OrderTable> queryForPageItems(int begin, int pageSize) {
        String sql="select top 4 orderid,number,kid,chanchenpengid,orderdate \n" +
                "from (select row_number() \n" +
                "over(order by  orderid asc) as rownumber,* \n" +
                "from ordertable) temp_row\n" +
                "where rownumber>?";
        String sql2="select top "+pageSize+"orderid,number,kid,chanchenpengid,orderdate \n" +
                "from (select row_number() \n" +
                "over(order by  orderid asc) as rownumber,* \n" +
                "from ordertable) temp_row\n" +
                "where rownumber>"+begin;
        String sql3="select orderid,number,kid,chanchenpengid,orderdate " +
                "from ordertable where kid >"+begin;
        return queryForList(OrderTable.class,sql2);
    }
}

4.数据展示

通过Web层的 request.setAttribute(“page”,page);我们将查询出来的分页对象存放在Request域中,在前端就可以通过 ${requestScope.page.属性l} 【eg: ${requestScope.page.pageTotal} 】 获取对应的属性。
代码如下(示例):

<table class="tablelist" style="margin-top: 36px">
        <thead>
        <tr>
            <th style="text-align: center"><input type="checkbox" value="" name="selectAll"
                                                  class="selectAllOrdertable"></th>
            <th style="text-align: center">订单id</th>
            <th style="text-align: center">数量</th>
            <th style="text-align: center">客户id</th>
            <th style="text-align: center">产品代码</th>
            <th style="text-align: center">产品单位</th>
            <th style="text-align: center">下单时间</th>
            <th style="text-align: center">操作</th>
        </tr>
        </thead>
        <tbody>
        <c:forEach items="${requestScope.page.items}" var="ordertable" varStatus="i">
            <tr>
                <td><input type="checkbox" id="checke" value="${ordertable.orderid }"></td>
                <td class="td-manage">${ordertable.orderid}</td>
                <td class="center">${ordertable.number}</td>
                <td class="center">${ordertable.kid}</td>
                <td class="center">${ordertable.chanchenpengid}</td>
                <td class="center">${ordertable.chanpindanwei}</td>

                <td class="center">
                    <fmt:formatDate value="${ordertable.orderdate }" pattern="yyyy-MM-dd HH:mm:ss" /></td>

                <td class="td-manage"><a title="${ordertable.orderid}" href="#"
                                         class="updateclass" style="text-decoration: none"> <i
                        class="layui-icon">&#xe642;编辑</i>
                </a> <%--<c:if test="${ordertable.orderid != 1 &&ordertable.orderid != 2}">--%>
                    <a title="${ordertable.orderid}" href="#" class="delclass"
                       style="text-decoration: none"> <i class="layui-icon">&#xe640;删除</i>
                    </a>
                <%--</c:if>--%></td>
            </tr>
        </c:forEach>
        </tbody>
    </table>
    <div>
        <nav aria-label="Page navigation">
            <ul class="pagination" >
                    <div width="100%" height:="10px"  margin="auto" text-align="center">
                        <c:if test="${requestScope.page.pageNo>1}">
                            <a href="${pageContext.request.contextPath}/orderTableServlet.do?action=page&pageNo=1">首页</a>
                            <a href="${pageContext.request.contextPath}/orderTableServlet.do?action=page&pageNo=${requestScope.page.pageNo-1}">上一页</a>
                        </c:if>

                        <%--页码输出的开始--%>
                        <c:choose>
                            <%--情况1:如果总页码小于等于5的情况,页码的范围是:1-总页码--%>
                            <c:when test="${ requestScope.page.pageTotal <= 5 }">
                                <c:set var="begin" value="1"/>
                                <c:set var="end" value="${requestScope.page.pageTotal}"/>
                            </c:when>
                            <%--情况2:总页码大于5的情况--%>
                            <c:when test="${requestScope.page.pageTotal > 5}">
                                <c:choose>
                                    <%--小情况1:当前页码为前面3个:123的情况,页码范围是:1-5.--%>
                                    <c:when test="${requestScope.page.pageNo <= 3}">
                                        <c:set var="begin" value="1"/>
                                        <c:set var="end" value="5"/>
                                    </c:when>
                                    <%--小情况2:当前页码为最后3个,8910,页码范围是:总页码减4 - 总页码--%>
                                    <c:when test="${requestScope.page.pageNo > requestScope.page.pageTotal-3}">
                                        <c:set var="begin" value="${requestScope.page.pageTotal-4}"/>
                                        <c:set var="end" value="${requestScope.page.pageTotal}"/>
                                    </c:when>
                                    <%--小情况34567,页码范围是:当前页码减2 - 当前页码加2--%>
                                    <c:otherwise>
                                        <c:set var="begin" value="${requestScope.page.pageNo-2}"/>
                                        <c:set var="end" value="${requestScope.page.pageNo+2}"/>
                                    </c:otherwise>
                                </c:choose>
                            </c:when>
                        </c:choose>

                        <c:forEach begin="${begin}" end="${end}" var="i">
                            <c:if test="${i == requestScope.page.pageNo}">
                                【${i}</c:if>
                            <c:if test="${i != requestScope.page.pageNo}">
                                <a href="${pageContext.request.contextPath}/orderTableServlet.do?action=page&pageNo=${i}">${i}</a>
                            </c:if>
                        </c:forEach>
                        <%--页码输出的结束--%>

                        <c:if test="${requestScope.page.pageNo < requestScope.page.pageTotal}">
                            <a href="${pageContext.request.contextPath}/orderTableServlet.do?action=page&pageNo=${requestScope.page.pageNo+1}">下一页</a>
                            <a href="${pageContext.request.contextPath}/orderTableServlet.do?action=page&pageNo=${requestScope.page.pageTotal}">末页</a>
                        </c:if>

                        &nbsp &nbsp共 ${requestScope.page.pageTotal} 页,${requestScope.page.pageTotalCount} 条记录   &nbsp跳转到 <input style="width:25px; height:12px" value="${param.pageNo}" name="pn" id="pn_input"/><input id="searchPageBtn" type="button" value="确定">
                        <script type="text/javascript">
                             $("#searchPageBtn").click(function () {
                                 var pageNo = $("#pn_input").val();
                                 // javaScript语言中提供了一个location地址栏对象
                                 // 它有一个属性叫href.它可以获取浏览器地址栏中的地址
                                 // href属性可读,可写
                                 location.href = "${pageScope.basePath}${ requestScope.page.url }&pageNo=" + pageNo;<%--${ requestScope.page.url }--%>
                                 /*location.href = "${pageContext.request.contextPath}/orderTableServlet.do?action=page&pageNo=" + pageNo;*/
                             });
                        </script>
                    </div>
                </li>

            </ul>
        </nav>
    </div>

分页数据的展示代码臃肿,如果在要用的地方都这样写的话,一是麻烦重复,二是代码不简洁。因此我们抽取出来分页的显示代码,要在使用分页功能的地方,通过静态包含的方式引入。
例如:

<%--静态包含页脚内容--%>
	<%@include file="/pages/common/page_nav.jsp"%>

三、总结

分页功能是个很常见的模块,对于写业务程序员想必是必须会分页的 对于平常很少练习的学生来说,独立的编写程序,的确有点困难。但大多数学生都是跟着视频敲代码,又缺乏思考,盲目的做个机器,当然我也是这样的。因此,要想真正的掌握并且培养独立思考的能力,就要有目的的练习和勤于思考的习惯。
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-10-03 16:57:32  更:2021-10-03 16:58:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 19:21:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码