java 抽奖程序结合数据库,redis实现
数据库脚本:
/** * SET NAMES utf8mb4; * SET FOREIGN_KEY_CHECKS = 0; * * -- ---------------------------- * -- Table structure for prizes * -- ---------------------------- * DROP TABLE IF EXISTS `prizes`; * CREATE TABLE `prizes` ( * `id` int NOT NULL AUTO_INCREMENT, * `name` varchar(255) NOT NULL, * `quantity` int NOT NULL, * `weight` int NOT NULL DEFAULT '1', * PRIMARY KEY (`id`) * ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; * * -- ---------------------------- * -- Records of prizes * -- ---------------------------- BEGIN; INSERT INTO `prizes` (`id`, `name`, `quantity`, `weight`) VALUES (1, 'huawei mate60pro', 10, 5); INSERT INTO `prizes` (`id`, `name`, `quantity`, `weight`) VALUES (2, 'vivo pro13', 15, 15); INSERT INTO `prizes` (`id`, `name`, `quantity`, `weight`) VALUES (3, ' redmi 12', 69, 10); INSERT INTO `prizes` (`id`, `name`, `quantity`, `weight`) VALUES (4, '苹果16', 5, 5); INSERT INTO `prizes` (`id`, `name`, `quantity`, `weight`) VALUES (5, '谢谢惠顾!', 60, 65); COMMIT; * * SET FOREIGN_KEY_CHECKS = 1; */
@Component public class Lottery { @Autowired private RedisTemplate<String, String> redisTemplate; private static final String DB_URL = "jdbc:mysql://localhost:3306/splm?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true"; private static final String DB_USER = "root"; private static final String DB_PASSWORD = "***"; public String runLottery() { String result = ""; try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) { // 初始化奖品 initializePrizes(conn); // 抽奖 String prizeId = drawPrize(); if (prizeId != null) { System.out.println(String.format("恭喜你,中奖奖品ID:%s,名称-%s", prizeId,redisTemplate.opsForValue().get("prize:"+prizeId+":name"))); updateDatabase(conn, prizeId); result= String.format("恭喜你,中奖奖品ID:%s,名称-%s", prizeId,redisTemplate.opsForValue().get("prize:"+prizeId+":name")); } else { System.out.println("很遗憾,没有中奖。"); result= "很遗憾,没有中奖。"; } } catch (Exception e) { e.printStackTrace(); } return result; } private void initializePrizes(Connection conn) throws Exception { String sql = "SELECT id,name, quantity, weight FROM prizes"; try (PreparedStatement stmt = conn.prepareStatement(sql); ResultSet rs = stmt.executeQuery()) { while (rs.next()) { String prizeId = rs.getString("id"); int quantity = rs.getInt("quantity"); int weight = rs.getInt("weight"); redisTemplate.opsForSet().add("prizes_set", prizeId); redisTemplate.opsForValue().set("prize:" + prizeId + ":quantity", String.valueOf(quantity)); redisTemplate.opsForValue().set("prize:" + prizeId + ":name", rs.getString("name")); redisTemplate.opsForValue().set("prize:" + prizeId + ":weight", String.valueOf(weight)); } } } private String drawPrize() { Random random = new Random(); Set<String> prizeSet = redisTemplate.opsForSet().members("prizes_set"); int totalWeight = 0; for (String prizeId : prizeSet) { totalWeight += Integer.parseInt(redisTemplate.opsForValue().get("prize:" + prizeId + ":weight")); } int randomWeight = random.nextInt(totalWeight); int currentWeight = 0; for (String prizeId : prizeSet) { currentWeight += Integer.parseInt(redisTemplate.opsForValue().get("prize:" + prizeId + ":weight")); if (randomWeight < currentWeight) { int quantity = Integer.parseInt(redisTemplate.opsForValue().get("prize:" + prizeId + ":quantity")); if (quantity > 0) { redisTemplate.opsForValue().decrement("prize:" + prizeId + ":quantity"); return prizeId; } } } return null; } private void updateDatabase(Connection conn, String prizeId) throws Exception { String sql = "UPDATE prizes SET quantity = quantity - 1 WHERE id = ? and quantity>0"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { stmt.setString(1, prizeId); stmt.executeUpdate(); } } }
调用:
@ApiOperation("模拟抽奖") @PostMapping(value = "/getLottery") public ResultVo getLottery() { String result = lottery.runLottery(); return ResultVo.ok(result); }