随着电子商务的快速发展,秒杀活动已经成为各大电商平台吸引用户的重要手段之一。秒杀活动通常会在短时间内吸引大量用户参与,这对系统的并发处理能力和稳定性提出了极高的要求。本文将详细介绍如何使用Spring Boot、Redis和Vue.js实现一个高并发的秒杀系统。
Spring Boot是一个基于Spring框架的快速开发框架,它简化了Spring应用的初始搭建和开发过程。Spring Boot提供了大量的自动配置和依赖管理功能,使得开发者可以快速构建独立运行的、生产级别的Spring应用。
Redis是一个开源的内存数据结构存储系统,它可以用作数据库、缓存和消息中间件。Redis支持多种数据结构,如字符串、哈希、列表、集合等,并且提供了丰富的操作命令。在秒杀系统中,Redis主要用于缓存商品库存和用户信息,以提高系统的响应速度和并发处理能力。
Vue.js是一个渐进式JavaScript框架,用于构建用户界面。Vue.js的核心库只关注视图层,易于与其他库或现有项目集成。Vue.js提供了响应式的数据绑定和组件化的开发方式,使得前端开发更加高效和灵活。
秒杀系统的核心需求包括:
秒杀系统的架构设计如下:
秒杀系统的数据库设计如下:
商品表(product):
id
:商品ID,主键。name
:商品名称。price
:商品价格。stock
:商品库存。start_time
:秒杀开始时间。end_time
:秒杀结束时间。用户表(user):
id
:用户ID,主键。username
:用户名。password
:密码。email
:邮箱。订单表(order):
id
:订单ID,主键。user_id
:用户ID,外键。product_id
:商品ID,外键。order_time
:订单时间。status
:订单状态。使用Spring Initializr创建一个新的Spring Boot项目,选择以下依赖:
配置application.properties
文件,设置数据库连接和Redis连接信息。
spring.datasource.url=jdbc:mysql://localhost:3306/seckill?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=root spring.redis.host=localhost spring.redis.port=6379
redis-server
vue create seckill-frontend
npm install axios vue-router vuex
Product
实体类。@Entity @Data public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private BigDecimal price; private Integer stock; private LocalDateTime startTime; private LocalDateTime endTime; }
ProductRepository
接口。public interface ProductRepository extends JpaRepository<Product, Long> { }
ProductService
服务类。@Service public class ProductService { @Autowired private ProductRepository productRepository; public List<Product> getAllProducts() { return productRepository.findAll(); } public Product getProductById(Long id) { return productRepository.findById(id).orElse(null); } public Product saveProduct(Product product) { return productRepository.save(product); } public void deleteProduct(Long id) { productRepository.deleteById(id); } }
ProductController
控制器类。@RestController @RequestMapping("/api/products") public class ProductController { @Autowired private ProductService productService; @GetMapping public List<Product> getAllProducts() { return productService.getAllProducts(); } @GetMapping("/{id}") public Product getProductById(@PathVariable Long id) { return productService.getProductById(id); } @PostMapping public Product createProduct(@RequestBody Product product) { return productService.saveProduct(product); } @PutMapping("/{id}") public Product updateProduct(@PathVariable Long id, @RequestBody Product product) { product.setId(id); return productService.saveProduct(product); } @DeleteMapping("/{id}") public void deleteProduct(@PathVariable Long id) { productService.deleteProduct(id); } }
User
实体类。@Entity @Data public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; private String email; }
UserRepository
接口。public interface UserRepository extends JpaRepository<User, Long> { Optional<User> findByUsername(String username); }
UserService
服务类。@Service public class UserService { @Autowired private UserRepository userRepository; public List<User> getAllUsers() { return userRepository.findAll(); } public User getUserById(Long id) { return userRepository.findById(id).orElse(null); } public User saveUser(User user) { return userRepository.save(user); } public void deleteUser(Long id) { userRepository.deleteById(id); } public Optional<User> findByUsername(String username) { return userRepository.findByUsername(username); } }
UserController
控制器类。@RestController @RequestMapping("/api/users") public class UserController { @Autowired private UserService userService; @GetMapping public List<User> getAllUsers() { return userService.getAllUsers(); } @GetMapping("/{id}") public User getUserById(@PathVariable Long id) { return userService.getUserById(id); } @PostMapping public User createUser(@RequestBody User user) { return userService.saveUser(user); } @PutMapping("/{id}") public User updateUser(@PathVariable Long id, @RequestBody User user) { user.setId(id); return userService.saveUser(user); } @DeleteMapping("/{id}") public void deleteUser(@PathVariable Long id) { userService.deleteUser(id); } }
SeckillService
服务类。@Service public class SeckillService { @Autowired private ProductRepository productRepository; @Autowired private RedisTemplate<String, Object> redisTemplate; public boolean seckill(Long productId, Long userId) { String stockKey = "product_stock_" + productId; String userKey = "seckill_user_" + productId; // 检查用户是否已经参与过秒杀 if (redisTemplate.opsForSet().isMember(userKey, userId)) { return false; } // 检查库存 Long stock = redisTemplate.opsForValue().decrement(stockKey); if (stock == null || stock < 0) { return false; } // 记录用户参与秒杀 redisTemplate.opsForSet().add(userKey, userId); return true; } }
SeckillController
控制器类。@RestController @RequestMapping("/api/seckill") public class SeckillController { @Autowired private SeckillService seckillService; @PostMapping("/{productId}") public ResponseEntity<String> seckill(@PathVariable Long productId, @RequestParam Long userId) { boolean result = seckillService.seckill(productId, userId); if (result) { return ResponseEntity.ok("秒杀成功"); } else { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("秒杀失败"); } } }
Order
实体类。@Entity @Data public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private Long userId; private Long productId; private LocalDateTime orderTime; private String status; }
OrderRepository
接口。public interface OrderRepository extends JpaRepository<Order, Long> { }
OrderService
服务类。@Service public class OrderService { @Autowired private OrderRepository orderRepository; public List<Order> getAllOrders() { return orderRepository.findAll(); } public Order getOrderById(Long id) { return orderRepository.findById(id).orElse(null); } public Order saveOrder(Order order) { return orderRepository.save(order); } public void deleteOrder(Long id) { orderRepository.deleteById(id); } }
OrderController
控制器类。@RestController @RequestMapping("/api/orders") public class OrderController { @Autowired private OrderService orderService; @GetMapping public List<Order> getAllOrders() { return orderService.getAllOrders(); } @GetMapping("/{id}") public Order getOrderById(@PathVariable Long id) { return orderService.getOrderById(id); } @PostMapping public Order createOrder(@RequestBody Order order) { return orderService.saveOrder(order); } @PutMapping("/{id}") public Order updateOrder(@PathVariable Long id, @RequestBody Order order) { order.setId(id); return orderService.saveOrder(order); } @DeleteMapping("/{id}") public void deleteOrder(@PathVariable Long id) { orderService.deleteOrder(id); } }
ProductList.vue
组件。<template> <div> <h1>商品列表</h1> <ul> <li v-for="product in products" :key="product.id"> {{ product.name }} - {{ product.price }}元 <button @click="seckill(product.id)">秒杀</button> </li> </ul> </div> </template> <script> import axios from 'axios'; export default { data() { return { products: [] }; }, created() { this.fetchProducts(); }, methods: { fetchProducts() { axios.get('/api/products') .then(response => { this.products = response.data; }) .catch(error => { console.error(error); }); }, seckill(productId) { const userId = 1; // 假设用户ID为1 axios.post(`/api/seckill/${productId}?userId=${userId}`) .then(response => { alert(response.data); }) .catch(error => { console.error(error); }); } } }; </script>
Login.vue
组件。<template> <div> <h1>用户登录</h1> <form @submit.prevent="login"> <label for="username">用户名:</label> <input type="text" id="username" v-model="username" required> <label for="password">密码:</label> <input type="password" id="password" v-model="password" required> <button type="submit">登录</button> </form> </div> </template> <script> import axios from 'axios'; export default { data() { return { username: '', password: '' }; }, methods: { login() { axios.post('/api/users/login', { username: this.username, password: this.password }) .then(response => { alert('登录成功'); this.$router.push('/'); }) .catch(error => { console.error(error); }); } } }; </script>
Seckill.vue
组件。<template> <div> <h1>秒杀活动</h1> <ul> <li v-for="product in products" :key="product.id"> {{ product.name }} - {{ product.price }}元 <button @click="seckill(product.id)">秒杀</button> </li> </ul> </div> </template> <script> import axios from 'axios'; export default { data() { return { products: [] }; }, created() { this.fetchProducts(); }, methods: { fetchProducts() { axios.get('/api/products') .then(response => { this.products = response.data; }) .catch(error => { console.error(error); }); }, seckill(productId) { const userId = 1; // 假设用户ID为1 axios.post(`/api/seckill/${productId}?userId=${userId}`) .then(response => { alert(response.data); }) .catch(error => { console.error(error); }); } } }; </script>
OrderList.vue
组件。<template> <div> <h1>订单列表</h1> <ul> <li v-for="order in orders" :key="order.id"> 订单ID: {{ order.id }} - 商品ID: {{ order.productId }} - 状态: {{ order.status }} </li> </ul> </div> </template> <script> import axios from 'axios'; export default { data() { return { orders: [] }; }, created() { this.fetchOrders(); }, methods: { fetchOrders() { axios.get('/api/orders') .then(response => { this.orders = response.data; }) .catch(error => { console.error(error); }); } } }; </script>
vue.config.js
文件,设置代理。module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } } };
# 启动Spring Boot应用 mvn spring-boot:run # 启动Vue.js应用 npm run serve
本文详细介绍了如何使用Spring Boot、Redis和Vue.js实现一个高并发的秒杀系统。通过合理的系统架构设计和性能优化,可以有效应对秒杀活动带来的高并发挑战。未来可以进一步优化系统的稳定性和扩展性,如引入消息队列、分布式缓存等。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。