From 9d444f55a38c3e724f9b52b005b7eb0dc7a74a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E7=82=AB=E5=A5=BD?= <143517814@qq.com> Date: Sun, 15 Dec 2024 21:00:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B3=A8=E9=87=8A=E4=BA=86=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E7=9A=84lsgwr.exam=E6=96=87=E4=BB=B6=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/lsgwr/exam/config/CORSConf.java | 7 +++ .../lsgwr/exam/config/IntercepterConfig.java | 4 +- .../java/lsgwr/exam/config/ServletConfig.java | 4 ++ .../lsgwr/exam/config/Swagger2Config.java | 20 ++++++- .../lsgwr/exam/controller/ExamController.java | 57 +++++++++++++++---- .../controller/UploadDownloadController.java | 23 ++++++-- .../main/java/lsgwr/exam/dto/RegisterDTO.java | 12 ++++ .../main/java/lsgwr/exam/entity/Action.java | 5 ++ .../src/main/java/lsgwr/exam/entity/Exam.java | 28 ++++++++- .../java/lsgwr/exam/entity/ExamRecord.java | 21 ++++++- .../lsgwr/exam/entity/ExamRecordLevel.java | 3 + .../src/main/java/lsgwr/exam/entity/Page.java | 4 ++ .../main/java/lsgwr/exam/entity/Question.java | 12 ++++ .../lsgwr/exam/entity/QuestionCategory.java | 5 ++ .../java/lsgwr/exam/entity/QuestionLevel.java | 4 +- .../lsgwr/exam/entity/QuestionOption.java | 3 + .../java/lsgwr/exam/entity/QuestionType.java | 7 ++- .../src/main/java/lsgwr/exam/entity/Role.java | 8 +++ .../src/main/java/lsgwr/exam/entity/User.java | 28 +++++++-- .../java/lsgwr/exam/enums/LoginTypeEnum.java | 7 +++ .../java/lsgwr/exam/enums/ResultEnum.java | 3 + .../main/java/lsgwr/exam/enums/RoleEnum.java | 4 ++ .../lsgwr/exam/exception/ExamException.java | 7 +++ .../exam/interceptor/LoginInterceptor.java | 36 +++++++++++- .../main/java/lsgwr/exam/qo/DownloadQo.java | 3 +- .../src/main/java/lsgwr/exam/qo/LoginQo.java | 6 ++ .../main/java/lsgwr/exam/qo/UploadModel.java | 8 +++ .../main/java/lsgwr/exam/qo/UploadModel2.java | 8 +++ 28 files changed, 308 insertions(+), 29 deletions(-) diff --git a/backend/src/main/java/lsgwr/exam/config/CORSConf.java b/backend/src/main/java/lsgwr/exam/config/CORSConf.java index d75d4e5..e0305e8 100644 --- a/backend/src/main/java/lsgwr/exam/config/CORSConf.java +++ b/backend/src/main/java/lsgwr/exam/config/CORSConf.java @@ -16,15 +16,22 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Slf4j public class CORSConf { + // 创建一个 WebMvcConfigurer Bean @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { + // 重写 addCorsMappings 方法 @Override public void addCorsMappings(CorsRegistry registry) { + // 记录初始化 CORSConfiguration 配置 log.info("初始化 CORSConfiguration 配置"); + // 添加映射 registry.addMapping("/**") + // 允许所有请求头 .allowedHeaders("*") + // 允许所有请求方法 .allowedMethods("*") + // 允许所有请求来源 .allowedOrigins("*"); } }; diff --git a/backend/src/main/java/lsgwr/exam/config/IntercepterConfig.java b/backend/src/main/java/lsgwr/exam/config/IntercepterConfig.java index 9ee60af..77d44a6 100644 --- a/backend/src/main/java/lsgwr/exam/config/IntercepterConfig.java +++ b/backend/src/main/java/lsgwr/exam/config/IntercepterConfig.java @@ -15,13 +15,15 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class IntercepterConfig implements WebMvcConfigurer { + // 注入LoginInterceptor @Autowired private LoginInterceptor loginInterceptor; + // 添加拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { // 拦截user下的api registry.addInterceptor(loginInterceptor).addPathPatterns("/api/**"); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/lsgwr/exam/config/ServletConfig.java b/backend/src/main/java/lsgwr/exam/config/ServletConfig.java index 5139cb3..a806a84 100644 --- a/backend/src/main/java/lsgwr/exam/config/ServletConfig.java +++ b/backend/src/main/java/lsgwr/exam/config/ServletConfig.java @@ -9,10 +9,14 @@ import org.springframework.http.HttpStatus; @Configuration public class ServletConfig { + // 创建一个WebServerFactoryCustomizer bean,用于自定义WebServerFactory @Bean public WebServerFactoryCustomizer webServerFactoryCustomizer() { + // 返回一个lambda表达式,用于自定义WebServerFactory return factory -> { + // 创建一个ErrorPage对象,用于处理404错误 ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/"); + // 将ErrorPage对象添加到WebServerFactory中 factory.addErrorPages(error404Page); }; } diff --git a/backend/src/main/java/lsgwr/exam/config/Swagger2Config.java b/backend/src/main/java/lsgwr/exam/config/Swagger2Config.java index a67cb04..817acf3 100644 --- a/backend/src/main/java/lsgwr/exam/config/Swagger2Config.java +++ b/backend/src/main/java/lsgwr/exam/config/Swagger2Config.java @@ -29,32 +29,48 @@ public class Swagger2Config { @Bean public Docket api() { + // 创建一个参数构建器 ParameterBuilder ticketPar = new ParameterBuilder(); + // 创建一个参数集合 List pars = new ArrayList<>(); + // 设置参数名 ticketPar.name("Access-Token").description("Rest接口权限认证token,无需鉴权可为空") + // 设置参数类型 .modelRef(new ModelRef("string")).parameterType("header") - //header中的ticket参数非必填,传空也可以 + // header中的ticket参数非必填,传空也可以 .required(false).build(); - //根据每个方法名也知道当前方法在设置什么参数 + // 根据每个方法名也知道当前方法在设置什么参数 pars.add(ticketPar.build()); return new Docket(DocumentationType.SWAGGER_2) + // 设置文档信息 .apiInfo(apiInfo()) + // 选择要扫描的接口 .select() // 自行修改为自己的包路径 .apis(RequestHandlerSelectors.basePackage("lsgwr")) + // 选择所有的路径 .paths(PathSelectors.any()) + // 构建Docket .build() + // 设置全局参数 .globalOperationParameters(pars); } private ApiInfo apiInfo() { + // 创建ApiInfo对象 return new ApiInfoBuilder() + // 设置API标题 .title("online exam by springboot") + // 设置API描述 .description("在线考试系统 by 梁山广 at 2021") + // 设置API服务条款URL .termsOfServiceUrl("https://github.com/19920625lsg/spring-boot-online-exam") + // 设置API版本 .version("2.0") + // 设置API联系人信息 .contact(new Contact("liangshanguang", "https://github.com/lsgwr/spring-boot-online-exam", "liangshanguang2@gmail.com")) + // 构建ApiInfo对象 .build(); } } \ No newline at end of file diff --git a/backend/src/main/java/lsgwr/exam/controller/ExamController.java b/backend/src/main/java/lsgwr/exam/controller/ExamController.java index 852805f..10b34fb 100644 --- a/backend/src/main/java/lsgwr/exam/controller/ExamController.java +++ b/backend/src/main/java/lsgwr/exam/controller/ExamController.java @@ -29,7 +29,10 @@ public class ExamController { private ExamService examService; /** - * @Description: 使用examService.getQuestionAll()获取数据,并将其包装在ResultVO对象中,用于获取所有考试列表 + * @Description: 使用examService.getQuestionAll()获取数据, + * + * 并将其包装在ResultVO对象中,用于获取所有考试列表 + * * @ApiOperation注解用于描述API操作,它将显示在SwaggerUI中 */ @GetMapping("/question/all") @@ -73,10 +76,20 @@ ResultVO> getQuestionAll() { /** * 创建问题 - * @Description: 从请求体中获取一个QuestionCreateSimplifyVo对象,将其属性复制到QuestionCreateVo,设置创建者的ID,并使用examService.questionCreate()创建问题。 - * @param questionCreateSimplifyVo 从请求体中获取的QuestionCreateSimplifyVo对象 + * @Description: 从请求体中获取一个QuestionCreateSimplifyVo对象, + * 将其属性复制到QuestionCreateVo,设置创建者的ID, + * + * 并使用examService.questionCreate()创建问题。 + * + * @param questionCreateSimplifyVo + * + * 从请求体中获取的QuestionCreateSimplifyVo对象 + * * @param request HttpServletRequest对象,用于获取当前用户的ID + * * @return ResultVO 对象,包含操作结果信息 + * + * */ @PostMapping("/question/create") @ApiOperation("创建问题") @@ -103,7 +116,10 @@ ResultVO> getQuestionAll() { } /** - * @Description: 获取全部问题列表,使用examService.getSelections()获取数据,并将其包装在ResultVO对象中 + * @Description: 获取全部问题列表, + * + * 使用examService.getSelections()获取数据,并将其包装在ResultVO对象中 + * * @return ResultVO 对象,包含问题列表 */ @GetMapping("/question/selection") @@ -221,7 +237,10 @@ ResultVO getSelections() { /** * @Description: 获取考试列表,适配前端卡片列表 - * @return ResultVO> 对象,包含考试列表卡片信息 + * + * @return ResultVO> 对象, + * + * 包含考试列表卡片信息 */ @GetMapping("/card/list") @ApiOperation("获取考试列表,适配前端卡片列表") @@ -244,7 +263,9 @@ ResultVO getSelections() { /** * @Description: 根据考试的id,获取考试详情 + * * @param id 考试id + * * @return ResultVO 对象,包含考试详情信息 */ @GetMapping("/detail/{id}") @@ -262,9 +283,13 @@ ResultVO getSelections() { } /** - * @Description: 使用examService.finishExam获取数据,并将其包装在ResultVO对象中,用于考试判分 + * @Description: 使用examService.finishExam获取数据, + * + * 并将其包装在ResultVO对象中,用于考试判分 * @param examId 考试id + * * @param answersMap 用户提交的答案 + * * @param request 获取用户id * @return */ @@ -290,9 +315,14 @@ ResultVO getSelections() { } /** - * @Description: 使用examService.getExamRecordList获取数据,并将其包装在ResultVO对象中,用于获取当前用户的考试记录 + * @Description: 使用examService.getExamRecordList获取数据, + * 并将其包装在ResultVO对象中,用于获取当前用户的考试记录 + * * @param request 获取用户id - * @return ResultVO> 返回一个包含考试记录列表的ResultVO对象,如果发生异常,则返回一个包含错误信息的ResultVO对象。 + * + * @return ResultVO> + * + * 返回一个包含考试记录列表的ResultVO对象,如果发生异常,则返回一个包含错误信息的ResultVO对象。 */ @GetMapping("/record/list") @ApiOperation("获取当前用户的考试记录") @@ -313,9 +343,16 @@ ResultVO getSelections() { } /** - * @Description: 使用examService.getExamRecordDetail获取数据,并将其包装在ResultVO对象中,用于获取指定id的考试记录详情 + * @Description: 使用examService.getExamRecordDetail获取数据, + * + * 并将其包装在ResultVO对象中,用于获取指定id的考试记录详情 + * * @param recordId 考试记录id - * @return ResultVO 返回一个包含考试记录详情的ResultVO对象,如果发生异常,则返回一个包含错误信息的ResultVO对象。 + * + * @return ResultVO + * 返回一个包含考试记录详情的ResultVO对象, + * + * 如果发生异常,则返回一个包含错误信息的ResultVO对象。 */ @GetMapping("/record/detail/{recordId}") @ApiOperation("根据考试记录id获取考试记录详情") diff --git a/backend/src/main/java/lsgwr/exam/controller/UploadDownloadController.java b/backend/src/main/java/lsgwr/exam/controller/UploadDownloadController.java index 35c7cc2..96a439a 100644 --- a/backend/src/main/java/lsgwr/exam/controller/UploadDownloadController.java +++ b/backend/src/main/java/lsgwr/exam/controller/UploadDownloadController.java @@ -15,13 +15,22 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; /*********************************************************** + * * @note : 文件上传下载的接口,由于Swagger的问题导致在SwaggerUI - * 里测试不成功,实际上前端是完全没有问题的 + * + * 里测试不成功, + * 实际上前端是完全没有问题的 * @author : 梁山广 - * * 为了支持Ajax请求和响应,最简单的解决方案返回一个ResponseEntity。 - * * 以下示例演示了上传文件的三种可能方式: - * * 1. 单文件上传 - `MultipartFile` - * * 2. 多文件上传 - `MultipartFile []` + * + * * 为了支持Ajax请求和响应, + * + * 最简单的解决方案返回一个ResponseEntity。 + * * 以下示例演示了上传文件 + * 的三种可能方式: + * * 1. 单文件上传 + * - `MultipartFile` + * * 2. 多文件上传 + * - `MultipartFile []` * * 3. 将文件上传到模型 - `@ModelAttribute` * @version : V1.0 at 2018/7/16 20:43 ***********************************************************/ @@ -32,10 +41,14 @@ import java.io.IOException; public class UploadDownloadController { // @Autowired + // AITestConfig aiTestConfig; + // // @PostMapping("/upload/single") + // @ApiOperation("单文件上传") + // public String uploadFile(@RequestParam("file") MultipartFile uploadfile) { // return FileTransUtil.uploadFile(uploadfile, "/root/" + File.separator + uploadfile.getOriginalFilename()); // } diff --git a/backend/src/main/java/lsgwr/exam/dto/RegisterDTO.java b/backend/src/main/java/lsgwr/exam/dto/RegisterDTO.java index 970c4f1..5bb03c6 100644 --- a/backend/src/main/java/lsgwr/exam/dto/RegisterDTO.java +++ b/backend/src/main/java/lsgwr/exam/dto/RegisterDTO.java @@ -10,9 +10,21 @@ import lombok.Data; @Data public class RegisterDTO { + /** + * 邮箱 + */ private String email; + /** + * 密码 + */ private String password; + /** + * 确认密码 + */ private String password2; + /** + * 手机号 + */ private String mobile; /** * 验证码 diff --git a/backend/src/main/java/lsgwr/exam/entity/Action.java b/backend/src/main/java/lsgwr/exam/entity/Action.java index 2c9d1df..020b58d 100644 --- a/backend/src/main/java/lsgwr/exam/entity/Action.java +++ b/backend/src/main/java/lsgwr/exam/entity/Action.java @@ -15,13 +15,18 @@ import javax.persistence.Id; @Data @Entity public class Action { + // 定义一个主键 @Id + // 自动生成主键 @GeneratedValue private Integer actionId; + // 定义一个动作名称 private String actionName; + // 定义一个动作描述 private String actionDescription; + // 定义一个默认选中状态 private Boolean defaultCheck; } diff --git a/backend/src/main/java/lsgwr/exam/entity/Exam.java b/backend/src/main/java/lsgwr/exam/entity/Exam.java index 5223eb2..1f96a59 100644 --- a/backend/src/main/java/lsgwr/exam/entity/Exam.java +++ b/backend/src/main/java/lsgwr/exam/entity/Exam.java @@ -20,36 +20,62 @@ import java.util.Date; @Data @DynamicUpdate public class Exam { + // 考试ID @Id private String examId; + // 考试名称 private String examName; + // 考试头像 private String examAvatar; + // 考试描述 private String examDescription; + // 考试问题ID private String examQuestionIds; + // 考试单选题ID private String examQuestionIdsRadio; + // 考试多选题ID private String examQuestionIdsCheck; + // 考试判断题ID private String examQuestionIdsJudge; + // 考试总分 private Integer examScore; + // 考试单选题总分 private Integer examScoreRadio; + // 考试多选题总分 private Integer examScoreCheck; + // 考试判断题总分 private Integer examScoreJudge; + // 考试创建者ID private String examCreatorId; + // 考试时间限制 private Integer examTimeLimit; + // 考试开始时间 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date examStartDate; + // 考试结束时间 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date examEndDate; /** + * + * * 创建时间, 设计表时设置了自动插入当前时间,无需在Java代码中设置了 + * + * */ + // 创建时间 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; /** * 更新时间,设计表时设置了自动插入当前时间,无需在Java代码中设置了。 - * 同时@DynamicUpdate注解可以时间当数据库数据变化时自动更新,无需人工维护 + * + * + * 同时@DynamicUpdate注解可以时间当数据库数据变化时自动更 + * + * 新,无需人工维护 */ + // 更新时间 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date updateTime; } diff --git a/backend/src/main/java/lsgwr/exam/entity/ExamRecord.java b/backend/src/main/java/lsgwr/exam/entity/ExamRecord.java index 5adda4b..2d73236 100644 --- a/backend/src/main/java/lsgwr/exam/entity/ExamRecord.java +++ b/backend/src/main/java/lsgwr/exam/entity/ExamRecord.java @@ -18,39 +18,58 @@ import java.util.Date; @Entity public class ExamRecord { /** + * + * * 主键 + * + * */ @Id private String examRecordId; /** + * * 参与的考试的id + * */ private String examId; /** - * 考生作答地每个题目的选项(题目和题目之间用_分隔,题目有多个选项地话用-分隔),用于查看考试详情 + * + * 考生作答地每个题目的选项(题目和题目之间用_分隔,题目 + * + * 有多个选项地话用-分隔),用于查看考试详情 */ private String answerOptionIds; /** + * * 参与者,即user的id + * */ private String examJoinerId; /** + * * 参加考试的日期 + * */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date examJoinDate; /** + * * 考试耗时(秒) + * */ private Integer examTimeCost; /** + * * 考试得分 + * */ private Integer examJoinScore; /** + * * 考试得分水平 + * */ private Integer examResultLevel; } diff --git a/backend/src/main/java/lsgwr/exam/entity/ExamRecordLevel.java b/backend/src/main/java/lsgwr/exam/entity/ExamRecordLevel.java index 2aa08b3..0496a85 100644 --- a/backend/src/main/java/lsgwr/exam/entity/ExamRecordLevel.java +++ b/backend/src/main/java/lsgwr/exam/entity/ExamRecordLevel.java @@ -16,9 +16,12 @@ import javax.persistence.Id; @Data @Entity public class ExamRecordLevel { + // 考试记录等级ID @Id @GeneratedValue private Integer examRecordLevelId; + // 考试记录等级名称 private String examRecordLevelName; + // 考试记录等级描述 private String examRecordLevelDescription; } diff --git a/backend/src/main/java/lsgwr/exam/entity/Page.java b/backend/src/main/java/lsgwr/exam/entity/Page.java index 7a31b0e..0202aa1 100644 --- a/backend/src/main/java/lsgwr/exam/entity/Page.java +++ b/backend/src/main/java/lsgwr/exam/entity/Page.java @@ -15,13 +15,17 @@ import javax.persistence.Id; @Data @Entity public class Page { + // 定义一个页面ID,使用@Id注解表示该字段为主键,使用@GeneratedValue注解表示该字段自动生成 @Id @GeneratedValue private Integer pageId; + // 定义一个页面名称 private String pageName; + // 定义一个页面描述 private String pageDescription; + // 定义一个动作ID,用于存储页面上的动作 private String actionIds; } diff --git a/backend/src/main/java/lsgwr/exam/entity/Question.java b/backend/src/main/java/lsgwr/exam/entity/Question.java index 67adf0b..5a0672c 100644 --- a/backend/src/main/java/lsgwr/exam/entity/Question.java +++ b/backend/src/main/java/lsgwr/exam/entity/Question.java @@ -19,21 +19,32 @@ import java.util.Date; @Entity @DynamicUpdate public class Question { + // 问题ID @Id private String questionId; + // 问题名称 private String questionName; + // 问题分数 private Integer questionScore; + // 问题创建者ID private String questionCreatorId; + // 问题等级ID private Integer questionLevelId; + // 问题类型ID private Integer questionTypeId; + // 问题分类ID private Integer questionCategoryId; + // 问题描述 private String questionDescription; + // 问题选项ID private String questionOptionIds; + // 问题答案选项ID private String questionAnswerOptionIds; /** * 创建时间, 设计表时设置了自动插入当前时间,无需在Java代码中设置了 */ + // 创建时间格式化 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; @@ -41,6 +52,7 @@ public class Question { * 更新时间,设计表时设置了自动插入当前时间,无需在Java代码中设置了。 * 同时@DynamicUpdate注解可以时间当数据库数据变化时自动更新,无需人工维护 */ + // 更新时间格式化 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date updateTime; } diff --git a/backend/src/main/java/lsgwr/exam/entity/QuestionCategory.java b/backend/src/main/java/lsgwr/exam/entity/QuestionCategory.java index ca08f22..6228991 100644 --- a/backend/src/main/java/lsgwr/exam/entity/QuestionCategory.java +++ b/backend/src/main/java/lsgwr/exam/entity/QuestionCategory.java @@ -18,14 +18,19 @@ import javax.persistence.Id; @Entity public class QuestionCategory { + // 主键 @Id + // 自动生成主键 @GeneratedValue + // 将该字段映射到JSON中的id字段 @JsonProperty("id") private Integer questionCategoryId; + // 将该字段映射到JSON中的name字段 @JsonProperty("name") private String questionCategoryName; + // 将该字段映射到JSON中的description字段 @JsonProperty("description") private String questionCategoryDescription; } diff --git a/backend/src/main/java/lsgwr/exam/entity/QuestionLevel.java b/backend/src/main/java/lsgwr/exam/entity/QuestionLevel.java index a056cbc..7e306d9 100644 --- a/backend/src/main/java/lsgwr/exam/entity/QuestionLevel.java +++ b/backend/src/main/java/lsgwr/exam/entity/QuestionLevel.java @@ -17,8 +17,10 @@ import javax.persistence.Id; @Entity @Data public class QuestionLevel { + // 定义实体类,表示问题等级 @Id @GeneratedValue + // 定义主键,自动生成 @JsonProperty("id") private Integer questionLevelId; @@ -27,4 +29,4 @@ public class QuestionLevel { @JsonProperty("description") private String questionLevelDescription; -} +} \ No newline at end of file diff --git a/backend/src/main/java/lsgwr/exam/entity/QuestionOption.java b/backend/src/main/java/lsgwr/exam/entity/QuestionOption.java index 3c06ef7..3e9a337 100644 --- a/backend/src/main/java/lsgwr/exam/entity/QuestionOption.java +++ b/backend/src/main/java/lsgwr/exam/entity/QuestionOption.java @@ -15,8 +15,11 @@ import javax.persistence.Id; @Data @Entity public class QuestionOption { + // 定义问题选项的ID @Id private String questionOptionId; + // 定义问题选项的内容 private String questionOptionContent; + // 定义问题选项的描述 private String questionOptionDescription; } diff --git a/backend/src/main/java/lsgwr/exam/entity/QuestionType.java b/backend/src/main/java/lsgwr/exam/entity/QuestionType.java index 46a4f55..8dd824d 100644 --- a/backend/src/main/java/lsgwr/exam/entity/QuestionType.java +++ b/backend/src/main/java/lsgwr/exam/entity/QuestionType.java @@ -17,14 +17,19 @@ import javax.persistence.Id; @Data @Entity public class QuestionType { + // 主键 @Id + // 自动生成主键 @GeneratedValue + // 将该字段映射到JSON中的id字段 @JsonProperty("id") private Integer questionTypeId; + // 将该字段映射到JSON中的name字段 @JsonProperty("name") private String questionTypeName; + // 将该字段映射到JSON中的description字段 @JsonProperty("description") private String questionTypeDescription; -} +} \ No newline at end of file diff --git a/backend/src/main/java/lsgwr/exam/entity/Role.java b/backend/src/main/java/lsgwr/exam/entity/Role.java index 31d529a..ff76979 100644 --- a/backend/src/main/java/lsgwr/exam/entity/Role.java +++ b/backend/src/main/java/lsgwr/exam/entity/Role.java @@ -16,14 +16,22 @@ import javax.persistence.Id; @Data @Entity public class Role { + // 角色ID @Id @GeneratedValue private Integer roleId; + // 角色名称 private String roleName; + // 角色描述 private String roleDescription; + // 角色详情 private String roleDetail; /** + * + * * 角色所能访问的页面的主键集合(用-连接起来字符串) + * + * */ private String rolePageIds; } diff --git a/backend/src/main/java/lsgwr/exam/entity/User.java b/backend/src/main/java/lsgwr/exam/entity/User.java index 23875bc..cee7425 100644 --- a/backend/src/main/java/lsgwr/exam/entity/User.java +++ b/backend/src/main/java/lsgwr/exam/entity/User.java @@ -19,27 +19,47 @@ import java.util.Date; @Entity @DynamicUpdate public class User { + // 用户ID @Id private String userId; + // 用户名 private String userUsername; + // 用户昵称 private String userNickname; + // 用户密码 private String userPassword; + // 用户角色ID private Integer userRoleId; + // 用户头像 private String userAvatar; + // 用户描述 private String userDescription; + // 用户邮箱 private String userEmail; + // 用户电话 private String userPhone; /** - * 创建时间, 设计表时设置了自动插入当前时间,无需在Java代码中设置了 + * + * + * 创建时间, 设计表时设置了自动插入 + * + * 当前时间,无需在Java代码中设置了 + * + * */ + // 创建时间 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; /** - * 更新时间,设计表时设置了自动插入当前时间,无需在Java代码中设置了。 - * 同时@DynamicUpdate注解可以时间当数据库数据变化时自动更新,无需人工维护 + * 更新时间,设计表时设置了自动插入 + * 当前时间,无需在Java代码中设置了。 + * 同时@DynamicUpdate注 + * 解可以时间当数据库数据变化时自动更 + * 新,无需人工维护 */ + // 更新时间 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date updateTime; -} +} \ No newline at end of file diff --git a/backend/src/main/java/lsgwr/exam/enums/LoginTypeEnum.java b/backend/src/main/java/lsgwr/exam/enums/LoginTypeEnum.java index 410aa30..7566895 100644 --- a/backend/src/main/java/lsgwr/exam/enums/LoginTypeEnum.java +++ b/backend/src/main/java/lsgwr/exam/enums/LoginTypeEnum.java @@ -4,12 +4,19 @@ import lombok.Getter; /** * 用户账号类型的枚举 + * + * * @author liangshanguang + * + * */ @Getter public enum LoginTypeEnum { /** + * * 用户的账号类型,1代表用户名,2代表邮箱 + * + * */ USERNAME(1, "用户名"), EMAIL(2, "邮箱"); diff --git a/backend/src/main/java/lsgwr/exam/enums/ResultEnum.java b/backend/src/main/java/lsgwr/exam/enums/ResultEnum.java index 8dacff6..d5bcea7 100644 --- a/backend/src/main/java/lsgwr/exam/enums/ResultEnum.java +++ b/backend/src/main/java/lsgwr/exam/enums/ResultEnum.java @@ -17,11 +17,14 @@ public enum ResultEnum { ORDER_UPDATE_ERR(15, "考试更新异常"), ORDER_DETAIL_EMPTY(16, "用户详情为空"); + // 构造方法,用于初始化错误码和错误信息 ResultEnum(Integer code, String message) { this.code = code; this.message = message; } + // 错误码 private Integer code; + // 错误信息 private String message; } diff --git a/backend/src/main/java/lsgwr/exam/enums/RoleEnum.java b/backend/src/main/java/lsgwr/exam/enums/RoleEnum.java index d37ab8d..b1c37fc 100644 --- a/backend/src/main/java/lsgwr/exam/enums/RoleEnum.java +++ b/backend/src/main/java/lsgwr/exam/enums/RoleEnum.java @@ -12,7 +12,11 @@ import lombok.Getter; public enum RoleEnum { /** + * + * * 用户角色,和数据库里面的role表相对应 + * + * */ ADMIN(1, "管理员"), TEACHER(2, "教师"), diff --git a/backend/src/main/java/lsgwr/exam/exception/ExamException.java b/backend/src/main/java/lsgwr/exam/exception/ExamException.java index 22a786e..b030afb 100644 --- a/backend/src/main/java/lsgwr/exam/exception/ExamException.java +++ b/backend/src/main/java/lsgwr/exam/exception/ExamException.java @@ -11,15 +11,22 @@ import lombok.Getter; @Getter public class ExamException extends RuntimeException { + // 定义异常代码 private Integer code; + // 构造函数,传入ResultEnum枚举类型 public ExamException(ResultEnum resultEnum) { + // 调用父类构造函数,传入ResultEnum枚举类型的消息 super(resultEnum.getMessage()); + // 将ResultEnum枚举类型的代码赋值给异常代码 this.code = resultEnum.getCode(); } + // 构造函数,传入异常代码和消息 public ExamException( Integer code, String message) { + // 调用父类构造函数,传入消息 super(message); + // 将传入的异常代码赋值给异常代码 this.code = code; } } diff --git a/backend/src/main/java/lsgwr/exam/interceptor/LoginInterceptor.java b/backend/src/main/java/lsgwr/exam/interceptor/LoginInterceptor.java index 3f1e58d..c892a52 100644 --- a/backend/src/main/java/lsgwr/exam/interceptor/LoginInterceptor.java +++ b/backend/src/main/java/lsgwr/exam/interceptor/LoginInterceptor.java @@ -27,44 +27,67 @@ import java.io.PrintWriter; public class LoginInterceptor implements HandlerInterceptor { /** + * * 有上面的@Component才能使得这个属性能从pplication.yml中取得拦截器的值 + * + * */ @Value("${interceptors.auth-ignore-uris}") private String authIgnoreUris; /** + * + * * 进入controller之前进行拦截 * + * * @param request 请求体 + * * @param response 响应体 + * * @param handler 处理者 + * * @return 是否继续往下走 + * * @throws Exception 拦截中出的异常 + * */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + // 打印进入拦截器 System.out.println("进入拦截器啦!"); + // 获取请求的URI String uri = request.getRequestURI(); + // 打印URI System.out.println(uri); + // 打印无需拦截的接口路径 System.out.println("无需拦截的接口路径:" + authIgnoreUris); + // 将无需拦截的接口路径分割成数组 String[] authIgnoreUriArr = authIgnoreUris.split(","); // 登录和注册接口不需要进行token拦截和校验 for (String authIgnoreUri : authIgnoreUriArr) { + // 如果请求的URI在无需拦截的接口路径中,则直接返回true if (authIgnoreUri.equals(uri)) { return true; } } // 注意要和前端适配Access-Token属性,前端会在登陆后的每个接口请求头加Access-Token属性 + // 获取请求头中的token String token = request.getHeader("Access-Token"); + // 如果token不在header中,则可能在参数中 if (token == null) { - // token不在header中时,也可能在参数中(RequestParam) + // 从参数中获取token token = request.getParameter("token"); } + // 如果token不为空 if (token != null) { // 请求中是携带参数的 + // 校验token Claims claims = JwtUtils.checkJWT(token); + // 如果token校验失败 if (claims == null) { // 返回null说明用户篡改了token,导致校验失败 + // 返回错误信息 sendJsonMessage(response, JsonData.buildError("token无效,请重新登录")); return false; } @@ -73,10 +96,12 @@ public class LoginInterceptor implements HandlerInterceptor { // 用户名 String username = (String) claims.get("username"); // 把这两个参数放到请求中,从而可以在controller中获取到,不需要在controller中在用Jwt解密了,request.getAttribute("属性名")即可获取 + // 将用户id和用户名放到请求中 request.setAttribute("user_id", id); request.setAttribute("username", username); return true; } + // 如果token为空,则返回错误信息 sendJsonMessage(response, JsonData.buildError("token为null,请先登录!")); return false; } @@ -88,12 +113,19 @@ public class LoginInterceptor implements HandlerInterceptor { * @param obj 返回的消息体 * @throws Exception 处理异常 */ - public static void sendJsonMessage(HttpServletResponse response, Object obj) throws Exception { + // 发送JSON消息 + public static void sendJsonMessage(HttpServletResponse response, Object obj) throws Exception { + // 创建Gson对象 Gson g = new Gson(); + // 设置响应内容类型为JSON response.setContentType("application/json; charset=utf-8"); + // 获取响应的PrintWriter对象 PrintWriter writer = response.getWriter(); + // 将对象转换为JSON字符串并写入响应 writer.print(g.toJson(obj)); + // 关闭PrintWriter对象 writer.close(); + // 刷新响应缓冲区 response.flushBuffer(); } } diff --git a/backend/src/main/java/lsgwr/exam/qo/DownloadQo.java b/backend/src/main/java/lsgwr/exam/qo/DownloadQo.java index cc7ac8c..8bb853f 100644 --- a/backend/src/main/java/lsgwr/exam/qo/DownloadQo.java +++ b/backend/src/main/java/lsgwr/exam/qo/DownloadQo.java @@ -13,5 +13,6 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor public class DownloadQo { + // 下载路径 String path; -} +} \ No newline at end of file diff --git a/backend/src/main/java/lsgwr/exam/qo/LoginQo.java b/backend/src/main/java/lsgwr/exam/qo/LoginQo.java index 8576b12..7d765b9 100644 --- a/backend/src/main/java/lsgwr/exam/qo/LoginQo.java +++ b/backend/src/main/java/lsgwr/exam/qo/LoginQo.java @@ -15,15 +15,21 @@ import lombok.NoArgsConstructor; @NoArgsConstructor public class LoginQo { /** + * * 1表示用户名,2表示邮箱 + * */ private Integer loginType; /** + * * 用户名/邮箱的字符串 + * */ private String userInfo; /** + * * 用户密码 + * */ private String password; } diff --git a/backend/src/main/java/lsgwr/exam/qo/UploadModel.java b/backend/src/main/java/lsgwr/exam/qo/UploadModel.java index fc4f1b3..dd75f15 100644 --- a/backend/src/main/java/lsgwr/exam/qo/UploadModel.java +++ b/backend/src/main/java/lsgwr/exam/qo/UploadModel.java @@ -17,11 +17,19 @@ import org.springframework.web.multipart.MultipartFile; @NoArgsConstructor public class UploadModel { /** + * + * * 要保存的文件 + * + * */ private MultipartFile[] files; /** + * + * * 文件要存储的文件夹 + * + * */ private String dir; } diff --git a/backend/src/main/java/lsgwr/exam/qo/UploadModel2.java b/backend/src/main/java/lsgwr/exam/qo/UploadModel2.java index 430b127..d12c789 100644 --- a/backend/src/main/java/lsgwr/exam/qo/UploadModel2.java +++ b/backend/src/main/java/lsgwr/exam/qo/UploadModel2.java @@ -17,11 +17,19 @@ import org.springframework.web.multipart.MultipartFile; @NoArgsConstructor public class UploadModel2 { /** + * + * * 要保存的文件列表 + * + * */ private MultipartFile file; /** + * + * * 文件要存储的文件夹 + * + * */ private String dir; }