1、任務總述
1、帶有分頁查看分類下的商品信息
2、購物模塊_模型抽取
3、購物模塊_添加商品到購物車
4、購物模塊_移除購物項
5、購物模塊_清空購物車
2、查詢類別下的商品信息_帶有分頁
SQL代碼分析:
#查看類別cid=1的商品信息
SELECT * FROM product WHERE cid = 1 LIMIT ? ,?
#統計類別爲1的商品的數量
SELECT COUNT(*) FROM product WHERE cid = 1
原理如下:
步驟實現:
1、準備工作 /jsp/header.jsp
<a href='/store_v5/ProductServlet?method=findProductsByCidWithPage&curPage=1&cid="+obj.cid+"'>"+obj.cname+"</a></li>";
2、創建PageModel類對象
public class PageModel {
//基本屬性
private int currentPageNum;//當前頁數,由用戶指定 *
private int pageSize = 6;//每頁顯示的條數,固定的 *
private int totalRecords;//總記錄條數,數據庫查出來的 *
private int totalPageNum;//總頁數,計算出來的 *
private int startIndex;//每頁開始記錄的索引,計算出來的 *
private int prePageNum;//上一頁 *
private int nextPageNum;//下一頁 *
private List<Product> list;//已經分好頁的結果集,該list中只有10條記錄
//擴展屬性
//一共每頁顯示9個頁碼按鈕
private int startPage;//開始頁碼
private int endPage;//結束頁碼
//完善屬性
private String url;//也可不必寫
//要想使用我的分頁,必須給我兩個參數。一個是要看哪一頁,另一個是總記錄條數
public PageModel(int currentPageNum,int totalRecords,int pageSize){
this.currentPageNum = currentPageNum;
this.totalRecords = totalRecords;
this.pageSize=pageSize;
//計算查詢記錄的開始索引
startIndex = (currentPageNum-1)*pageSize;
//計算總頁數
totalPageNum = totalRecords%pageSize==0?(totalRecords/pageSize):(totalRecords/pageSize+1);
startPage = currentPageNum - 4; //5
endPage = currentPageNum + 4; //13
//看看總頁數夠不夠9頁
if(totalPageNum>9){
//超過了9頁
if(startPage < 1){
startPage = 1;
endPage = startPage+8;
}
if(endPage>totalPageNum){
endPage = totalPageNum;
startPage = endPage-8;
}
}else{
//不夠9頁
startPage = 1;
endPage = totalPageNum;
}
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getStartPage() {
return startPage;
}
public void setStartPage(int startPage) {
this.startPage = startPage;
}
public int getEndPage() {
return endPage;
}
public void setEndPage(int endPage) {
this.endPage = endPage;
}
public int getPrePageNum() {
prePageNum = currentPageNum-1;
if(prePageNum<1){
prePageNum = 1;
}
return prePageNum;
}
public int getNextPageNum() {
nextPageNum = currentPageNum+1;
if(nextPageNum>totalPageNum){
nextPageNum = totalPageNum;
}
return nextPageNum;
}
public int getCurrentPageNum() {
return currentPageNum;
}
public void setCurrentPageNum(int currentPageNum) {
this.currentPageNum = currentPageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalRecords() {
return totalRecords;
}
public void setTotalRecords(int totalRecords) {
this.totalRecords = totalRecords;
}
public int getTotalPageNum() {
return totalPageNum;
}
public void setTotalPageNum(int totalPageNum) {
this.totalPageNum = totalPageNum;
}
public int getStartIndex() {
return startIndex;
}
public void setStartIndex(int startIndex) {
this.startIndex = startIndex;
}
public void setPrePageNum(int prePageNum) {
this.prePageNum = prePageNum;
}
public void setNextPageNum(int nextPageNum) {
this.nextPageNum = nextPageNum;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
}
3、ProductServlet -> findProductsByCidWithPage
獲取cid,num
調用業務層功能:以分頁形式查詢當前類別下商品信息
返回PageModel對象(1_當前頁商品信息2_分頁3_url)
將PageModel對象放入request
轉發到/jsp/product_list.jsp
public String findProductsByCidWithPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取參數(當前頁面)
int curPage = Integer.parseInt(request.getParameter("curPage"));
//System.out.println(curPage);
String cid = request.getParameter("cid");
//調用業務層的方法(根據pid查信息)
ProductService service = new ProductServiceImpl();
try {
PageModel page = service.findProductsByCidWithPage(curPage,cid);
//將獲取到的商品放入request
request.setAttribute("page", page);
} catch (SQLException e) {
e.printStackTrace();
}
return "/jsp/product_list_COPY.jsp";
}
4、ProductService
創建PageModel對象 目的:計算分頁參數
關聯集合
關聯url
@Override
public PageModel findProductsByCidWithPage(int cpage,String cid) throws SQLException {
int productsNum = dao.getProductsNum(cid);
PageModel page = new PageModel(cpage,productsNum,6);
page.setList(dao.findProductsByCidWithPage(page.getStartIndex(),cid,page.getPageSize()));
page.setUrl("ProductServlet?method=findProductsByCidWithPage&cid="+cid);
return page;
}
5、ProductDao
1_統計當前類別下商品個數
2_統計當前類別的當前頁中的商品信息
@Override
public int getProductsNum(String cid) throws SQLException {
String sql = "select count(*) from product where cid = ?";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
Long num = (Long) qr.query(sql, new ScalarHandler(),cid);
return num.intValue();
}
@Override
public List<Product> findProductsByCidWithPage(int num,String cid,int pageNum) throws SQLException {
String sql = "select * from product where cid = ? limit ?,?";
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
return qr.query(sql, new BeanListHandler<Product>(Product.class),cid,num,pageNum);
}
6、/jsp/product_list_COPY.jsp
獲取分頁對象並實現商品分頁
<c:if test="${empty page.list}">
<div class="row" style="width:1210px;margin:0 auto;"><h3>暫無商品信息!</h3></div>
</c:if>
<c:if test="${not empty page.list}">
<div class="row" style="width:1210px;margin:0 auto;">
<div class="col-md-12">
<ol class="breadcrumb">
<li><a href="ProductServlet?method=findProductsByCidWithPage&curPage=1">首頁</a></li>
</ol>
</div>
<c:forEach items="${page.list }" var="p">
<div class="col-md-2">
<a href="ProductServlet?method=findProductByPid&pid=${p.pid}">
<img src="${pageContext.request.contextPath}/${p.pimage}" width="170" height="170" style="display: inline-block;">
</a>
<p><a href="ProductServlet?method=findProductByPid&pid=${p.pid}" style='color:green'>${p.pname}</a></p>
<p><font color="#FF0000">商城價:¥${p.shop_price}</font></p>
</div>
</c:forEach>
</div>
<!--分頁 -->
<div style="width:380px;margin:0 auto;margin-top:50px;">
<ul class="pagination" style="text-align:center; margin-top:10px;">
<c:if test="${page.currentPageNum!=1 }">
<li><a href="${pageContext.request.contextPath}/${page.url}&curPage=${page.prePageNum}" aria-label="Previous"><span aria-hidden="true">«</span></a></li>
</c:if>
<c:forEach begin="1" end="${page.totalPageNum }" var="i">
<c:if test="${page.currentPageNum== i }">
<li><a>${i }</a></li>
</c:if>
<c:if test="${page.currentPageNum!= i }">
<li><a href="${pageContext.request.contextPath}/${page.url}&curPage=${i}">${i }</a></li>
</c:if>
</c:forEach>
<c:if test="${page.currentPageNum!=page.totalPageNum }">
<li>
<a href="${pageContext.request.contextPath}/${page.url}&curPage=${page.nextPageNum}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</c:if>
</ul>
</div>
</c:if>
約定:1、當前頁: curPage 2、向request放入PageModel屬性名稱page
小結:1、在第二期學習的時候就已經自己實現了商品模塊分類的功能,只不過實現的功能沒有這麼全面而已。我只實現了讀取所有商品並分頁,而這次還對不同的分類做了商品模塊分頁的操作。
2、自己實現的與參考的還是有區別的,比如Page對象和PageModel對象,PageModel對象在類中就已經把許多屬性在創建對象的時候就可以計算並完成初始化,還多了url、以及其他擴展屬性,並不是我一定要改變自己所學的代碼,是因爲這種封裝值得學習,有學習的價值。
3、我自己寫的Page對象的屬性太少,以至於Service中要額外計算大量的數值,看起來就很繁瑣。就好比Servlet中獲取到了curPage還要自己判斷是不是空值,其實在header.jsp中直接一個參數curPage=1就可以解決了。
4、總的來說就是:對象封裝要搞好;Service除了對特定功能的實現最好不要有其他繁雜的東西;代碼一定要一次次優化!
3、抽取購物車模型
步驟實現:
1、完成CartItem類對象的書寫封裝
public class CartItem {
private Product product; //商品信息:包含pid、pimage、pname
private int num = 0; //購買的數量
private double price = 0; //購買該商品的小計
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
price = num*product.getShop_price();
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
2、完成Cart類對象的書寫封裝
public class Cart {
Map<String, CartItem> products = new HashMap<String, CartItem>();//存放pid和商品信息
double totalPrice; //購物車總計價格
String pid; //商品類別
public void clearCart(){//清空購物車
products.clear();
}
/*添加購物項到購物車
當用戶點擊加入購物車按鈕,可以將當前要購買的商品id,商品數量發送到服務端,服務端根據商品id查詢到商品信息
有了商品信息Product對象,有了要購買商品數量,當前的購物項也就可以獲取到了*/
public void addCartItem(CartItem cartItem){//添加購物項
pid = cartItem.getProduct().getPid();
if(products.containsKey(pid)){
CartItem old = products.get(pid);
products.get(pid).setNum(old.getNum()+cartItem.getNum());
}else{
products.put(pid, cartItem);
}
}
public void removeCartItem(String pid){//移除購物項
products.remove(pid);
}
//返回MAP中所有的值
public Collection getCartItems(){
return products.values();
}
public double getTotalPrice() {
//totalPrice默認值設置爲0
totalPrice = 0;
//獲取到Map中所有的購物項
Collection<CartItem> values = products.values();
//遍歷所有的購物項,將購物項上的小計相加
for (CartItem cartItem : values) {
totalPrice+=cartItem.getPrice();
}
return totalPrice;
}
public void setTotalPrice(double totalPrice) {
this.totalPrice = totalPrice;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public Map<String, CartItem> getProducts() {
return products;
}
public void setProducts(Map<String, CartItem> products) {
this.products = products;
}
}
小結:
1、購物模塊:購物項+購物車,分開創建類
2、購物車一定要有:(清空購物車、移除購物項、添加購物項、計算總金額)等功能
3、功能實現一定要和實際相結合,根據實際來寫,功能就不會少。
4、添加商品到購物車
內存分析:
原理如下:
步驟實現:
1、準備工作
*/jsp/product_list.jsp 修改連接
<a href="${pageContext.request.contextPath}/ProductServlet?method=findProductByPid&pid=${p.pid}">
*/jsp/product_info.jsp
自己設置form表單,設置form method action
設置隱藏域向服務端傳遞商品pid
<form action="/store_v5/CartServlet?method=addCartItemToCart" method="post">
<div><strong>${product.pname }</strong></div>
<div style="border-bottom: 1px dotted #dddddd;width:350px;margin:10px 0 10px 0;">
<div>編號:${product.pid }</div>
</div>
<div style="margin:10px 0 10px 0;">商城價: <strong style="color:#ef0101;">¥:${product.shop_price}元/份</strong> 市場價: <del>¥${product.market_price}元/份</del>
</div>
<div style="margin:10px 0 10px 0;">促銷: <a target="_blank" title="限時搶購 (2020-05-23 ~ 2020-06-01)" style="background-color: #f07373;">限時搶購</a> </div>
<div style="padding:10px;border:1px solid #e7dbb1;width:330px;margin:15px 0 10px 0;;background-color: #fffee6;">
<div style="margin:5px 0 10px 0;">白色</div>
<div style="border-bottom: 1px solid #faeac7;margin-top:20px;padding-left: 10px;">購買數量:
<input id="quantity" name="num" value="1" maxlength="4" size="10" type="text">
<input type="hidden" name="pid" value="${product.pid}">
</div>
<div style="margin:20px 0 10px 0;;text-align: center;">
<%--加入到購物車 --%>
<a href="${pageContext.request.contextPath}/jsp/cart.jsp">
<input style="background: url('${pageContext.request.contextPath}/img/product.gif') no-repeat scroll 0 -600px rgba(0, 0, 0, 0);height:36px;width:127px;" value="加入購物車" type="submit">
</a> 收藏商品</div>
</div>
</form>
PS:如果一個表單中有多個按鈕,點擊不同的按鈕提交到不同路徑
var form= document.getElementById(“formId”); form.submit();
2、CartServlet -> addCartItemToCart
(從session獲取購物車
如果獲取不到,創建購物車對象,放在session中
如果獲取到,使用即可)
(獲取到商品id,數量
通過商品id查詢都商品對象
獲取到待購買的購物項)
(調用購物車上的方法
重定向到/jsp/cart.jsp)
//添加購物項到購物車
public String addCartItemToCart(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException {
//從request獲取session
HttpSession session = request.getSession();
//從session獲取購物車對象,並獲取pid與num
Cart cart = (Cart)session.getAttribute("cart");
String pid = request.getParameter("pid");
int num = Integer.parseInt(request.getParameter("num"));
ProductService service = new ProductServiceImpl();
//如果獲取不到,創建對象;否則添加商品
if(cart==null) cart = new Cart();
CartItem cartItem = new CartItem();
cartItem.setProduct(service.findProductByPid(pid));
cartItem.setNum(num);
//調用購物車上的方法
cart.addCartItem(cartItem);
//存放對象並重定向到cart.jsp
session.setAttribute("cart", cart);
response.sendRedirect("/store_v5/jsp/cart.jsp");
return null;
}
3、/jsp/cart.jsp 獲取購物車上商品信息(直接用c:if和c:foreach來做)
<c:if test="${empty cart.cartItems}">
<div class="row">
<div class="col-md-12"><h3>購物車中暫無商品!</h3></div>
</div>
</c:if>
<c:if test="${not empty cart.cartItems}">
<div class="row">
<div style="margin:0 auto; margin-top:10px;width:950px;">
<strong style="font-size:16px;margin:5px 0;">訂單詳情</strong>
<table class="table table-bordered">
<tbody>
<tr class="warning">
<th>圖片</th>
<th>商品</th>
<th>價格</th>
<th>數量</th>
<th>小計</th>
<th>操作</th>
</tr>
<c:forEach items="${cart.cartItems}" var="item">
<tr class="active">
<td width="60" width="40%">
<input type="hidden" name="pid" value="${item.product.pid }">
<img src="${pageContext.request.contextPath}/${item.product.pimage }" width="70" height="60">
</td>
<td width="30%">
<a target="_blank"> ${item.product.pname }</a>
</td>
<td width="20%">
¥${item.product.shop_price }
</td>
<td width="10%">
<input disabled="disabled" type="text" name="quantity" value="${item.num }" maxlength="4" size="10">
</td>
<td width="15%">
<span class="subtotal">¥${item.price }</span>
</td>
<td>
<a href="javascript:;" class="delete">刪除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
<div style="margin-right:130px;">
<div style="text-align:right;">
<em style="color:#ff6600;">
登錄後確認是否享有優惠
</em> 贈送積分: <em style="color:#ff6600;">${cart.totalPrice }</em> 商品金額: <strong style="color:#ff6600;">¥${cart.totalPrice }元</strong>
</div>
<div style="text-align:right;margin-top:10px;margin-bottom:10px;">
<a href="${pageContext.request.contextPath}/jsp/order_info.jsp" id="clear" class="clear">清空購物車</a>
<a href="${pageContext.request.contextPath}/jsp/order_info.jsp">
<%--提交表單 --%>
<input type="submit" width="100" value="提交訂單" name="submit" border="0" style="background: url('${pageContext.request.contextPath}/img/register.gif') no-repeat scroll 0 0 rgba(0, 0, 0, 0);
height:35px;width:100px;color:white;">
</a>
</div>
</div>
</c:if>
重定向/轉發區別:
1、一次還是兩次請求響應 request域數據丟失
2、路徑顯示問題
3、第二次訪問位置
4、重定向一定要加上項目名稱,否則報錯
5、移除購物車中的購物項
原理如下:
步驟實現:
1、準備工作
在刪除購物項的a標籤添加id屬性
<a href="javascript:;" class="delete" id="${item.product.pid}">刪除</a>
爲購物車上的刪除鏈接綁定了點擊事件
$(function(){
//頁面加載完畢之後獲取到class的值爲delete元素,爲其綁定點擊事件
$(".delete").click(function(){
if(confirm("確認刪除?")){
//獲取到被刪除商品pid
var pid=this.id;
window.location.href="/store_v5/CartServlet?method=removeCartItem&id="+pid;
}
});
});
2、CartServlet -> removeCartItem
獲取待刪除商品pid
獲取到購物車
調用購物車刪除購物項方法
重定向到/jsp/cart.jsp
//移除購物項到購物車
public String delCartItemFromCart(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException {
//從session獲取購物車對象,並獲取pid
Cart cart = (Cart)request.getSession().getAttribute("cart");
String pid = request.getParameter("pid");
//調用購物車上的方法
cart.removeCartItem(pid);
//重定向到cart.jsp
response.sendRedirect("/store_v5/jsp/cart.jsp");
return null;
}
6、清空購物車
原理如下:
步驟實現:
1、準備工作
/jsp/cart.jsp 修改連接或寫script
<a href="${pageContext.request.contextPath}/CartServlet?method=clearCart" id="clear" class="clear">清空購物車</a>
或
<a href="javascript:;" id="clear" class="clear">清空購物車</a>
$(function(){
//頁面加載完畢之後獲取到class的值爲delete元素,爲其綁定點擊事件
$("#clear").click(function(){
if(confirm("確認清空購物車?")){
window.location.href="/store_v5/CartServlet?method=clearCart";
}
});
});
2、CartServlet -> clearCart
獲取購物車
調用購物車的清空方法
重定向到/jsp/cart.jsp頁面
//移除購物項到購物車
public String clearCart(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException {
//從session獲取購物車對象
Cart cart = (Cart)request.getSession().getAttribute("cart");
//調用購物車上的方法
cart.clearCart();
//重定向到cart.jsp
response.sendRedirect("/store_v5/jsp/cart.jsp");
return null;
}
不積小流,無以成江海~