未登陆时使用cookie,登陆后使用redis,用户登陆时,cookie已存在购物车,合并后需要清除cookie数据
1.新建一个购物车实体类:
public class Cart implements Serializable{
private String sellerId;//商家ID
private String sellerName;//商家名称
private List<TbOrderItem> orderItemList;//购物明细
//getter and setter ......
}
2.未登录:cookie
服务层:
//1.根据商品SKU ID- itemId查询SKU商品信息
//2.获取商家ID getSellerId();
//3.根据商家ID判断购物车列表中是否存在该商家的购物车 List<Cart>
//4.如果购物车列表中不存在该商家的购物车
//4.1 新建购物车对象
//4.2 将新建的购物车对象添加到购物车列表
//5.如果购物车列表中存在该商家的购物车 Cart –List<TbOrderItem>
// 查询购物车明细列表中是否存在该商品 itemId
//5.1. 如果没有,新增购物车明细 TbOrderItem
//5.2. 如果有,在原购物车明细上添加数量,更改金额 TbOrderItem 修改Num
/**
* 购物车服务实现类
* @author Administrator
*
*/
@Service
public class CartServiceImpl implements CartService {
@Autowired
private TbItemMapper itemMapper;
@Override
public List<Cart> addGoodsToCartList(List<Cart> cartList, Long itemId, Integer num) {
//1.根据商品SKU ID查询SKU商品信息
TbItem item = itemMapper.selectByPrimaryKey(itemId);
if(item==null){
throw new RuntimeException("商品不存在");
}
if(!item.getStatus().equals("1")){
throw new RuntimeException("商品状态无效");
}
//2.获取商家ID
String sellerId = item.getSellerId();
//3.根据商家ID判断购物车列表中是否存在该商家的购物车
Cart cart = searchCartBySellerId(cartList,sellerId);
//4.如果购物车列表中不存在该商家的购物车
if(cart==null){
//4.1 新建购物车对象 ,
cart=new Cart();
cart.setSellerId(sellerId);
cart.setSellerName(item.getSeller());
TbOrderItem orderItem = createOrderItem(item,num);
List orderItemList=new ArrayList();
orderItemList.add(orderItem);
cart.setOrderItemList(orderItemList);
//4.2将购物车对象添加到购物车列表
cartList.add(cart);
}else{
//5.如果购物车列表中存在该商家的购物车
// 判断购物车明细列表中是否存在该商品
TbOrderItem orderItem = searchOrderItemByItemId(cart.getOrderItemList(),itemId);
if(orderItem==null){
//5.1. 如果没有,新增购物车明细
orderItem=createOrderItem(item,num);
cart.getOrderItemList().add(orderItem);
}else{
//5.2. 如果有,在原购物车明细上添加数量,更改金额
orderItem.setNum(orderItem.getNum()+num);
orderItem.setTotalFee(new BigDecimal(orderItem.getNum()*orderItem.getPrice().doubleValue()) );
//如果数量操作后小于等于0,则移除
if(orderItem.getNum()<=0){
cart.getOrderItemList().remove(orderItem);//移除购物车明细
}
//如果移除后cart的明细数量为0,则将cart移除
if(cart.getOrderItemList().size()==0){
cartList.remove(cart);
}
}
}
return cartList;
}
/**
* 根据商家ID查询购物车对象
* @param cartList
* @param sellerId
* @return
*/
private Cart searchCartBySellerId(List<Cart> cartList, String sellerId){
for(Cart cart:cartList){
if(cart.getSellerId().equals(sellerId)){
return cart;
}
}
return null;
}
/**
* 根据商品明细ID查询
* @param orderItemList
* @param itemId
* @return
*/
private TbOrderItem searchOrderItemByItemId(List<TbOrderItem> orderItemList ,Long itemId ){
for(TbOrderItem orderItem :orderItemList){
if(orderItem.getItemId().longValue()==itemId.longValue()){
return orderItem;
}
}
return null;
}
/**
* 创建订单明细
* @param item
* @param num
* @return
*/
private TbOrderItem createOrderItem(TbItem item,Integer num){
if(num<=0){
throw new RuntimeException("数量非法");
}
TbOrderItem orderItem=new TbOrderItem();
orderItem.setGoodsId(item.getGoodsId());
orderItem.setItemId(item.getId());
orderItem.setNum(num);
orderItem.setPicPath(item.getImage());
orderItem.setPrice(item.getPrice());
orderItem.setSellerId(item.getSellerId());
orderItem.setTitle(item.getTitle());
orderItem.setTotalFee(new BigDecimal(item.getPrice().doubleValue()*num));
return orderItem;
}
}
控制层:
(1)从cookie中取出购物车
(2)向购物车添加商品
(3)将购物车存入cookie
@RestController
@RequestMapping("/cart")
public class CartController {
@Reference
private CartService cartService;
@Autowired
private HttpServletRequest request;
@Autowired
private HttpServletResponse response;
/**
* 购物车列表
* @param request
* @return
*/
@RequestMapping("/findCartList")
public List<Cart> findCartList(){
String cartListString = util.CookieUtil.getCookieValue(request, "cartList","UTF-8");
if(cartListString==null || cartListString.equals("")){
cartListString="[]";
}
List<Cart> cartList_cookie = JSON.parseArray(cartListString, Cart.class);
return cartList_cookie;
}
/**
* 添加商品到购物车
* @param request
* @param response
* @param itemId
* @param num
* @return
*/
@RequestMapping("/addGoodsToCartList")
public Result addGoodsToCartList(Long itemId,Integer num){
try {
List<Cart> cartList =findCartList();//获取购物车列表
cartList = cartService.addGoodsToCartList(cartList, itemId, num);
util.CookieUtil.setCookie(request, response, "cartList", JSON.toJSONString(cartList),3600*24,"UTF-8");
return new Result(true, "添加成功");
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "添加失败");
}
}
}
3.已登陆:redis
判断当前用户是否登陆,如果未登录采用Cookie存储,如果登录则采用Redis存储。登录后要进行Cookie购物车与Redis购物车的合并操作,并清除Cookie购物车
spring-security.xml 更改配置:
去掉
<http pattern="/cart/*.do" security="none"></http>
添加
<http use-expressions="false" entry-point-ref="casProcessingFilterEntryPoint">
<intercept-url pattern="/cart/*.do" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/**" access="ROLE_USER"/>
<custom-filter position="CAS_FILTER" ref="casAuthenticationFilter" />
<custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
<custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
</http>
access=“IS_AUTHENTICATED_ANONYMOUSLY” 用于设置资源可以在不登陆时可以访问。
此配置与 security="none"的区别在于当用户未登陆时获取登陆人账号的值为anonymousUser ,而security="none"的话,无论是否登陆都不能获取登录人账号的值
服务层:
@Autowired
private RedisTemplate redisTemplate;
@Override
public List<Cart> findCartListFromRedis(String username) {
System.out.println("从redis中提取购物车数据....."+username);
List<Cart> cartList = (List<Cart>) redisTemplate.boundHashOps("cartList").get(username);
if(cartList==null){
cartList=new ArrayList();
}
return cartList;
}
@Override
public void saveCartListToRedis(String username, List<Cart> cartList) {
System.out.println("向redis存入购物车数据....."+username);
redisTemplate.boundHashOps("cartList").put(username, cartList);
}
控制层:
findCartList方法
/**
* 购物车列表
* @param request
* @return
*/
@RequestMapping("/findCartList")
public List<Cart> findCartList(){
String username = SecurityContextHolder.getContext().getAuthentication().getName();
if(username.equals("anonymousUser")){//如果未登录
//读取本地购物车//
..........
return cartList_cookie;
}else{//如果已登录
List<Cart> cartList_redis =cartService.findCartListFromRedis(username);//从redis中提取
return cartList_redis;
}
}
addGoodsToCartList方法
/**
* 添加商品到购物车
* @param request
* @param response
* @param itemId
* @param num
* @return
*/
@RequestMapping("/addGoodsToCartList")
public Result addGoodsToCartList(Long itemId,Integer num){
String username = SecurityContextHolder.getContext().getAuthentication().getName();
System.out.println("当前登录用户:"+username);
try {
List<Cart> cartList =findCartList();//获取购物车列表
cartList = cartService.addGoodsToCartList(cartList, itemId, num);
if(username.equals("anonymousUser")){ //如果是未登录,保存到cookie
util.CookieUtil.setCookie(request, response, "cartList", JSON.toJSONString(cartList),3600*24 ,"UTF-8");
System.out.println("向cookie存入数据");
}else{//如果是已登录,保存到redis
cartService.saveCartListToRedis(username, cartList);
}
return new Result(true, "添加成功");
} catch (RuntimeException e) {
e.printStackTrace();
return new Result(false, e.getMessage());
}catch (Exception e) {
e.printStackTrace();
return new Result(false, "添加失败");
}
}
登陆后合并:
服务层:
public List<Cart> mergeCartList(List<Cart> cartList1, List<Cart> cartList2) {
System.out.println("合并购物车");
for(Cart cart: cartList2){
for(TbOrderItem orderItem:cart.getOrderItemList()){
cartList1= addGoodsToCartList(cartList1,orderItem.getItemId(),orderItem.getNum());
}
}
return cartList1;
}
控制层:
@RequestMapping("/findCartList")
public List<Cart> findCartList(){
String username = SecurityContextHolder.getContext().getAuthentication().getName();
String cartListString = util.CookieUtil.getCookieValue(request, "cartList", "UTF-8");
if(cartListString==null || cartListString.equals("")){
cartListString="[]";
}
List<Cart> cartList_cookie = JSON.parseArray(cartListString, Cart.class);
if(username.equals("anonymousUser")){//如果未登录
return cartList_cookie;
}else{
List<Cart> cartList_redis =cartService.findCartListFromRedis(username);//从redis中提取
if(cartList_cookie.size()>0){//如果本地存在购物车
//合并购物车
cartList_redis=cartService.mergeCartList(cartList_redis, cartList_cookie);
//清除本地cookie的数据
util.CookieUtil.deleteCookie(request, response, "cartList");
//将合并后的数据存入redis
cartService.saveCartListToRedis(username, cartList_redis);
}
return cartList_redis;
}
}