当前位置: 首页 > article >正文

OJ在线评测系统 后端基础部分开发 完善CRUD相关接口

完善相关接口

判斷编程语言是否合法

先从用户的请求拿到Language

package com.dduo.dduoj.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dduo.dduoj.common.ErrorCode;
import com.dduo.dduoj.exception.BusinessException;
import com.dduo.dduoj.model.dto.questionsubmit.JudgeInfo;
import com.dduo.dduoj.model.dto.questionsubmit.QuestionSubmitAddRequest;
import com.dduo.dduoj.model.enums.QuestionSubmitLanguageEnum;
import com.dduo.dduoj.model.enums.QuestionSubmitStatusEnum;
import com.dduo.dduoj.service.mapper.QuestionSubmitMapper;
import com.dduo.dduoj.service.mapper.entity.Question;
import com.dduo.dduoj.service.mapper.entity.QuestionSubmit;
import com.dduo.dduoj.service.mapper.entity.User;
import com.dduo.dduoj.service.QuestionService;
import com.dduo.dduoj.service.QuestionSubmitService;
import javax.annotation.Resource;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 提交题目服务实现
 *
 */
@Service
public class QuestionSubmitServiceImpl extends ServiceImpl<QuestionSubmitMapper, QuestionSubmit>
        implements QuestionSubmitService {

    @Resource
    private QuestionService questionService;

    /**
     * 提交题目
     *
     * @param questionSubmitAddRequest
     * @param loginUser
     * @return
     */
    @Override
    public long doQuestionSubmit(QuestionSubmitAddRequest questionSubmitAddRequest, User loginUser) {
        // 编程语言是否合法
        String language = questionSubmitAddRequest.getLanguage();
        QuestionSubmitLanguageEnum enumByValue = QuestionSubmitLanguageEnum.getEnumByValue(language);
        if (enumByValue==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"编程语言错误");
        }
        long questionId = questionSubmitAddRequest.getQuestionId();
        // 判断实体是否存在,根据类别获取实体
        Question question = questionService.getById(questionId);
        if (question == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // 是否提交题目
        long userId = loginUser.getId();
        // 每个用户串行提交题目
        // 锁必须要包裹住事务方法
        QuestionSubmit questionSubmit = new QuestionSubmit();
        questionSubmit.setUserId(userId);
        questionSubmit.setQuestionId(questionId);
        questionSubmit.setCode(questionSubmitAddRequest.getCode());
        questionSubmit.setLanguage(language);
        //设置初始状态
        questionSubmit.setStatus(QuestionSubmitStatusEnum.WATING.getValue());
        questionSubmit.setJudgeInfo("{}");
        boolean save = this.save(questionSubmit);
        if(!save){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"数据插入失败");
        }
        return questionSubmit.getId();
    }

}

写好了 idea启动

代码运行成功

我们

使用接口文档提交题目试一试

数据库中数据录入成功

为了防止用户根据id爬取题目

建议把id的生成规则改成ASSIGN_ID

非连续递增

而不是从1开始递增

数值传到数据库中进行一个转换

/**
 * 创建
 *
 * @param questionAddRequest
 * @param request
 * @return
 */
@PostMapping("/add")
public BaseResponse<Long> addQuestion(@RequestBody QuestionAddRequest questionAddRequest, HttpServletRequest request) {
    if (questionAddRequest == null) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }
    Question question = new Question();
    BeanUtils.copyProperties(questionAddRequest, question);
    List<String> tags = questionAddRequest.getTags();
    if (tags != null) {
        question.setTags(GSON.toJson(tags));
    }
    List<JudgeCase> judgeCase = questionAddRequest.getJudgeCase();
    if (judgeCase != null) {
        question.setJudgeCase(GSON.toJson(judgeCase));
    }
    List<JudgeConfig> judgeConfig = questionAddRequest.getJudgeConfig();
    if (judgeConfig != null) {
        question.setJudgeConfig(GSON.toJson(judgeConfig));
    }
    questionService.validQuestion(question, true);
    User loginUser = userService.getLoginUser(request);
    question.setUserId(loginUser.getId());
    question.setFavourNum(0);
    question.setThumbNum(0);
    boolean result = questionService.save(question);
    ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
    long newQuestionId = question.getId();
    return ResultUtils.success(newQuestionId);
}

