Jelajahi Sumber

feat: 删除redis缓存,统一使用guava缓存,增加评价题目功能

ChenSiTong 6 tahun lalu
induk
melakukan
6aed5cd0b7
26 mengubah file dengan 376 tambahan dan 363 penghapusan
  1. 21 21
      pom.xml
  2. 1 1
      src/main/java/nju/seec/helper/api/bok/KnowledgeApi.java
  3. 8 4
      src/main/java/nju/seec/helper/api/bok/QuestionApi.java
  4. 7 16
      src/main/java/nju/seec/helper/aspect/event/EventAspect.java
  5. 1 1
      src/main/java/nju/seec/helper/aspect/event/ExerciseRecordEventAspect.java
  6. 3 0
      src/main/java/nju/seec/helper/controller/CommentController.java
  7. 5 0
      src/main/java/nju/seec/helper/controller/EventController.java
  8. 9 2
      src/main/java/nju/seec/helper/controller/KnowledgeController.java
  9. 12 0
      src/main/java/nju/seec/helper/controller/QuestionController.java
  10. 1 1
      src/main/java/nju/seec/helper/controller/QuizController.java
  11. 1 2
      src/main/java/nju/seec/helper/dto/quiz/QuizStudentAnswerDTO.java
  12. 30 30
      src/main/java/nju/seec/helper/dto/user/ResetPasswordDTO.java
  13. 39 39
      src/main/java/nju/seec/helper/dto/user/UserDTO.java
  14. 20 20
      src/main/java/nju/seec/helper/dto/validator/phone/Phone.java
  15. 21 21
      src/main/java/nju/seec/helper/dto/validator/phone/PhoneValidator.java
  16. 32 32
      src/main/java/nju/seec/helper/dto/validator/schoolemail/SchoolEmail.java
  17. 54 54
      src/main/java/nju/seec/helper/dto/validator/schoolemail/SchoolEmailValidator.java
  18. 0 23
      src/main/java/nju/seec/helper/entity/Admin.java
  19. 8 0
      src/main/java/nju/seec/helper/service/QuestionService.java
  20. 6 1
      src/main/java/nju/seec/helper/service/impl/QuestionServiceImpl.java
  21. 1 1
      src/main/java/nju/seec/helper/service/impl/QuizStudentAnswerServiceImpl.java
  22. 2 2
      src/main/java/nju/seec/helper/util/cache/GuavaCacheUtils.java
  23. 43 43
      src/main/java/nju/seec/helper/util/cache/RedisCacheUtils.java
  24. 5 7
      src/main/java/nju/seec/helper/util/oss/OssObjectUrlUtils.java
  25. 21 21
      src/main/resources/application-deploy.yml
  26. 25 21
      src/main/resources/application-dev.yml

+ 21 - 21
pom.xml

@@ -10,7 +10,7 @@
     </parent>
     <groupId>cn.seecoder</groupId>
     <artifactId>helper-backend</artifactId>
-    <version>5.1.0</version>
+    <version>5.2.0</version>
     <packaging>jar</packaging>
     <name>helper</name>
     <description>backend</description>
@@ -33,14 +33,14 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-jpa</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-data-redis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-mail</artifactId>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>org.springframework.boot</groupId>-->
+<!--            <artifactId>spring-boot-starter-data-redis</artifactId>-->
+<!--        </dependency>-->
+<!--        <dependency>-->
+<!--            <groupId>org.springframework.boot</groupId>-->
+<!--            <artifactId>spring-boot-starter-mail</artifactId>-->
+<!--        </dependency>-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
@@ -64,10 +64,10 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-websocket</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-cache</artifactId>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>org.springframework.boot</groupId>-->
+<!--            <artifactId>spring-boot-starter-cache</artifactId>-->
+<!--        </dependency>-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
@@ -121,14 +121,14 @@
             <artifactId>hibernate-types-52</artifactId>
             <version>2.9.5</version>
         </dependency>
-        <dependency>
-            <groupId>org.hibernate</groupId>
-            <artifactId>hibernate-jcache</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.ehcache</groupId>
-            <artifactId>ehcache</artifactId>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>org.hibernate</groupId>-->
+<!--            <artifactId>hibernate-jcache</artifactId>-->
+<!--        </dependency>-->
+<!--        <dependency>-->
+<!--            <groupId>org.ehcache</groupId>-->
+<!--            <artifactId>ehcache</artifactId>-->
+<!--        </dependency>-->
         <!--一个工具类库,不用自己造轮子了!!!-->
         <dependency>
             <groupId>cn.hutool</groupId>

+ 1 - 1
src/main/java/nju/seec/helper/api/bok/KnowledgeApi.java

@@ -33,7 +33,7 @@ public class KnowledgeApi {
     }
 
     @SuppressWarnings("unchecked")
