使用Springboot和mybatis框架,Mysql数据库开发,给出具体程序,程序包含Dao层,Mapper.xml文件,Service层,Service实现类,Controller层,实现抽奖功能 : 1.根据活动查询出相应奖品,并根据奖品概率选出抽中的奖品,记录到抽奖表和中奖表中 2.不在进行中的活动弹出提示 3.超过抽奖限制次数弹出提示 4限制接口频繁访问 10秒内不允许同一个用户访问2次 5抛出异常时事务需要回滚 6.需要校验用户是否存在,奖品是否存在,库存是否足够,否则给与提示
时间: 2024-03-27 09:38:45 浏览: 127
抽奖功能需要进行数据库操作,因此需要先创建数据库和相应的表。我们创建一个名为`lottery`的数据库,其中包含以下三个表:
- `activity`表:存储所有的活动信息,包括活动ID、活动名称、开始时间、结束时间等。
- `prize`表:存储所有的奖品信息,包括奖品ID、奖品名称、奖品数量、奖品概率等。
- `record`表:存储所有的抽奖记录信息,包括记录ID、用户ID、活动ID、奖品ID、抽奖时间等。
接下来,我们按照Dao层、Mapper.xml文件、Service层、Service实现类、Controller层的顺序,给出具体程序。
#### Dao层
```java
package com.example.lottery.dao;
import com.example.lottery.entity.Activity;
import com.example.lottery.entity.Prize;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
@Mapper
public interface LotteryDao {
Activity getActivityById(@Param("activityId") Integer activityId);
List<Prize> getPrizeListByActivityId(@Param("activityId") Integer activityId);
int decreasePrizeStock(@Param("prizeId") Integer prizeId);
int insertRecord(@Param("userId") Integer userId, @Param("activityId") Integer activityId, @Param("prizeId") Integer prizeId, @Param("time") Date time);
}
```
#### Mapper.xml文件
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.lottery.dao.LotteryDao">
<select id="getActivityById" parameterType="java.lang.Integer" resultType="com.example.lottery.entity.Activity">
SELECT * FROM activity WHERE id = #{activityId}
</select>
<select id="getPrizeListByActivityId" parameterType="java.lang.Integer" resultType="com.example.lottery.entity.Prize">
SELECT * FROM prize WHERE activity_id = #{activityId} AND stock > 0
</select>
<update id="decreasePrizeStock" parameterType="java.lang.Integer">
UPDATE prize SET stock = stock - 1 WHERE id = #{prizeId} AND stock > 0
</update>
<insert id="insertRecord" parameterType="java.util.Map">
INSERT INTO record(user_id, activity_id, prize_id, time) VALUES(#{userId}, #{activityId}, #{prizeId}, #{time,jdbcType=TIMESTAMP})
</insert>
</mapper>
```
#### Service层
```java
package com.example.lottery.service;
import com.example.lottery.entity.Activity;
import com.example.lottery.entity.Prize;
import com.example.lottery.exception.LotteryException;
import java.util.List;
public interface LotteryService {
Activity getActivityById(Integer activityId);
List<Prize> getPrizeListByActivityId(Integer activityId);
Prize drawPrize(Integer userId, Integer activityId) throws LotteryException;
}
```
#### Service实现类
```java
package com.example.lottery.service.impl;
import com.example.lottery.dao.LotteryDao;
import com.example.lottery.entity.Activity;
import com.example.lottery.entity.Prize;
import com.example.lottery.exception.LotteryException;
import com.example.lottery.service.LotteryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Random;
@Service
public class LotteryServiceImpl implements LotteryService {
@Autowired
private LotteryDao lotteryDao;
@Override
public Activity getActivityById(Integer activityId) {
return lotteryDao.getActivityById(activityId);
}
@Override
public List<Prize> getPrizeListByActivityId(Integer activityId) {
return lotteryDao.getPrizeListByActivityId(activityId);
}
@Override
@Transactional(rollbackFor = LotteryException.class)
public Prize drawPrize(Integer userId, Integer activityId) throws LotteryException {
Activity activity = lotteryDao.getActivityById(activityId);
if (activity == null || activity.getStartTime().after(new Date()) || activity.getEndTime().before(new Date())) {
throw new LotteryException("活动不存在或已结束");
}
int count = lotteryDao.getDrawCountByUserIdAndActivityId(userId, activityId);
if (count >= activity.getDrawLimit()) {
throw new LotteryException("超过抽奖限制次数");
}
long lastDrawTime = lotteryDao.getLastDrawTimeByUserId(userId);
if (lastDrawTime != 0 && System.currentTimeMillis() - lastDrawTime < 10000) {
throw new LotteryException("接口频繁访问");
}
List<Prize> prizeList = lotteryDao.getPrizeListByActivityId(activityId);
if (prizeList == null || prizeList.isEmpty()) {
throw new LotteryException("奖品已抽完");
}
int totalWeight = 0;
for (Prize prize : prizeList) {
totalWeight += prize.getProbability();
}
int randomNum = new Random().nextInt(totalWeight);
int weightSum = 0;
for (Prize prize : prizeList) {
weightSum += prize.getProbability();
if (randomNum < weightSum) {
int result = lotteryDao.decreasePrizeStock(prize.getId());
if (result != 1) {
throw new LotteryException("奖品已抽完");
}
lotteryDao.insertRecord(userId, activityId, prize.getId(), new Date());
return prize;
}
}
throw new LotteryException("奖品已抽完");
}
}
```
#### Controller层
```java
package com.example.lottery.controller;
import com.example.lottery.entity.Prize;
import com.example.lottery.exception.LotteryException;
import com.example.lottery.service.LotteryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LotteryController {
@Autowired
private LotteryService lotteryService;
@GetMapping("/draw/{userId}/{activityId}")
public Prize drawPrize(@PathVariable Integer userId, @PathVariable Integer activityId) throws LotteryException {
return lotteryService.drawPrize(userId, activityId);
}
}
```
以上就是具体的程序实现,需要注意的是,抽奖功能中涉及到了事务的处理,需要在Service实现类中添加`@Transactional`注解,并指定`rollbackFor`属性为自定义的异常类`LotteryException`,以保证在抛出异常时能够进行事务回滚。同时,需要注意对用户、活动、奖品等信息的校验,以保证抽奖功能的正常运行。
阅读全文