e3mall商城總結12之購物車的實現、以及購物車小計問題、json406報錯

說在前面的話

一、本節主要講了e3mall購物車的實現方法,我搭建的項目和系統購物車有一些區別,所以這裏須要說一下。系統搭建的項目在未登錄的狀況下也能夠經過cookie進行加入購物車,當用戶要下單的時候再進行攔截(配置攔截器),若用戶沒登錄。則跳轉登錄頁面,登錄完成後繼續剛纔的操做,同時把cookies中的商品加入到後臺redis緩存中(其中須要判斷redis中是否含有該商品,若含有,則增長數量),而後進行支付購買。若用戶已登錄,加入的購物車則直接保存到後臺redis緩存中。相似JD。
二、而我搭建的項目購物車是不存入cookies中的,在e3mall-cart這個項目中就配置了攔截器,若用戶未登錄則強制登錄,登錄後繼續以前的操做,保存的購物車商品數據都是存在redis緩存中的。所以我搭建的業務邏輯稍微簡單一點。
三、後面我把留下的做業也作了,就是在修改購物車中商品的數量的時候,該商品的小計不會跟隨數量的變化而變化這個BUG。
html

說在前面的話

用戶在購物車選購商品的時候,強制登錄。登陸後把購物車數據保存到服務端。須要永久保存,能夠保存到數據庫中。能夠把購物車數據保存到redis中。此處保存到redis中。
redis使用的數據類型(由於購物車的數據不須要使用TTL,所以建議使用hash)
a)使用hash數據類型
b)Hash的key應該是用戶id。Hash中的field是商品id,value能夠把商品信息轉換成json
添加購物車
直接把商品數據保存到redis中。
如何判斷是否登陸?
a)從cookie中取token
b)取不到未登陸
c)取到token,到redis中查詢token是否過時。
d)若是過時,未登陸狀態
e)沒過時登陸狀態。java

判斷用戶是否登陸

應該使用springmvc攔截器實現。
一、實現一個HandlerInterceptor接口。
二、在執行handler方法以前作業務處理
三、從cookie中取token。使用CookieUtils工具類實現。
四、沒有取到token,用戶未登陸。攔截,使用response.sendredirect()進行跳轉
五、取到token,調用sso系統的服務,根據token查詢用戶信息。
六、沒有返回用戶信息(null)。登陸已通過期,未登陸,攔截,使用response.sendredirect()進行跳轉
七、返回用戶信息。用戶是登陸狀態。能夠把用戶對象保存到request中,在Controller中能夠經過判斷request中是否包含用戶對象,肯定是否爲登陸狀態,放行。web

首先來配置一下登錄攔截器
Logininterceptor .javaredis

package cn.tsu.cart.e3mall.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.jboss.netty.util.internal.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import cn.tsu.cart.e3mall.config.CartConfig;
import cn.tsu.cart.e3mall.service.TokenService;
import cn.tsu.e3mall.pojo.TbUser;
import cn.tsu.e3mall.utils.CookieUtils;
import cn.tsu.e3mall.utils.E3Result;
import cn.tsu.sso.e3mall.service.UserService;
/**
 * 判斷用戶是否登陸的攔截器
 * @author xiaofeng
 *
 */
public class Logininterceptor implements HandlerInterceptor {
	
	
	@Autowired
	private TokenService tokenService;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception 
	{
		//獲取請求的連接
		String url = request.getRequestURL().toString();
		//若是連接中包含cart
		if (url.contains("cart"))
		{
			//從cookie中取token。使用CookieUtils工具類實現
			String cookieValue = CookieUtils.getCookieValue(request, "USER_LOGIN_TOKEN");
			//若是取到的數據不爲空
			if (StringUtils.isNotBlank(cookieValue))
			{
				//經過token獲取e3result對象
				E3Result e3Result = tokenService.getToken(cookieValue);
				//若是對象的status是200的話,說明取到
				if (e3Result.getStatus() == 200) 
				{
					//轉爲tbuser對象
					TbUser tbUser = (TbUser) e3Result.getData();
					request.setAttribute("tbUser", tbUser);
					return true;
				}
			}
		}
		//不然則跳轉登錄頁面並把url也傳過去。
		response.sendRedirect(CartConfig.LOGIN_HEAD+"/page/login?redirect="+url);
		return false;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub

	}

}