-    public List<BokKnowledgeNodeVO> getKnowledgeNodes() {
+    public List<BokKnowledgeNodeVO> getAllKnowledgeNodes() {
         Object cache = cacheUtils.get(BOK_KNOWLEDGE_CACHE_NAME, "all");
         if (cache instanceof List) {
             return (List<BokKnowledgeNodeVO>) cache;

+ 8 - 4
src/main/java/nju/seec/helper/api/bok/QuestionApi.java

@@ -117,10 +117,6 @@ public class QuestionApi {
         restRequestUtil.sendDeleteRequest(tqUrl + "/" + questionId);
     }
 
-    public void starQuestion(String userId, String questionId) {
-
-    }
-
     private QuestionVO getQuestion(BaseQuestionDTO baseQuestionDTO) {
         QuestionVO questionVO = new QuestionVO();
         questionVO.setType(baseQuestionDTO.getType());
@@ -148,6 +144,14 @@ public class QuestionApi {
         return questionVO;
     }
 
+    public void starQuestion(String userId, String questionId) {
+
+    }
+
+    public void likeQuestion(String userId, String questionId) {
+
+    }
+
     @Data
     private static class BokSearchResult {
         @JsonProperty("_embedded")

+ 7 - 16
src/main/java/nju/seec/helper/aspect/event/EventAspect.java

@@ -1,9 +1,6 @@
 package nju.seec.helper.aspect.event;
 
 import com.google.common.collect.ImmutableMap;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
 import lombok.SneakyThrows;
 import nju.seec.helper.api.dataanalysis.EventAction;
 import nju.seec.helper.api.dataanalysis.EventApi;
@@ -63,7 +60,7 @@ public class EventAspect {
                         })
                 ),
                 EventType.QUIZ, ImmutableMap.of(
-                        EventAction.PARTICIPATE, (joinPoint -> {
+                        EventAction.COMPLETE, (joinPoint -> {
                             Object[] args = joinPoint.getArgs();
                             LoginUser user = null;
                             Long quizId = null;
@@ -91,20 +88,14 @@ public class EventAspect {
         void handleEvent(JoinPoint joinPoint);
     }
 
-    @NoArgsConstructor(access = AccessLevel.PRIVATE)
-    private static class DoNothingHandler implements EventHandler {
-        @Getter
-        private static final DoNothingHandler INSTANCE = new DoNothingHandler();
-
-        @Override
-        public void handleEvent(JoinPoint joinPoint) {
-
-        }
-    }
+    private final EventHandler doNothing = (joinPoint) -> {
+    };
 
     @SneakyThrows
     @AfterReturning("@annotation(event)")
-    public void reportEvent(JoinPoint joinPoint, nju.seec.helper.aspect.event.Event event) {
-        eventHandleMap.getOrDefault(event.type(), Collections.emptyMap()).getOrDefault(event.action(), DoNothingHandler.getINSTANCE()).handleEvent(joinPoint);
+    public void reportEvent(JoinPoint joinPoint, Event event) {
+        eventHandleMap.getOrDefault(event.type(), Collections.emptyMap())
+                .getOrDefault(event.action(), doNothing)
+                .handleEvent(joinPoint);
     }
 }

+ 1 - 1
src/main/java/nju/seec/helper/aspect/event/ExerciseRecordEventAspect.java

@@ -46,7 +46,7 @@ public class ExerciseRecordEventAspect {
                 Objects.requireNonNull(quizStudentAnswerDTO)
                         .getRecords()
                         .entrySet()
-                        .stream()
+                        .parallelStream()
                         .map(answerRecordEntry ->
                                 exerciseApi.createExerciseRecord(
                                         userId, answerRecordEntry.getKey(), answerRecordEntry.getValue().getStartAt(), answerRecordEntry.getValue().getEndAt(), questionStudentAnswerInfoMap.get(answerRecordEntry.getKey()).getCorrect()

+ 3 - 0
src/main/java/nju/seec/helper/controller/CommentController.java

@@ -105,6 +105,9 @@ public class CommentController {
         return PageResponse.of(commentService.getSelfCommentsBySlideAndPageNumber(user, slideId, pageNumber, show, pageable));
     }
 
+    /**
+     * 修改评论的展示状态
+     */
     @Auth(roles = {UserRole.TEACHER, UserRole.STUDENT}, message = "修改评论展示状态")
     @PutMapping("/{commentId}/show")
     public void modifyCommentShow(LoginUser user,

+ 5 - 0
src/main/java/nju/seec/helper/controller/EventController.java

@@ -9,6 +9,8 @@ import org.springframework.web.bind.annotation.RestController;
 import java.util.List;
 
 /**
+ * 事件
+ *
  * @author cst
  */
 @RestController
@@ -20,6 +22,9 @@ public class EventController {
         this.eventService = eventService;
     }
 
+    /**
+     * 获取所有事件
+     */
     @GetMapping
     public List<Event> getAllEvents() {
         return eventService.getAllEvents();

+ 9 - 2
src/main/java/nju/seec/helper/controller/KnowledgeController.java

@@ -9,6 +9,8 @@ import org.springframework.web.bind.annotation.RestController;
 import java.util.List;
 
 /**
+ * 知识点
+ *
  * @author cst
  */
 @RestController
@@ -20,8 +22,13 @@ public class KnowledgeController {
         this.knowledgeApi = knowledgeApi;
     }
 
+    /**
+     * 获取所有知识点
+     *
+     * @return
+     */
     @GetMapping
-    public List<BokKnowledgeNodeVO> getKnowledgeNodes() {
-        return knowledgeApi.getKnowledgeNodes();
+    public List<BokKnowledgeNodeVO> getAllKnowledgeNodes() {
+        return knowledgeApi.getAllKnowledgeNodes();
     }
 }

+ 12 - 0
src/main/java/nju/seec/helper/controller/QuestionController.java

@@ -107,9 +107,21 @@ public class QuestionController {
         return questionService.getIdsOfCreatedQuestions(user);
     }
 
+    /**
+     * 收藏题目
+     */
     @Auth(roles = UserRole.STUDENT, message = "收藏题目")
     @PostMapping("/{questionId}/star")
     public void starQuestion(LoginUser user, @PathVariable String questionId) {
         questionService.starQuestion(user, questionId);
     }
+
+    /**
+     * 评价题目
+     */
+    @Auth(roles = UserRole.STUDENT, message = "评价题目")
+    @PostMapping("/{questionId}/like")
+    public void likeQuestion(LoginUser user, @PathVariable String questionId) {
+        questionService.likeQuestion(user, questionId);
+    }
 }

+ 1 - 1
src/main/java/nju/seec/helper/controller/QuizController.java

@@ -95,7 +95,7 @@ public class QuizController {
     }
 
     /**
-     * 修改测试 (仅限未开始时可以修改)
+     * 修改测试 (仅限无人提交时可以修改)
      */
     @Auth(roles = {UserRole.TEACHER}, message = "修改测试")
     @PutMapping("/{quizId}")

+ 1 - 2
src/main/java/nju/seec/helper/dto/quiz/QuizStudentAnswerDTO.java

@@ -1,7 +1,6 @@
 package nju.seec.helper.dto.quiz;
 
 import lombok.Data;
-import lombok.Getter;
 
 import javax.validation.Valid;
 import javax.validation.constraints.NotEmpty;
@@ -19,11 +18,11 @@ public class QuizStudentAnswerDTO implements Serializable {
     @NotEmpty(message = "回答不能为空")
     private Map<String, Object> answers;
 
+    @NotNull(message = "缺少做题记录")
     @Valid
     private Map<String, AnswerRecordDTO> records;
 
     @Data
-    @Getter
     public static class AnswerRecordDTO {
         @NotNull(message = "缺少做题开始时间")
         private LocalDateTime startAt;

+ 30 - 30
src/main/java/nju/seec/helper/dto/user/ResetPasswordDTO.java

@@ -1,30 +1,30 @@
-package nju.seec.helper.dto.user;
-
-import lombok.Data;
-import nju.seec.helper.dto.validator.schoolemail.SchoolEmail;
-import org.hibernate.validator.constraints.Length;
-
-import javax.validation.constraints.NotBlank;
-import java.io.Serializable;
-
-/**
- * @author cst
- */
-@Data
-public class ResetPasswordDTO implements Serializable {
-    private static final long serialVersionUID = 3884011149489695206L;
-    @NotBlank(message = "邮箱不能为空")
-    @SchoolEmail
-    private String username;
-    /**
-     * 验证码
-     */
-    @NotBlank(message = "邮箱验证码不能为空")
-    private String code;
-    /**
-     * 密码
-     */
-    @NotBlank(message = "密码不能为空")
-    @Length(max = 50, message = "密码长度不能超过50位")
-    private String password;
-}
+//package nju.seec.helper.dto.user;
+//
+//import lombok.Data;
+//import nju.seec.helper.dto.validator.schoolemail.SchoolEmail;
+//import org.hibernate.validator.constraints.Length;
+//
+//import javax.validation.constraints.NotBlank;
+//import java.io.Serializable;
+//
+///**
+// * @author cst
+// */
+//@Data
+//public class ResetPasswordDTO implements Serializable {
+//    private static final long serialVersionUID = 3884011149489695206L;
+//    @NotBlank(message = "邮箱不能为空")
+//    @SchoolEmail
+//    private String username;
+//    /**
+//     * 验证码
+//     */
+//    @NotBlank(message = "邮箱验证码不能为空")
+//    private String code;
+//    /**
+//     * 密码
+//     */
+//    @NotBlank(message = "密码不能为空")
+//    @Length(max = 50, message = "密码长度不能超过50位")
+//    private String password;
+//}

+ 39 - 39
src/main/java/nju/seec/helper/dto/user/UserDTO.java

@@ -1,39 +1,39 @@
-package nju.seec.helper.dto.user;
-
-import lombok.Data;
-import nju.seec.helper.dto.groups.Create;
-import nju.seec.helper.dto.validator.phone.Phone;
-import nju.seec.helper.dto.validator.schoolemail.SchoolEmail;
-import nju.seec.helper.enums.UserRole;
-import org.hibernate.validator.constraints.Length;
-
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import java.io.Serializable;
-
-/**
- * @author cst
- */
-@Data
-public class UserDTO implements Serializable {
-    private static final long serialVersionUID = -5962331511813309322L;
-    @NotBlank(message = "姓名不能为空")
-    @Length(min = 2, max = 50, message = "姓名长度必须在2到50之间")
-    private String name;
-    @NotBlank(message = "邮箱不能为空", groups = Create.class)
-    @SchoolEmail(groups = Create.class)
-    private String email;
-    @NotBlank(message = "邮箱验证码不能为空", groups = Create.class)
-    private String emailCode;
-    @NotBlank(message = "手机号不能为空", groups = Create.class)
-    @Phone(groups = Create.class)
-    private String phone;
-    @NotBlank(message = "手机号验证码不能为空", groups = Create.class)
-    private String phoneCode;
-    @NotBlank(message = "密码不能为空", groups = Create.class)
-    @Length(max = 50, message = "密码长度不能超过50位", groups = Create.class)
-    private String password;
-
-    @NotNull(message = "缺少用户类型", groups = Create.class)
-    private UserRole role;
-}
+//package nju.seec.helper.dto.user;
+//
+//import lombok.Data;
+//import nju.seec.helper.dto.groups.Create;
+//import nju.seec.helper.dto.validator.phone.Phone;
+//import nju.seec.helper.dto.validator.schoolemail.SchoolEmail;
+//import nju.seec.helper.enums.UserRole;
+//import org.hibernate.validator.constraints.Length;
+//
+//import javax.validation.constraints.NotBlank;
+//import javax.validation.constraints.NotNull;
+//import java.io.Serializable;
+//
+///**
+// * @author cst
+// */
+//@Data
+//public class UserDTO implements Serializable {
+//    private static final long serialVersionUID = -5962331511813309322L;
+//    @NotBlank(message = "姓名不能为空")
+//    @Length(min = 2, max = 50, message = "姓名长度必须在2到50之间")
+//    private String name;
+//    @NotBlank(message = "邮箱不能为空", groups = Create.class)
+//    @SchoolEmail(groups = Create.class)
+//    private String email;
+//    @NotBlank(message = "邮箱验证码不能为空", groups = Create.class)
+//    private String emailCode;
+//    @NotBlank(message = "手机号不能为空", groups = Create.class)
+//    @Phone(groups = Create.class)
+//    private String phone;
+//    @NotBlank(message = "手机号验证码不能为空", groups = Create.class)
+//    private String phoneCode;
+//    @NotBlank(message = "密码不能为空", groups = Create.class)
+//    @Length(max = 50, message = "密码长度不能超过50位", groups = Create.class)
+//    private String password;
+//
+//    @NotNull(message = "缺少用户类型", groups = Create.class)
+//    private UserRole role;
+//}

+ 20 - 20
src/main/java/nju/seec/helper/dto/validator/phone/Phone.java

@@ -1,20 +1,20 @@
-package nju.seec.helper.dto.validator.phone;
-
-import javax.validation.Constraint;
-import javax.validation.Payload;
-import java.lang.annotation.*;
-
-/**
- * @author cst
- */
-@Documented
-@Target({ElementType.PARAMETER, ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@Constraint(validatedBy = PhoneValidator.class)
-public @interface Phone {
-    String message() default "手机号格式错误";
-
-    Class<?>[] groups() default {};
-
-    Class<? extends Payload>[] payload() default {};
-}
+//package nju.seec.helper.dto.validator.phone;
+//
+//import javax.validation.Constraint;
+//import javax.validation.Payload;
+//import java.lang.annotation.*;
+//
+///**
+// * @author cst
+// */
+//@Documented
+//@Target({ElementType.PARAMETER, ElementType.FIELD})
+//@Retention(RetentionPolicy.RUNTIME)
+//@Constraint(validatedBy = PhoneValidator.class)
+//public @interface Phone {
+//    String message() default "手机号格式错误";
+//
+//    Class<?>[] groups() default {};
+//
+//    Class<? extends Payload>[] payload() default {};
+//}

+ 21 - 21
src/main/java/nju/seec/helper/dto/validator/phone/PhoneValidator.java

@@ -1,21 +1,21 @@
-package nju.seec.helper.dto.validator.phone;
-
-import javax.validation.ConstraintValidator;
-import javax.validation.ConstraintValidatorContext;
-
-/**
- * @author cst
- */
-public class PhoneValidator implements ConstraintValidator<Phone, String> {
-    private static final String PHONE_REGEX = "1[3-9]\\d{9}";
-
-    @Override
-    public boolean isValid(String value, ConstraintValidatorContext context) {
-        return value != null && value.matches(PHONE_REGEX);
-    }
-
-    @Override
-    public void initialize(Phone constraintAnnotation) {
-
-    }
-}
+//package nju.seec.helper.dto.validator.phone;
+//
+//import javax.validation.ConstraintValidator;
+//import javax.validation.ConstraintValidatorContext;
+//
+///**
+// * @author cst
+// */
+//public class PhoneValidator implements ConstraintValidator<Phone, String> {
+//    private static final String PHONE_REGEX = "1[3-9]\\d{9}";
+//
+//    @Override
+//    public boolean isValid(String value, ConstraintValidatorContext context) {
+//        return value != null && value.matches(PHONE_REGEX);
+//    }
+//
+//    @Override
+//    public void initialize(Phone constraintAnnotation) {
+//
+//    }
+//}

+ 32 - 32
src/main/java/nju/seec/helper/dto/validator/schoolemail/SchoolEmail.java

@@ -1,32 +1,32 @@
-package nju.seec.helper.dto.validator.schoolemail;
-
-import javax.validation.Constraint;
-import javax.validation.Payload;
-import javax.validation.constraints.Email;
-import javax.validation.constraints.Pattern;
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import static java.lang.annotation.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * @author cst
- * copy from {@link Email}
- */
-@Documented
-@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
-@Retention(RUNTIME)
-@Constraint(validatedBy = SchoolEmailValidator.class)
-public @interface SchoolEmail {
-    String message() default "该邮箱不是校邮";
-
-    Class<?>[] groups() default {};
-
-    Class<? extends Payload>[] payload() default {};
-
-    String regexp() default ".+@.*(edu.cn)";
-
-    Pattern.Flag[] flags() default {};
-}
+//package nju.seec.helper.dto.validator.schoolemail;
+//
+//import javax.validation.Constraint;
+//import javax.validation.Payload;
+//import javax.validation.constraints.Email;
+//import javax.validation.constraints.Pattern;
+//import java.lang.annotation.Documented;
+//import java.lang.annotation.Retention;
+//import java.lang.annotation.Target;
+//
+//import static java.lang.annotation.ElementType.*;
+//import static java.lang.annotation.RetentionPolicy.RUNTIME;
+//
+///**
+// * @author cst
+// * copy from {@link Email}
+// */
+//@Documented
+//@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
+//@Retention(RUNTIME)
+//@Constraint(validatedBy = SchoolEmailValidator.class)
+//public @interface SchoolEmail {
+//    String message() default "该邮箱不是校邮";
+//
+//    Class<?>[] groups() default {};
+//
+//    Class<? extends Payload>[] payload() default {};
+//
+//    String regexp() default ".+@.*(edu.cn)";
+//
+//    Pattern.Flag[] flags() default {};
+//}

+ 54 - 54
src/main/java/nju/seec/helper/dto/validator/schoolemail/SchoolEmailValidator.java

@@ -1,54 +1,54 @@
-package nju.seec.helper.dto.validator.schoolemail;
-
-import org.hibernate.validator.internal.constraintvalidators.AbstractEmailValidator;
-import org.hibernate.validator.internal.util.logging.Log;
-import org.hibernate.validator.internal.util.logging.LoggerFactory;
-
-import javax.validation.ConstraintValidatorContext;
-import java.lang.invoke.MethodHandles;
-import java.util.regex.Matcher;
-import java.util.regex.PatternSyntaxException;
-
-/**
- * @author cst
- * copy from {@link org.hibernate.validator.internal.constraintvalidators.bv.EmailValidator}
- */
-public class SchoolEmailValidator extends AbstractEmailValidator<SchoolEmail> {
-    private static final Log LOG = LoggerFactory.make(MethodHandles.lookup());
-    private java.util.regex.Pattern pattern;
-
-    @Override
-    public void initialize(SchoolEmail emailAnnotation) {
-        super.initialize(emailAnnotation);
-
-        javax.validation.constraints.Pattern.Flag[] flags = emailAnnotation.flags();
-        int intFlag = 0;
-        for (javax.validation.constraints.Pattern.Flag flag : flags) {
-            intFlag = intFlag | flag.getValue();
-        }
-
-        // we only apply the regexp if there is one to apply
-        if (!".*".equals(emailAnnotation.regexp()) || emailAnnotation.flags().length > 0) {
-            try {
-                pattern = java.util.regex.Pattern.compile(emailAnnotation.regexp(), intFlag);
-            } catch (PatternSyntaxException e) {
-                throw LOG.getInvalidRegularExpressionException(e);
-            }
-        }
-    }
-
-    @Override
-    public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
-        if (value == null) {
-            return true;
-        }
-
-        boolean isValid = super.isValid(value, context);
-        if (pattern == null || !isValid) {
-            return isValid;
-        }
-
-        Matcher m = pattern.matcher(value);
-        return m.matches();
-    }
-}
+//package nju.seec.helper.dto.validator.schoolemail;
+//
+//import org.hibernate.validator.internal.constraintvalidators.AbstractEmailValidator;
+//import org.hibernate.validator.internal.util.logging.Log;
+//import org.hibernate.validator.internal.util.logging.LoggerFactory;
+//
+//import javax.validation.ConstraintValidatorContext;
+//import java.lang.invoke.MethodHandles;
+//import java.util.regex.Matcher;
+//import java.util.regex.PatternSyntaxException;
+//
+///**
+// * @author cst
+// * copy from {@link org.hibernate.validator.internal.constraintvalidators.bv.EmailValidator}
+// */
+//public class SchoolEmailValidator extends AbstractEmailValidator<SchoolEmail> {
+//    private static final Log LOG = LoggerFactory.make(MethodHandles.lookup());
+//    private java.util.regex.Pattern pattern;
+//
+//    @Override
+//    public void initialize(SchoolEmail emailAnnotation) {
+//        super.initialize(emailAnnotation);
+//
+//        javax.validation.constraints.Pattern.Flag[] flags = emailAnnotation.flags();
+//        int intFlag = 0;
+//        for (javax.validation.constraints.Pattern.Flag flag : flags) {
+//            intFlag = intFlag | flag.getValue();
+//        }
+//
+//        // we only apply the regexp if there is one to apply
+//        if (!".*".equals(emailAnnotation.regexp()) || emailAnnotation.flags().length > 0) {
+//            try {
+//                pattern = java.util.regex.Pattern.compile(emailAnnotation.regexp(), intFlag);
+//            } catch (PatternSyntaxException e) {
+//                throw LOG.getInvalidRegularExpressionException(e);
+//            }
+//        }
+//    }
+//
+//    @Override
+//    public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
+//        if (value == null) {
+//            return true;
+//        }
+//
+//        boolean isValid = super.isValid(value, context);
+//        if (pattern == null || !isValid) {
+//            return isValid;
+//        }
+//
+//        Matcher m = pattern.matcher(value);
+//        return m.matches();
+//    }
+//}

+ 0 - 23
src/main/java/nju/seec/helper/entity/Admin.java

@@ -1,23 +0,0 @@
-//package nju.seec.helper.entity;
-//
-//import lombok.Data;
-//
-//import javax.persistence.*;
-//
-///**
-// * @author cst
-// */
-//@Data
-//@Entity
-//@Table(name = "admin", uniqueConstraints = @UniqueConstraint(name = "username_unique", columnNames = "username"))
-//public class Admin {
-//    @Id
-//    @GeneratedValue(strategy = GenerationType.IDENTITY)
-//    private Long id;
-//
-//    @Column(nullable = false)
-//    private String username;
-//
-//    @Column(nullable = false)
-//    private String password;
-//}

+ 8 - 0
src/main/java/nju/seec/helper/service/QuestionService.java

@@ -103,4 +103,12 @@ public interface QuestionService {
      * @param questionId
      */
     void starQuestion(LoginUser user, String questionId);
+
+    /**
+     * 评价题目
+     *
+     * @param user
+     * @param questionId
+     */
+    void likeQuestion(LoginUser user, String questionId);
 }

+ 6 - 1
src/main/java/nju/seec/helper/service/impl/QuestionServiceImpl.java

@@ -139,6 +139,11 @@ public class QuestionServiceImpl implements QuestionService {
 
     @Override
     public void starQuestion(LoginUser user, String questionId) {
-        questionApi.starQuestion(String.valueOf(user.getId()), questionId);
+        questionApi.starQuestion(String.valueOf(user.getPid()), questionId);
+    }
+
+    @Override
+    public void likeQuestion(LoginUser user, String questionId) {
+        questionApi.likeQuestion(String.valueOf(user.getPid()), questionId);
     }
 }

+ 1 - 1
src/main/java/nju/seec/helper/service/impl/QuizStudentAnswerServiceImpl.java

@@ -50,7 +50,7 @@ public class QuizStudentAnswerServiceImpl implements QuizStudentAnswerService {
     }
 
     @ExerciseRecordEvent
-    @Event(type = EventType.QUIZ, action = EventAction.PARTICIPATE)
+    @Event(type = EventType.QUIZ, action = EventAction.COMPLETE)
     @Transactional(rollbackFor = Exception.class)
     @Override
     public QuizStudentAnswerVO submitQuizStudentAnswer(LoginUser user, Long quizId, QuizStudentAnswerDTO quizStudentAnswerDTO) {

+ 2 - 2
src/main/java/nju/seec/helper/util/cache/GuavaCacheUtils.java

@@ -18,7 +18,7 @@ import java.util.stream.Collectors;
  */
 @Component
 public class GuavaCacheUtils {
-    private Cache<Object, Object> cache;
+    private final Cache<String, Object> cache;
 
     public GuavaCacheUtils(@Value("${guavaCache.maximumSize}") Long maximumSize,
                            @Value("${guavaCache.expireAfterAccessInSeconds}") Long expireAfterAccessInSeconds,
@@ -44,7 +44,7 @@ public class GuavaCacheUtils {
         return cache.getIfPresent(combineKey(cacheName, key));
     }
 
-    public ImmutableMap<Object, Object> multiGet(String cacheName, Collection<String> keys) {
+    public ImmutableMap<String, Object> multiGet(String cacheName, Collection<String> keys) {
         Collection<String> body = keys.stream().map(s -> combineKey(cacheName, s)).collect(Collectors.toList());
         return cache.getAllPresent(body);
     }

+ 43 - 43
src/main/java/nju/seec/helper/util/cache/RedisCacheUtils.java

@@ -1,43 +1,43 @@
-package nju.seec.helper.util.cache;
-
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-/**
- * use redis
- *
- * @author cst
- */
-@Component
-public class RedisCacheUtils {
-    private final RedisTemplate<String, String> redisTemplate;
-
-    public RedisCacheUtils(RedisTemplate<String, String> redisTemplate) {
-        this.redisTemplate = redisTemplate;
-    }
-
-    public void set(String cacheName, String key, String value, long expireTime, TimeUnit timeUnit) {
-        redisTemplate.opsForValue().set(combineKey(cacheName, key), value, expireTime, timeUnit);
-    }
-
-    public String get(String cacheName, String key) {
-        return redisTemplate.opsForValue().get(combineKey(cacheName, key));
-    }
-
-    public List<String> multiGet(String cacheName, List<String> keys) {
-        List<String> body = keys.stream().map(key -> combineKey(cacheName, key)).collect(Collectors.toList());
-        return redisTemplate.opsForValue().multiGet(body);
-    }
-
-    public void remove(String cacheName, String key) {
-        redisTemplate.delete(cacheName + ":" + key);
-    }
-
-    private String combineKey(String cacheName, String key) {
-        return cacheName + ":" + key;
-    }
-}
+//package nju.seec.helper.util.cache;
+//
+//import org.springframework.data.redis.core.RedisTemplate;
+//import org.springframework.stereotype.Component;
+//
+//import java.util.List;
+//import java.util.concurrent.TimeUnit;
+//import java.util.stream.Collectors;
+//
+///**
+// * use redis
+// *
+// * @author cst
+// */
+//@Component
+//public class RedisCacheUtils {
+//    private final RedisTemplate<String, String> redisTemplate;
+//
+//    public RedisCacheUtils(RedisTemplate<String, String> redisTemplate) {
+//        this.redisTemplate = redisTemplate;
+//    }
+//
+//    public void set(String cacheName, String key, String value, long expireTime, TimeUnit timeUnit) {
+//        redisTemplate.opsForValue().set(combineKey(cacheName, key), value, expireTime, timeUnit);
+//    }
+//
+//    public String get(String cacheName, String key) {
+//        return redisTemplate.opsForValue().get(combineKey(cacheName, key));
+//    }
+//
+//    public List<String> multiGet(String cacheName, List<String> keys) {
+//        List<String> body = keys.stream().map(key -> combineKey(cacheName, key)).collect(Collectors.toList());
+//        return redisTemplate.opsForValue().multiGet(body);
+//    }
+//
+//    public void remove(String cacheName, String key) {
+//        redisTemplate.delete(cacheName + ":" + key);
+//    }
+//
+//    private String combineKey(String cacheName, String key) {
+//        return cacheName + ":" + key;
+//    }
+//}

+ 5 - 7
src/main/java/nju/seec/helper/util/oss/OssObjectUrlUtils.java

@@ -1,11 +1,9 @@
 package nju.seec.helper.util.oss;
 
 import nju.seec.helper.util.Consts;
-import nju.seec.helper.util.cache.RedisCacheUtils;
+import nju.seec.helper.util.cache.GuavaCacheUtils;
 import org.springframework.stereotype.Component;
 
-import java.util.concurrent.TimeUnit;
-
 /**
  * @author cst
  */
@@ -13,19 +11,19 @@ import java.util.concurrent.TimeUnit;
 public class OssObjectUrlUtils {
     private static final String OSS_OBJECT_URL_NAME = Consts.SYS_NAME + "_oss_object_url";
     private static final long OSS_OBJECT_URL_LIVING_SECONDS = 20 * 60;
-    private final RedisCacheUtils cacheUtils;
+    private final GuavaCacheUtils cacheUtils;
     private final OssUtils ossUtils;
 
-    public OssObjectUrlUtils(RedisCacheUtils cacheUtils, OssUtils ossUtils) {
+    public OssObjectUrlUtils(GuavaCacheUtils cacheUtils, OssUtils ossUtils) {
         this.cacheUtils = cacheUtils;
         this.ossUtils = ossUtils;
     }
 
     public String getUrl(String objectName) {
-        String url = cacheUtils.get(OSS_OBJECT_URL_NAME, objectName);
+        String url = (String) cacheUtils.get(OSS_OBJECT_URL_NAME, objectName);
         if (url == null) {
             url = ossUtils.getUrl(objectName, OSS_OBJECT_URL_LIVING_SECONDS);
-            cacheUtils.set(OSS_OBJECT_URL_NAME, objectName, url, OSS_OBJECT_URL_LIVING_SECONDS, TimeUnit.SECONDS);
+            cacheUtils.set(OSS_OBJECT_URL_NAME, objectName, url);
         }
         return url;
     }

+ 21 - 21
src/main/resources/application-deploy.yml

@@ -16,31 +16,31 @@ spring:
   http:
     encoding:
       force: true
-  redis:
-    host: localhost
-    port: 6379
+#  redis:
+#    host: localhost
+#    port: 6379
   data:
-    redis:
-      repositories:
-        enabled: false
+#    redis:
+#      repositories:
+#        enabled: false
     web:
       pageable:
         max-page-size: 1000
         one-indexed-parameters: true
-  mail:
-    host: smtp.exmail.qq.com
-    username: noreply@seecoder.cn
-    password: eNrZcqucgcFtLC29
-    properties:
-      mail:
-        smtp:
-          auth: true
-          socketFactory:
-            class: javax.net.ssl.SSLSocketFactory
-            port: 465
-          starttls:
-            enable: true
-            required: true
+#  mail:
+#    host: smtp.exmail.qq.com
+#    username: noreply@seecoder.cn
+#    password: eNrZcqucgcFtLC29
+#    properties:
+#      mail:
+#        smtp:
+#          auth: true
+#          socketFactory:
+#            class: javax.net.ssl.SSLSocketFactory
+#            port: 465
+#          starttls:
+#            enable: true
+#            required: true
   servlet:
     multipart:
       max-file-size: 50MB
@@ -71,7 +71,7 @@ bok:
 guavaCache:
   maximumSize: 1000
   expireAfterAccessInSeconds: 0
-  expireAfterWriteInSeconds: 600
+  expireAfterWriteInSeconds: 900
 jwt:
   secret: SEEC-1919810-OIDC-114514
 # 自定义数据

+ 25 - 21
src/main/resources/application-dev.yml

@@ -14,31 +14,31 @@ spring:
   http:
     encoding:
       force: true
-  redis:
-    host: localhost
-    port: 6379
+#  redis:
+#    host: localhost
+#    port: 6379
   data:
-    redis:
-      repositories:
-        enabled: false
+#    redis:
+#      repositories:
+#        enabled: false
     web:
       pageable:
         max-page-size: 1000
         one-indexed-parameters: true
-  mail:
-    host: smtp.exmail.qq.com
-    username: noreply@seecoder.cn
-    password: eNrZcqucgcFtLC29
-    properties:
-      mail:
-        smtp:
-          auth: true
-          socketFactory:
-            class: javax.net.ssl.SSLSocketFactory
-            port: 465
-          starttls:
-            enable: true
-            required: true
+#  mail:
+#    host: smtp.exmail.qq.com
+#    username: noreply@seecoder.cn
+#    password: eNrZcqucgcFtLC29
+#    properties:
+#      mail:
+#        smtp:
+#          auth: true
+#          socketFactory:
+#            class: javax.net.ssl.SSLSocketFactory
+#            port: 465
+#          starttls:
+#            enable: true
+#            required: true
   servlet:
     multipart:
       max-file-size: 50MB
@@ -71,7 +71,7 @@ data-analysis:
 guavaCache:
   maximumSize: 1000
   expireAfterAccessInSeconds: 0
-  expireAfterWriteInSeconds: 600
+  expireAfterWriteInSeconds: 900
 jwt:
   secret: SEEC-1919810-OIDC-114514
 # 自定义数据
@@ -80,3 +80,7 @@ jwt:
 #    from: ${spring.mail.username}
 #    subject: seecoder
 #  user-timeout-seconds: 43200
+management:
+  endpoint:
+    health:
+      show-details: always