@PostMapping("/update")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Boolean> updateQuestion(@RequestBody QuestionUpdateRequest questionUpdateRequest) {
    if (questionUpdateRequest == null || questionUpdateRequest.getId() <= 0) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }
    Question question = new Question();
    BeanUtils.copyProperties(questionUpdateRequest, question);
    List<String> tags = questionUpdateRequest.getTags();
    if (tags != null) {
        question.setTags(GSON.toJson(tags));
    }
    List<JudgeCase> judgeCase = questionUpdateRequest.getJudgeCase();
    if (judgeCase != null) {
        question.setJudgeCase(GSON.toJson(judgeCase));
    }
    List<JudgeConfig> judgeConfig = questionUpdateRequest.getJudgeConfig();
    if (judgeConfig != null) {
        question.setJudgeConfig(GSON.toJson(judgeConfig));
    }
    // 参数校验
    questionService.validQuestion(question, false);
    long id = questionUpdateRequest.getId();
    // 判断是否存在
    Question oldQuestion = questionService.getById(id);
    ThrowUtils.throwIf(oldQuestion == null, ErrorCode.NOT_FOUND_ERROR);
    boolean result = questionService.updateById(question);
    return ResultUtils.success(result);
}

@PostMapping("/edit")
public BaseResponse<Boolean> editQuestion(@RequestBody QuestionEditRequest questionEditRequest, HttpServletRequest request) {
    if (questionEditRequest == null || questionEditRequest.getId() <= 0) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }
    Question question = new Question();
    BeanUtils.copyProperties(questionEditRequest, question);
    List<String> tags = questionEditRequest.getTags();
    if (tags != null) {
        question.setTags(GSON.toJson(tags));
    }
    List<JudgeCase> judgeCase = questionEditRequest.getJudgeCase();
    if (judgeCase != null) {
        question.setJudgeCase(GSON.toJson(judgeCase));
    }
    List<JudgeConfig> judgeConfig = questionEditRequest.getJudgeConfig();
    if (judgeConfig != null) {
        question.setJudgeConfig(GSON.toJson(judgeConfig));
    }
    // 参数校验
    questionService.validQuestion(question, false);
    User loginUser = userService.getLoginUser(request);
    long id = questionEditRequest.getId();
    // 判断是否存在
    Question oldQuestion = questionService.getById(id);
    ThrowUtils.throwIf(oldQuestion == null, ErrorCode.NOT_FOUND_ERROR);
    // 仅本人或管理员可编辑
    if (!oldQuestion.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) {
        throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
    }
    boolean result = questionService.updateById(question);
    return ResultUtils.success(result);
}

枯燥的测试

完善

查询提交信息

接口功能 能够根据用户id 题目id 编程语言 去查询提交记录

注意事项 仅本人和管理员能看见自己提交代码的答案 提交代码

实现方案 先查询

package com.dduo.dduoj.model.dto.questionsubmit;

import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;

import java.io.Serializable;

//查询请求
@Data
public class QuestionSubmitQueryRequest implements Serializable {
    /**
     * 编程语言
     */
    private String language;    

    /**
     * 提交状态
     */
    private Integer status;

    /**
     * 题目id
     */
    private Long questionId;

    /**
     * 用户id
     */
    private Long userId;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}

QuestionSubmitVO

/**
 * 包装类转对象
 *
 * @param questionSubmitVO
 * @return
 */
public static QuestionSubmit voToObj(QuestionSubmitVO questionSubmitVO) {
    if (questionSubmitVO == null) {
        return null;
    }
    QuestionSubmit questionSubmit = new QuestionSubmit();
    BeanUtils.copyProperties(questionSubmitVO, questionSubmit);
    JudgeInfo judgeInfoObj = questionSubmitVO.getJudgeInfo();
    if (judgeInfoObj != null) {
        questionSubmit.setJudgeInfo(JSONUtil.toJsonStr(judgeInfoObj));
    }
    return questionSubmit;
}

/**
 * 对象转包装类
 *
 * @param questionSubmit
 * @return
 */
