博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
购物车功能设计(二)(使用redis实现购物车功能)
阅读量:3952 次
发布时间:2019-05-24

本文共 14635 字,大约阅读时间需要 48 分钟。

使用redis实现购物车

redis是什么

redis是一款开源的、功能强大、支持多种数据类型、高性能的键值对存储数据库。

redis支持的数据类型有:

  • 字符串
  • 哈希
  • 列表
  • 有序集合
  • 散列
  • 集合

为什么选择redis来实现购物车

将购物车数据存放到Redis中,可以加快购物车的读写性能,从而提高用户体验,缺点就是Redis数据是存放到内存,相对成本较高。但是这个成本,一般企业都可以接受。

一般情况下购物车功能都是使用session/cookie实现的,也就是将整个购物车数据都存储到session中。这样做的好处就是不用操作数据库就可以实现,同时用户可以不同登录就可以将商品加入到购物车中,缺点就是1. 导致session过于臃肿 2. session数据默认是存储到文件中的,所以操作session是相对比较慢的。

如何使用redis实现购物车功能

  1. 首先我们创建一个JedisClient类来操作redis
/*  Created by IntelliJ IDEA.  User: Kalvin  Date: 2020/5/13  Time: 14:21*/package com.lianwei.lssg.cache;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.stereotype.Component;import java.util.Map;import java.util.Set;import java.util.concurrent.TimeUnit;@Componentpublic class JedisClient {
@Autowired private StringRedisTemplate redisTemplate; // Key(键),简单的key-value操作 /** * 实现命令:TTL key,以秒为单位,返回给定 key的剩余生存时间(TTL, time to live)。 * * @param key * @return */ public long ttl(String key) {
return redisTemplate.getExpire(key); } /** * 实现命令:expire 设置过期时间,单位秒 * * @param key * @return */ public void expire(String key, long timeout) {
redisTemplate.expire(key, timeout, TimeUnit.SECONDS); } /** * 实现命令:INCR key,增加key一次 * * @param key * @return */ public long incr(String key, long delta) {
return redisTemplate.opsForValue().increment(key, delta); } /** * 实现命令:KEYS pattern,查找所有符合给定模式 pattern的 key */ public Set
keys(String pattern) {
return redisTemplate.keys(pattern); } /** * 实现命令:DEL key,删除一个key * * @param key */ public void del(String key) {
redisTemplate.delete(key); } // String(字符串) /** * 实现命令:SET key value,设置一个key-value(将字符串值 value关联到 key) * * @param key * @param value */ public void set(String key, String value) {
redisTemplate.opsForValue().set(key, value); } /** * 实现命令:SET key value EX seconds,设置key-value和超时时间(秒) * * @param key * @param value * @param timeout * (以秒为单位) */ public void set(String key, String value, long timeout) {
redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS); } /** * 实现命令:GET key,返回 key所关联的字符串值。 * * @param key * @return value */ public String get(String key) {
return (String)redisTemplate.opsForValue().get(key); } // Hash(哈希表) /** * 实现命令:HEXISTS key field,查找哈希表中是否包含指定键值对 key中给定域 field的值 * @param key * @param field * @return */ public Boolean hexists(String key, String field){
return redisTemplate.opsForHash().hasKey(key, field); } /** * 实现命令:HSET key field value,将哈希表 key中的域 field的值设为 value * * @param key * @param field * @param value */ public void hset(String key, String field, Object value) {
redisTemplate.opsForHash().put(key, field, value); } /** * 实现命令:HGET key field,返回哈希表 key中给定域 field的值 * * @param key * @param field * @return */ public String hget(String key, String field) {
return (String) redisTemplate.opsForHash().get(key, field); } /** * 实现命令:HDEL key field [field ...],删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。 * * @param key * @param fields */ public void hdel(String key, Object... fields) {
redisTemplate.opsForHash().delete(key, fields); } /** * 实现命令:HGETALL key,返回哈希表 key中,所有的域和值。 * * @param key * @return */ public Map
hgetall(String key) {
return redisTemplate.opsForHash().entries(key); } // List(列表) /** * 实现命令:LPUSH key value,将一个值 value插入到列表 key的表头 * * @param key * @param value * @return 执行 LPUSH命令后,列表的长度。 */ public long lpush(String key, String value) {
return redisTemplate.opsForList().leftPush(key, value); } /** * 实现命令:LPOP key,移除并返回列表 key的头元素。 * * @param key * @return 列表key的头元素。 */ public String lpop(String key) {
return (String)redisTemplate.opsForList().leftPop(key); } /** * 实现命令:RPUSH key value,将一个值 value插入到列表 key的表尾(最右边)。 * * @param key * @param value * @return 执行 LPUSH命令后,列表的长度。 */ public long rpush(String key, String value) {
return redisTemplate.opsForList().rightPush(key, value); }}

