带条件的分页【重点】

           

二、前台

1、不带条件的查询

    [1 ]实现Dao方法:getPageList ()、getTotalItemNum ()
    ◆在BookDao中写接口方法
    /**
     * 获取在指定条件下的分页数据
     * @param pageNo 不能使用pageCondition返回的pageNoStr。要使用经过Page对象纠正的
     * @param pageSize
     * @param pageCondition
     * @return
     */
    List<Book> getPageList (int pageNo, int pageSize, PageCondition pageCondition);
    
    /**
     * 带条件的查询
     * @param pageCondition
     * @return 返回在指定的条件下一共同拥有多少条记录
     */
    int getTotalItemNum (PageCondition pageCondition );
    
    
    ◇此时须要更改Dao :
         /**
         * 获取单一值的接口方法
         * @param connection
         * @param sql
         * @param params
         * @return
         */
         <V > V getSingleValue (Connection connection , String sql , Object ... params);
    
    ◇DaoImpi中实现该接口方法:
        @Override
         public <V > V getSingleValue (Connection connection , String sql,
                Object ... params ) {
            V v = null;
             try {
                v = (V ) runner .query (connection , sql , new ScalarHandler(), params);
             } catch (SQLException e ) {
                 // TODO Auto-generated catch block
                e .printStackTrace ();
             }
             return v ;
         }
    
    [2 ]实现Page类
    package com.atguigu.bookstore.fun;
    import java .util .List ;

    /**
     * 封装分页信息的类
     * @author Phenix
     *
     * @param <T>相应详细的实体类
     */
    public class Page<T> {
        
         //代表当前页码
         private int pageNo ;
        
         //页面上的数据
         private List <T > list ;
        
         //每页显示的数据数量
         public static final int PAGE_SIZE = 3;
        
         //总记录数
         private int totalItemNum ;
        
         //总页数
         private int totalPageNum ;
        
        
         public Page (String pageNoStr , int totalItemNum ) {
            
             //先获取总记录数,以计算总页数
             this.totalItemNum = totalItemNum ;
            
             //计算总页数
             this.totalPageNum = (totalItemNum % PAGE_SIZE == 0) ? totalItemNum/ PAGE_SIZE : totalItemNum/PAGE_SIZE + 1 ;
            
             //对pageNoStr进行类型转换
            pageNo = 1;
             try {
                pageNo = Integer .parseInt (pageNoStr );
             } catch (NumberFormatException e ) {/*假设转换失败则保持默认值*/ }

             //限定pageNo的有效范围
             if(pageNo < 1) {
                pageNo = 1;
             }
            
             if(pageNo > totalPageNum ) {
                pageNo = totalPageNum ;
             }
            
         }

         public List <T > getList () {
             return list ;
         }

         public void setList (List <T > list ) {
             this.list = list;
         }

         public int getPageNo () {
             return pageNo ;
         }

         public int getTotalItemNum () {
             return totalItemNum ;
         }

         public int getTotalPageNum () {
             return totalPageNum ;
         }

         public boolean isHasPrev () {
             return pageNo > 1;
         }
        
         public boolean isHasNext () {
             return pageNo < totalPageNum ;
         }
        
         public int getPrevNo () {
             return pageNo - 1;
         }
        
         public int getNextNo () {
             return pageNo + 1;
         }
        
    }
    
    [3 ]实现与分页相关的Service层代码
    ◇BookService中加入例如以下接口方法:获取book类的分页信息
        Page <Book > getBookPage (String pageNoStr );
    ◇在BookServiceImpi中实现该方法
        @Override
         public Page <Book > getBookPage (PageCondition pageCondition) {
         int totalItemNum = bookDao.getTotalItemNum( pageCondition);
        
        Page <Book > page = new Page<>(pageCondition. getPageNoStr(), totalItemNum);
        
         //这里。pageNo必须使用Page类纠正过的,不能使用pageCondition中的pageNoStr
        List <Book > list = bookDao .getPageList (page .getPageNo (), Page.PAGE_SIZE, pageCondition);
        
        page .setList (list );
        
         return page ;//返回book类的分页信息
    }

    ◆在client .jsp请求
    <iframe src ="client/BookClientServlet?method=getPage" name="targetFrame"></iframe>
    ◆BookClientServlet中进行转发
         protected void getPage (HttpServletRequest request ,
            HttpServletResponse response ) throws ServletException, IOException {
        
        String pageNoStr = request .getParameter ("pageNo");  
        Page <Book > page = bookService .getBookPage (pageNoStr );   
        WebUtils .myForward (request , response , "/client/book/bookList.jsp" , "page", page);
        
    }
    ◆在bookList .jsp中接收数据
        $ {page .list }
    
    

    [4 ]页面 (文本框输入数字跳转页面 )
        ① 给文本框加一个Id 属性: <input id ="pageCode" class="inpType" type="text" name= "pageNo" />
        ②导入jquery: <script type ="text/javascript" src="script/jquery-1.7.2.js"></script>【已经加过base标签】
        ③书写JS代码:
        版本号一:能够容错,由于Page类内置了容错校验
         <script type ="text/javascript">
            $ (function (){
                $ ("#pageCode").change(function(){
                     //去掉前后空格
                    var pageCode =$ .trim (this. value);
                     //推断用户输入的页码是否为数字
                     if(isNaN(pageCode)){
                         //假设不是将文本框置空。并停止函数的运行
                         this.value="" ;
                         return false;
                     }
                     //假设是数字。则跳转到指定的页码
                    var url ="${pageContext.request.contextPath }/"+
                     "client/BookClientServlet?method=getPage&pageNo=" +pageCode ; 
                    window .location .href =url ;
                 });
             });
         </script >
    

    