public static QuestionSubmitVO objToVo(QuestionSubmit questionSubmit) {
    if (questionSubmit == null) {
        return null;
    }
    QuestionSubmitVO questionSubmitVO = new QuestionSubmitVO();
    BeanUtils.copyProperties(questionSubmit, questionSubmitVO);
    String judgeInfoStr = questionSubmit.getJudgeInfo();
    questionSubmitVO.setJudgeInfo(JSONUtil.toBean(judgeInfoStr, JudgeInfo.class));
    return questionSubmitVO;
}

先查询再根据权限去脱敏

/**
 * 分页获取题目提交(除了管理员外 普通用户是能看见非答案 提交代码等非公开信息)
 *
 * @param questionSubmitQueryRequest
 * @return
 */
@PostMapping("/list/page")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Page<QuestionSubmitVO>> listQuestionSubmitByPage(@RequestBody QuestionSubmitQueryRequest questionSubmitQueryRequest,HttpServletRequest request) {
    long current = questionSubmitQueryRequest.getCurrent();
    long size = questionSubmitQueryRequest.getPageSize();
    //从数据库中获取信息
    Page<QuestionSubmit> questionSubmitPage = questionSubmitService.page(new Page<>(current, size),
            questionSubmitService.getQueryWrapper(questionSubmitQueryRequest));
    //返回脱敏方法
    return ResultUtils.success(questionSubmitService.getQuestionSubmitVOPage(questionSubmitPage,request));
}

脱敏处理

/*
* 单条数据
* */
@Override
public QuestionSubmitVO getQuestionSubmitVO(QuestionSubmit questionSubmit, User loginUser) {
    QuestionSubmitVO questionSubmitVO = QuestionSubmitVO.objToVo(questionSubmit);
    // 脱敏:仅本人和管理员能看见自己(提交 userId 和登录用户 id 不同)提交的代码
    long userId = loginUser.getId();
    // 处理脱敏
    if (userId != questionSubmit.getUserId() && !userService.isAdmin(loginUser)) {
        questionSubmitVO.setCode(null);
    }
    return questionSubmitVO;
}

/*
 * 多条数据
 * */
@Override
public Page<QuestionSubmitVO> getQuestionSubmitVOPage(Page<QuestionSubmit> questionSubmitPage, User loginUser) {
    List<QuestionSubmit> questionSubmitList = questionSubmitPage.getRecords();
    Page<QuestionSubmitVO> questionSubmitVOPage = new Page<>(questionSubmitPage.getCurrent(), questionSubmitPage.getSize(), questionSubmitPage.getTotal());
    if (CollectionUtils.isEmpty(questionSubmitList)) {
        return questionSubmitVOPage;
    }
    List<QuestionSubmitVO> questionSubmitVOList = questionSubmitList.stream()
            .map(questionSubmit -> getQuestionSubmitVO(questionSubmit, loginUser))
            .collect(Collectors.toList());
    questionSubmitVOPage.setRecords(questionSubmitVOList);
    return questionSubmitVOPage;
}

QuestionSubmitServiceImpl

package com.dduo.dduoj.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dduo.dduoj.common.ErrorCode;
import com.dduo.dduoj.constant.CommonConstant;
import com.dduo.dduoj.exception.BusinessException;
import com.dduo.dduoj.judge.JudgeService;
import com.dduo.dduoj.model.dto.questionsubmit.QuestionSubmitAddRequest;
import com.dduo.dduoj.model.dto.questionsubmit.QuestionSubmitQueryRequest;
import com.dduo.dduoj.model.entity.Question;
import com.dduo.dduoj.model.entity.QuestionSubmit;
import com.dduo.dduoj.model.entity.User;
import com.dduo.dduoj.model.enums.QuestionSubmitLanguageEnum;
import com.dduo.dduoj.model.enums.QuestionSubmitStatusEnum;
import com.dduo.dduoj.mapper.QuestionSubmitMapper;
import com.dduo.dduoj.model.vo.QuestionSubmitVO;
import com.dduo.dduoj.service.QuestionService;
import com.dduo.dduoj.service.QuestionSubmitService;
import javax.annotation.Resource;

import com.dduo.dduoj.service.UserService;
import com.dduo.dduoj.utils.SqlUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 提交题目服务实现
 *
 */
