家居网购项目实现06

以下皆为部分代码,详见 https://github.com/liyuelian/furniture_mall.git

14.功能13-首页分页

14.1需求分析/图解

  1. 顾客进入首页页面
  2. 分页显示家居
  3. 正确显示分页导航条

14.2思路分析

14.3代码实现

14.3.1web层

配置customerFurnServlet

<servlet>
<servlet-name>CustomerFurnServlet</servlet-name>
<servlet-class>com.li.furns.web.CustomerFurnServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CustomerFurnServlet</servlet-name>
<url-pattern>/customerFurnServlet</url-pattern>
</servlet-mapping>

实现servlet

package com.li.furns.web;

import com.li.furns.entity.Furn;
import com.li.furns.entity.Page;
import com.li.furns.service.FurnService;
import com.li.furns.service.impl.FurnServiceImpl;
import com.li.furns.utils.DataUtils; import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException; public class CustomerFurnServlet extends BasicServlet { private FurnService furnService = new FurnServiceImpl(); /**
* 处理首页分页请求
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//这里的业务逻辑和原先的家居后台分页非常相似
int pageNo = DataUtils.parseInt(req.getParameter("pageNo"), 1);
int pageSize = DataUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);
//调用service方法,获取Page对象
Page<Furn> page = furnService.page(pageNo, pageSize);
//将page放入request域中
req.setAttribute("page", page);
//请求转发到/views/customer/index.jsp - 真正的主页
req.getRequestDispatcher("/views/customer/index.jsp")
.forward(req, resp);
}
}

14.3.2前端页面

1.web/index.jsp

<%--
Created by IntelliJ IDEA.
User: li
Date: 2022/12/21
Time: 17:14
Version: 1.0
--%>
<%-- 直接请求到CustomerFurnServlet,
获取网站首页要显示的分页数据,类似我们的网站入口页面
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--注意这里如果没有子元素的话不要分行!!!--%>
<jsp:forward page="/customerFurnServlet?action=page&pageNo=1"></jsp:forward>

2.web/views/customer/index.jsp

循环标签显示家居信息

<%--循环输出--%>
<c:forEach items="${requestScope.page.items}" var="furn">
<div class="col-lg-3 col-md-6 col-sm-6 col-xs-6 mb-6" data-aos="fade-up"
data-aos-delay="200">
<!-- Single Prodect -->
<div class="product">
<div class="thumb">
<a href="shop-left-sidebar.html" class="image">
<img src="${furn.imgPath}" alt="Product"/>
<img class="hover-image" src="${furn.imgPath}"
alt="Product"/>
</a>
<span class="badges">
<span class="new">New</span>
</span>
<div class="actions">
<a href="#" class="action wishlist" data-link-action="quickview"
title="Quick view" data-bs-toggle="modal"
data-bs-target="#exampleModal"><i
class="icon-size-fullscreen"></i></a>
</div>
<button title="Add To Cart" class=" add-to-cart">Add
To Cart
</button>
</div>
<div class="content">
<h5 class="title">
<a href="shop-left-sidebar.html">${furn.name}</a></h5>
<span class="price">
<span class="new">家居: ${furn.name}</span>
</span>
<span class="price">
<span class="new">厂商: ${furn.maker}</span>
</span>
<span class="price">
<span class="new">价格: ¥${furn.price}</span>
</span>
<span class="price">
<span class="new">销量: ${furn.sales}</span>
</span>
<span class="price">
<span class="new">库存: ${furn.stock}</span>
</span>
</div>
</div>
</div>
</c:forEach>
<%--循环结束--%>

前端导航栏

<ul>
<%--如果当前页大于1,就显示上一页--%>
<c:if test="${requestScope.page.pageNo>1}">
<li><a href="customerFurnServlet?action=page&pageNo=${requestScope.page.pageNo-1}">上页</a></li>
</c:if>
<%-- 显示所有的分页数
先确定开始页数 begin 第一页
再确定结束页数 end 第page.TotalCount页
--%>
<c:set var="begin" value="1"/>
<c:set var="end" value="${requestScope.page.pageTotalCount}"/>
<c:forEach begin="${begin}" end="${end}" var="i">
<%--如果i为当前页,就使用class=active来修饰--%>
<c:if test="${i==requestScope.page.pageNo}">
<li><a class="active" href="customerFurnServlet?action=page&pageNo=${i}">${i}</a></li>
</c:if>
<c:if test="${i!=requestScope.page.pageNo}">
<li><a href="customerFurnServlet?action=page&pageNo=${i}">${i}</a></li>
</c:if>
</c:forEach>
<%-- --%>
<%-- 如果当前页小于总页数,就往下一页--%>
<c:if test="${requestScope.page.pageNo < requestScope.page.pageTotalCount}">
<li><a href="customerFurnServlet?action=page&pageNo=${requestScope.page.pageNo+1}">下页</a></li>
</c:if>
<li><a>共${requestScope.page.pageTotalCount}页</a></li>
<li><a>共${requestScope.page.totalRow}记录</a></li>
</ul>

14.4完成测试

在浏览器访问http://localhost:8080/furniture_mall/,点击分页超链接,可以完成分页显示数据


15.功能14-首页搜索

15.1需求分析/图解

  1. 顾客点击首页搜索框,可以输入家居名
  2. 正确显示分页导航条,并且要求在分页基础上保留上次搜索条件(即点击分页,显示的家居信息仍要符合搜索条件)

15.2思路分析

15.3代码实现

15.3.1dao层

FurnDAO

/**
* 根据furnName返回符合条件的记录数
*
* @param furnName 搜索条件
* @return 返回符合条件的记录数
*/
public int getTotalRowByName(String furnName); /**
* 根据 begin,pageSize,furnName,返回furn的记录
*
* @param furnName 搜索条件
* @return 返回furn对象集合
*/
public List<Furn> getPageItemByName(int begin, int pageSize, String furnName);

FurnDAOImpl

@Override
public int getTotalRowByName(String furnName) {
String sql = "SELECT COUNT(*) " +
"FROM `furn` " +
"WHERE `name` LIKE ?";
return ((Number) queryScalar(sql, "%" + furnName + "%")).intValue();
} @Override
public List<Furn> getPageItemByName(int begin, int pageSize, String furnName) {
String sql = "SELECT `id` , `name` , `maker` , `price` , `sales` , `stock` , `img_path` AS imgPath " +
"FROM `furn` " +
"WHERE `name` LIKE ? LIMIT ?,?";
return queryMulti(sql, Furn.class, "%" + furnName + "%", begin, pageSize);
}

FurnDAOImplTest

@Test
public void getPageTotalCountByName() {
System.out.println("根据名字’沙发‘搜索=>" + furnDAO.getTotalRowByName("沙发"));
} @Test
public void getPageItemByName() {
//从第0条记录开始,每页显示5个记录
List<Furn> furns = furnDAO.getPageItemByName(0, 5, "沙发");
for (Furn furn : furns) {
System.out.println(furn);
}
}


15.3.2service层

FurnService

/**
* 根据传入的pageNo,pageSize和furnName,返回对应的page对象
*
* @param pageNo 表示第几页
* @param pageSize 表示一页取出多少条记录
* @param furnName 搜索的家居名
* @return 返回对应的page对象
*/
public Page<Furn> pageByName(int pageNo, int pageSize, String furnName);

FurnServiceImpl

@Override
public Page<Furn> pageByName(int pageNo, int pageSize, String furnName) {
//先创建一个page对象,然后根据实际情况填充属性
Page<Furn> page = new Page<>();
//1.当前第几页
page.setPageNo(pageNo);
//2.每页取出多少条记录
page.setPageSize(pageSize);
//3.根据名字来返回总记录数
int totalRow = furnDAO.getTotalRowByName(furnName);
page.setTotalRow(totalRow);
//4.总页数 = 总记录数 / 每页记录数
int pageTotalCount = totalRow / pageSize;
if (totalRow % pageSize > 0) {
//如果有余数就把总页数 +1
pageTotalCount++;
}
page.setPageTotalCount(pageTotalCount);
//5.数据集合items
//SELECT * FROM table_name
//LIMIT 每页显示记录数*(第几页-1),每页显示记录数
int begin = (pageNo - 1) * pageSize;
List<Furn> pageItems = furnDAO.getPageItemByName(begin, pageSize, furnName);
page.setItems(pageItems);
//6.还差一个url,分页导航,先放一放
return page;
}

FurnServiceImplTest

@Test
public void pageByName() {
Page<Furn> page = furnService.pageByName(1, 5, "桌子");
for (Furn furn : page.getItems()) {
System.out.println(furn);
}
}

15.3.3web层

CustomerFurnServlet

/**
* 处理首页搜索请求
* 并进行分页(只对搜索到的信息分页)
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void pageByName(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求参数
int pageNo = DataUtils.parseInt(req.getParameter("pageNo"), 1);
int pageSize = DataUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);
//如果参数有name但没有值,接收的就是空串
//如果参数没有name,接收到的就是null
String furnName = req.getParameter("furnName");
//这样做,将""和null的业务逻辑合并在一起
if (furnName == null) {
furnName = "";
}
//调用service方法,获取Page对象
Page<Furn> page = furnService.pageByName(pageNo, pageSize, furnName);
//将page放入request中
req.setAttribute("page", page);
//请求转发到/customer/index.jsp
req.getRequestDispatcher("/views/customer/index.jsp")
.forward(req, resp);
}

15.3.4customer/index.jsp

修改搜索框参数

<form class="action-form" action="customerFurnServlet">
<input type="hidden" name="action" value="pageByName">
<input class="form-control" name="furnName" placeholder="输入家居名搜索" type="text" >
<button class="submit" type="submit"><i class="icon-magnifier"></i></button>
</form>

关于携带上次检索条件,即点击分页,显示的家居信息仍要符合搜索条件:

  1. 功能13-首页分页实现,在导航栏的超链接上附上了请求的servlet路径,servlet中方法以及当前页数等参数。检索信息的分页首页分页 的导航栏,两者功能是相似的,只是在请求的servlet,servlet方法等参数不一致

  2. 检索信息的分页:

    由于furnName的值在搜索栏中提交给CustomerFurnServlet,我们可以在CustomerFurnServlet的pageByName方法中获取到的furnName值,并设置在page的属性url中,返回给jsp页面,这样就可以拿到furnName了

  3. 改进CustomerFurnServlet

    protected void pageByName(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //获取请求参数
    int pageNo = DataUtils.parseInt(req.getParameter("pageNo"), 1);
    int pageSize = DataUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);
    //如果参数有name但没有值,接收的就是空串
    //如果参数没有name,接收到的就是null
    String furnName = req.getParameter("furnName");
    //这样做,将""和null的业务逻辑合并在一起
    if (furnName == null) {
    furnName = "";
    }
    //调用service方法,获取Page对象
    Page<Furn> page = furnService.pageByName(pageNo, pageSize, furnName);
    //根据furnName
    StringBuilder url = new StringBuilder("customerFurnServlet?action=pageByName");
    if (!"".equals(furnName)) {//如果furnName不为空串,就拼接 furnName参数
    url.append("&furnName=").append(furnName);
    }
    page.setUrl(url.toString());
    //将page放入request中
    req.setAttribute("page", page);
    //请求转发到/customer/index.jsp
    req.getRequestDispatcher("/views/customer/index.jsp")
    .forward(req, resp);
    }
  4. index.jsp的分页导航栏

    <ul>
    <%--如果当前页大于1,就显示上一页--%>
    <c:if test="${requestScope.page.pageNo > 1}">
    <li><a href="${requestScope.page.url}&pageNo=${requestScope.page.pageNo-1}">上页</a></li>
    </c:if>
    <%-- 显示所有的分页数
    先确定开始页数 begin 第一页
    再确定结束页数 end 第page.TotalCount页
    --%>
    <c:set var="begin" value="1"/>
    <c:set var="end" value="${requestScope.page.pageTotalCount}"/>
    <c:forEach begin="${begin}" end="${end}" var="i">
    <%--如果i为当前页,就使用class=active来修饰--%>
    <c:if test="${i==requestScope.page.pageNo}">
    <li><a class="active" href="${requestScope.page.url}&pageNo=${i}">${i}</a></li>
    </c:if>
    <c:if test="${i!=requestScope.page.pageNo}">
    <li><a href="${requestScope.page.url}&pageNo=${i}">${i}</a></li>
    </c:if>
    </c:forEach>
    <%-- --%>
    <%-- 如果当前页小于总页数,就往下一页--%>
    <c:if test="${requestScope.page.pageNo < requestScope.page.pageTotalCount}">
    <li><a href="${requestScope.page.url}&pageNo=${requestScope.page.pageNo+1}">下页</a></li>
    </c:if>
    <li><a>共${requestScope.page.pageTotalCount}页</a></li>
    <li><a>共${requestScope.page.totalRow}记录</a></li>
    </ul>

15.3.5bugFix

上述代码虽然可以解决搜索信息的分页问题,但是如果我们第一次进入首页的时候,走的是CustomerFurnServlet的page方法,因此返回的page的url中是null,如果这时直接点击分页导航栏,就会显示错误,因为获取不到page的url属性,超链接拼接错误。

解决方案:直接将web/index.jsp的action改为pageByName,由于没有给furnName参数,默认搜索的是所有家居信息

15.4完成测试

访问urlhttp://localhost:8080/furniture_mall/,首次进入首页,点击分页导航栏,功能正常

在搜索框中搜索家居名称,成功返回合法数据,点击分页导航栏,功能正常

搜索结果第一页:

搜素结果第三页:

最新文章

  1. C# 中的as和is小结
  2. mono支持gb2312
  3. SpringMVC+spring-security+sitemesh+hibernate+freemarker整合-转
  4. 读&lt;&lt;CLR via C#&gt;&gt; 详谈泛型
  5. android 电容屏(一):电容屏基本原理篇
  6. slf4j绑定log4j失败
  7. asp.net + Jquery 实现类似Gridview功能 (一)
  8. 控制台调用天气API例子
  9. Struts 2 之配置文件
  10. Vue 部署IIS 单页面刷新报404问题
  11. 痞子衡嵌入式:ARM Cortex-M文件那些事(4)- 可重定向文件(.o/.a)
  12. 微信小程序中用户登录和登录态维护
  13. vue mock自己总结
  14. MapReduce论文学习
  15. 基于OpenSSL的HTTPS通信C++实现
  16. torchvision里densenet代码分析
  17. CentOS 6.5静态IP的设置(NAT和桥接联网方式都适用)
  18. VBox添加虚拟磁盘挂载
  19. SpringBoot启动器详解pom.xml
  20. JavaScript异常处理

热门文章

  1. vue2.x引入threejs
  2. vue3的Async Components异步组件
  3. 洛谷P4197 Peaks (Kruskal重构树)
  4. VM运行centos网络配置(出现错误)详解
  5. Linux 下搭建 Hive 环境
  6. 在IDEA 、springboot中使用切面aop实现日志信息的记录到数据库
  7. SQL--插入单引号值
  8. 十、RHEL Podman命令
  9. Java安全之Tomcat6 Filter内存马
  10. 夯实Java基础,一篇文章全解析线程问题