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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值