@Service
public class QuestionSubmitServiceImpl extends ServiceImpl<QuestionSubmitMapper, QuestionSubmit>
        implements QuestionSubmitService {

    @Resource
    private QuestionService questionService;

    @Resource
    private UserService userService;

    @Resource
    @Lazy
    private JudgeService judgeService;

    /**
     * 提交题目
     *
     * @param questionSubmitAddRequest
     * @param loginUser
     * @return
     */
    @Override
    public long doQuestionSubmit(QuestionSubmitAddRequest questionSubmitAddRequest, User loginUser) {
        // 校验编程语言是否合法
        String language = questionSubmitAddRequest.getLanguage();
        QuestionSubmitLanguageEnum languageEnum = QuestionSubmitLanguageEnum.getEnumByValue(language);
        if (languageEnum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "编程语言错误");
        }
        long questionId = questionSubmitAddRequest.getQuestionId();
        // 判断实体是否存在,根据类别获取实体
        Question question = questionService.getById(questionId);
        if (question == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // 是否已提交题目
        long userId = loginUser.getId();
        // 每个用户串行提交题目
        QuestionSubmit questionSubmit = new QuestionSubmit();
        questionSubmit.setUserId(userId);
        questionSubmit.setQuestionId(questionId);
        questionSubmit.setCode(questionSubmitAddRequest.getCode());
        questionSubmit.setLanguage(language);
        // 设置初始状态
        questionSubmit.setStatus(QuestionSubmitStatusEnum.WAITING.getValue());
        questionSubmit.setJudgeInfo("{}");
        boolean save = this.save(questionSubmit);
        if (!save){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "数据插入失败");
        }
        Long questionSubmitId = questionSubmit.getId();
        // 执行判题服务
        CompletableFuture.runAsync(() -> {
            judgeService.doJudge(questionSubmitId);
        });
        return questionSubmitId;
    }


    /**
     * 获取查询包装类(用户根据哪些字段查询,根据前端传来的请求对象,得到 mybatis 框架支持的查询 QueryWrapper 类)
     *
     * @param questionSubmitQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<QuestionSubmit> getQueryWrapper(QuestionSubmitQueryRequest questionSubmitQueryRequest) {
        QueryWrapper<QuestionSubmit> queryWrapper = new QueryWrapper<>();
        if (questionSubmitQueryRequest == null) {
            return queryWrapper;
        }
        String language = questionSubmitQueryRequest.getLanguage();
        Integer status = questionSubmitQueryRequest.getStatus();
        Long questionId = questionSubmitQueryRequest.getQuestionId();
        Long userId = questionSubmitQueryRequest.getUserId();
        String sortField = questionSubmitQueryRequest.getSortField();
        String sortOrder = questionSubmitQueryRequest.getSortOrder();

        // 拼接查询条件
        queryWrapper.eq(StringUtils.isNotBlank(language), "language", language);
        queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(questionId), "questionId", questionId);
        queryWrapper.eq(QuestionSubmitStatusEnum.getEnumByValue(status) != null, "status", status);
        queryWrapper.eq("isDelete", false);
        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                sortField);
        return queryWrapper;
    }

    /*
    * 单条数据
    * */
    @Override
    public QuestionSubmitVO getQuestionSubmitVO(QuestionSubmit questionSubmit, User loginUser) {
        QuestionSubmitVO questionSubmitVO = QuestionSubmitVO.objToVo(questionSubmit);
        // 脱敏:仅本人和管理员能看见自己(提交 userId 和登录用户 id 不同)提交的代码
        long userId = loginUser.getId();
        // 处理脱敏
        if (userId != questionSubmit.getUserId() && !userService.isAdmin(loginUser)) {
            questionSubmitVO.setCode(null);
        }
        return questionSubmitVO;
    }

    /*
     * 多条数据
     * */
    @Override
    public Page<QuestionSubmitVO> getQuestionSubmitVOPage(Page<QuestionSubmit> questionSubmitPage, User loginUser) {
        List<QuestionSubmit> questionSubmitList = questionSubmitPage.getRecords();
        Page<QuestionSubmitVO> questionSubmitVOPage = new Page<>(questionSubmitPage.getCurrent(), questionSubmitPage.getSize(), questionSubmitPage.getTotal());
        if (CollectionUtils.isEmpty(questionSubmitList)) {
            return questionSubmitVOPage;
        }
        List<QuestionSubmitVO> questionSubmitVOList = questionSubmitList.stream()
                .map(questionSubmit -> getQuestionSubmitVO(questionSubmit, loginUser))
                .collect(Collectors.toList());
        questionSubmitVOPage.setRecords(questionSubmitVOList);
        return questionSubmitVOPage;
    }

}