2、在首页显示真实的分类数据
    ①创建ClientServlet ,用于跳转到前台页面 ,跟实体类无关。和前台页面相关
    ②改动index .jsp中的代码
             <jsp :forward page="client/ClientServlet?method=toClientUI"></jsp :forward >
    ③在toClientUI ()方法中获取数据库分类列表数据,跳转到client .jsp显示
         public class ClientServlet extends BaseServlet {
         private static final long serialVersionUID = 1L;
        
         private CateService cateService =new CateServiceImpl ();
        
         protected void toClientUI (HttpServletRequest request , HttpServletResponse response) throws ServletException, IOException {
            List <Category > cateList = cateService .getCateList ();
            
            WebUtils .myForward (request , response , "/client/client.jsp", "cateList", cateList);
         }

         }
    
    注意:改动web .xml将ClientServlet注冊一下。
    <servlet >
         <display -name >ClientServlet </display -name >
         <servlet -name >ClientServlet </servlet -name >
         <servlet -class> com.atguigu.bookstore.servlet.client.ClientServlet </servlet -class>
    </servlet >
    <servlet -mapping >
      <servlet -name >ClientServlet </servlet -name >
      <url-pattern>/client /ClientServlet </url -pattern >
    </servlet -mapping >
      
    ④改动client .jsp 中的分类列表
        <li>所有分类 </li >
         <c :forEach items ="${cateList }" var ="category" >
             <li ><a href ="#"> ${category.cateName }</a></li >
         </c :forEach >
      
    ⑤后台中跳转到前台页面的超链接也要跟着改动
    <a href="client/ClientServlet?

method=toClientUI" >进入前台 </a >

    

