Redis实现购物车功能(Java代码实现)

1、思路讲解

        1.1、添加购物车

                当用户点击商品详情,查看商品时,点击了添加购物车,在添加购物的时,需要将商品的相关信息添加到redis数据库中,可以将这些添加到购物车中的信息封装成给实体类,就定义成Cart实体类,而这给实体类中需要存在的属性,需要的是能够在购物车展示时必须要使用到属性,如:商品对象(通过商品对象可以展示出商品的单价,以及商品对应的编号,每个用户只能对应一个商品编号的购物车,当成hashkey)、用户id(用户id是唯一的,需要通过用户id当成存储在Redis中唯一的Hash的Key)、数量。

        1.2、查看用户对应的购物车

        当用户点击购物车的时候,需要去进行查询用户对应的购物车详细,返回给前端数据,前端绑定数据到界面展示效果,而数据的获取需要通过用户id去到的。所以后端接口需要接收一个用户的id,通过id去获取这个redis中存储的值。

        1.3、更改商品数量

        当用户在购物车界面点击了加/减/数量输入的操作的时候,redis中数据也要跟着一起改变,这里就要进行ajax处理,对redis中的数据进行操作,如何去操作?通过Key先找到用户对应的购物车,随后根据商品的id找到hashkey中对应的value值,进行value值得更新

        1.4、删除购物车

        思路跟1.3中的思路差不多,但是这里它需要的是执行删除操作,需要通过用户的id跟商品的编号去删除,所对应的value值

2、基本配置

        2.1、配置pom.xml相关依赖

<!-- redis -->
<properties>
    <spring-data-redis.version>1.7.1.RELEASE</spring-data-redis.version>
    <jedis.version>2.9.0</jedis.version>
  </properties>

<!-- 配置Redis的相关依赖 -->
 <!-- redis -->
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>${jedis.version}</version>
      <exclusions>
        <exclusion>
          <artifactId>commons-pool2</artifactId>
          <groupId>org.apache.commons</groupId>
        </exclusion>
      </exclusions>
    </dependency>
<!-- Json相关依赖 -->
    <dependency>
      <groupId>com.alibaba.fastjson2</groupId>
      <artifactId>fastjson2</artifactId>
      <version>2.0.47</version>
    </dependency>

        2.2、配置redis的连接文件(propreties文件)

#ip地址
redis.hostName=127.0.0.1
#端口号
redis.port=6379
#如果有密码
redis.password=
#客户端超时时间单位是毫秒 默认是2000
redis.timeout=10000

#redis缓存数据过期时间单位秒
redis.expiration=3600

##################### redis连接池配置 ###########################################
#最大空闲数
redis.maxIdle=300
#连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal
#redis.maxActive=600
#控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性
redis.maxTotal=1000
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
redis.maxWaitMillis=1000
#连接的最小空闲时间 默认1800000毫秒(30分钟)
redis.minEvictableIdleTimeMillis=300000
#每次释放连接的最大数目,默认3
redis.numTestsPerEvictionRun=1024
#逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
redis.timeBetweenEvictionRunsMillis=30000
#是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
redis.testOnBorrow=true
#在空闲时检查有效性, 默认false
redis.testWhileIdle=true

        spring-redis的集成配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:contet="http://www.springframework.org/schema/context"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
    <!-- 1.导入redis配置文件 -->
    <!--    <contet:property-placeholder location="redis.properties"/>-->
    <!-- 2.创建redis数据库连接池 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!--最大空闲数-->
        <property name="maxIdle" value="${redis.maxIdle}"/>
        <!--连接池的最大数据库连接数  -->
        <property name="maxTotal" value="${redis.maxTotal}"/>
        <!--最大建立连接等待时间-->
        <property name="maxWaitMillis" value="${redis.maxWaitMillis}"/>
        <!--逐出连接的最小空闲时间 默认1800000毫秒(30分钟)-->
        <property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}"/>
        <!--每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3-->
        <property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"/>
        <!--逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1-->
        <property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}"/>
        <!--是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个-->
        <property name="testOnBorrow" value="${redis.testOnBorrow}"/>
        <!--在空闲时检查有效性, 默认false  -->
        <property name="testWhileIdle" value="${redis.testWhileIdle}"/>
    </bean>
    <!-- 3.创建redis连接工厂类 -->
    <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
          destroy-method="destroy">
        <property name="poolConfig" ref="poolConfig"/>
        <!--IP地址 -->
        <property name="hostName" value="${redis.hostName}"/>
        <!--端口号  -->
        <property name="port" value="${redis.port}"/>
        <!--如果Redis设置有密码  -->
        <property name="password" value="${redis.password}"/>
        <!--客户端超时时间单位是毫秒  -->
        <property name="timeout" value="${redis.timeout}"/>
    </bean>
    <!-- 4.创建redistemplate模板类 -->
    <!-- redis操作模板,使用该对象可以操作redis  -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <!--redis是key-value-->
        <property name="connectionFactory" ref="connectionFactory"/>
        <!--如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!!  -->
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
        </property>
        <property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
        </property>
        <!--开启事务  -->
        <property name="enableTransactionSupport" value="false"/>
    </bean>
