
目录一、答题获取上下题1.1 controller1.2 service1.3 缓存方法1.4 redis1.5 b端增删题目修改二、竞赛题目列表获取2.1 controller2.2 service2.3 缓存调用2.4 b端撤销发布三、用户竞赛答题获取上下题3.1 controller3.2 service3.3 缓存一、答题获取上下题1.1 controlleroj-modules/oj-friend/src/main/java/com/yj/friend/controller/question/QuestionController.javaGetMapping(/preQuestion)publicRStringpreQuestion(LongquestionId){returnR.success(questionService.preQuestion(questionId));}GetMapping(/nextQuestion)publicRStringnextQuestion(LongquestionId){returnR.success(questionService.nextQuestion(questionId));}1.2 serviceoj-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();LonglquestionCacheManage.preQuestion(questionId);returnl.toString();}OverridepublicStringnextQuestion(LongquestionId){refreshQuestionList();LonglquestionCacheManage.nextQuestion(questionId);returnl.toString();}1.3 缓存方法oj-modules/oj-friend/src/main/java/com/yj/friend/manage/QuestionCacheManage.java题目相关的缓存方法获得缓存的数量以及上下题的idpackagecom.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(){ListQuestionDOquestionDOListquestionMapper.selectList(newLambdaQueryWrapperQuestionDO().orderByAsc(QuestionDO::getCreateTime).select(QuestionDO::getQuestionId));if(CollectionUtil.isEmpty(questionDOList))return;ListLonglistquestionDOList.stream().map(QuestionDO::getQuestionId).toList();redisService.rightPushAll(CacheConstants.QUESTION_LIST,list);}publicLongpreQuestion(LongquestionId){LongindexredisService.indexOfList(CacheConstants.QUESTION_LIST,questionId);//第一题if(0index){thrownewServiceException(ResultCodeEnum.FAILED_FIRST_QUESTION);}//获取上一题returnredisService.indexList(CacheConstants.QUESTION_LIST,index-1,Long.class);}publicLongnextQuestion(LongquestionId){LongindexredisService.indexOfList(CacheConstants.QUESTION_LIST,questionId);LonglistSizegetListSize();//最后一题if(listSize-1index){thrownewServiceException(ResultCodeEnum.FAILED_LAST_QUESTION);}//获取下一题returnredisService.indexList(CacheConstants.QUESTION_LIST,index1,Long.class);}}1.4 redisoj-common/oj-common-redis/src/main/java/com/yj/common/redis/service/RedisService.java新增获取索引与数据的方法。/** * 底层使用list结构获取指定数据的索引 */publicTLongindexOfList(finalStringkey,Tvalue){returnredisTemplate.opsForList().indexOf(key,value);}/** * 底层使用list结构获取指定索引的数据 */publicTTindexList(finalStringkey,Longindex,ClassTclazz){Objectindex1redisTemplate.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. 判断题目是否存在QuestionDOquestionDOquestionMapper.selectById(questionId);if(nullquestionDO){thrownewServiceException(ResultCodeEnum.FAILED_NOT_EXISTS);}// 2. 删除esquestionRepository.deleteById(questionId);// 3. 删除缓存questionCacheManage.deleteCache(questionId);// 4. 删除数据库returnquestionMapper.deleteById(questionId);}Overridepublicbooleanadd(QuestionAddDTOquestionAddDTO){// 1.构建查询条件标题 或 内容 重复ListQuestionDOquestionDOSquestionMapper.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. 拷贝属性并插入QuestionDOquestionDOnewQuestionDO();BeanUtil.copyProperties(questionAddDTO,questionDO);// 4. 插入数据库introwquestionMapper.insert(questionDO);if(row0){returnfalse;}// 5. 插入esQuestionESquestionESBeanUtil.copyProperties(questionDO,QuestionES.class);questionRepository.save(questionES);// 6. 缓存questionCacheManage.addCache(questionDO.getQuestionId());returntrue;}二、竞赛题目列表获取2.1 controlleroj-modules/oj-friend/src/main/java/com/yj/friend/controller/exam/ExamController.javaGetMapping(/getFirstQuestion)publicRStringgetFirstQuestion(LongexamId){returnR.success(examService.getFirstQuestion(examId));}2.2 serviceoj-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){LongquestionListSizeexamCacheManager.getExamQuestionListSize(examId);if(questionListSizenull||questionListSize0){//如果缓存中没有数据刷新缓存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){//查询竞赛题目ListExamQuestionDOexamQuestionDOSexamQuestionMapper.selectList(newLambdaQueryWrapperExamQuestionDO().eq(ExamQuestionDO::getExamId,examId).orderByAsc(ExamQuestionDO::getQuestionOrder).select(ExamQuestionDO::getQuestionId));//判断是否有数据if(CollectionUtil.isEmpty(examQuestionDOS))return;//将题目题目id转换为listListLongquestionIdListexamQuestionDOS.stream().map(ExamQuestionDO::getQuestionId).toList();//刷新缓存StringexamQuestionListKeygetExamQuestionListKey(examId);redisService.rightPushAll(examQuestionListKey,questionIdList);LongsecondsChronoUnit.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_LISTexamId;}2.4 b端撤销发布oj-modules/oj-system/src/main/java/com/yj/system/manage/ExamCacheManage.javapublicvoiddeleteCache(LongexamId){redisService.removeForList(getExamListKey(),examId);redisService.deleteObject(getDetailKey(examId));redisService.deleteObject(getExamQuestionListKey(examId));}privateStringgetExamQuestionListKey(LongexamId){returnCacheConstants.EXAM_QUESTION_LISTexamId;}三、用户竞赛答题获取上下题3.1 controlleroj-modules/oj-friend/src/main/java/com/yj/friend/controller/exam/ExamController.javaGetMapping(/preQuestion)publicRStringpreQuestion(LongexamId,LongquestionId){returnR.success(examService.preQuestion(examId,questionId));}GetMapping(/nextQuestion)publicRStringnextQuestion(LongexamId,LongquestionId){returnR.success(examService.nextQuestion(examId,questionId));}3.2 serviceoj-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);LonglexamCacheManager.preQuestion(examId,questionId);returnl.toString();}//从竞赛缓存题目列表中获取下一个题目OverridepublicStringnextQuestion(LongexamId,LongquestionId){refreshQuestionList(examId);LonglexamCacheManager.nextQuestion(examId,questionId);returnl.toString();}3.3 缓存oj-modules/oj-friend/src/main/java/com/yj/friend/manage/ExamCacheManager.java//从竞赛缓存题目列表中获取上一个题目publicLongpreQuestion(LongexamId,LongquestionId){//获取题目在列表中的索引StringexamQuestionListKeygetExamQuestionListKey(examId);LongindexredisService.indexOfList(examQuestionListKey,questionId);if(0index){thrownewServiceException(ResultCodeEnum.FAILED_FIRST_QUESTION);}returnredisService.indexList(examQuestionListKey,index-1,Long.class);}//从竞赛缓存题目列表中获取下一个题目publicLongnextQuestion(LongexamId,LongquestionId){//获取题目在列表中的索引StringexamQuestionListKeygetExamQuestionListKey(examId);LongindexredisService.indexOfList(examQuestionListKey,questionId);longsizegetExamQuestionListSize(examId)-1;if(sizeindex){thrownewServiceException(ResultCodeEnum.FAILED_LAST_QUESTION);}returnredisService.indexList(examQuestionListKey,index1,Long.class);}