3、★带条件的查询★重点★

    难点:查询条件时有时无,要做到适配不同的情况
    ①查询条件包含
        pageNo页码
        minPrice 价格区间最小值
        maxPrice 价格区间最大值
        cateId   分类Id
    ②将查询条件封装为PageCondition类
         (1) 为每一个查询条件设置默认值
                pageNo 页码,默认值:1,终于还是交给Page类纠正
                minPrice 默认值:0
                maxPrice 默认值:Integer .MAX_VALUE
                cateId 默认值:null为了避免有可能产生的歧义,所以应声明为Integer类型
         (2) 在构造器中。获取String类型的參数,进行类型转换,若不论什么一个条件数据转换失败则保持默认值
         (3) 提供getXxx()方法
        代码例如以下:
         public class PageCondition {
            
         //  (1)pageNo 页码 声明为String类型是为了直接交给Page类的构造器
             private String pageNoStr = "1";
            
         //  (2)minPrice 价格区间的最小值 默认值的作用是在页面没有传入该參数时仍然能够查询
             private int minPrice = 0;
            
         //  (3)maxPrice 价格区间的最大值
             private int maxPrice = Integer .MAX_VALUE ;
            
         //  (4)cateId   分类ID
             private Integer cateId = null;
            
             public PageCondition (String pageNoStr , String minPriceStr, String maxPriceStr, String cateIdStr) {
                
                 this.pageNoStr = pageNoStr ;
                
                 //转换失败。使用默认值
                 try {
                     this.minPrice = Integer.parseInt( minPriceStr);
                 } catch (NumberFormatException e ) {/*保持默认值*/}
                
                 try {
                     this.maxPrice = Integer.parseInt( maxPriceStr);
                 } catch (NumberFormatException e ) {/*保持默认值*/}
                
                 try {
                     this.cateId = Integer.parseInt(cateIdStr);
                 } catch (NumberFormatException e ) {/*保持默认值*/}
                
             }

             public String getPageNoStr () {
                 return pageNoStr ;
             }

             public int getMinPrice () {
                 return minPrice ;
             }

             public int getMaxPrice () {
                 return maxPrice ;
             }

             public Integer getCateId () {
                 return cateId ;
             }

            @Override
             public String toString () {
                 return "PageCondition [pageNoStr=" + pageNoStr + ", minPrice="
                         + minPrice + ", maxPrice=" + maxPrice + ", cateId=" + cateId
                         + "]";
             }
            
         }
    ③在Dao中升级原有的分页方法
         (1) int getTotalItemNum (PageCondition pageCondition )。依据相关条件进行相关查询
        ·原本不带条件的SQL语句:SELECT COUNT (*) FROM book
        ·带所有条件的SQL语句
            SELECT
              COUNT (*)
            FROM
              book
            WHERE price <= 10000
              AND price >= 0
              AND cate_id = 1
        ·适配详细情况的SQL语句
            pageCondition .getCateId ()的返回值是否为null。决定是否附加“AND cate_id = 1 
            ○第一部分
            SELECT
              `book_id` bookId ,
              `book_name` bookName ,
              `author` author ,
              `price` price ,
              `store_num` storeNum ,
              `salse_amount` salseAmount ,
              `imp_path` imgPath ,
              `cate_id` cateId
            FROM
              book
            WHERE price >= 0
              AND price <= 10000
            ○第二部分
              AND cate_id = 1
              依据pageCondition .getCateId ()的返回值是否为null,决定是否附加
            ○第三部分
              LIMIT ?

