diff --git a/pom.xml b/pom.xml
index 9a594a3..3201389 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,6 +33,7 @@
mysql
mysql-connector-java
+ runtime
org.projectlombok
@@ -72,7 +73,6 @@
javax.servlet
javax.servlet-api
- 9.0.41
diff --git a/src/main/java/com/lh/controller/VoteController.java b/src/main/java/com/lh/controller/VoteController.java
index 305446f..0c7d8f7 100644
--- a/src/main/java/com/lh/controller/VoteController.java
+++ b/src/main/java/com/lh/controller/VoteController.java
@@ -1,6 +1,7 @@
package com.lh.controller;
import com.lh.bean.RespBean;
+import com.lh.exception.MyException;
import com.lh.service.VoteService;
import com.lh.until.Utils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -43,7 +44,7 @@ public class VoteController {
//获取某个候选人的被投票记录
@GetMapping("/getVotesByCandidate/{candidateJwcode}")
- public RespBean getVotesByCandidate(@PathVariable("candidateJwcode") String candidateJwcode) {
+ public RespBean getVotesByCandidate(@PathVariable("candidateJwcode") String candidateJwcode) throws MyException {
return RespBean.ok("获取成功",voteService.getVotesByCandidate(candidateJwcode));
}
}
diff --git a/src/main/java/com/lh/mapper/VoterMapper.java b/src/main/java/com/lh/mapper/VoterMapper.java
index 09fd863..923106d 100644
--- a/src/main/java/com/lh/mapper/VoterMapper.java
+++ b/src/main/java/com/lh/mapper/VoterMapper.java
@@ -9,7 +9,7 @@ import java.util.List;
@Mapper
public interface VoterMapper {
// 查询用户今日投票信息
- //List countVotesToday(@Param("jwcode") String jwcode);
+ List countVotesToday(@Param("jwcode") String jwcode);
//插入投票记录
void insertVote(@Param("jwcode") String jwcode, @Param("candidateJwcode") String candidateJwcode,@Param("name") String namne);
//根据候选人的jwcode查询投票记录
diff --git a/src/main/java/com/lh/service/VoteService.java b/src/main/java/com/lh/service/VoteService.java
index d4a19a6..18c915e 100644
--- a/src/main/java/com/lh/service/VoteService.java
+++ b/src/main/java/com/lh/service/VoteService.java
@@ -12,5 +12,5 @@ public interface VoteService {
//获取所有候选人
List getCandidates(String VoterJwcode);
//获取某个候选人的被投票记录
- List getVotesByCandidate(String candidateJwcode);
+ List getVotesByCandidate(String candidateJwcode) throws MyException;
}
diff --git a/src/main/java/com/lh/service/VoteServiceImpl.java b/src/main/java/com/lh/service/VoteServiceImpl.java
index 960ce0d..bf56593 100644
--- a/src/main/java/com/lh/service/VoteServiceImpl.java
+++ b/src/main/java/com/lh/service/VoteServiceImpl.java
@@ -13,6 +13,8 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import java.sql.Timestamp;
@@ -25,6 +27,9 @@ import java.util.concurrent.TimeUnit;
@Service
public class VoteServiceImpl implements VoteService {
+
+ private static final Logger logger = LoggerFactory.getLogger(VoteServiceImpl.class);
+
@Autowired
private VoterMapper voterMapper;
@Autowired
@@ -42,103 +47,113 @@ public class VoteServiceImpl implements VoteService {
// 初始化时加载所有候选人数据并缓存到 Redis
@PostConstruct
- public void initCandidatesCache() {
- List candidates = candidatesMapper.getCandidates(); // 从数据库加载所有教师信息
- for (Candidate candidate : candidates) {
- candidateCacheRepository.saveCandidate(candidate); // 将数据保存到 Redis
+ public void initCandidatesCache() throws MyException {
+ try {
+ List candidates = candidatesMapper.getCandidates();
+ for (Candidate candidate : candidates) {
+ candidateCacheRepository.saveCandidate(candidate);
+ }
+ logger.info("Candidate cache initialized successfully.");
+ } catch (Exception e) {
+ logger.error("Failed to initialize candidate cache.", e);
+ throw new MyException("初始化候选人缓存失败");
}
}
- //投票
+ // 投票
@Override
@Transactional(rollbackFor = Exception.class)
public Integer insertVote(String voterJwcode, String candidateJwcode, String voterName) throws MyException {
- // 1. 检查 Redis 中用户今天的投票次数
+
String redisKey = "vote_count:" + voterJwcode + ":" + LocalDateTime.now().toLocalDate();
- String currentVoteCount = stringRedisTemplate.opsForValue().get(redisKey);
+ String currentVoteCountStr = stringRedisTemplate.opsForValue().get(redisKey);
+ int voteCountToday = currentVoteCountStr == null ? 0 : Integer.parseInt(currentVoteCountStr);
- int voteCountToday = currentVoteCount == null ? 0 : Integer.parseInt(currentVoteCount);
if (voteCountToday >= dailyVoteLimit) {
throw new MyException("今日投票次数已达上限");
}
- // 2. 检查该用户是否已经为该候选人投票
String voteStatusKey = "vote_status:" + voterJwcode + ":" + candidateJwcode;
Boolean hasVoted = stringRedisTemplate.hasKey(voteStatusKey);
if (hasVoted != null && hasVoted) {
throw new MyException("您已经为该候选人投票,不能重复投票");
}
-
- // 3. 增加候选人的投票数(Hash 表和 ZSet 同步更新)
String candidateKey = "candidate:" + candidateJwcode;
- // 4.使用 Redis 的 Hash 增加候选人投票数
+ // 使用 Redis 的 Hash 增加候选人投票数
redisTemplate.opsForHash().increment(candidateKey, "votes", 1);
- // 5.使用 Redis 的 ZSet 增加候选人投票数
+ // 使用 Redis 的 ZSet 增加候选人投票数
redisTemplate.opsForZSet().incrementScore("candidate:votes", candidateJwcode, 1);
- // 6. 更新 Redis 中的投票次数
+ // 更新 Redis 中的投票次数
redisTemplate.opsForValue().increment(redisKey, 1);
- // 7.设置 Redis 键的过期时间为当天的23:59:59
+
+ // 设置 Redis 键的过期时间为当天的23:59:59
LocalDateTime now = LocalDateTime.now();
LocalDateTime endOfDay = now.toLocalDate().atTime(23, 59, 59);
long secondsUntilEndOfDay = Duration.between(now, endOfDay).getSeconds();
+ // 更新投票次数的过期时间
redisTemplate.expire(redisKey, secondsUntilEndOfDay, TimeUnit.SECONDS);
- //8.更新投票重复键
+ // 更新投票重复键
stringRedisTemplate.opsForValue().set(voteStatusKey, "true", secondsUntilEndOfDay, TimeUnit.SECONDS);
- //9.控制台打印剩余长时间过期
- System.out.println("Redis键" + redisKey + "将在" + secondsUntilEndOfDay + "秒后过期。");
- System.out.println("Redis键" + voteStatusKey + "将在" + secondsUntilEndOfDay + "秒后过期。");
-
- //10.将投票请求发送到 Kafka 消息队列
- voteProducer.sendVoteMessage(new VoteMessage(voterJwcode,
- candidateJwcode, voterName,
- Timestamp.valueOf(LocalDateTime.now()).toString()));
+
+ // 将投票请求发送到 Kafka 消息队列
+ voteProducer.sendVoteMessage(new VoteMessage(voterJwcode, candidateJwcode, voterName, Timestamp.valueOf(LocalDateTime.now()).toString()));
+
return dailyVoteLimit - voteCountToday - 1;
}
- //获取所有候选人
- //先查redis中有没有数据,没有就从数据库中查
+ // 获取所有候选人
@Override
public List getCandidates(String voterJwcode) {
- // 从 Redis 中获取按投票数排序的候选人 jwCode 列表
- Set