controller层代码

/**
 * 提交题目
 *
 * @param questionSubmitAddRequest
 * @param request
 * @return 提交记录的 id
 */
@PostMapping("/")
public BaseResponse<Long> doQuestionSubmit(@RequestBody QuestionSubmitAddRequest questionSubmitAddRequest,
                                           HttpServletRequest request) {
    if (questionSubmitAddRequest == null || questionSubmitAddRequest.getQuestionId() <= 0) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }
    // 登录才能点赞
    final User loginUser = userService.getLoginUser(request);
    long questionSubmitId = questionSubmitService.doQuestionSubmit(questionSubmitAddRequest, loginUser);
    return ResultUtils.success(questionSubmitId);
}

listQuestionSubmitByPage

/**
 * 分页获取题目提交(除了管理员外 普通用户是能看见非答案 提交代码等非公开信息)
 *
 * @param questionSubmitQueryRequest
 * @return
 */
@PostMapping("/list/page")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Page<QuestionSubmitVO>> listQuestionSubmitByPage(@RequestBody QuestionSubmitQueryRequest questionSubmitQueryRequest, HttpServletRequest request) {
    long current = questionSubmitQueryRequest.getCurrent();
    long size = questionSubmitQueryRequest.getPageSize();
    //从数据库中获取信息
    Page<QuestionSubmit> questionSubmitPage = questionSubmitService.page(new Page<>(current, size),
            questionSubmitService.getQueryWrapper(questionSubmitQueryRequest));
    final User loginUser = userService.getLoginUser(request);
    //返回脱敏方法
    return ResultUtils.success(questionSubmitService.getQuestionSubmitVOPage(questionSubmitPage, loginUser));
}

http://www.kler.cn/news/326984.html

相关文章:

  • 【ARM 嵌入式 C 入门及渐进26 -- 内敛函数和宏定义的区别】
  • armbian安装docker
  • MongoDB的查询/超详细/表达式符号
  • SQLMap使用指南
  • Linux服务安装node,npm与yarn
  • 0-1开发自己的obsidian plugin DAY 6
  • 数据挖掘的基本步骤和流程解析:深入洞察与策略实施
  • 重修设计模式-行为型-责任链模式
  • ubuntu24.04 最好的输入法是什么?
  • 【ARM 嵌入式 编译系列 10.6 -- ARM toolchain examples】
  • 【Docker】解决Docker Engine stopped
  • cocos打包后发布web,控制台报错.plist资源下载404
  • Netty 与 WebSocket之间的关系
  • 宠物空气净化器该怎么选?希喂、美的、有哈这三款有推荐的吗?
  • 将 Go 作为脚本语言用及一些好用的包
  • 渗透测试入门学习——编写python脚本实现对网站登录页面的暴力破解
  • 自动化办公-Python中的for循环
  • 网络安全中的 EDR 是什么:概述和功能
  • 【芋道源码】gitee很火的开源项目pig——后台管理快速开发框架使用笔记(微服务版之本地开发环境篇)
  • 计算机网络面试题——第二篇
  • java中创建jdbc应用程序
  • OJ在线评测系统 前端 完善题目提交服务 细讲异步前端请求与后端接口交互
  • 代码随想录算法训练营第34天|46. 携带研究材料、416. 分割等和子集
  • Android 12系统源码_输入系统(三)输入事件的加工和分发
  • Spring RestTemplate 升级 WebClient 导致 OutOfMemoryError
  • SQL进阶技巧:如何利用if语句简化where或join中的条件 | if条件语句的优雅使用方法
  • QT界面制作
  • 粉丝们得以一窥索菲亚罗兰奢华的90岁生日庆祝仪式! 她已完成了所有的遗愿清单 !
  • 选择租用徐州存储服务器有什么作用?
  • 大数据-149 Apache Druid 基本介绍 技术特点 应用场景