商城项目第三天
今日任务
- 添加购物车
- 删除某个购物项
- 清空购物车
- 生成订单
##Redis优化 (选做)
一定要开启 redis 导入工具类 配置文件
####CategoryService
/*
查询所有分类信息
使用redis优化
1:去redis中查询分类信息
获取连接对象 查询
get("categories")
2.1:如果不存在
查询mysql数据库 dao
将java集合---JSON形式数据
存储到 redis中
2.2:如果存在
去 redis中取出来
拿出来的 JSON形式的集合
JSON集合---java集合
*/
public List<Category> findCategorys() {
List<Category> list = null;
try {
//连接redis 获取 jedis对象
Jedis jedis = RedisUtils.getJedis();
// 去redis中获取 键为 categories
String categories = jedis.get("categories");
if(categories==null){
// 没有 第一次来查询
list = categoryDao.findCategorys();
// 把查出来的结果 刷到 redis中
// 将javalist集合 转换成 json格式 字符串
String s = JSONArray.fromObject(list).toString();
jedis.set("categories",s);
}else{
// 如果 有 就是 categories 但是这是一个JSON格式的字符串
// JSON格式 字符串 ---- 还原回 List集合 List<Category>
// JSONArray.toList(JSONArray,Class) Class 什么意思? 代表谁的类型
// 将字符串格式json categories 转换成 JSONArray对象形式的 json
JSONArray jsonArray = JSONArray.fromObject(categories);
list = JSONArray.toList(jsonArray, Category.class);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
购物车实体对象
购物车实体对象
package com.itheima.domain;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/*
购物车
包含
多个购物项 采用的是 Map形式存储
总金额
*/
public class Cart {
private double total;
private Map<String,CartItem> itemMap = new HashMap<>();
public Cart() {
}
public Cart(double total,
Map<String, CartItem> itemMap) {
this.total = total;
this.itemMap = itemMap;
}
/**
添加购物车方法
购物项CartItem
判断 pid 是否存在与 itemMap键集中
存在
根据pid获取到之前的 购物项信息 更新数量
再存储
不存在
直接添加到 购物项集合itemMap中
最终都要更新 购物车总金额
*/
public void addCart(CartItem item){
// 获取到 添加的购物项中pid
String pid = item.getProduct().getPid();
// 判断 pid是否在集合中
if(itemMap.containsKey(pid)){
//存在
//取出之前的购物项
CartItem old = itemMap.get(pid);
// 将新的 count 与 old 的count 相加
int newCount = item.getCount()+old.getCount();
// 更新 old中的 count就行
old.setCount(newCount);
}else{
//不存在 第一添加
itemMap.put(pid,item);
}
// 最终都要更新 总金额
// 把新添加的购物项中小计,和之前总金额相加
total += item.getSubTotal();
}
/*
删除 某个购物项 根据pid
*/
public void removeItem(String pid){
//删除
CartItem removeItem = itemMap.remove(pid);
// 更新总金额
total -= removeItem.getSubTotal();
}
/**
* 清空购物车
*
*/
public void clearCart(){
itemMap.clear();
total=0;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
/*
如果 在转换json的时候
返回的 Map 的话
在页面中找到的json是一个 键值对 对象形式
无法完成遍历!!!
怎么办呢 ?
页面中需要的 值 集
所以 我们干脆 将 这个 get方法的返回值 就变成 返回值集
*/
public Collection<CartItem> getItemMap() {
return itemMap.values();
}
public void setItemMap(
Map<String, CartItem> itemMap) {
this.itemMap = itemMap;
}
@Override
public String toString() {
return "Cart{" +
"total=" + total +
", itemMap=" + itemMap +
'}';
}
}
购物项实体对象
package com.itheima.domain;
/*
一个购物项 有 商品+数量+小计 组合成的
三个属性
商品+数量+小计
*/
public class CartItem {
private Product product;
private int count;
private double subTotal;
public CartItem() {
}
public CartItem(Product product, int count, double subTotal) {
this.product = product;
this.count = count;
this.subTotal = subTotal;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
// 获取 小计 金额 = 商品价格*数量
public double getSubTotal() {
return product.getShop_price()*count;
}
public void setSubTotal(double subTotal) {
this.subTotal = subTotal;
}
@Override
public String toString() {
return "CartItem{" +
"product=" + product +
", count=" + count +
", subTotal=" + subTotal +
'}';
}
}
添加购物车功能
添加购物车步骤:
- 添加购物车按钮绑定点击事件
- 获取商品主键和添加数量
- 发送AJAX请求,提交主键和数量,页面跳转到购物车页面
- Servlet接收添加购物车的请求
- 封装购物车数据,添加到购物车对象中,响应JSON数据
- 购物车页面发送AJAX请求,从服务器端session域对象中获取购物车
- 购物车页面展示数据
info.html
function addCart(){
// 获取当前商品id 与选购数量
var pid = HM.getParameter("pid");
//获取录入的数量
var count = $("#count").val();
var url = "/cart?method=addCart";
var params = "pid="+pid+"&count="+count;
HM.ajax(url,params,function(data){
if(data.code==1){
alert(data.message);
// 应该跳转到哪里? 购物车详情页面
//http://www.itheima342.com:8020/web/view/cart/list.html
location.href="http://www.itheima342.com:8020/web/view/cart/list.html";
}
})
}
CartServlet
package com.itheima.web.servlet;
import com.itheima.constant.Constant;
import com.itheima.domain.Cart;
import com.itheima.domain.CartItem;
import com.itheima.domain.Category;
import com.itheima.domain.Product;
import com.itheima.service.CategoryService;
import com.itheima.service.ProductService;
import com.itheima.utils.BeanFactory;
import com.itheima.web.view.Result;
import net.sf.json.JSONObject;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/cart")
public class CartServlet extends BaseServlet {
private ProductService productService = BeanFactory.newInstance(ProductService.class);
/*
添加购物车
1:获取 pid count
2: 根据pid 查询商品信息
3:封装 购物项对象
4:添加到购物车
5:返回json数据
*/
public void addCart(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// 获取pid count
String pid = request.getParameter("pid");
int count = Integer.parseInt(request.getParameter("count"));
// 根据pid查询商品信息
Product product = productService.info(pid);
// 封装 购物项
CartItem cartItem = new CartItem();
cartItem.setCount(count);
cartItem.setProduct(product);
cartItem.setSubTotal(cartItem.getSubTotal());
// 找到 购物车 将购物项添加到购物车中
Cart cart = getCart(request);
/*
保证在一次会话中 购物车对象只有一个
单独写一个功能 获取购物车
*/
cart.addCart(cartItem);
// 封装 Result对象 转换成 json传递给页面
Result result = new Result(Constant.SUCCESS,"购物项已经添加到购物车中");
String s = JSONObject.fromObject(result).toString();
response.getWriter().write(s);
}
/*
展示 购物车
*/
public void showCart(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// 接收到请求之后 从session域中获取 购物车
Cart cart = getCart(request);
if(cart==null){
// 封装 Result对象 转换成 json传递给页面
Result result = new Result(Constant.FAILS,"购物车空空如也");
String s = JSONObject.fromObject(result).toString();
response.getWriter().write(s);
return;
}
// 封装 Result对象 转换成 json传递给页面
Result result = new Result(Constant.SUCCESS,"查询购物车成功",cart);
String s = JSONObject.fromObject(result).toString();
response.getWriter().write(s);
}
/**
* 获取购物车对象 保证一次会话中 只有一个购物车对象
* 购物车对象存储到session域中
* 从里面取出
* @param request
* @return
*/
public Cart getCart(HttpServletRequest request){
// 从session取出购物车
Cart cart = (Cart)request.getSession().getAttribute("cart");
// 如果没有 呢
if(cart==null){
// 创建一个新的
cart = new Cart();
// 存到域中
request.getSession().setAttribute("cart",cart);
}
return cart;
}
}
list.html
// 购物车页面加载完毕 需要 去发送一个请求 将这个购物车对象
$(function(){
// 直接发送请求
var url="/cart?method=showCart";
var params = "";
HM.ajax(url,params,function(data){
// data.data 是 返回来的购物车对象
if(data.code){
// data.data 就是cart的json 对象形式
var cart = data.data;
$("#total").html(cart.total+"元");
// 如何拿到购物项???
//cart.itemMap ; 购物项们?不是数组形式
// 后台改进之后 cart.itemMap就是一个数组形式了
var items = cart.itemMap;
$.each(items, function(index,ele) {
// 拼接tr
var str = "<tr class=\"active\">\n" +
"\t\t\t\t\t\t\t\t\t<td width=\"60\" width=\"40%\">\n" +
"\t\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"id\" value=\"22\">\n" +
"\t\t\t\t\t\t\t\t\t\t<img src=\"http://www.itheima335.com:8020/web/"+ele.product.pimage+"\" width=\"70\" height=\"60\">\n" +
"\t\t\t\t\t\t\t\t\t</td>\n" +
"\t\t\t\t\t\t\t\t\t<td width=\"30%\">\n" +
"\t\t\t\t\t\t\t\t\t\t<a target=\"_blank\">"+ele.product.pname+"</a>\n" +
"\t\t\t\t\t\t\t\t\t</td>\n" +
"\t\t\t\t\t\t\t\t\t<td width=\"20%\">\n" +
"\t\t\t\t\t\t\t\t\t\t¥"+ele.product.shop_price+"\n" +
"\t\t\t\t\t\t\t\t\t</td>\n" +
"\t\t\t\t\t\t\t\t\t<td width=\"10%\">\n" +
"\t\t\t\t\t\t\t\t\t\t"+ele.count+"\n" +
"\t\t\t\t\t\t\t\t\t</td>\n" +
"\t\t\t\t\t\t\t\t\t<td width=\"15%\">\n" +
"\t\t\t\t\t\t\t\t\t\t<span class=\"subtotal\">"+ele.subTotal+"</span>\n" +
"\t\t\t\t\t\t\t\t\t</td>\n" +
"\t\t\t\t\t\t\t\t\t<td>\n" +
"\t\t\t\t\t\t\t\t\t\t<a href=\"javascript:;\" \"deleCartItem('"+ele.product.pid+"')\" class=\"delete\">删除</a>\n" +
"\t\t\t\t\t\t\t\t\t</td>\n" +
"\t\t\t\t\t\t\t\t</tr>";
$("#cart").append(str)
});
}
})
})
删除购物车
删除购物车实现步骤:
- 购物车页面删除链接绑定点击事件
- 提示是否删除
- 发送AJAX请求,传递商品主键
- Servlet获取商品主键,删除Session中的购物车
- 响应删除功能信息
- 购物车页面重新加载
list.html
function deleteCartItem(pid){
// 发送ajax请求 根据pid删除 购物项
var url = "/cart?method=deleteCartItem";
var params = "pid="+pid;
HM.ajax(url,params,function(data){
if(data.code==1){
alert(data.message);
// 重写刷新 当前页面
location.reload();
}
})
}
CartServlet
/*
根据pid删除 购物车中的购物项
*/
public void deleteCartItem(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// 获取 pid
String pid = request.getParameter("pid");
// 接收到请求之后 从session域中获取 购物车
Cart cart = getCart(request);
// 调用 从 购物车中删除 购物项 根据pid
cart.removeItem(pid);
// 封装 Result对象 转换成 json传递给页面
Result result = new Result(Constant.SUCCESS,"删除购物项成功");
String s = JSONObject.fromObject(result).toString();
response.getWriter().write(s);
}
清空购物车
清空购物车实现步骤:
- 清空购物车按钮绑定事件
- 提示用户是否确认清空
- 发送AJAX请求
- Servlet将session中的购物车清空
- 响应清空成功信息
- 购物车重新加载页面
list.html
// 清空购物车
function clearCart(){
// 发送ajax请求 根据pid删除 购物项
var url = "/cart?method=clearCart";
HM.ajax(url,"",function(data){
if(data.code==1){
alert(data.message);
// 重写刷新 当前页面
location.reload();
}
})
}
CartServlet
/*
清空购物车
*/
public void clearCart(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// 接收到请求之后 从session域中获取 购物车
Cart cart = getCart(request);
// 调用 从 购物车中删除 购物项 根据pid
cart.clearCart();
// 封装 Result对象 转换成 json传递给页面
Result result = new Result(Constant.SUCCESS,"清空购物车成功");
String s = JSONObject.fromObject(result).toString();
response.getWriter().write(s);
}
订单生成
订单实体对象
public class Orders {
//主键
private String oid;
//下单时间
private String datetime;
//订单总金额
private double total;
//订单状态
private int state;
//收货地址
private String address;
//收货人
private String name;
//联系电话
private String telphone;
//用户主键
private String uid;
public String getOid() {
return oid;
}
public void setOid(String oid) {
this.oid = oid;
}
public Date getDatetime() {
return datetime;
}
public void setDatetime(Date datetime) {
this.datetime = datetime;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTelphone() {
return telphone;
}
public void setTelphone(String telphone) {
this.telphone = telphone;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
}
public class OrderItem {
//商品件数
private int count;
//总金额
private double subTotal;
//商品主键
private String pid;
//订单主键
private String oid;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public double getSubTotal() {
return subTotal;
}
public void setSubTotal(double subTotal) {
this.subTotal = subTotal;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getOid() {
return oid;
}
public void setOid(String oid) {
this.oid = oid;
}
实现步骤
- 提交订单按钮绑定事件,向服务器发送AJAX请求
- Servlet接收请求,从session购物车中取出购物车数据
- session对象中取出User对象,判断是否处于登录状态
- 判断购物车中是否有商品
- 将购物车中的数据转换成订单数据
- 调用service方法传递订单对象
- 订单对象保存到数据表
- 添加事物处理
list.html
// 生成订单
function orderSubmit(){
// 发送ajax请求 根据pid删除 购物项
var url = "/orders?method=orderSubmit";
HM.ajax(url,"",function(data){
if(data.code==1){
alert(data.message);
}
if(data.code==2){
alert(data.message);
location.href="http://www.itheima342.com:8020/web/login.html";
}
if(data.code==0){
alert(data.message);
location.href="http://www.itheima342.com:8020/web/index.html";
}
})
}
OrderServlet
package com.itheima.web.servlet;
import com.itheima.constant.Constant;
import com.itheima.domain.*;
import com.itheima.service.OrdersService;
import com.itheima.service.ProductService;
import com.itheima.utils.BeanFactory;
import com.itheima.utils.UUIDUtils;
import com.itheima.web.view.Result;
import net.sf.json.JSONObject;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
@WebServlet("/orders")
public class OrdersServlet extends BaseServlet {
private OrdersService ordersService = BeanFactory.newInstance(OrdersService.class);
/*
提交订单生成订单
*/
public void orderSubmit(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// 判断用户是否登陆
User user = (User)request.getSession().getAttribute("user");
if(user==null){
// 没有登陆
// 封装 Result对象 转换成 json传递给页面
Result result = new Result(Constant.LOGOUT,"您还没有登陆,请登录");
String s = JSONObject.fromObject(result).toString();
response.getWriter().write(s);
return;
}
//登陆成功
// 将购物车 从 session取出来
Cart cart = (Cart)request.getSession().getAttribute("cart");
if(cart==null){
// 购物车没物件!!
// 封装 Result对象 转换成 json传递给页面
Result result = new Result(Constant.FAILS,"购物车为空,请添加商品");
String s = JSONObject.fromObject(result).toString();
response.getWriter().write(s);
return;
}
// 将购物车中内容取出 存储到 订单对象中
// 创建一个订单对象
Orders orders = new Orders();
String oid = UUIDUtils.getUUID();
orders.setOid(oid);
orders.setUid(user.getUid());
//
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String ordertime = sdf.format(date);
orders.setOrdertime(ordertime);
// 订单金额 从购物车中获取
orders.setTotal(cart.getTotal());
// 订单状态
orders.setState(Constant.WEI_FU_KUAN);
ordersService.saveOrders(orders);
// -------------------生成订单项----------------
// 获取所有的购物项
Collection<CartItem> cartItems = cart.getItemMap();
for (CartItem cartItem : cartItems) {
// 封装 订单项
// 创建订单项对象
OrderItem orderItem = new OrderItem();
orderItem.setOid(oid);
orderItem.setPid(cartItem.getProduct().getPid());
orderItem.setCount(cartItem.getCount());
orderItem.setSubTotal(cartItem.getSubTotal());
ordersService.saveOrderItem(orderItem);
}
// 封装 Result对象 转换成 json传递给页面
Result result = new Result(Constant.SUCCESS,"订单已经生成,请后天来付款~~");
String s = JSONObject.fromObject(result).toString();
response.getWriter().write(s);
}
}
OrderService
package com.itheima.service.impl;
import com.itheima.dao.OrdersDao;
import com.itheima.domain.OrderItem;
import com.itheima.domain.Orders;
import com.itheima.service.OrdersService;
import com.itheima.utils.BeanFactory;
import java.sql.SQLException;
public class OrdersServiceImpl implements OrdersService{
private OrdersDao ordersDao = BeanFactory.newInstance(OrdersDao.class);
@Override
public void saveOrders(Orders orders) {
try {
ordersDao.saveOrders(orders);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void saveOrderItem(OrderItem orderItem) {
try {
ordersDao.saveOrderItem(orderItem);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
OrderDao
package com.itheima.dao.impl;
import com.itheima.dao.OrdersDao;
import com.itheima.domain.OrderItem;
import com.itheima.domain.Orders;
import com.itheima.utils.C3P0Utils;
import org.apache.commons.dbutils.QueryRunner;
import java.sql.SQLException;
public class OrdersDaoImpl implements OrdersDao {
private QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
/**
* 保存订单
* @param orders
* @throws SQLException
*/
public void saveOrders(Orders orders) throws SQLException {
String sql = "insert into orders values(?,?,?,?,?,?,?,?)";
Object[] params = {orders.getOid(),orders.getOrdertime(),orders.getTotal(),
orders.getState(),orders.getAddress(),orders.getName(),
orders.getTelephone(),orders.getUid()};
qr.update(sql,params);
}
/*
保存订单项
*/
public void saveOrderItem(OrderItem orderItem) throws SQLException {
String sql = "insert into orderitem values(?,?,?,?)";
Object[] params = {orderItem.getCount(),orderItem.getSubTotal(),
orderItem.getPid(),orderItem.getOid()};
qr.update(sql,params);
}
}