, ?

            
            
        ◆详细更改例如以下:

        ★1、在BookDao .java中重载两个方法

         /**
         * 获取在指定条件下的分页数据
         * @param pageNo 表示当前页,不能使用pageCondition返回的pageNoStr。要使用经过Page对象纠正的
         * @param pageSize 页面显示的条目数
         * @param pageCondition
         * @return
         */
        List <Book > getPageList (int pageNo, int pageSize, PageCondition pageCondition);
        
         /**
         * 带条件的查询
         * @param pageCondition
         * @return 返回在指定的条件下一共同拥有多少条记录
         */
         int getTotalItemNum (PageCondition pageCondition );
    

        ★2、在BookDaoImpl .java中实现上述两个方法

        @Override
         public List <Book > getPageList (int pageNo, int pageSize,
                PageCondition pageCondition ) {
            
            Connection connection = JDBCUtils .getConnection ();
            
            String sql = "SELECT `book_id` bookId,"
                     + "`book_name` bookName,"
                     + "`author` author,"
                     + "`price` price,"
                     + "`store_num` storeNum,"
                     + "`salse_amount` salseAmount,"
                     + "`imp_path` imgPath,`cate_id` cateId "
                     + "FROM book WHERE price>=?

and price<=?

;

            
            Integer cateId = pageCondition .getCateId ();
            
             //依据实际情况决定是否增加这个条件
             if(cateId != null) sql = sql + " and `cate_id`=" + cateId;
            
            sql = sql + " LIMIT ?,?";
            
            List <Book > list = this.getBeanList (connection , sql ,
                    pageCondition .getMinPrice (),
                    pageCondition .getMaxPrice (),
                     (pageNo -1)* pageSize,
                    pageSize );
            
            JDBCUtils .releaseConnection (connection );
            
             return list ;
            
         }
         //获取总记录数
        @Override
         public int getTotalItemNum (PageCondition pageCondition ) {
            
            Connection connection = JDBCUtils .getConnection ();
            
            String sql = "SELECT COUNT(*) FROM book WHERE price >= ? AND price <= ?

";

            
            Integer cateId = pageCondition .getCateId ();
            
             if(cateId != null) sql = sql + " AND cate_id = " + cateId;
            
             long itemNum = this.getSingleValue (connection , sql , pageCondition.getMinPrice(), pageCondition.getMaxPrice());
            
            JDBCUtils .releaseConnection (connection );
            
             return (int) itemNum;
         }
    
        ☆对以上更改进行单元測试
         private BookDao bookDao = new BookDaoImpl ();
        @Test
         public void testGetPageListInCon () {

            PageCondition pageCondition = new PageCondition ("1", null, null, null);
            
            List <Book > list = bookDao .getPageList (1, 3 , pageCondition);
            
             for (Iterator iterator = list .iterator (); iterator.hasNext();) {
                Book book = (Book ) iterator .next ();
                System .out .println (book );
             }
            
         }
        @Test
         public void testGetItemNumInCon () {
            
            PageCondition pageCondition = new PageCondition ("1", "30", "50", "2" );
            
             int totalItemNum = bookDao.getTotalItemNum( pageCondition);
            
            System .out .println (totalItemNum );
            
         }
    

        ★3、在BookService中对该方法重载

        Page <Book > getBookPage (PageCondition pageCondition );
        

        ★4、在BookServiceImpl实现该接口

        @Override
         public Page <Book > getBookPage (PageCondition pageCondition) {
         //总记录数从Dao中获取,先获取总记录数,以计算总页数
         int totalItemNum = bookDao.getTotalItemNum( pageCondition);
         //创建分页类对象,并在构造器中对传入的当前页和总记录数进行校验
        Page <Book > page = new Page<Book>( pageCondition.getPageNoStr(), totalItemNum );
        
         //这里pageNo必须使用Page类纠正过的。不能使用PageCondition中的pageNoStr,它不具备纠正能力
         //getPageList()获取在指定条件下的分页数据
        List <Book > list = bookDao .getPageList (page .getPageNo (), Page.PAGE_SIZE, pageCondition);
         //将page对象设置到list集合其中
        page .setList (list );
        
         return page ;
         }
        

        ☆对该接口实行单元測试:

        @Test
         public void testGetPageInCon () {
             //查询第一页。价格在30-77之间。书的分类Id是5的有记录
            PageCondition pageCondition = new PageCondition ("1", "30", "77", "5" );   
            Page <Book > page = bookService.getBookPage( pageCondition);     
             int totalItemNum = page .getTotalItemNum ();  
             int totalPageNum = page .getTotalPageNum ();
             int pageNo = page .getPageNo ();  
            Iterator <Book > iterator = page .getList ().iterator ();
            
             while (iterator .hasNext ()) {            
                Book book = (Book ) iterator .next ();         
                System .out .println (book .getBookId ());
                 //5 7 18
             }
            
            System .out .println ("总记录数:"+totalItemNum );   //总记录数:3
            System .out .println ("总页数:"+totalPageNum);     //总页数:1
            System .out .println ("当前页:"+pageNo);//    当前页:1   
         }
    

        ★5、在BookClientServlet中添加getPageInCondition ()方法

         protected void getPageInCondition (HttpServletRequest request,
            HttpServletResponse response ) throws ServletException, IOException {
        
         //获取请求參数
        String pageNoStr = request .getParameter ("pageNo");
        String minPriceStr = request .getParameter ("minPrice");
        String maxPriceStr = request .getParameter ("maxPrice");
        String cateIdStr = request .getParameter ("cateId");
        
         //封装条件对象
        PageCondition pageCondition = new PageCondition(pageNoStr, minPriceStr, maxPriceStr, cateIdStr );
        
        Page <Book > page = bookService.getBookPage( pageCondition);
        
        WebUtils .myForward (request , response , "/client/book/bookList.jsp" , "page", page);
        
         }
        

        ★6、在bookList .jsp中更改价格查询的提交地址

         <form action="client/BookClientServlet?method=getPageInCondition" method="post">
            价格
             <input type ="text" class= "inpType" name ="minPrice" />-
             <input type ="text" class= "inpType" name ="maxPrice" />
             <input type ="submit" value ="查询" />
         </form >
        

        ★7、在client .jsp中做相同更改

         <li >所有分类 </li >
         <c :forEach items ="${cateList }" var ="category" >
         <li ><a href="client/BookClientServlet?