</beans>

        2.3、配置json的接收以及json对象的转换(在Spring-MVC中)

    <!--配置JSON对象接收-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                    <property name="supportedMediaTypes">
                        <list>
                            <value>text/html;charset=UTF-8</value>
                            <value>application/json;charset=UTF-8</value>
                        </list>
                    </property>
                </bean>
                <!-- json转换器 -->
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                    <property name="supportedMediaTypes">
                        <list>
                            <value>text/html;charset=UTF-8</value>
                            <value>application/json;charset=UTF-8</value>
                        </list>
                    </property>
                </bean>
            </list>
        </property>
    </bean>

3、代码实现

        实现功能的service包下的接口

package com.zking.fresh.service;

import com.zking.fresh.model.Cart;

import java.util.List;

public interface ICartRedisService {

    /**
     * 添加购物车方法
     * @param cart
     */
     Integer addCart(Cart cart);

    /**
     * 查看购物车方法
     * @param uid
     */
    List<Cart> listCart(Integer uid);
    /**
     * 删除单个商品
     * @param cart
     */
    Boolean delCart(Cart cart);

    /**
     * 修改购物车商品
     * @param cart
     */
    void updateCart(Cart cart,String type);

    /**
     * 删除所有购物车商品
     * @param cart
     */
    void delAll(Cart cart);

}

实现类

package com.zking.fresh.service.imp;

import com.zking.fresh.model.Cart;
import com.zking.fresh.service.ICartRedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Redis实现购物基本功能方法
 */
@Service
public class CartRedisServiceImpl implements ICartRedisService {

    @Autowired
    private RedisTemplate<String,Object> template;

    public HashOperations<String, Object, Object> getOpsHash(){
        return template.opsForHash();
    }

    @Override
    public Integer addCart(Cart cart) {
        //判断购物车商品是否存在
        Cart cart1 = (Cart) getOpsHash().get(cart.getUsersId() + "", cart.getGoodsId() + "");
        //判断不为空时候说明用户有购物车存在
        if(cart1!=null){
            //更新数量
            cart1.setCartNum(cart.getCartNum()+cart1.getCartNum());
            //更新redis数据
            getOpsHash().put(cart1.getUsersId()+"",cart1.getGoodsId()+"",cart1);
            //return
            return 1;
        }else{
            //不存在则将数据添加到redis中
            getOpsHash().put(cart.getUsersId()+"",cart.getGoodsId()+"",cart);
            //return
            return 2;
        }
    }

    /**
     * 查询购物车
     * @param uid
     * @return
     */
    @Override
    public List<Cart> listCart(Integer uid) {
        //获取当前用户的所有购物车数量
        Map<Object, Object> entries = getOpsHash().entries(uid + "");
        Set<Map.Entry<Object, Object>> entries1 = entries.entrySet();
        //获取内部所有的值
        List<Cart> carts = new ArrayList<>();
        for (Map.Entry<Object, Object> objectObjectEntry : entries1) {
            carts.add((Cart) objectObjectEntry.getValue());
        }
        return carts;
    }

    /***
     * 删除购物车商品
     * @param cart
     * @return
     */
    @Override
    public Boolean delCart(Cart cart) {
        Long delete = getOpsHash().delete(cart.getUsersId() + "", cart.getGoodsId() + "");
        if (delete>0)
            return true;
        else
            return false;
    }

    /**
     * 修改商品数量
     * @param cart
     * @param type
     */
    @Override
    public void updateCart(Cart cart,String type) {
        //获取到对应的商品
        Cart o = (Cart) getOpsHash().get(cart.getUsersId() + "", cart.getGoodsId() + "");
        //判断类型
        if(type.equals("1")){
            //加
            o.setCartNum(o.getCartNum()+1);
        }else if(type.equals("2")){
            //减
            o.setCartNum(o.getCartNum()-1);
        }else{
            //输入
            o.setCartNum(cart.getCartNum());
        }
        //更新redis中的数量
        getOpsHash().put(cart.getUsersId()+"",cart.getGoodsId()+"",o);
    }

    @Override
    public void delAll(Cart cart) {
        Long delete = getOpsHash().delete(cart.getUsersId() + "", "*");
    }
}

最后在对应的controller层调用对应的接口方法即可 !       

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
购物车数据库设计方面,选择使用Redis作为存储数据库的主要原因是Redis具有高性能、支持多种数据类型以及对大规模数据量和频繁修改的处理能力。相比传统的关系型数据库如MySQL,Redis能更好地应对购物车数据量大、修改频繁的情况,减轻数据库的压力。 在Redis中,可以使用哈希表数据类型来存储购物车信息。每个购物车可以用一个哈希表来表示,哈希表的键可以是用户ID,值则是购物车中的商品ID和数量。这样可以方便地更新购物车中商品的数量、添加新的商品,同时也可以快速获取购物车中的商品列表。此外,使用有序集合数据类型,可以将购物车中的商品按照添加的时间进行排序,以便显示最新添加的商品。 除了购物车信息,还可以考虑使用Redis的其他数据类型来存储一些相关的信息。例如,可以使用字符串类型存储用户的购物车总价或折扣信息,使用列表类型存储用户的浏览记录,使用集合类型存储用户收藏的商品等。这样可以在购物车数据库中集中存储与用户购物相关的信息,方便操作和管理。 总结而言,Redis购物车数据库的设计可以使用哈希表存储购物车信息,其他数据类型存储相关信息。这样的设计能够提供高性能、灵活的存储和操作方式,以满足购物车数据量大、修改频繁的需求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Redis购物车的架构实现](https://blog.csdn.net/suifeng629/article/details/102910277)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [购物车功能设计(二)(使用redis实现购物车功能)](https://blog.csdn.net/qq_43900677/article/details/108969435)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值