e3mall项目:购物车模块
程序员文章站
2024-02-27 19:52:27
...
e3mall项目:购物车模块
准备工作:创建服务层子工程:e3-cart,在其工程下创建e3-cart-interface、e3-cart-service。创建表现层子工程:e3-cart-web。创建好包结构,导入相关配置文件和静态资源。
一、服务层相关代码(CartService、CartServiceI,pl)
package cn.e3mall.cart.service;
import cn.e3mall.common.entity.E3Result;
import cn.e3mall.entity.TbItem;
import java.util.List; /**
* 购物车相关 service层
* Author: xushuai
* Date: 2018/5/30
* Time: 12:41
* Description:
*/
public interface CartService {
/**
* 添加商品到购物车
* @auther: xushuai
* @date: 2018/5/30 12:41
*/
void addProductToCart(Long itemId, Long userId, Integer num);
/**
* 将cookie中的商品列表添加到服务端
* @auther: xushuai
* @date: 2018/5/30 14:20
* @return: List<TbItem> 商品列表
*/
void addProductFromCookie(List<TbItem> items, Long userId);
/**
* 更新服务端商品数量
* @auther: xushuai
* @date: 2018/5/30 14:57
*/
void update(Long itemId, Long userId,Integer num);
/**
* 删除服务端指定商品
* @auther: xushuai
* @date: 2018/5/30 15:35
*/
void delete(Long itemId, Long userId);
/**
* 获取指定用户的购物车信息
* @auther: xushuai
* @date: 2018/5/30 16:00
* @return:
* @throws:
*/
List<TbItem> getItemListFromRedis(Long userId);
}
package cn.e3mall.cart.service.impl;
import cn.e3mall.cart.service.CartService;
import cn.e3mall.common.entity.E3Result;
import cn.e3mall.common.redis.JedisClient;
import cn.e3mall.common.utils.JsonUtils;
import cn.e3mall.dao.TbItemMapper;
import cn.e3mall.entity.TbItem;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 购物车相关 service层实现
* Author: xushuai
* Date: 2018/5/30
* Time: 12:41
* Description:
*/
@Service
public class CartServiceImpl implements CartService {
@Autowired
private JedisClient jedisClient;
@Value("${redis.cart}")
private String cart;
@Autowired
private TbItemMapper itemMapper;
@Override
public void addProductToCart(Long itemId, Long userId, Integer num) {
//生成redis的key
String key = cart + ":" + userId;
//生成redis的field
String field = itemId.toString();
//判断商品是否已存在
String json = jedisClient.hget(key, field);
if(StringUtils.isNotBlank(json)){
//存在,数量相加
TbItem item = JsonUtils.jsonToPojo(json, TbItem.class);
item.setNum(item.getNum() + num);
//将新的item对象,写入redis
jedisClient.hset(key,field,JsonUtils.objectToJson(item));
}
//不存在,查询该商品信息
TbItem item = itemMapper.selectByPrimaryKey(itemId);
item.setNum(num);
//对图片数据进行处理
String image = item.getImage();
if(StringUtils.isNotBlank(image)){
item.setImage(image.split(",")[0]);
}
//将item对象,写入redis
jedisClient.hset(key,field,JsonUtils.objectToJson(item));
}
@Override
public void addProductFromCookie(List<TbItem> items, Long userId) {
//遍历商品集合,添加到redis中
for(TbItem item : items){
//执行添加操作
addProductToCart(item.getId(),userId,item.getNum());
}
}
@Override
public void update(Long itemId, Long userId, Integer num) {
//生成redis的key
String key = cart + ":" + userId;
//生成redis的field
String field = itemId.toString();
//获取redis中的商品
String json = jedisClient.hget(key, field);
TbItem item = JsonUtils.jsonToPojo(json, TbItem.class);
//修改商品数量
item.setNum(num);
//然后重新写入
jedisClient.hset(key,field,JsonUtils.objectToJson(item));
}
@Override
public void delete(Long itemId, Long userId) {
//执行删除
jedisClient.hdel(cart+":"+userId,itemId.toString());
}
/**
* 获取指定用户的购物车商品列表
* @auther: xushuai
* @date: 2018/5/30 14:42
* @param: userId 用户ID
* @return: List<TbItem> 商品列表
*/
@Override
public List<TbItem> getItemListFromRedis(Long userId) {
//使用用户ID生成redis的key
String key = cart + ":" + userId;
//获取该key中所有的值
List<String> stringList = jedisClient.hvals(key);
//遍历集合,生成商品列表
List<TbItem> itemList = new ArrayList<>();
for(String json : stringList){
TbItem item = JsonUtils.jsonToPojo(json, TbItem.class);
itemList.add(item);
}
//返回商品列表
return itemList;
}
}
二、表现层相关代码(CartController、LoginInterceptor)
package cn.e3mall.cart.controller;
import cn.e3mall.cart.service.CartService;
import cn.e3mall.common.utils.CookieUtils;
import cn.e3mall.common.utils.JsonUtils;
import cn.e3mall.entity.TbItem;
import cn.e3mall.entity.TbUser;
import cn.e3mall.service.ItemService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
/**
* 购物车 web层
* Author: xushuai
* Date: 2018/5/29
* Time: 21:05
* Description:
*/
@Controller
public class CartController {
@Autowired
private ItemService itemService;
@Autowired
private CartService cartService;
@Value("${cookie.timeout}")
private Integer cookieTimeout;
/**
* 添加指定商品到购物车
* @auther: xushuai
* @date: 2018/5/29 21:06
*/
@RequestMapping("/cart/add/{itemId}")
public String addToCart(@PathVariable Long itemId,
@RequestParam(defaultValue = "1") Integer num,
HttpServletRequest request, HttpServletResponse response){
//判断当前是否为登录状态
TbUser user = (TbUser) request.getAttribute("user");
if(user != null){
//为登录状态
//调用service保存商品数据
cartService.addProductToCart(itemId,user.getId(),num);
//保存成功,返回
return "cartSuccess";
}
//获取cookie中的购物车列表
List<TbItem> items = getProductListByCart(request);
//校验当前添加商品是否在购物车中已存在
boolean flag = false;
for (TbItem item : items){
//已存在
if(item.getId() == itemId.longValue()){
//对数量进行增加
item.setNum(item.getNum() + num);
//修改标志,并退出循环
flag = true;
break;
}
}
//通过标志判断购物车是否存在该商品
if(!flag){
//不存在,按ID查询商品信息
TbItem item = (TbItem) itemService.load(itemId).getData();
item.setNum(num);
//处理图片数据
String image = item.getImage();
if(StringUtils.isNotBlank(image)){
item.setImage(image.split(",")[0]);
}
items.add(item);
}
//将最新的购物车列表写入cookie
CookieUtils.setCookie(request,response,
"CART",JsonUtils.objectToJson(items),cookieTimeout,true);
return "cartSuccess";
}
/**
* 展示购物车
* @auther: xushuai
* @date: 2018/5/29 22:32
* @return:
* @throws:
*/
@RequestMapping("/cart/cart")
public String showCart(HttpServletRequest request, HttpServletResponse response, Model model){
//判断当前是否为登录状态
TbUser user = (TbUser) request.getAttribute("user");
if(user != null){
//为登录状态,同步cookie中的数据到服务端
List<TbItem> items = getProductListByCart(request);
if(items != null){
//执行同步操作
cartService.addProductFromCookie(items, user.getId());
//删除cookie中的数据
CookieUtils.deleteCookie(request,response,"CART");
//查询服务端购物车数据
List<TbItem> itemList = cartService.getItemListFromRedis(user.getId());
//保存同步后的商品列表
model.addAttribute("cartList",itemList);
return "cart";
}
}
//为离线状态
//从cookie中取出购物车商品列表
List<TbItem> items = getProductListByCart(request);
//将购物车商品列表保存,发送到页面
model.addAttribute("cartList",items);
return "cart";
}
/**
* 更新购物车内指定商品数量
* @auther: xushuai
* @date: 2018/5/30 12:12
*/
@RequestMapping("/cart/update/num/{itemId}/{num}")
@ResponseBody
public String updateNum(@PathVariable Long itemId,@PathVariable Integer num,
HttpServletRequest request,HttpServletResponse response){
//判断当前是否为登录状态
TbUser user = (TbUser) request.getAttribute("user");
if(user != null){
//为登录状态,修改服务端对应商品数量
cartService.update(itemId,user.getId(),num);
//修改完成,返回
return itemId.toString();
}
//从cookie中取出购物车信息
List<TbItem> items = getProductListByCart(request);
//遍历商品列表,进行商品数量更新
boolean flag = false;
if(items != null && items.size() > 0){
for(TbItem item : items){
//如果存在该商品进行数量更新
if(item.getId() == itemId.longValue()){
item.setNum(num);
//修改标志为true
flag = true;
break;
}
}
}
//根据标志位判断是否做了修改
if(flag){
//做了修改,将新的购物车信息写入cookie
CookieUtils.setCookie(request,response,
"CART",JsonUtils.objectToJson(items),cookieTimeout,true);
}
//没有修改不做任何操作,返回即可
return itemId.toString();
}
@RequestMapping("/cart/delete/{itemId}")
public String delete(@PathVariable Long itemId,HttpServletRequest request,HttpServletResponse response){
//判断当前是否为登录状态
TbUser user = (TbUser) request.getAttribute("user");
if(user != null){
//登录状态,删除服务端指定商品
cartService.delete(itemId,user.getId());
//重定向到购物车列表
return "redirect:/cart/cart.html";
}else{
//未登录状态
//从cookie中取出购物车商品列表
List<TbItem> items = getProductListByCart(request);
//操作标志
boolean flag = false;
//健壮性判断
if(items != null && items.size() > 0){
//遍历商品列表,删除指定ID的商品
for(TbItem item : items){
if(item.getId() == itemId.longValue()){
//从cookie中删除该商品
items.remove(item);
//修改操作标志为true
flag = true;
//退出循环
break;
}
}
}
//判断操作标志
if(flag){
//进行了数据操作,将新的商品列表写入cookie
CookieUtils.setCookie(request,response,
"CART",JsonUtils.objectToJson(items),cookieTimeout,true);
}
}
//没有进行数据操作,不做任何处理
//重定向到购物车列表
return "redirect:/cart/cart.html";
}
/**
* 从cookie中获取购物车列表
* @auther: xushuai
* @date: 2018/5/29 21:37
*/
private List<TbItem> getProductListByCart(HttpServletRequest request) {
//从cookie中取数据
String value = CookieUtils.getCookieValue(request, "CART", true);
//如果json为空,返回一个空集合
if(StringUtils.isBlank(value)){
return new ArrayList<>();
}
//不为空,将json字符串转换为list集合
return JsonUtils.jsonToList(value,TbItem.class);
}
}
package cn.e3mall.cart.interceptor;
import cn.e3mall.common.entity.E3Result;
import cn.e3mall.common.redis.JedisClient;
import cn.e3mall.common.utils.CookieUtils;
import cn.e3mall.entity.TbUser;
import cn.e3mall.sso.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 登录状态判断拦截器
* Author: xushuai
* Date: 2018/5/30
* Time: 12:24
* Description:
*/
public class LoginInterceptor implements HandlerInterceptor{
@Autowired
private UserService userService;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
//从cookie中取出token信息
String token = CookieUtils.getCookieValue(httpServletRequest, "token");
//判断token是否为空
if(StringUtils.isBlank(token)){
//为空,直接放行
return true;
}
//不为空,使用token获取登录用户信息
E3Result e3Result = userService.getLoginUser(token);
//如果e3result中的status属性不是200,说明该登录状态为已过期,直接放行
if(e3Result.getStatus() != 200){
return true;
}
//登录状态正常,进行处理
//获取用户数据
TbUser user = (TbUser) e3Result.getData();
//将user保存到request中
httpServletRequest.setAttribute("user",user);
//放行
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
三、页面修改及其js修改
(1)设置小计处的id
(2)cart.js修改
var CART = {
itemNumChange : function(){
$(".increment").click(function(){//+
var _thisInput = $(this).siblings("input");
_thisInput.val(eval(_thisInput.val()) + 1);
$.post("/cart/update/num/"+_thisInput.attr("itemId")+"/"+_thisInput.val() + ".action?r=" + Math.random(),function(data){
CART.refreshTotalPrice(data);
});
});
$(".decrement").click(function(){//-
var _thisInput = $(this).siblings("input");
if(eval(_thisInput.val()) == 1){
return ;
}
_thisInput.val(eval(_thisInput.val()) - 1);
$.post("/cart/update/num/"+_thisInput.attr("itemId")+"/"+_thisInput.val() + ".action?r=" + Math.random(),function(data){
CART.refreshTotalPrice(data);
});
});
/*$(".itemnum").change(function(){
var _thisInput = $(this);
$.post("/service/cart/update/num/"+_thisInput.attr("itemId")+"/"+_thisInput.val(),function(data){
CART.refreshTotalPrice();
});
});*/
},
refreshTotalPrice : function(itemId){ //重新计算总价
var total = 0;
$(".itemnum").each(function(i,e){
var _this = $(e);
total += (eval(_this.attr("itemPrice")) * 10000 * eval(_this.val())) / 10000;
});
$("#allMoney2").html(new Number(total/100).toFixed(2)).priceFormat({ //价格格式化插件
prefix: '¥',
thousandsSeparator: ',',
centsLimit: 2
});
total = 0;
$(".itemnum").each(function(i,e){
var _this = $(e);
// alert(_this.attr("itemId"));
// alert(itemId);
if(_this.attr("itemId") == itemId){
total += (eval(_this.attr("itemPrice")) * 10000 * eval(_this.val())) / 10000;
}
});
$("#total_price"+itemId).html(new Number(total/100).toFixed(2)).priceFormat({ //价格格式化插件
prefix: '¥',
thousandsSeparator: ',',
centsLimit: 2
});
}
};
$(function(){
CART.itemNumChange();
});
(3)修改内容(对上方js修改进行说明)