带条件的分页重点
Posted cynchanpin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了带条件的分页重点相关的知识,希望对你有一定的参考价值。
二、前台
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" />
③书写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>
以上是关于带条件的分页重点的主要内容,如果未能解决你的问题,请参考以下文章
springboot+thymeleaf处理带搜索条件的分页问题解决思路
序列化表单为json对象,datagrid带额外参提交一次查询 后台用Spring data JPA 实现带条件的分页查询