删除一个购物项功能
分析:
cart.jsp页面
1.入口在cart.jsp页面,“删除”a标签所有的位置,点击这个a标签后,触发事件,为了页面功能友好,点击后,应该弹出对话框,询问是否确认删除,确认删除后,执行后台的删除功能。删除功能需要携带pid,直到删除的是哪一个。
2.传递pid是一个问题,pid从哪里获取呢?pid应该从<c:foreach> entry中获取得到entry.value.product.pid。
3.为了页面更加友好,如果购物车中的购物项为空,那么就给一个购物车为空的图片。图片从网上小米网上获取后,放在工程中。注意,判断的是购物项,而不是购物车
ProductServlet
1.获取要删除商品的的pid,删除商品的同时,需要注意修改购物车的总计,
准备:
步骤:
在cart.jsp页面
1.在“删除”所有a标签页面加入点击事件,οnclick="delProFormCart('${entry.value.product.key}')" 携带pid, 注意必须单引号,加入单引号才会识别是参数,而不是字符串。
2.编写oncilck 触发的函数, 加入友好提示confirm() ,如果确认删除,跳转到后台执行删除购物项的代码。
3,在显示整个购物车对象的位置判断购物项是否为空。${empty cart.cartItems}
在ProductServlet
1.获取要删除商品的pid。
2.获取session的购物车对象中的Map集合 cartItems
2.1。修改购物车对象的总价
3,根据pid删除cartItems中的购物项cartItem
3.1,把cartItems重新放回购物车中,把购物车重新放回session域中
(这步可以省略,因为cartltems,cart指向的数值与原来的数值内存地址是同一个,即,原来的数值已经发生变化,即使不放回去,数值已经变了。
这里涉及java,数据传值传参问题。 可以说java传数据都是传值,不是传引用。基本数据类型,还有String常量池的赋值,都是传统传值。
但,对象传递即在堆内存的数据,传形参同名,但起始不是同一个,而他们指向的内存地址才是同一个。)
4.跳转回cart.jsp页面
cart.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>黑马商城购物车</title>
<link rel="stylesheet" href="css/bootstrap.min.css" type="text/css" />
<script src="js/jquery-1.11.3.min.js" type="text/javascript"></script>
<script src="js/bootstrap.min.js" type="text/javascript"></script>
<script type="text/javascript">
function delProFromCart(pid){
if(confirm("您是否确定删除该商品")){
location.href="${pageContext.request.contextPath}/product?method=delProFromCart&pid="+pid;
}
}
</script>
<!-- 引入自定义css文件 style.css -->
<link rel="stylesheet" href="css/style.css" type="text/css" />
<style>
body {
margin-top: 20px;
margin: 0 auto;
}
.carousel-inner .item img {
width: 100%;
height: 300px;
}
font {
color: #3164af;
font-size: 18px;
font-weight: normal;
padding: 0 10px;
}
</style>
</head>
<body>
<!-- 引入header.jsp -->
<jsp:include page="/header.jsp"></jsp:include>
<div class="container">
<div class="row">
<!-- 判断购物车内的购物项是否为空 -->
<c:if test="${!empty cart.cartItems }">
<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="entry">
<tr class="active">
<td width="60" width="40%">
<input type="hidden" name="id" value="22">
<img src="${entry.value.product.pimage }" width="70" height="60">
</td>
<td width="30%">
<a target="_blank">${entry.value.product.pname }</a>
</td>
<td width="20%">
¥${entry.value.product.shop_price }
</td>
<td width="10%">
<input type="text" name="quantity" value="${entry.value.buyNum }" maxlength="4" size="10">
</td>
<td width="15%">
<span class="subtotal">${entry.value.subtotal }</span>
</td>
<td>
<a href="javascript:;" class="delete" οnclick="delProFromCart('${entry.key}')">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</c:if>
<!-- 购物车为空 -->
<c:if test="${empty cart.cartItems }">
<img src="${pageContext.request.contextPath }/images/cart-empty.png">
</c:if>
</div>
<div style="margin-right:130px;">
<div style="text-align:right;">
<em style="color:#ff6600;">
登录后确认是否享有优惠
</em> 赠送积分: <em style="color:#ff6600;">${cart.total }</em> 商品金额: <strong style="color:#ff6600;">¥${cart.total }元</strong>
</div>
<div style="text-align:right;margin-top:10px;margin-bottom:10px;">
<a href="order_info.htm" id="clear" class="clear">清空购物车</a>
<a href="order_info.htm">
<input type="submit" width="100" value="提交订单" name="submit" border="0" style="background: url('./images/register.gif') no-repeat scroll 0 0 rgba(0, 0, 0, 0);
height:35px;width:100px;color:white;">
</a>
</div>
</div>
</div>
<!-- 引入footer.jsp -->
<jsp:include page="/footer.jsp"></jsp:include>
</body>
</html>
ProductServlet
package com.itheima.web.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.google.gson.Gson;
import com.itheima.domain.Cart;
import com.itheima.domain.CartItem;
import com.itheima.domain.Category;
import com.itheima.domain.PageBean;
import com.itheima.domain.Product;
import com.itheima.service.ProductService;
import com.itheima.utils.JedisPoolUtils;
import redis.clients.jedis.Jedis;
public class ProductServlet extends BaseServlet {
//在购物车中删除某一个购物项
public void delProFromCart(HttpServletRequest request, HttpServletResponse response) throws IOException {
//获取要删除购物项的pid
String pid = request.getParameter("pid");
//获取购物车对象
Cart cart = (Cart) request.getSession().getAttribute("cart");
if(cart!=null) {
//获取购物车对象中的Map集合cartItems
Map<String, CartItem> cartItems = cart.getCartItems();
//修改总价
cart.setTotal(cart.getTotal()-cartItems.get(pid).getSubtotal());
//根据pid删除购物项
cartItems.remove(pid);
}
//跳转会购物车页面
response.sendRedirect(request.getContextPath()+"/cart.jsp");
}
//把商品加入购车功能
public void addProductToCart(HttpServletRequest request,HttpServletResponse response) throws IOException {
ProductService service = new ProductService();
HttpSession session = request.getSession();
//获取商品pid,根据pid获去加入购物车的商品
String pid = request.getParameter("pid");
Product product = service.findProductByPid(pid);
int buyNum = Integer.parseInt( request.getParameter("buyNum"));
//计算这次加入购物车的小计
double newSubtotal = (buyNum * product.getShop_price());
//判断之前是否已存在该购物项
//获取购物车对象,第一次没有就创建一个,购物车对象放在session里
Cart cart = (Cart) session.getAttribute("cart");
if(cart==null) {
cart = new Cart();
}
//定义购物车里购物项的小计,如果购物车里没有该购物项,则小计为这个加入购物车的小计
double subtotal = newSubtotal;
//获取购物车里的购物项集合,并判断,如果不存在直接封装购物项
Map<String, CartItem> cartItems = cart.getCartItems();
if(cartItems.containsKey(pid)) {
//如果购物项已经存在,修改购物数量,还有小计,
buyNum += cartItems.get(pid).getBuyNum();
subtotal = newSubtotal + cartItems.get(pid).getSubtotal();
}
//封装购物项
CartItem cartItem = new CartItem();
cartItem.setBuyNum(buyNum);
cartItem.setProduct(product);
cartItem.setSubtotal(subtotal);
//重新封装购物车
cartItems.put(pid, cartItem);
cart.setCartItems(cartItems);
//重新更新商品总计
double total = cart.getTotal() + newSubtotal;
cart.setTotal(total);
//把购物车项重新放回session域
session.setAttribute("cart", cart);
//重定向到购物车页面
response.sendRedirect(request.getContextPath()+"/cart.jsp");
}
//显示商品详细信息product_info.jsp 功能
public void productInfo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ProductService service= new ProductService();
//获取商品pid cid currentPage
String pid = request.getParameter("pid");
String cid = request.getParameter("cid");
String currentPage = request.getParameter("currentPage");
//根据pid查询商品
Product product = service.findProductByPid(pid);
//传到request域 转发到product_info.jsp
request.setAttribute("product", product);
//需要currentPage与cid,为了返回上一级功能作必要参数
request.setAttribute("cid", cid);
request.setAttribute("currentPage", currentPage);
//第一次访问,pids的值就是pid
String pids = pid;
//获取cookies
Cookie[] cookies = request.getCookies();
if(cookies!=null) {
//不为空才执行该搓澡
for(Cookie cookie:cookies) {
if(cookie.getName().equals("pids")){
//获取pids ----- 3-2-1
pids = cookie.getValue();
//把“-”去除
String[] split = pids.split("-");//[3,2,1]
//翻到LinkedList方便之后的修改pids操作
List<String> asList = Arrays.asList(split);
LinkedList<String> list = new LinkedList<String>(asList);
//判断cookie pids中已经存在该pid
if(list.contains(pid)) {
//已经存在,删除后再添加到头
list.remove(pid);
list.addFirst(pid);
}else {
//不存在,直接添加到头
list.addFirst(pid);
}
//从新变回3-2-1模式 限制显示数量为7个
StringBuffer sb = new StringBuffer();
for(int i=0; i<list.size(); i++) {
sb.append(list.get(i));
sb.append("-");
}
pids=sb.substring(0, sb.length()-1);
}
}
}
//把pids存到cookies中
Cookie cookie_pids = new Cookie("pids", pids);
response.addCookie(cookie_pids);
request.getRequestDispatcher("/product_info.jsp").forward(request, response);
}
//根据商品分类cid查找商品,并显示在商品列表product_list.jsp功能
public void productListByCid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ProductService service= new ProductService();
//设置当前显示条数当前页,为null默认为第一页,
String currentPageStr = request.getParameter("currentPage");
if(currentPageStr==null) {
currentPageStr="1";
}
int currentPage = Integer.parseInt(currentPageStr);
int currentCount = 12;
//获取cid,并根据cid获取商品列表
String cid = request.getParameter("cid");
//传递数据到service层,封装pageBean
PageBean<Product> pageBean = service.findPageBean(currentPage,currentCount,cid);
//把pageBean传到request域
request.setAttribute("pageBean", pageBean);
//分页跳转回这个功能的时候需要cid
request.setAttribute("cid", cid);
//历史商品记录显示
//从cookies获取pids
Cookie[] cookies = request.getCookies();
List<Product> historyProductList = new ArrayList<Product>();
if(cookies!=null) {
for(Cookie cookie :cookies) {
if(cookie.getName().equals("pids")) {
String pids = cookie.getValue();
String[] split = pids.split("-");
//根据数组中的每个pid 进行遍历获取商品,限制数量为7个
for(int i=0; i<split.length&&i<7;i++) {
Product product = service.findProductByPid(split[i]);
historyProductList.add(product);
}
}
}
}
//把历史商品集合传到request域
request.setAttribute("historyProductList", historyProductList);
request.getRequestDispatcher("/product_list.jsp").forward(request, response);
}
//查找所有商品分类
public void findAllCategory(HttpServletRequest request, HttpServletResponse response) throws IOException {
// ProductService service = new ProductService();
// //从redis获取,并判断是否已存在categoryListJson
// Jedis jedis = JedisPoolUtils.getJedis();
// String categoryListJson = jedis.get("categoryListJson");
// if(categoryListJson==null) {
// //如果不存在,从数据库查找,并存在redis中
// List<Category> categoryList = service.findAllCategory();
// Gson gson = new Gson();
// categoryListJson = gson.toJson(categoryList);
// jedis.set("categoryListJson", categoryListJson);
// }
// response.setContentType("text/html;charset=UTF-8");
// response.getWriter().write(categoryListJson);
//从数据库查找所有商品分类
ProductService service = new ProductService();
List<Category> categoryList = service.findAllCategory();
//把categoryList变为json格式
Gson gson = new Gson();
String categoryListJson = gson.toJson(categoryList);
//把jason传回ajax
//有中文解决乱码问题
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(categoryListJson);
}
//首页index显示热门商品与最新商品功能
public void index (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ProductService service = new ProductService();
//获取热门商品---list<Product>--hotProductList
List<Product> hotProductList = service.findHotProduct();
//获取最新商品--list<Product>--newProductList
List<Product> newProductList = service.findNewProduct();
//传到request域
request.setAttribute("hotProductList", hotProductList);
request.setAttribute("newProductList", newProductList);
//转发
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
}
ProductService
package com.itheima.service;
import java.sql.SQLException;
import java.util.List;
import com.itheima.dao.ProductDao;
import com.itheima.domain.Category;
import com.itheima.domain.PageBean;
import com.itheima.domain.Product;
public class ProductService {
//获取热门商品
public List<Product> findHotProduct() {
ProductDao dao = new ProductDao();
List<Product> hotProductList=null;
try {
hotProductList = dao.findHotProduct();
} catch (SQLException e) {
e.printStackTrace();
}
return hotProductList;
}
//获取最新商品
public List<Product> findNewProduct() {
ProductDao dao = new ProductDao();
List<Product> newProductList=null;
try {
newProductList = dao.findNewProduct();
} catch (SQLException e) {
e.printStackTrace();
}
return newProductList;
}
//查找商品所有分类
public List<Category> findAllCategory() {
ProductDao dao = new ProductDao();
List<Category> categoryList =null;
try {
categoryList = dao.findAllCategory();
} catch (SQLException e) {
e.printStackTrace();
}
return categoryList;
}
//封装PageBean对象
public PageBean<Product> findPageBean(int currentPage, int currentCount, String cid) {
ProductDao dao = new ProductDao();
//创建PageBean对象
PageBean<Product> pageBean = new PageBean<Product>();
//封装当前页
pageBean.setCurrentPage(currentPage);
//封装当前显示条数
pageBean.setCurrentCount(currentCount);
//封装总共条数
int totalCount =0;
try {
totalCount = dao.findTotalCount(cid).intValue();
} catch (SQLException e) {
e.printStackTrace();
}
pageBean.setTotalCount(totalCount);
//封装总共页数
int totalPage = (int) Math.ceil((1.0*totalCount/currentCount));
pageBean.setTotalPage(totalPage);
//封装商品列表
int index = (currentPage-1)*currentCount;
List<Product> productList =null;
try {
productList = dao.findProductByCid(cid,index,currentCount);
} catch (SQLException e) {
e.printStackTrace();
}
pageBean.setList(productList);
return pageBean;
}
//根据pid查询商品
public Product findProductByPid(String pid) {
ProductDao dao = new ProductDao();
Product product =null;
try {
product = dao.findProductByPid(pid);
} catch (SQLException e) {
e.printStackTrace();
}
return product;
}
}
ProductDao
package com.itheima.dao;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import com.itheima.domain.Category;
import com.itheima.domain.Product;
import com.itheima.utils.DataSourceUtils;
public class ProductDao {
//获取热门商品
public List<Product> findHotProduct() throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select * from product where is_hot=? limit ?,?";
return runner.query(sql, new BeanListHandler<Product>(Product.class), 1,0,9);
}
//获取最新商品
public List<Product> findNewProduct() throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select * from product order by pdate desc limit ?,?";
return runner.query(sql, new BeanListHandler<Product>(Product.class), 0,9);
}
//查找商品所有分类
public List<Category> findAllCategory() throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select * from category";
return runner.query(sql, new BeanListHandler<Category>(Category.class));
}
// 根据cid查询还有起始索引获得指定数量的商品集合
public List<Product> findProductByCid(String cid, int index, int currentCount) throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select * from product where cid=? limit ?,?";
return runner.query(sql, new BeanListHandler<Product>(Product.class), cid,index,currentCount);
}
//根据cid查询所有商品的总数
public Long findTotalCount(String cid) throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select count(*) from product where cid=?";
Long query = (Long) runner.query(sql, new ScalarHandler(), cid);
return query;
}
//根据pid查询商品
public Product findProductByPid(String pid) throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select * from product where pid=?";
Product query = runner.query(sql, new BeanHandler<Product>(Product.class), pid);
return query;
}
}