1 案例效果
2 案例分析
3 代码实现
1 CartItem对象
package www.test.domain;
public class CartItem {
private Product product;
private int buyNum;
private double subtotal;
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public int getBuyNum() {
return buyNum;
}
public void setBuyNum(int buyNum) {
this.buyNum = buyNum;
}
public double getSubtotal() {
return subtotal;
}
public void setSubtotal(double subtotal) {
this.subtotal = subtotal;
}
}
2 Cart对象
package www.test.domain;
import java.util.HashMap;
import java.util.Map;
public class Cart {
//该购物车中存储的n个购物项
private Map<String,CartItem> cartItems = new HashMap<String,CartItem>();
//商品的总计
private double total;
public Map<String, CartItem> getCartItems() {
return cartItems;
}
public void setCartItems(Map<String, CartItem> cartItems) {
this.cartItems = cartItems;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
}
3 ProductServlet对象
package www.test.web.servlet;
import java.io.IOException;
import java.sql.SQLException;
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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.google.gson.Gson;
import redis.clients.jedis.Jedis;
import www.test.domain.Cart;
import www.test.domain.CartItem;
import www.test.domain.Category;
import www.test.domain.Product;
import www.test.service.ProductService;
import www.test.utils.JedisPoolUtils;
import www.test.vo.PageBean;
public class ProductServlet extends BaseServlet {
/*public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获得请求的哪个方法method
String methodName = request.getParameter("method");
//防止非空,将productListByCid放在前面,这样就能避免
if("productListByCid".equals(methodName)){
productListByCid(request,response);
}else if("categoryList".equals(methodName)){
categoryList(request,response);
}else if("index".equals(methodName)){
index(request,response);
}else if("productInfo".equals(methodName)){
productInfo(request,response);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}*/
// 模块中的方法是通过方法名进行区分的
// 1 显示商品类别的功能
public void categoryList(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ProductService service = new ProductService();
// 先从缓存中查询categoryList 如果有直接使用 没有在从数据库中查询 存到缓存中
// 1、获得jedis对象 连接redis数据库
Jedis jedis = JedisPoolUtils.getJedis();
String categoryListJson = jedis.get("categoryListJson");
// 2、判断categoryListJson是否为空
if (categoryListJson == null) {
System.out.println("缓存没有数据 查询数据库");
// 准备分类数据
List<Category> categoryList = null;
try {
categoryList = service.findAllCategory();
} catch (SQLException e) {
e.printStackTrace();
}
// 使用转换工具将categoryList转换成json格式
Gson gson = new Gson();
categoryListJson = gson.toJson(categoryList);
// 将从数据库中获得的categoryListJson存储到缓存中
jedis.set("categoryListJson", categoryListJson);
}
// 将转换后的json格式字符串写出
// 写出前先解决乱码问题
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(categoryListJson);
}
// 2 显示首页的功能
public void index(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ProductService service = new ProductService();
// 获取热门商品-----List<Product>
List<Product> hotProductList = null;
try {
hotProductList = service.findHotProductList();
} catch (SQLException e) {
e.printStackTrace();
}
// 获取最新商品-----List<Product>
List<Product> newProductList = null;
try {
newProductList = service.findNewProductList();
} catch (SQLException e) {
e.printStackTrace();
}
// 准备分类数据
/*
* List<Category> categoryList =null; try { categoryList =
* service.findAllCategory(); } catch (SQLException e) {
*
* e.printStackTrace(); } request.setAttribute("categoryList",
* categoryList);
*/
// 将获取的数据存入request域
request.setAttribute("hotProductList", hotProductList);
request.setAttribute("newProductList", newProductList);
// 转发
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
// 3 显示商品的详细信息的功能
public void productInfo(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取cid和当前页
String cid = request.getParameter("cid");
String currentPage = request.getParameter("currentPage");
// 获取pid
String pid = request.getParameter("pid");
// 传递给service层并调取service层的方法
ProductService service = new ProductService();
Product product = null;
try {
product = service.findProductByPid(pid);
} catch (SQLException e) {
e.printStackTrace();
}
// 存储到request域中
request.setAttribute("product", product);
request.setAttribute("cid", cid);
request.setAttribute("currentPage", currentPage);
// 获取客户端携带的cookie----获得名字是pids的cookie
String pids = pid;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("pids".equals(cookie.getName())) {
pids = cookie.getValue();
// 1-3-2 本次访问的商品的pid是8----->8-1-3-2
// 1-3-2 本次访问的商品的pid是3----->3-1-2
// 1-3-2 本次访问的商品的pid是1----->2-1-3
// 将pids拆成一个数组
String[] split = pids.split("-");// {3,1,2}
// 数组转换成集合
List<String> asList = Arrays.asList(split);// [3,1,2]
LinkedList<String> list = new LinkedList<String>(asList); // [3,1,2]
// 判断集合中是否存在当前的pid
/*
* if(list.contains(pid)){ //包含当前查看的商品的pid //先删掉然后放在头上
* list.remove(pid); list.addFirst(pid); }else{
* //不包含当前查看的商品的pid 直接将该pid放在头上 list.addFirst(pid); }
*/
// 上面代码的优化
// 不管包不包含都需要放到头上
if (list.contains(pid)) {
// 包含当前查看的商品的pid
list.remove(pid);
}
list.addFirst(pid);
// 将[3,1,2]转成3-1-2字符串
StringBuffer sb = new StringBuffer();
for (int i = 0; i < list.size() && i < 7; ++i) {
sb.append(list.get(i));
sb.append("-"); // 3-1-2-
}
// 去掉3-1-2-后面的-
// substring包含头不包含尾
pids = sb.substring(0, sb.length() - 1);
}
}
}
// 创建cookie回写
Cookie cookie_pids = new Cookie("pids", pids);
cookie_pids.setMaxAge(60 * 60); // 单位为秒 设置cookie的存储事件一个小时
// 设置cookie的携带路径
cookie_pids.setPath(request.getContextPath());
// 将cookie_pids写回去
response.addCookie(cookie_pids);
// 转发
request.getRequestDispatcher("/product_info.jsp").forward(request, response);
}
// 4 根据商品的类别获得商品的列表
public void productListByCid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取cid
String cid = request.getParameter("cid");
String currentPageStr = request.getParameter("currentPage");
if(currentPageStr == null){
currentPageStr = "1";
}
int currentPage = Integer.parseInt(currentPageStr);
int currentCount =12;
//根据cid查询商品
ProductService service = new ProductService();
PageBean<Product> pageBean = service.findProductListByCid(cid,currentPage,currentCount);
request.setAttribute("pageBean", pageBean);
request.setAttribute("cid", cid);
//定义一个集合记录历史商品信息的集合
List<Product> historyProductList = new ArrayList<Product>();
//获取客户端携带的名字叫pids的cookie
Cookie[] cookies = request.getCookies();
if(cookies!=null){
for (Cookie cookie : cookies) {
if("pids".equals(cookie.getName())){
String pids = cookie.getValue(); //3-1-2
String[] split = pids.split("-");
for(String pid:split){
Product product =null;
try {
product = service.findProductByPid(pid);
historyProductList.add(product);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
//将历史记录的集合放到域中
request.setAttribute("historyProductList", historyProductList);
//转发
request.getRequestDispatcher("/product_list.jsp").forward(request, response);
}
// 5 将商品添加到购物车 addProductToCart
public void addProductToCart(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ProductService service = new ProductService();
HttpSession session = request.getSession();
//获得要放到购物车的商品的pid
String pid = request.getParameter("pid");
//获得该商品的购买数量
int buyNum = Integer.parseInt(request.getParameter("buyNum")) ;
//获得product对象
Product product = null;
try {
product = service.findProductByPid(pid);
} catch (SQLException e) {
e.printStackTrace();
}
//计算小计
double subtotal = product.getShop_price()*buyNum;
//封装cartItem
CartItem item = new CartItem();
item.setProduct(product);
item.setBuyNum(buyNum);
item.setSubtotal(subtotal);
//获得购物车---判断是否在session中已经存在购物车
Cart cart = (Cart) session.getAttribute("cart");
if(cart==null){
cart = new Cart();
}
// 将购物项放到车中----key是pid
//先判断购物车中是否已经包含此购物项目------判断key是否已经存在
//如果购物车已经存在该商品-----将现在买的数量与原有的数进行相加操作
Map<String, CartItem> cartItems = cart.getCartItems();
double newsubtotal = 0.0;
if(cartItems.containsKey(pid)){
//取出原有的商品的数量
CartItem cartItem = cartItems.get(pid);
int oldBuyNum = cartItem.getBuyNum();
//修改后的数量
int newBuyNum = oldBuyNum + buyNum;
cartItem.setBuyNum(newBuyNum);
//修改小计
//原来该商品的小计
double oldsubtotal = cartItem.getSubtotal();
//新买的该商品的小计
newsubtotal = buyNum*product.getShop_price();
cartItem.setSubtotal(newsubtotal+oldsubtotal);
//修改之后重新存入
cart.setCartItems(cartItems);
}else{
//如果购物车中没有该商品
cart.getCartItems().put(product.getPid(), item);
newsubtotal = buyNum*product.getShop_price();
}
//计算总计
double total = cart.getTotal()+newsubtotal;
cart.setTotal(total);
// 将车再次放入session
session.setAttribute("cart", cart);
//转发 直接跳转到购物车页面 转发的话,每次刷新金额都不变化不可以
//request.getRequestDispatcher("/cart.jsp").forward(request, response);
response.sendRedirect(request.getContextPath()+"/cart.jsp");
}
}
4 product_info.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!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>
<!-- 引入自定义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;
}
</style>
<script type="text/javascript">
function addCart() {
//获得购买商品的数量
var buyNum = $("#buyNum").val();
location.href="${pageContext.request.contextPath }/product?method=addProductToCart&pid=${product.pid}&buyNum="+buyNum;
}
</script>
</head>
<body>
<!-- 引入header.jsp -->
<jsp:include page="/header.jsp"></jsp:include>
<div class="container">
<div class="row">
<div
style="border: 1px solid #e4e4e4; 930px; margin-bottom: 10px; margin: 0 auto; padding: 10px; margin-bottom: 10px;">
<a href="./index.htm">首页 ></a> <a href="./蔬菜分类.htm">蔬菜 ></a>
<a>无公害蔬菜</a>
</div>
<div style="margin: 0 auto; 950px;">
<div class="col-md-6">
<img style="opacity: 1; 400px; height: 350px;" title=""
class="medium"
src="${pageContext.request.contextPath }/${product.pimage}">
</div>
<div class="col-md-6">
<div>
<strong>${product.pname }</strong>
</div>
<div
style="border-bottom: 1px dotted #dddddd; 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="限时抢购 (2014-07-30 ~ 2015-01-01)"
style="background-color: #f07373;">限时抢购</a>
</div>
<div
style="padding: 10px; border: 1px solid #e7dbb1; 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="buyNum" name="buyNum" value="1"maxlength="4" size="10" type="text">
</div>
<div style="margin: 20px 0 10px 0;; text-align: center;">
<a href="javascript:void(0);" onclick="addCart()"> <input
style="background: url('./images/product.gif') no-repeat scroll 0 -600px rgba(0, 0, 0, 0); height: 36px; 127px;"
value="加入购物车" type="button">
</a> 收藏商品
</div>
</div>
<a href="${pageContext.request.contextPath }/product?method=productListByCid&cid=${cid }¤tPage=${currentPage}">返回商品列表</a>
</div>
</div>
<div class="clear"></div>
<div style=" 950px; margin: 0 auto;">
<div
style="background-color: #d3d3d3; 930px; padding: 10px 10px; margin: 10px 0 10px 0;">
<strong>商品介绍</strong>
</div>
<div>
<img
src="${pageContext.request.contextPath }/${product.pimage}">
</div>
<div
style="background-color: #d3d3d3; 930px; padding: 10px 10px; margin: 10px 0 10px 0;">
<strong>商品参数</strong>
</div>
<div style="margin-top: 10px; 900px;">
<table class="table table-bordered">
<tbody>
<tr class="active">
<th colspan="2">基本参数</th>
</tr>
<tr>
<th width="10%">级别</th>
<td width="30%">标准</td>
</tr>
<tr>
<th width="10%">标重</th>
<td>500</td>
</tr>
<tr>
<th width="10%">浮动</th>
<td>200</td>
</tr>
</tbody>
</table>
</div>
<div style="background-color: #d3d3d3; 900px;">
<table class="table table-bordered">
<tbody>
<tr class="active">
<th><strong>商品评论</strong></th>
</tr>
<tr class="warning">
<th>暂无商品评论信息 <a>[发表商品评论]</a></th>
</tr>
</tbody>
</table>
</div>
<div style="background-color: #d3d3d3; 900px;">
<table class="table table-bordered">
<tbody>
<tr class="active">
<th><strong>商品咨询</strong></th>
</tr>
<tr class="warning">
<th>暂无商品咨询信息 <a>[发表商品咨询]</a></th>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- 引入footer.jsp -->
<jsp:include page="/footer.jsp"></jsp:include>
</body>
</html>
5 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>
<!-- 引入自定义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">
<div style="margin: 0 auto; margin-top: 10px; 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="${pageContext.request.contextPath }/${entry.value.product.pimage}"
width="70" height="60"></td>
<!--${cart.cartItems }获得是Map<String,CartItem>
entry.value获得是CartItem
entry.value.product获得product
-->
<td width="30%"><a target="_blank"> ${entry.value.product.pname}</a></td>
<td width="20%">¥${entry.value.product.shop_price}</td>
<td width="10%">
${entry.value.buyNum }
</td>
<td width="15%"><span class="subtotal">¥${entry.value.subtotal }</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.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; 100px; color: white;">
</a>
</div>
</div>
</div>
<!-- 引入footer.jsp -->
<jsp:include page="/footer.jsp"></jsp:include>
</body>
</html>