在這裏插入圖片描述

下面再看看代碼

service層代碼:
CartServiceImpl.javaspring

package cn.tsu.cart.e3mall.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.tsu.cart.e3mall.service.CartService;
import cn.tsu.e3mall.dao.TbItemMapper;
import cn.tsu.e3mall.jedis.JedisClient;
import cn.tsu.e3mall.pojo.TbItem;
import cn.tsu.e3mall.utils.E3Result;
import cn.tsu.e3mall.utils.JsonUtils;
import cn.tsu.sso.e3mall.service.config.UserConfig;
/**
 * 操做購物車
 * @author xiaofeng
 *
 */
@Service
public class CartServiceImpl implements CartService {

	@Autowired
	private JedisClient jedisClient;
	
	@Autowired
	private TbItemMapper itemMapper;
	
	// 添加購物車 
	@Override
	public E3Result addCart(Long userid, Long itemid, int num) {
		//查詢redis緩存中是否含有該field
		Boolean hexists = jedisClient.hexists(UserConfig.CART_REDIS_PRE+userid,itemid+"");
		//若是有
		if (hexists) {
			//獲取該hash的field的值
			String hget = jedisClient.hget(UserConfig.CART_REDIS_PRE+userid,itemid+"");
			//將string值轉化爲對象
			TbItem tbItem = JsonUtils.jsonToPojo(hget, TbItem.class);
			//增長數量
			tbItem.setNum(tbItem.getNum()+num);
			//
			String json = JsonUtils.objectToJson(tbItem);
			jedisClient.hset(UserConfig.CART_REDIS_PRE+userid, itemid+"", json);
		}else {
			TbItem tbItem = itemMapper.selectByPrimaryKey(itemid);
			tbItem.setNum(num);
			String images = tbItem.getImage();
			if (StringUtils.isNotBlank(images)) {
				tbItem.setImage(images.split(",")[0]); 
			}
			jedisClient.hset(UserConfig.CART_REDIS_PRE+userid, itemid+"", JsonUtils.objectToJson(tbItem));
		}
		return E3Result.ok();
	}
	//獲取購物車
	@Override
	public List<TbItem> getCart(Long userid) {
		//經過hashkey獲取hash全部的值(不包含field)
		List<String> list = jedisClient.hvals(UserConfig.CART_REDIS_PRE+userid);
		List<TbItem> tbItems = new ArrayList<TbItem>();
		//遍歷list,將list中的json數據轉爲tbItems對象
		for (String string : list) {
			TbItem tbItem = JsonUtils.jsonToPojo(string, TbItem.class);
			tbItems.add(tbItem);
		}		
		return tbItems;
	}
	// 更新購物車的num數量
	@Override
	public E3Result updateCartNum(Long userid, Long itemid, int num) {
		//經過key獲取json
		String hget = jedisClient.hget(UserConfig.CART_REDIS_PRE+userid, itemid+"");
		//把json轉化爲tbitem對象
		TbItem tbItem = JsonUtils.jsonToPojo(hget, TbItem.class);
		//把新的num設置到對象中
		tbItem.setNum(num);
		jedisClient.hset(UserConfig.CART_REDIS_PRE+userid, itemid+"", JsonUtils.objectToJson(tbItem));
		return E3Result.ok();
	}
	// 根據itemid刪除購物車
	@Override
	public E3Result deleteCartByItemId(Long userid, Long itemid) {
		//直接刪除hashkey的field
		jedisClient.hdel(UserConfig.CART_REDIS_PRE+userid, itemid+"");
		return E3Result.ok();
	}
}

controller層:
CartController .java數據庫

package cn.tsu.cart.e3mall.controller;


import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
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.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import cn.tsu.cart.e3mall.service.CartService;
import cn.tsu.e3mall.pojo.TbItem;
import cn.tsu.e3mall.pojo.TbUser;
import cn.tsu.e3mall.utils.E3Result;
 