method=getPageInCondition&cateId=${category.cateId }" >$ {category .cateName }</a ></li >

         </c :forEach >
        
        

        ★8、给分类信息增加target属性使其在mainContent中显示

         <li >所有分类 </li >
         <c :forEach items ="${cateList }" var ="category" >
         <li ><a target ="targetFrame" href="client/BookClientServlet?method=getPageInCondition&cateId=${category.cateId }" >$ {category .cateName }</a ></li >
         </c :forEach >
    
    
        

4、在页面上保持查询条件

    [1 ]会导致“丢失”查询条件的行为

         (1) 翻页的超链接
            ·可以保持的条件:pageNo
            ○分类、价格会丢失
            →可将下面条件附着在超链接之后
             &cateId =$ {param .cateId }&minPrice =$ {param .minPrice }&maxPrice= ${param.maxPrice }
            比如:
             <a href="client/BookClientServlet?

method=getPageInCondition&pageNo=${page.prevNo }

             &cateId =$ {param .cateId }&minPrice =$ {param .minPrice }&maxPrice= ${param.maxPrice }">上一页</a>

            
    ·改进:对超链接进行批量操作
    <script type ="text/javascript">
    $(function(){
        var conditonStr ="&cateId=${param.cateId }&minPrice=${param.minPrice }&maxPrice=${param.maxPrice }";
        $ ("a"). each(function(){
             this.href=this .href +conditonStr ;
         });
        
        $ ("#pageCode").change(function(){
             //去掉前后空格
            var pageCode =$ .trim (this. value);
             //推断用户输入的页码是否为数字
             if(isNaN(pageCode)){
                 //假设不是将文本框置空。并停止函数的运行
                 this.value="" ;
                 return false;
             }
             //假设是数字。则跳转到指定的页码
            var url ="${pageContext.request.contextPath }/"+
             "client/BookClientServlet?method=getPageInCondition&pageNo=" +pageCode +conditonStr ;  
            window .location .href =url ;
         });
    });
    </script >
    
    
         (2) 跳转页面的文本框
            ·可以保持的条件:pageNo
            ○分类、价格会丢失
            
        ◇在bookList .jsp中改动JS代码中的URL地址
         <script type ="text/javascript">
        $ (function (){
            $ ("#pageCode").change(function(){
                 //去掉前后空格
                var pageCode =$ .trim (this. value);
                 //推断用户输入的页码是否为数字
                 if(isNaN(pageCode)){
                     //假设不是将文本框置空,并停止函数的运行
                     this.value="" ;
                     return false;
                 }
                 //假设是数字。则跳转到指定的页码
                var url ="${pageContext.request.contextPath }/"+
                 "client/BookClientServlet?method=getPageInCondition&pageNo=" +pageCode +
                 "&cateId=${param.cateId }&minPrice=${param.minPrice }&maxPrice=${param.maxPrice }"; 
                window .location .href =url ;
             });
         });
        </script >
        注意:方法名要更改为:getPageInCondition    
        疑问?EL表达式能写在JS里面吗?
        解答:能够的。由于Jsp页面的翻译和执行先于JS ,浏览器取得该超链接地址是被翻译过的。
        
         (3) 查询价格的表单提交
            ·可以保持价格信息
            ○会丢失pageNo和分类
            因此要附着: &pageNo =$ {param .pageNo }&cateId= ${param.cateId }
            
        ◇将其附着在表单提交的地址后面
         <form action="client/BookClientServlet?method=getPageInCondition&pageNo=${param.pageNo }&cateId=${param.cateId }" method="post">
            价格
             <input type ="text" class= "inpType" name ="minPrice" value="${param.minPrice }"/>-
             <input type ="text" class= "inpType" name ="maxPrice" value="${param.maxPrice }" />
             <input type ="submit" value ="查询" />
         </form >
            
            
         (4) 点击分类超链接【会话控制能够解决】
            分类信息client .jsp和bookList .jsp非同一个页面在bookList .jsp中即使用param对象,在client .jsp中也获取不到它的值
            因此临时先不动分类Client .jsp,之后能够将pageCondition放到session里面,那么这两个页面就能够协同工作了。
            ·可以保持分类
            ○丢失分类、价格、页码
                
            

    [2 ]保持查询条件

         (1) 在跳转页面时将已存在的查询条件携带提交
         (2) ${param.xxx }
        翻页的超链接:自己发出的不存在保持查询条件的问题。能够将查询条件附着在超链接上面,
         <a href ="...let?method=getPageInCondition&pageNo=${num }&minPrice=${param.minPrice }"> ${num }</a>
         <a href ="...let?method=getPageInCondition&pageNo=${num }&minPrice=30"> ${num }</a>
         (3) 注意:Servlet方法的名字要改成getPageInCondition
    
    
    
    [3 ]在bookList .jsp中显示当前的分类名称
    ◇在client .jsp中将每个分类都附着cateName信息
    <li>所有分类 </li >
    <c:forEach items ="${cateList }" var ="category" >
         <li ><a target ="targetFrame" href="client/BookClientServlet?

