使用Springboot和mybatis框架开发,给出具体程序,程序包含不同表Dao层,不同表Service层,不同表Service实现类,不同表Controller层,使用已有工具类LotteryUtils(程序已有),实现抽奖功能 :1.根据活动查询出相应奖品,并根据奖品概率选出抽中的奖品,记录到抽奖表和中奖表中 2.不在进行中的活动弹出提示 3.超过抽奖限制次数弹出提示 4限制接口频繁访问 10秒内不允许同一个用户访问2次 5抛出异常时事务需要回滚 6.需要校验用户是否存在,奖品是否存在,库存是否足够,否则给与提示
时间: 2024-03-27 10:41:18 浏览: 54
使用Springboot+mybatis+mySql搭建的一个信息系统基础开发框架.zip
好的,以下是一个简单的程序示例,仅供参考:
1. 表Dao层
```java
@Repository
public interface LotteryDao {
// 根据活动查询奖品
List<Lottery> selectByActivityId(Long activityId);
// 更新奖品库存
int updateStock(Long id, int stock);
// 插入抽奖记录
int insertLotteryRecord(LotteryRecord record);
// 插入中奖记录
int insertWinningRecord(WinningRecord record);
}
```
2. 表Service层
```java
public interface LotteryService {
// 抽奖
void draw(Long activityId, Long userId) throws LotteryException;
}
```
3. 表Service实现类
```java
@Service
@Transactional(rollbackFor = Exception.class)
public class LotteryServiceImpl implements LotteryService {
@Autowired
private LotteryDao lotteryDao;
@Autowired
private UserService userService;
@Autowired
private LotteryUtils lotteryUtils;
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final String DRAW_LIMIT_KEY = "draw_limit_%d_%d";
@Override
public void draw(Long activityId, Long userId) throws LotteryException {
// 校验活动是否进行中
Activity activity = activityService.selectById(activityId);
if (activity.getStatus() != ActivityStatus.IN_PROGRESS) {
throw new LotteryException("活动未进行中");
}
// 校验用户是否存在
User user = userService.selectById(userId);
if (user == null) {
throw new LotteryException("用户不存在");
}
// 校验是否超过抽奖限制次数
String drawLimitKey = String.format(DRAW_LIMIT_KEY, activityId, userId);
String drawLimit = redisTemplate.opsForValue().get(drawLimitKey);
if (drawLimit != null && Integer.parseInt(drawLimit) >= activity.getDrawLimit()) {
throw new LotteryException("超过抽奖限制次数");
}
// 校验是否频繁访问
String drawFreqKey = String.format(DRAW_FREQ_KEY, userId);
String lastDrawTime = redisTemplate.opsForValue().get(drawFreqKey);
if (lastDrawTime != null && System.currentTimeMillis() - Long.parseLong(lastDrawTime) < 10000) {
throw new LotteryException("访问频繁,请稍后再试");
}
redisTemplate.opsForValue().set(drawFreqKey, String.valueOf(System.currentTimeMillis()));
// 查询奖品
List<Lottery> lotteryList = lotteryDao.selectByActivityId(activityId);
if (lotteryList == null || lotteryList.size() == 0) {
throw new LotteryException("奖品不存在");
}
// 选出抽中的奖品
Lottery lottery = lotteryUtils.drawLottery(lotteryList);
if (lottery == null) {
throw new LotteryException("没有抽中任何奖品");
}
// 更新奖品库存
int updated = lotteryDao.updateStock(lottery.getId(), lottery.getStock() - 1);
if (updated != 1) {
throw new LotteryException("奖品库存不足");
}
// 插入抽奖记录
LotteryRecord lotteryRecord = new LotteryRecord();
lotteryRecord.setActivityId(activityId);
lotteryRecord.setUserId(userId);
lotteryRecord.setLotteryId(lottery.getId());
lotteryDao.insertLotteryRecord(lotteryRecord);
// 插入中奖记录
WinningRecord winningRecord = new WinningRecord();
winningRecord.setActivityId(activityId);
winningRecord.setUserId(userId);
winningRecord.setLotteryId(lottery.getId());
lotteryDao.insertWinningRecord(winningRecord);
// 更新抽奖次数限制
if (drawLimit == null) {
redisTemplate.opsForValue().set(drawLimitKey, "1", activity.getDuration(), TimeUnit.SECONDS);
} else {
redisTemplate.opsForValue().increment(drawLimitKey);
}
}
}
```
4. 表Controller层
```java
@RestController
@RequestMapping("/lottery")
public class LotteryController {
@Autowired
private LotteryService lotteryService;
@PostMapping("/draw")
public Result draw(@RequestParam Long activityId, @RequestParam Long userId) {
try {
lotteryService.draw(activityId, userId);
return Result.success();
} catch (LotteryException e) {
return Result.fail(e.getMessage());
}
}
}
```
以上示例中,LotteryUtils是一个已经存在的工具类,用于抽奖功能的实现。同时,为了实现限制访问频率的功能,我们使用了Redis作为缓存。在抛出异常时,使用@Transactional注解保证事务回滚。
阅读全文