/**
 * 購物車處理
 * @author xiaofeng
 *
 */
@Controller
public class CartController {
	
	@Autowired
	private CartService cartService;
	//添加購物車
	@RequestMapping("/cart/add/{productid}")
	//@PathVariable表示須要從url取值
	public String AddCart(@PathVariable Long productid,Integer num,
			HttpServletRequest request,HttpServletResponse response) {
		//tbUser是loginInterceptor攔截器最後放行的時候set進去的
		TbUser tbUser = (TbUser) request.getAttribute("tbUser");
		//調用service方法進行添加購物車
		if (tbUser !=null) {
			E3Result e3Result = cartService.addCart(tbUser.getId(), productid, num);
		}
		return "cartSuccess";
	}
	//跳轉到購物車頁面
	@RequestMapping("/cart/cart")
	public String ToCart(Model model,HttpServletRequest request) {
		TbUser user = (TbUser) request.getAttribute("tbUser");
		List<TbItem> cartList = cartService.getCart(user.getId());
		model.addAttribute("cartList", cartList);
		return "cart";
	}
	
	//修改購物車中的商品數量
	@RequestMapping("/cart/update/num/{itemid}/{num}")
	@ResponseBody
	public E3Result updateCartNum(@PathVariable Long itemid ,@PathVariable Integer num,HttpServletRequest request) {
		TbUser tbuser = (TbUser) request.getAttribute("tbUser"); 
		E3Result e3Result = cartService.updateCartNum(tbuser.getId(), itemid, num);
		return e3Result;
	}
	
	//根據itemid刪除redis中的購物車商品
	@RequestMapping("cart/delete/{itemid}")
	public String deleteCartByItemId(@PathVariable Long itemid,HttpServletRequest request) {
		TbUser tbUser = (TbUser) request.getAttribute("tbUser");
		E3Result e3Result = cartService.deleteCartByItemId(tbUser.getId(), itemid);
		return "redirect:/cart/cart.html"; 
	}
}

從新計算小計

在這裏插入圖片描述
用戶點擊-,和用戶直接修改數據相似。
cart.js文件apache

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",function(data){
				CART.refreshTotalPrice();
			});
			//從新計算小計
			var htmlvale = $(_thisInput).parent().parent().siblings(".pSubtotal").find("span");
			var value =(eval(_thisInput.attr("itemPrice")))*_thisInput.val();
			htmlvale.html(new Number(value/100).toFixed(2)).priceFormat({ //價格格式化插件
				 prefix: '¥',
				 thousandsSeparator: ',',
				 centsLimit: 2
			});
		});
		$(".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",function(data){
				CART.refreshTotalPrice();
			});
			//從新計算小計
			var htmlvale = $(_thisInput).parent().parent().siblings(".pSubtotal").find("span"); 
			var value =(eval(_thisInput.attr("itemPrice")))*_thisInput.val();
			htmlvale.html(new Number(value/100).toFixed(2)).priceFormat({ //價格格式化插件
				 prefix: '¥',
				 thousandsSeparator: ',',
				 centsLimit: 2
			});   
		});
		$(".itemnum").change(function(){
			var _thisInput = $(this);
			$.post("/cart/update/num/"+_thisInput.attr("itemId")+"/"+_thisInput.val() + ".action",function(data){
				CART.refreshTotalPrice();
			});
			
			//從新計算小計
			var htmlvale = $(_thisInput).parent().parent().siblings(".pSubtotal").find("span"); 
			var value =(eval(_thisInput.attr("itemPrice")))*_thisInput.val();
			htmlvale.html(new Number(value/100).toFixed(2)).priceFormat({ //價格格式化插件
				 prefix: '¥',
				 thousandsSeparator: ',',
				 centsLimit: 2
			});  
		});
	},
	refreshTotalPrice : function(){ //從新計算總價
		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
		});
	}
};

$(function(){
	CART.itemNumChange();
});

json返回406報錯問題

406報錯有兩種可能,一種是jackson的jar包沒有加入(90%可能),剩下10%則是由於在springmvc中,若攔截形式是*.html,則是不能夠返回json數據的,否則就會報錯406。
相關文章
相關標籤/搜索