文章目录[隐藏]
购物车模块功能
1、加入商品
2、更新商品数
3、查询商品数
4、移除商品
5、单选/取消
6、全选/取消
7、购物车列表
学习目标
1、购物车模块的设计思想
2、如何封装一个高复用的购物车核心方法
3、解决浮点型商业运算中丢失精度的问题
CartController.java
controller.portal 包下新建一个 CartController.java
package com.mmall.controller.portal; import com.mmall.common.Const; import com.mmall.common.ResponseCode; import com.mmall.common.ServerResponse; import com.mmall.pojo.User; import com.mmall.service.ICartService; import com.mmall.vo.CartVo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpSession; /** * @Author: Geekerstar(jikewenku.com) * @Date: 2018/6/24 8:46 * @Description: */ @Controller @RequestMapping("/cart") public class CartController { @Autowired private ICartService iCartService; @RequestMapping("add.do") public ServerResponse<CartVo> add(HttpSession session, Integer count, Integer productId) { User user = (User) session.getAttribute(Const.CURRENT_USER); if (user == null) { return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(), ResponseCode.NEED_LOGIN.getDesc()); } return iCartService.add(user.getId(), productId, count); } }
ICartService.java
service 包下新建 ICartService.java 及其实现类 CartServiceImpl.java
package com.mmall.service; import com.mmall.common.ServerResponse; import com.mmall.vo.CartVo; /** * @Author: Geekerstar(jikewenku.com) * @Date: 2018/6/24 8:48 * @Description: */ public interface ICartService { ServerResponse<CartVo> add(Integer userId, Integer productId, Integer count); }
CartServiceImpl.java
编写实现类
package com.mmall.service.impl; import com.google.common.collect.Lists; import com.mmall.common.Const; import com.mmall.common.ResponseCode; import com.mmall.common.ServerResponse; import com.mmall.dao.CartMapper; import com.mmall.dao.ProductMapper; import com.mmall.pojo.Cart; import com.mmall.pojo.Product; import com.mmall.service.ICartService; import com.mmall.util.BigDecimalUtil; import com.mmall.util.PropertiesUtil; import com.mmall.vo.CartProductVo; import com.mmall.vo.CartVo; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.util.List; /** * @Author: Geekerstar(jikewenku.com) * @Date: 2018/6/24 8:49 * @Description: */ @Service("iCartService") public class CartServiceImpl implements ICartService { @Autowired private CartMapper cartMapper; @Autowired private ProductMapper productMapper; public ServerResponse<CartVo> add(Integer userId,Integer productId,Integer count){ if(productId == null || count == null){ return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),ResponseCode.ILLEGAL_ARGUMENT.getDesc()); } Cart cart = cartMapper.selectCartByUserIdProductId(userId,productId); if(cart == null){ //这个产品不在这个购物车里,需要新增一个这个产品的记录 Cart cartItem = new Cart(); cartItem.setQuantity(count); cartItem.setChecked(Const.Cart.CHECKED); cartItem.setProductId(productId); cartItem.setUserId(userId); cartMapper.insert(cartItem); }else{ //这个产品已经在购物车里了. //如果产品已存在,数量相加 count = cart.getQuantity() + count; cart.setQuantity(count); cartMapper.updateByPrimaryKeySelective(cart); } CartVo cartVo = this.getCartVoLimit(userId); return ServerResponse.createBySuccess(cartVo); } private CartVo getCartVoLimit(Integer userId){ CartVo cartVo = new CartVo(); List<Cart> cartList = cartMapper.selectCartByUserId(userId); List<CartProductVo> cartProductVoList = Lists.newArrayList(); BigDecimal cartTotalPrice = new BigDecimal("0"); if(CollectionUtils.isNotEmpty(cartList)){ for(Cart cartItem : cartList){ CartProductVo cartProductVo = new CartProductVo(); cartProductVo.setId(cartItem.getId()); cartProductVo.setUserId(userId); cartProductVo.setProductId(cartItem.getProductId()); Product product = productMapper.selectByPrimaryKey(cartItem.getProductId()); if(product != null){ cartProductVo.setProductMainImage(product.getMainImage()); cartProductVo.setProductName(product.getName()); cartProductVo.setProductSubtitle(product.getSubtitle()); cartProductVo.setProductStatus(product.getStatus()); cartProductVo.setProductPrice(product.getPrice()); cartProductVo.setProductStock(product.getStock()); //判断库存 int buyLimitCount = 0; if(product.getStock() >= cartItem.getQuantity()){ //库存充足的时候 buyLimitCount = cartItem.getQuantity(); cartProductVo.setLimitQuantity(Const.Cart.LIMIT_NUM_SUCCESS); }else{ buyLimitCount = product.getStock(); cartProductVo.setLimitQuantity(Const.Cart.LIMIT_NUM_FAIL); //购物车中更新有效库存 Cart cartForQuantity = new Cart(); cartForQuantity.setId(cartItem.getId()); cartForQuantity.setQuantity(buyLimitCount); cartMapper.updateByPrimaryKeySelective(cartForQuantity); } cartProductVo.setQuantity(buyLimitCount); //计算总价 cartProductVo.setProductTotalPrice(BigDecimalUtil.mul(product.getPrice().doubleValue(),cartProductVo.getQuantity())); cartProductVo.setProductChecked(cartItem.getChecked()); //如果不判断是否有商品就进行添加购物车操作,会报空指针异常。 if(cartItem.getChecked() == Const.Cart.CHECKED){ //如果已经勾选,增加到整个的购物车总价中 cartTotalPrice = BigDecimalUtil.add(cartTotalPrice.doubleValue(),cartProductVo.getProductTotalPrice().doubleValue()); } cartProductVoList.add(cartProductVo); } } } cartVo.setCartTotalPrice(cartTotalPrice); cartVo.setCartProductVoList(cartProductVoList); cartVo.setAllChecked(this.getAllCheckedStatus(userId)); cartVo.setImageHost(PropertiesUtil.getProperty("ftp.server.http.prefix")); return cartVo; } private boolean getAllCheckedStatus(Integer userId){ if(userId == null){ return false; } return cartMapper.selectCartProductCheckedStatusByUserId(userId) == 0; } }
CartMapper.java
Cart selectCartByUserIdProductId(@Param("userId") Integer userId, @Param("productId")Integer productId); List<Cart> selectCartByUserId(Integer userId); int selectCartProductCheckedStatusByUserId(Integer userId);
CartMapper.xml
<select id="selectCartByUserIdProductId" resultMap="BaseResultMap" parameterType="map"> SELECT <include refid="Base_Column_List"/> from mmall_cart where user_id = #{userId} and product_id = #{productId} </select> <select id="selectCartByUserId" resultMap="BaseResultMap" parameterType="int"> SELECT <include refid="Base_Column_List"/> from mmall_cart where user_id = #{userId} </select> <select id="selectCartProductCheckedStatusByUserId" resultType="int" parameterType="int"> SELECT count(1) from mmall_cart where checked = 0 and user_id = #{userId} </select>
Const.java
public interface Cart{ int CHECKED = 1;//即购物车选中状态 int UN_CHECKED = 0;//购物车中未选中状态 String LIMIT_NUM_FAIL = "LIMIT_NUM_FAIL"; String LIMIT_NUM_SUCCESS = "LIMIT_NUM_SUCCESS"; }
CartProductVo.java
package com.mmall.vo; import java.math.BigDecimal; /** * @Author: Geekerstar(jikewenku.com) * @Date: 2018/6/24 8:56 * @Description: */ public class CartProductVo { //结合了产品和购物车的一个抽象对象 private Integer id; private Integer userId; private Integer productId; private Integer quantity;//购物车中此商品的数量 private String productName; private String productSubtitle; private String productMainImage; private BigDecimal productPrice; private Integer productStatus; private BigDecimal productTotalPrice; private Integer productStock; private Integer productChecked;//此商品是否勾选 private String limitQuantity;//限制数量的一个返回结果 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public Integer getProductId() { return productId; } public void setProductId(Integer productId) { this.productId = productId; } public Integer getQuantity() { return quantity; } public void setQuantity(Integer quantity) { this.quantity = quantity; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getProductSubtitle() { return productSubtitle; } public void setProductSubtitle(String productSubtitle) { this.productSubtitle = productSubtitle; } public String getProductMainImage() { return productMainImage; } public void setProductMainImage(String productMainImage) { this.productMainImage = productMainImage; } public BigDecimal getProductPrice() { return productPrice; } public void setProductPrice(BigDecimal productPrice) { this.productPrice = productPrice; } public Integer getProductStatus() { return productStatus; } public void setProductStatus(Integer productStatus) { this.productStatus = productStatus; } public BigDecimal getProductTotalPrice() { return productTotalPrice; } public void setProductTotalPrice(BigDecimal productTotalPrice) { this.productTotalPrice = productTotalPrice; } public Integer getProductStock() { return productStock; } public void setProductStock(Integer productStock) { this.productStock = productStock; } public Integer getProductChecked() { return productChecked; } public void setProductChecked(Integer productChecked) { this.productChecked = productChecked; } public String getLimitQuantity() { return limitQuantity; } public void setLimitQuantity(String limitQuantity) { this.limitQuantity = limitQuantity; } }
CartVo.java
package com.mmall.vo; import java.math.BigDecimal; import java.util.List; /** * @Author: Geekerstar(jikewenku.com) * @Date: 2018/6/24 8:57 * @Description: */ public class CartVo { private List<CartProductVo> cartProductVoList; private BigDecimal cartTotalPrice; private Boolean allChecked;//是否已经都勾选 private String imageHost; public List<CartProductVo> getCartProductVoList() { return cartProductVoList; } public void setCartProductVoList(List<CartProductVo> cartProductVoList) { this.cartProductVoList = cartProductVoList; } public BigDecimal getCartTotalPrice() { return cartTotalPrice; } public void setCartTotalPrice(BigDecimal cartTotalPrice) { this.cartTotalPrice = cartTotalPrice; } public Boolean getAllChecked() { return allChecked; } public void setAllChecked(Boolean allChecked) { this.allChecked = allChecked; } public String getImageHost() { return imageHost; } public void setImageHost(String imageHost) { this.imageHost = imageHost; } }
BigDecimalUtil.java
util 包下新建 BigDecimalUtil 工具类
package com.mmall.util; import java.math.BigDecimal; /** * @Author: Geekerstar(jikewenku.com) * @Date: 2018/6/24 9:09 * @Description: */ public class BigDecimalUtil { private BigDecimalUtil(){ } public static BigDecimal add(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2); } public static BigDecimal sub(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.subtract(b2); } public static BigDecimal mul(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.multiply(b2); } public static BigDecimal div(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.divide(b2,2,BigDecimal.ROUND_HALF_UP);//四舍五入,保留 2 位小数 //除不尽的情况 } }
测试
编写测试文件 BigDecimalTest.java
package com.mmall.test; import java.math.BigDecimal; import org.junit.Test; /** * @Author: Geekerstar(jikewenku.com) * @Date: 2018/6/24 9:02 * @Description: */ public class BigDecimalTest { @Test public void test1(){ System.out.println(0.05+0.01); System.out.println(1.0-0.42); System.out.println(4.015*100); System.out.println(123.3/100); } @Test public void test2(){ BigDecimal b1 = new BigDecimal(0.05); BigDecimal b2 = new BigDecimal(0.01); System.out.println(b1.add(b2)); } @Test public void test3(){ BigDecimal b1 = new BigDecimal("0.05"); BigDecimal b2 = new BigDecimal("0.01"); System.out.println(b1.add(b2)); } }