method=getPageInCondition&cateId=${category.cateId }&cateName=${category.cateName }">${ category.cateName }</a></li >

    </c:forEach>
    
    ◇在bookList .jsp中获取cateName
    //<td colspan="2">当前分类:${param.cateName }</td>
    <td colspan ="2"> 当前分类:${param.cateName==null ? '所有分类':param.cateName }</td>
    
    ◆当点击所有分类的时候显示空白,如今要给所有分类也加上超链接以便于用户能回到所有分类
    <li><a target ="targetFrame" href="client/BookClientServlet?

method=getPageInCondition&cateName=所有分类" >所有分类 </a ></li >

    

    眼下的局限性:

    仅仅能在当前分类下保持查询(先点击“科学”再点击价格能够保持,可是再次点击别的分类就保持不了)
    
    

    

5、点击图书名称显示单本书的信息  

    ①给书名加超链接
    <li>书名: <a href="client/BookClientServlet?method=getBook&bookId=${book.bookId }">${book.bookName }</a></li >
    
    ②在BookClientServlet中写getBook ()方法
    protected void getBook(HttpServletRequest request ,
            HttpServletResponse response ) throws ServletException, IOException {
        
        String bookId = request .getParameter ("bookId");
        
        Book book = bookService .getBookById (bookId );
        
        WebUtils .myForward (request , response , "/client/book/book.jsp" , "book", book);
        
    }
        
    ③创建book .jsp页面用于显示图书信息
    注意:编码为UTF -8
    ◇导入: <base href ="http://${pageContext.request.serverName }:${pageContext.request.serverPort }${pageContext.request.contextPath }/" />
    ◇<link rel ="stylesheet" type ="text/css" href="style/css.css" />
    ◇<script type ="text/javascript" src="script/jquery-1.7.2.js"></script>
    <script type ="text/javascript">
        $ (function (){
            $ ("button").click(function(){       
                 //借助window.history.go(-1)实现后退功能
                window .history .go (-1);       
             }); 
         });
    </script >
        
    ◇在body中书写
    <body>
         <img class="bookImg" src="${book.imgPath }" >
         <p >书名:$ {book .bookName }</p >
         <p >作者:$ {book .author }</p >
         <p >价格:$ {book .price }</p >
         <p >库存:$ {book .storeNum }</p >
         <p >销量:$ {book .salseAmount }</p >
         <p ><button >回到上一页 </button ></p >
    </body> 
        
原文地址:https://www.cnblogs.com/cynchanpin/p/6985817.html