在redis数据库中我们使用cart作为filed 以用户名作为key 购物车内容为value

/*  Created by IntelliJ IDEA.  User: Kalvin  Date: 2020/5/12  Time: 17:41*/package com.lianwei.lssg.controller.before;import com.alibaba.fastjson.JSON;import com.lianwei.lssg.cache.JedisClient;import com.lianwei.lssg.entity.LssgCart;import com.lianwei.lssg.entity.LssgCartItem;import com.lianwei.lssg.entity.LssgProduct;import com.lianwei.lssg.service.before.LssgProductService;import org.apache.shiro.SecurityUtils;import org.apache.shiro.subject.Subject;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import javax.annotation.Resource;import java.math.BigDecimal;import java.util.HashMap;import java.util.Map;import java.util.Set;@Controller@RequestMapping("cart")public class CartController {
@Resource private JedisClient jedisClient; @Resource private LssgProductService lssgProductService; private static final String REDIS_CART = "cart"; /** * 商品加入到购物车 * */ @RequestMapping("/addProductToCart") @ResponseBody public LssgCart addProductToCart(@RequestParam("productId")Integer productId, @RequestParam(value = "nums",required = false)String nums){
//获取已登录的用户信息 Subject subject = SecurityUtils.getSubject(); String userLoginName = (String)subject.getPrincipal(); LssgProduct lssgProduct = lssgProductService.selectOneProductByProductId(productId); /** * 判断lssgProduct是否为空 * */ String productNumState; if(lssgProduct.getProductNum()<=0){
productNumState = "无货"; }else {
productNumState = "有货"; } /** * 存在一个问题:当session超时后因该强制用户进行登入,只有登入成功才能做相应的操作 * */ if(("").equals(userLoginName)){
System.out.println("session超时了"); /*map.put("lssg",false);*/ return null; } Boolean hexists = jedisClient.hexists(REDIS_CART, userLoginName); System.out.println("hexists---->"+hexists); LssgCart lssgCart = null; if(nums==null|| nums.equals("")){
nums = String.valueOf(1); } BigDecimal num =new BigDecimal(nums); if(!hexists){
lssgCart = new LssgCart(); LssgCartItem lssgCartItem = new LssgCartItem(lssgProduct,num,lssgProduct.getProductMallPrice(),productNumState); lssgCartItem.setSubtotalPrice((lssgProduct.getProductMallPrice()).multiply(lssgCartItem.getBuyNum())); Map
lssgCartItemMap = new HashMap
(); lssgCartItemMap.put(String.valueOf(lssgProduct.getProductId()),lssgCartItem); lssgCart.setCartItems(lssgCartItemMap); lssgCart.setTotalPrice(lssgCartItem.getSubtotalPrice()); }else {
lssgCart = JSON.parseObject(jedisClient.hget(REDIS_CART,userLoginName),LssgCart.class); if(lssgCart.getCartItems().containsKey(String.valueOf(lssgProduct.getProductId()))){
LssgCartItem lssgCartItem = lssgCart.getCartItems().get(String.valueOf(lssgProduct.getProductId())); //数量 lssgCartItem.setBuyNum(lssgCartItem.getBuyNum().add(num)); //小计+商品的单价(由于是BigDecimal类型所以用他自己封装好的) lssgCartItem.setSubtotalPrice((lssgProduct.getProductMallPrice()).multiply(lssgCartItem.getBuyNum())); lssgCart.getCartItems().put(String.valueOf(lssgProduct.getProductId()),lssgCartItem); }else{
//没买过,先创建新的购物项 LssgCartItem lssgCartItem = new LssgCartItem(lssgProduct,num,lssgProduct.getProductMallPrice(),productNumState); lssgCartItem.setSubtotalPrice((lssgProduct.getProductMallPrice()).multiply(lssgCartItem.getBuyNum())); //存入购物车的Map集合 lssgCart.getCartItems().put(String.valueOf(lssgProduct.getProductId()),lssgCartItem); } //计算总价格,并加入到购物车 BigDecimal sum = new BigDecimal("0.00"); Set
ks = lssgCart.getCartItems().keySet(); for(String key: ks){
LssgCartItem lssgCartItem = lssgCart.getCartItems().get(key); sum = sum.add(((lssgCartItem.getLssgProduct().getProductMallPrice()).multiply(lssgCartItem.getBuyNum()))); } lssgCart.setTotalPrice(sum); } jedisClient.hset(REDIS_CART,userLoginName, JSON.toJSONString(lssgCart)); System.out.println("添加成功!"); jedisClient.hget(REDIS_CART,userLoginName); return JSON.parseObject(jedisClient.hget(REDIS_CART,userLoginName),LssgCart.class); } /** *购物车信息展示到前台购物车页 * */ @RequestMapping("/fromCartShowProduct") @ResponseBody public LssgCart fromCartShowProduct(){
//获取已登录的用户信息 Subject subject = SecurityUtils.getSubject(); String userLoginName = (String) subject.getPrincipal(); /** * 存在一个问题:当session超时后因该强制用户进行登入,只有登入成功才能做相应的操作 * */ if(("").equals(userLoginName)){
System.out.println("session超时了"); /*map.put("lssg",false);*/ return null; } Boolean hexists = jedisClient.hexists(REDIS_CART, userLoginName); if(hexists){
return JSON.parseObject(jedisClient.hget(REDIS_CART,userLoginName),LssgCart.class); } return null; } /** * 实现购物车页面通过+/-/输入 按钮来对商品的数量更新操作 * */ @RequestMapping("/updateCartProductNum") @ResponseBody public LssgCart decCartProductNum(@RequestParam("productId")Integer productId, @RequestParam("nums")String nums){
//获取已登录的用户信息 Subject subject = SecurityUtils.getSubject(); String userLoginName = (String) subject.getPrincipal(); LssgCart lssgCart = JSON.parseObject(jedisClient.hget(REDIS_CART,userLoginName),LssgCart.class); Map
lssgCartItemMap = lssgCart.getCartItems(); LssgCartItem lssgCartItem = lssgCartItemMap.get(String.valueOf(productId)); //购物项(该商品)原来的小计 BigDecimal oldSubtotalPrice = lssgCartItem.getSubtotalPrice(); System.out.println("oldSubtotalPrice--->"+oldSubtotalPrice); BigDecimal num =new BigDecimal(nums); //更新购买数量 lssgCartItem.setBuyNum(num); //更新小计 lssgCartItem.setSubtotalPrice((lssgCartItem.getBuyNum()).multiply(lssgCartItem.getLssgProduct().getProductMallPrice())); //把购物项放到购物项(map)集合里 lssgCartItemMap.put(String.valueOf(productId),lssgCartItem); lssgCart.setCartItems(lssgCartItemMap); //更新购物车总价 新的购物车总价 = 原来购物车总价 - 原来购物项的小计 + 新的购物项的小计 lssgCart.setTotalPrice(lssgCart.getTotalPrice().subtract(oldSubtotalPrice).add(lssgCartItem.getSubtotalPrice())); //更新购物车到redis jedisClient.hset(REDIS_CART,userLoginName,JSON.toJSONString(lssgCart)); //从redis中取出购物车传到到前台 return JSON.parseObject(jedisClient.hget(REDIS_CART,userLoginName),LssgCart.class); } /** * 删除购物车中某一个购物项 * */ @RequestMapping("/delCartProduct") @ResponseBody public LssgCart delCartProduct(@RequestParam("productId")Integer productId, @RequestParam("nums")String nums){
//获取已登录的用户信息 Subject subject = SecurityUtils.getSubject(); String userLoginName = (String) subject.getPrincipal(); LssgCart lssgCart = JSON.parseObject(jedisClient.hget(REDIS_CART,userLoginName),LssgCart.class); Map
lssgCartItemMap = lssgCart.getCartItems(); LssgCartItem lssgCartItem = lssgCartItemMap.get(String.valueOf(productId)); BigDecimal num =new BigDecimal(nums); System.out.println("num---->"+num); //通过商品id删除该购物项 lssgCartItemMap.remove(String.valueOf(productId)); //更新总价 新的购物车总价 = 原来购物车总价 - 原来购物项的小计 lssgCart.setTotalPrice(lssgCart.getTotalPrice().subtract(((lssgCartItem.getLssgProduct().getProductMallPrice()).multiply(num)))); //更新购物车到redis jedisClient.hset(REDIS_CART,userLoginName,JSON.toJSONString(lssgCart)); //从redis中取出购物车传到到前台 return JSON.parseObject(jedisClient.hget(REDIS_CART,userLoginName),LssgCart.class); } /** * 清空购物车 * */ @RequestMapping("/emptyCart") public void emptyCart(){
//获取已登录的用户信息 Subject subject = SecurityUtils.getSubject(); String userLoginName = (String) subject.getPrincipal(); jedisClient.hdel(REDIS_CART,userLoginName); } /** *删除已结算的购物项 * */ @RequestMapping("/delProductByProductIds") @ResponseBody public LssgCart delProductByProductIds(@RequestParam(value="productIds[]")String[] productIds){
//获取已登录的用户信息 Subject subject = SecurityUtils.getSubject(); String userLoginName = (String) subject.getPrincipal(); LssgCart lssgCart = JSON.parseObject(jedisClient.hget(REDIS_CART,userLoginName),LssgCart.class); BigDecimal delTotalPrice =new BigDecimal("0.00"); Map
lssgCartItemMap = lssgCart.getCartItems(); for(String productId : productIds){ LssgCartItem lssgCartItem = lssgCartItemMap.get(productId); // MySQL数据库中商品加上相对应的库存量 delTotalPrice = delTotalPrice.add(lssgCartItem.getSubtotalPrice()); //通过商品id删除该购物项 lssgCartItemMap.remove(productId); } //更新总价 新的购物车总价 = 原来购物车总价 - 要结算购物项的小计 lssgCart.setTotalPrice(lssgCart.getTotalPrice().subtract(delTotalPrice)); //更新购物车到redis jedisClient.hset(REDIS_CART,userLoginName,JSON.toJSONString(lssgCart)); //从redis中取出购物车传到到前台 return JSON.parseObject(jedisClient.hget(REDIS_CART,userLoginName),LssgCart.class); } /** * 统计购物车中的购物项 * */ @RequestMapping("/countCartItme") @ResponseBody public Integer countCartItme(){ //获取已登录的用户信息 Subject subject = SecurityUtils.getSubject(); String userLoginName = (String) subject.getPrincipal(); LssgCart lssgCart = JSON.parseObject(jedisClient.hget(REDIS_CART,userLoginName),LssgCart.class); if(lssgCart==null){ return 0; } return lssgCart.getCartItems().size(); }}

在lssgCartItemMap.put(String.valueOf(lssgProduct.getProductId()),lssgCartItem);中我们把商品ID作为购物项集合lssgCartItemMap的key

转载地址:http://fnuzi.baihongyu.com/

你可能感兴趣的文章
卓越领导看过程
查看>>
领导力与各种循环挑战
查看>>
达成谈判协议 - 避免操之过急
查看>>
销售人说话“十大忌”
查看>>
营销中的“战略非对称”
查看>>
android 如何开关Mediatek开发的Feature
查看>>
Android电话功能各部分深入探讨
查看>>
Android应用技巧总结
查看>>
Android创建sdcard详细图解
查看>>
Android开发:如何实现TCP和UDP传输
查看>>
Android电源管理相关应用技巧分享
查看>>
Android录音失真具体解决方案
查看>>
Android根文件系统相关应用介绍
查看>>
Android文件系统深入剖析
查看>>
Android判断网络状态方法详解
查看>>
在Android上实现Junit单元测试的四部曲
查看>>
有效控制Android应用程序的耗电量
查看>>
Android术语列表概览
查看>>
全方位解读Android多媒体框架源码
查看>>
Android音乐编程的管理音频硬件
查看>>