目录
- 一、答题获取上下题
- 1.1 controller
- 1.2 service
- 1.3 缓存方法
- 1.4 redis
- 1.5 b端增删题目修改
- 二、竞赛题目列表获取
- 2.1 controller
- 2.2 service
- 2.3 缓存调用
- 2.4 b端撤销发布
- 三、用户竞赛答题获取上下题
- 3.1 controller
- 3.2 service
- 3.3 缓存
一、答题获取上下题
1.1 controller
oj-modules/oj-friend/src/main/java/com/yj/friend/controller/question/QuestionController.java
@GetMapping("/preQuestion")publicR<String>preQuestion(LongquestionId){returnR.success(questionService.preQuestion(questionId));}@GetMapping("/nextQuestion")publicR<String>nextQuestion(LongquestionId){returnR.success(questionService.nextQuestion(questionId));}1.2 service
oj-modules/oj-friend/src/main/java/com/yj/friend/service/question/IQuestionService.java,接口定义
StringpreQuestion(LongquestionId);StringnextQuestion(LongquestionId);oj-modules/oj-friend/src/main/java/com/yj/friend/service/question/impl/QuestionServiceImpl.java,方法,先从缓存获取,没有再从数据库获取
@OverridepublicStringpreQuestion(LongquestionId){refreshQuestionList();Longl=questionCacheManage.preQuestion(questionId);returnl.toString();}@OverridepublicStringnextQuestion(LongquestionId){refreshQuestionList();Longl=questionCacheManage.nextQuestion(questionId);returnl.toString();}1.3 缓存方法
oj-modules/oj-friend/src/main/java/com/yj/friend/manage/QuestionCacheManage.java,题目相关的缓存方法,获得缓存的数量,以及上下题的id
packagecom.yj.friend.manage;importcn.hutool.core.collection.CollectionUtil;importcom.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;importcom.yj.common.core.constants.CacheConstants;importcom.yj.common.core.enums.ResultCodeEnum;importcom.yj.common.redis.service.RedisService;importcom.yj.common.security.exception.ServiceException;importcom.yj.friend.domain.question.QuestionDO;importcom.yj.friend.mapper.question.QuestionMapper;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importjava.util.List;@ComponentpublicclassQuestionCacheManage{@AutowiredprivateRedisServiceredisService;@AutowiredprivateQuestionMapperquestionMapper;//获取缓存中的数据数量publicLonggetListSize(){returnredisService.getListSize(CacheConstants.QUESTION_LIST);}//刷新缓存publicvoidrefreshCache(){List<QuestionDO>questionDOList=questionMapper.selectList(newLambdaQueryWrapper<QuestionDO>().orderByAsc(QuestionDO::getCreateTime).select(QuestionDO::getQuestionId));if(CollectionUtil.isEmpty(questionDOList))return;List<Long>list=questionDOList.stream().map(QuestionDO::getQuestionId).toList();redisService.rightPushAll(CacheConstants.QUESTION_LIST,list);}publicLongpreQuestion(LongquestionId){Longindex=redisService.indexOfList(CacheConstants.QUESTION_LIST,questionId);//第一题if(0==index){thrownewServiceException(ResultCodeEnum.FAILED_FIRST_QUESTION);}//获取上一题returnredisService.indexList(CacheConstants.QUESTION_LIST,index-1,Long.class);}publicLongnextQuestion(LongquestionId){Longindex=redisService.indexOfList(CacheConstants.QUESTION_LIST,questionId);LonglistSize=getListSize();//最后一题if(listSize-1==index){thrownewServiceException(ResultCodeEnum.FAILED_LAST_QUESTION);}//获取下一题returnredisService.indexList(CacheConstants.QUESTION_LIST,index+1,Long.class);}}1.4 redis
oj-common/oj-common-redis/src/main/java/com/yj/common/redis/service/RedisService.java,新增获取索引与数据的方法。
/** * 底层使用list结构,获取指定数据的索引 */public<T>LongindexOfList(finalStringkey,Tvalue){returnredisTemplate.opsForList().indexOf(key,value);}/** * 底层使用list结构,获取指定索引的数据 */public<T>TindexList(finalStringkey,Longindex,Class<T>clazz){Objectindex1=redisTemplate.opsForList().index(key,index);returnJSON.parseObject(String.valueOf(index1),clazz);}1.5 b端增删题目修改
oj-modules/oj-system/src/main/java/com/yj/system/manage/QuestionCacheManage.java缓存使用方法:
packagecom.yj.system.manage;importcom.yj.common.core.constants.CacheConstants;importcom.yj.common.redis.service.RedisService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importjava.util.List;@ComponentpublicclassQuestionCacheManage{@AutowiredprivateRedisServiceredisService;publicvoidaddCache(LongquestionId){redisService.leftPushForList(CacheConstants.QUESTION_LIST,questionId);}publicvoiddeleteCache(LongquestionId){redisService.removeForList(CacheConstants.QUESTION_LIST,questionId);}}service修改:增加缓存的增删
@Overridepublicintdelete(LongquestionId){// 1. 判断题目是否存在QuestionDOquestionDO=questionMapper.selectById(questionId);if(null==questionDO){thrownewServiceException(ResultCodeEnum.FAILED_NOT_EXISTS);}// 2. 删除esquestionRepository.deleteById(questionId);// 3. 删除缓存questionCacheManage.deleteCache(questionId);// 4. 删除数据库returnquestionMapper.deleteById(questionId);}@Overridepublicbooleanadd(QuestionAddDTOquestionAddDTO){// 1.构建查询条件:标题 或 内容 重复List<QuestionDO>questionDOS=questionMapper.selectList(Wrappers.lambdaQuery(QuestionDO.class).and(wrapper->wrapper.eq(QuestionDO::getTitle,questionAddDTO.getTitle()).or().eq(QuestionDO::getContent,questionAddDTO.getContent())));// 2. 如果存在重复数据,抛出异常if(CollectionUtil.isNotEmpty(questionDOS)){thrownewServiceException(ResultCodeEnum.FAILED_ALREADY_EXISTS);}// 3. 拷贝属性并插入QuestionDOquestionDO=newQuestionDO();BeanUtil.copyProperties(questionAddDTO,questionDO);// 4. 插入数据库introw=questionMapper.insert(questionDO);if(row<=0){returnfalse;}// 5. 插入esQuestionESquestionES=BeanUtil.copyProperties(questionDO,QuestionES.class);questionRepository.save(questionES);// 6. 缓存questionCacheManage.addCache(questionDO.getQuestionId());returntrue;}二、竞赛题目列表获取
2.1 controller
oj-modules/oj-friend/src/main/java/com/yj/friend/controller/exam/ExamController.java
@GetMapping("/getFirstQuestion")publicR<String>getFirstQuestion(LongexamId){returnR.success(examService.getFirstQuestion(examId));}2.2 service
oj-modules/oj-friend/src/main/java/com/yj/friend/service/exam/IExamService.java,方法接口
StringgetFirstQuestion(LongexamId);oj-modules/oj-friend/src/main/java/com/yj/friend/service/exam/impl/ExamServiceImpl.java,方法实现
@OverridepublicStringgetFirstQuestion(LongexamId){LongquestionListSize=examCacheManager.getExamQuestionListSize(examId);if(questionListSize==null||questionListSize<=0){//如果缓存中没有数据,刷新缓存examCacheManager.refreshExamQuestionCache(examId);}//从缓存中获取第一个题目returnexamCacheManager.getFirstQuestion(examId).toString();}2.3 缓存调用
oj-modules/oj-friend/src/main/java/com/yj/friend/service/exam/impl/ExamServiceImpl.java
//刷新竞赛题目缓存publicvoidrefreshExamQuestionCache(LongexamId){//查询竞赛题目List<ExamQuestionDO>examQuestionDOS=examQuestionMapper.selectList(newLambdaQueryWrapper<ExamQuestionDO>().eq(ExamQuestionDO::getExamId,examId).orderByAsc(ExamQuestionDO::getQuestionOrder).select(ExamQuestionDO::getQuestionId));//判断是否有数据if(CollectionUtil.isEmpty(examQuestionDOS))return;//将题目题目id转换为listList<Long>questionIdList=examQuestionDOS.stream().map(ExamQuestionDO::getQuestionId).toList();//刷新缓存StringexamQuestionListKey=getExamQuestionListKey(examId);redisService.rightPushAll(examQuestionListKey,questionIdList);Longseconds=ChronoUnit.SECONDS.between(LocalDateTime.now(),LocalDateTime.now().plusSeconds(1).withHour(0).withMinute(0).withSecond(0).withNano(0));redisService.expire(examQuestionListKey,seconds,TimeUnit.SECONDS);}//从缓存中获取第一个题目publicLonggetFirstQuestion(LongexamId){returnredisService.indexList(getExamQuestionListKey(examId),0L,Long.class);}privateStringgetExamQuestionListKey(LongexamId){returnCacheConstants.EXAM_QUESTION_LIST+examId;}2.4 b端撤销发布
oj-modules/oj-system/src/main/java/com/yj/system/manage/ExamCacheManage.java
publicvoiddeleteCache(LongexamId){redisService.removeForList(getExamListKey(),examId);redisService.deleteObject(getDetailKey(examId));redisService.deleteObject(getExamQuestionListKey(examId));}privateStringgetExamQuestionListKey(LongexamId){returnCacheConstants.EXAM_QUESTION_LIST+examId;}三、用户竞赛答题获取上下题
3.1 controller
oj-modules/oj-friend/src/main/java/com/yj/friend/controller/exam/ExamController.java
@GetMapping("/preQuestion")publicR<String>preQuestion(LongexamId,LongquestionId){returnR.success(examService.preQuestion(examId,questionId));}@GetMapping("/nextQuestion")publicR<String>nextQuestion(LongexamId,LongquestionId){returnR.success(examService.nextQuestion(examId,questionId));}3.2 service
oj-modules/oj-friend/src/main/java/com/yj/friend/service/exam/IExamService.java,接口方法
StringpreQuestion(LongexamId,LongquestionId);StringnextQuestion(LongexamId,LongquestionId);oj-modules/oj-friend/src/main/java/com/yj/friend/service/exam/impl/ExamServiceImpl.java
//从竞赛缓存题目列表中获取上一个题目@OverridepublicStringpreQuestion(LongexamId,LongquestionId){refreshQuestionList(examId);Longl=examCacheManager.preQuestion(examId,questionId);returnl.toString();}//从竞赛缓存题目列表中获取下一个题目@OverridepublicStringnextQuestion(LongexamId,LongquestionId){refreshQuestionList(examId);Longl=examCacheManager.nextQuestion(examId,questionId);returnl.toString();}3.3 缓存
oj-modules/oj-friend/src/main/java/com/yj/friend/manage/ExamCacheManager.java
//从竞赛缓存题目列表中获取上一个题目publicLongpreQuestion(LongexamId,LongquestionId){//获取题目在列表中的索引StringexamQuestionListKey=getExamQuestionListKey(examId);Longindex=redisService.indexOfList(examQuestionListKey,questionId);if(0==index){thrownewServiceException(ResultCodeEnum.FAILED_FIRST_QUESTION);}returnredisService.indexList(examQuestionListKey,index-1,Long.class);}//从竞赛缓存题目列表中获取下一个题目publicLongnextQuestion(LongexamId,LongquestionId){//获取题目在列表中的索引StringexamQuestionListKey=getExamQuestionListKey(examId);Longindex=redisService.indexOfList(examQuestionListKey,questionId);longsize=getExamQuestionListSize(examId)-1;if(size==index){thrownewServiceException(ResultCodeEnum.FAILED_LAST_QUESTION);}returnredisService.indexList(examQuestionListKey,index+1,Long.class);}