Springboot整合redis,实现购物车功能

723 阅读2分钟

下面是一个基于Spring Boot和Redis的购物车功能示例:

  1. 集成Redis

在Spring Boot中集成Redis很简单,只需要在pom.xml中添加以下依赖:

phpCopy code
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

然后在application.properties中配置Redis连接信息,例如:

Copy code
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=yourpassword

2.设计购物车数据结构

购物车可以使用Redis的Hash类型来存储,其中每一个Hash对应一个用户的购物车,Hash的key为用户ID,Hash的field为商品ID,Hash的value为商品数量。

makefileCopy code
redisKey: cart:userId
redisField: productId
redisValue: productNum

3.实现购物车功能

下面是一个简单的购物车功能实现示例,包括添加商品、删除商品和清空购物车功能:

typescriptCopy code
@Service
public class CartServiceImpl implements CartService {
    
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void addProduct(String userId, String productId, int productNum) {
        BoundHashOperations<String, String, Integer> ops = redisTemplate.boundHashOps("cart:" + userId);
        Integer oldNum = ops.get(productId);
        if (oldNum == null) {
            oldNum = 0;
        }
        ops.put(productId, oldNum + productNum);
    }

    @Override
    public void removeProduct(String userId, String productId) {
        BoundHashOperations<String, String, Integer> ops = redisTemplate.boundHashOps("cart:" + userId);
        ops.delete(productId);
    }

    @Override
    public void clearCart(String userId) {
        redisTemplate.delete("cart:" + userId);
    }
}

4.结合数据库设计

购物车功能常常需要与商品信息进行联合查询,可以使用MySQL来存储商品信息。下面是一个简单的商品信息表设计:

sqlCopy code
CREATE TABLE `product` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `price` decimal(10,2) NOT NULL,
  `description` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

5.实现购物车与数据库联合查询功能

在购物车中加入商品信息查询:

  1. ShoppingCartService接口的实现类ShoppingCartServiceImpl
javaCopy code
@Service
public class ShoppingCartServiceImpl implements ShoppingCartService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    
    private static final String REDIS_KEY_PREFIX = "shopping_cart_";
    
    private static final long REDIS_KEY_EXPIRATION = 3600L; // Redis键过期时间,单位秒
    
    @Override
    public void addToCart(int userId, int productId, int quantity) {
        // 1. 向数据库中插入购物车记录
        ShoppingCart shoppingCart = new ShoppingCart(userId, productId, quantity);
        shoppingCartMapper.insert(shoppingCart);
        
        // 2. 向Redis中插入购物车记录
        String redisKey = REDIS_KEY_PREFIX + userId;
        String field = String.valueOf(productId);
        redisTemplate.opsForHash().put(redisKey, field, quantity);
        redisTemplate.expire(redisKey, REDIS_KEY_EXPIRATION, TimeUnit.SECONDS);
    }
    
    @Override
    public void updateQuantity(int userId, int productId, int quantity) {
        // 1. 更新数据库中的购物车记录
        shoppingCartMapper.updateQuantity(userId, productId, quantity);
        
        // 2. 更新Redis中的购物车记录
        String redisKey = REDIS_KEY_PREFIX + userId;
        String field = String.valueOf(productId);
        redisTemplate.opsForHash().put(redisKey, field, quantity);
        redisTemplate.expire(redisKey, REDIS_KEY_EXPIRATION, TimeUnit.SECONDS);
    }
    
    @Override
    public void deleteFromCart(int userId, int productId) {
        // 1. 删除数据库中的购物车记录
        shoppingCartMapper.delete(userId, productId);
        
        // 2. 删除Redis中的购物车记录
        String redisKey = REDIS_KEY_PREFIX + userId;
        String field = String.valueOf(productId);
        redisTemplate.opsForHash().delete(redisKey, field);
    }
    
    @Override
    public Map<Integer, Integer> getCart(int userId) {
        // 1. 从Redis中获取购物车记录
        String redisKey = REDIS_KEY_PREFIX + userId;
        Map<Object, Object> redisEntries = redisTemplate.opsForHash().entries(redisKey);
        
        // 2. 如果Redis中不存在购物车记录,则从数据库中获取
        if (redisEntries == null || redisEntries.isEmpty()) {
            List<ShoppingCart> shoppingCarts = shoppingCartMapper.selectByUserId(userId);
            if (shoppingCarts == null || shoppingCarts.isEmpty()) {
                return null;
            } else {
                Map<Integer, Integer> cart = new HashMap<>();
                for (ShoppingCart shoppingCart : shoppingCarts) {
                    cart.put(shoppingCart.getProductId(), shoppingCart.getQuantity());
                }
                return cart;
            }
        } else {
            Map<Integer, Integer> cart = new HashMap<>();
            for (Map.Entry<Object, Object> entry : redisEntries.entrySet()) {
                int productId = Integer.parseInt((String) entry.getKey());
                int quantity = (int) entry.getValue();
                cart.put(productId, quantity);
            }
            return cart;
        }
    }
} 

注意:上述的demo只是简单例子,上面的demo代码会存在redis与数据库数据一致性的问题,后续后出一篇详细介绍如何保证缓存与数据库数据一致性的文章。