Преглед изворни кода

refactor: 重构幻灯片相关功能的实现

ChenSiTong пре 6 година
родитељ
комит
f660f98762

+ 0 - 2
src/main/java/nju/seec/helper/HelperApplication.java

@@ -3,7 +3,6 @@ package nju.seec.helper;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
-import org.springframework.cache.annotation.EnableCaching;
 import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 
 /**
@@ -12,7 +11,6 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 @SpringBootApplication
 @ConfigurationPropertiesScan(basePackages = "nju.seec.helper.config")
 @EnableJpaRepositories(basePackages = "nju.seec.helper.data.dao")
-@EnableCaching
 public class HelperApplication {
 
     public static void main(String[] args) {

+ 10 - 1
src/main/java/nju/seec/helper/data/dao/CourseDAO.java

@@ -1,6 +1,7 @@
 package nju.seec.helper.data.dao;
 
 import nju.seec.helper.data.entity.Course;
+import nju.seec.helper.util.exception.HelperException;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.stereotype.Repository;
 
@@ -9,5 +10,13 @@ import org.springframework.stereotype.Repository;
  */
 @Repository
 public interface CourseDAO extends JpaRepository<Course, String> {
-
+    /**
+     * 封装findById方法
+     *
+     * @param courseId
+     * @return
+     */
+    default Course findCourseById(String courseId) {
+        return this.findById(courseId).orElseThrow(() -> HelperException.of(HelperException.ExceptionType.NOT_FOUND, "找不到课程"));
+    }
 }

+ 14 - 0
src/main/java/nju/seec/helper/data/dao/SlideDAO.java

@@ -1,6 +1,7 @@
 package nju.seec.helper.data.dao;
 
 import nju.seec.helper.data.entity.Slide;
+import nju.seec.helper.util.exception.HelperException;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
@@ -11,6 +12,18 @@ import org.springframework.stereotype.Repository;
  */
 @Repository
 public interface SlideDAO extends JpaRepository<Slide, Integer> {
+    /**
+     * 封装findById方法
+     *
+     * @param slideId
+     * @return
+     */
+    default Slide findSlideById(int slideId) {
+        return this.findById(slideId).orElseThrow(() -> HelperException.of(
+                HelperException.ExceptionType.NOT_FOUND, "找不到幻灯片")
+        );
+    }
+
     /**
      * 根据课程ID和幻灯片名是否包含关键字分页查询
      *
@@ -32,6 +45,7 @@ public interface SlideDAO extends JpaRepository<Slide, Integer> {
 
     /**
      * 判断是否存在相同幻灯片名
+     *
      * @param name
      * @return
      */

+ 1 - 1
src/main/java/nju/seec/helper/data/entity/Item.java

@@ -30,7 +30,7 @@ public class Item {
 
     private String content;
 
-    @ManyToOne
+    @ManyToOne(cascade = CascadeType.ALL)
     @JoinColumn(name = "slide_id")
     private Slide slide;
 }

+ 2 - 2
src/main/java/nju/seec/helper/data/entity/Slide.java

@@ -34,8 +34,8 @@ public class Slide {
     @Column(nullable = false, unique = true)
     private String name;
 
-    @OneToMany(mappedBy = "slide")
-    @OrderColumn(name = "index")
+    @OneToMany(mappedBy = "slide", cascade = CascadeType.ALL)
+    @OrderColumn(name = "number")
     private List<Item> items = new ArrayList<>();
 
     @Column(name = "create_time", updatable = false)

+ 0 - 35
src/main/java/nju/seec/helper/logic/convert/DTOConvertFactory.java

@@ -1,35 +0,0 @@
-package nju.seec.helper.logic.convert;
-
-import com.google.common.collect.ImmutableMap;
-import lombok.experimental.UtilityClass;
-import nju.seec.helper.data.entity.Item;
-import nju.seec.helper.data.entity.Slide;
-import nju.seec.helper.data.entity.SlideQuiz;
-import nju.seec.helper.util.CopyUtils;
-import nju.seec.helper.web.dto.SlideDTO;
-import nju.seec.helper.web.dto.SlideQuizDTO;
-
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * @author cst
- */
-@UtilityClass
-public class DTOConvertFactory {
-    @SuppressWarnings("rawtypes")
-    private static final Map<Class, DTOConverter> MAP = new ImmutableMap.Builder<Class, DTOConverter>()
-            .put(SlideDTO.class, (DTOConverter<SlideDTO, Slide>) slideDTO -> {
-                Slide slide = CopyUtils.copy(slideDTO, Slide.class, "items");
-                slide.setItems(slideDTO.getItems().stream().map(itemDTO -> CopyUtils.copy(itemDTO, Item.class)).collect(Collectors.toList()));
-                return slide;
-            })
-            .put(SlideQuizDTO.class, (DTOConverter<SlideQuizDTO, SlideQuiz>) slideQuizDTO -> CopyUtils.copy(slideQuizDTO, SlideQuiz.class))
-            .build();
-
-    @SuppressWarnings("unchecked")
-    public <DTO, Entity> Entity convert(DTO dto) {
-        return (Entity) MAP.get(dto.getClass())
-                .convert(dto);
-    }
-}

+ 0 - 15
src/main/java/nju/seec/helper/logic/convert/DTOConverter.java

@@ -1,15 +0,0 @@
-package nju.seec.helper.logic.convert;
-
-/**
- * @author cst
- */
-@FunctionalInterface
-public interface DTOConverter<DTO, Entity> {
-    /**
-     * 将DTO转化为相应的Entity
-     *
-     * @param dto
-     * @return Entity
-     */
-    Entity convert(DTO dto);
-}

+ 0 - 40
src/main/java/nju/seec/helper/logic/convert/EntityConvertFactory.java

@@ -1,40 +0,0 @@
-package nju.seec.helper.logic.convert;
-
-import com.google.common.collect.ImmutableMap;
-import lombok.experimental.UtilityClass;
-import nju.seec.helper.data.entity.Course;
-import nju.seec.helper.data.entity.Slide;
-import nju.seec.helper.logic.vo.CourseVO;
-import nju.seec.helper.logic.vo.ItemVO;
-import nju.seec.helper.logic.vo.SlideVO;
-import nju.seec.helper.util.CopyUtils;
-import org.springframework.beans.BeanUtils;
-import org.springframework.data.util.Pair;
-
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * @author cst
- */
-@UtilityClass
-public class EntityConvertFactory {
-    @SuppressWarnings("rawtypes")
-    private final Map<Pair, EntityConverter> MAP = new ImmutableMap.Builder<Pair, EntityConverter>()
-            .put(Pair.of(Course.class, CourseVO.class), (EntityConverter<Course, CourseVO>) course -> CopyUtils.copy(course, CourseVO.class))
-            .put(Pair.of(Slide.class, SlideVO.class), (EntityConverter<Slide, SlideVO>) slide -> {
-                SlideVO slideVO = new SlideVO();
-                BeanUtils.copyProperties(slide, slideVO, "items");
-                slideVO.setItems(slide.getItems().stream()
-                        .map(item -> CopyUtils.copy(item, ItemVO.class))
-                        .collect(Collectors.toList()));
-                return slideVO;
-            })
-            .build();
-
-    @SuppressWarnings("unchecked")
-    public <Entity, VO> VO convert(Entity entity, Class<VO> classOfVO) {
-        return (VO) MAP.get(Pair.of(entity.getClass(), classOfVO))
-                .convert(entity);
-    }
-}

+ 0 - 15
src/main/java/nju/seec/helper/logic/convert/EntityConverter.java

@@ -1,15 +0,0 @@
-package nju.seec.helper.logic.convert;
-
-/**
- * @author cst
- */
-@FunctionalInterface
-public interface EntityConverter<Entity, VO> {
-    /**
-     * 将Entity转化为相应的VO
-     *
-     * @param entity
-     * @return VO
-     */
-    VO convert(Entity entity);
-}

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

@@ -27,12 +27,4 @@ public interface CourseService {
      * @return
      */
     List<CourseVO> getStudentCourses(int studentId, Pageable pageable);
-
-    /**
-     * 根据ID获取课程
-     *
-     * @param courseId
-     * @return
-     */
-    Course findCourseById(String courseId);
 }

+ 11 - 0
src/main/java/nju/seec/helper/logic/service/SlideService.java

@@ -1,6 +1,7 @@
 package nju.seec.helper.logic.service;
 
 import nju.seec.helper.logic.vo.SlideVO;
+import nju.seec.helper.util.enums.SlideState;
 import nju.seec.helper.web.dto.SlideDTO;
 import org.springframework.data.domain.Pageable;
 
@@ -53,6 +54,16 @@ public interface SlideService {
      */
     SlideVO update(SlideDTO slideDTO);
 
+    /**
+     * 更新幻灯片状态
+     *
+     * @param slideId
+     * @param state
+     * @return
+     */
+    SlideVO updateState(int slideId, SlideState state);
+
+
     /**
      * 删除幻灯片
      *

+ 6 - 7
src/main/java/nju/seec/helper/logic/service/impl/CourseServiceImpl.java

@@ -2,11 +2,11 @@ package nju.seec.helper.logic.service.impl;
 
 import nju.seec.helper.data.dao.CourseDAO;
 import nju.seec.helper.data.entity.Course;
-import nju.seec.helper.logic.convert.EntityConvertFactory;
 import nju.seec.helper.logic.service.CourseService;
 import nju.seec.helper.logic.vo.CourseVO;
 import nju.seec.helper.util.FakerUtils;
 import nju.seec.helper.util.exception.HelperException;
+import org.springframework.beans.BeanUtils;
 import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
 
@@ -44,7 +44,7 @@ public class CourseServiceImpl implements CourseService {
         }
 
         return courses.stream()
-                .map(course -> EntityConvertFactory.convert(course, CourseVO.class))
+                .map(this::copyCourseToCourseVO)
                 .collect(Collectors.toList());
     }
 
@@ -53,10 +53,9 @@ public class CourseServiceImpl implements CourseService {
         return getTeacherCourses(studentId, pageable);
     }
 
-    @Override
-    public Course findCourseById(String courseId) {
-        return courseDAO.findById(courseId).orElseThrow(() -> HelperException.of(
-                HelperException.ExceptionType.NOT_FOUND, "找不到课程")
-        );
+    private CourseVO copyCourseToCourseVO(Course course) {
+        CourseVO courseVO = new CourseVO();
+        BeanUtils.copyProperties(course, courseVO);
+        return courseVO;
     }
 }

+ 52 - 28
src/main/java/nju/seec/helper/logic/service/impl/SlideServiceImpl.java

@@ -1,19 +1,17 @@
 package nju.seec.helper.logic.service.impl;
 
+import nju.seec.helper.data.dao.CourseDAO;
 import nju.seec.helper.data.dao.SlideDAO;
 import nju.seec.helper.data.entity.Course;
+import nju.seec.helper.data.entity.Item;
 import nju.seec.helper.data.entity.Slide;
-import nju.seec.helper.logic.convert.DTOConvertFactory;
-import nju.seec.helper.logic.convert.EntityConvertFactory;
-import nju.seec.helper.logic.service.CourseService;
 import nju.seec.helper.logic.service.SlideService;
+import nju.seec.helper.logic.vo.ItemVO;
 import nju.seec.helper.logic.vo.SlideVO;
+import nju.seec.helper.util.enums.SlideState;
 import nju.seec.helper.util.exception.HelperException;
 import nju.seec.helper.web.dto.SlideDTO;
-import org.springframework.cache.annotation.CacheConfig;
-import org.springframework.cache.annotation.CacheEvict;
-import org.springframework.cache.annotation.CachePut;
-import org.springframework.cache.annotation.Cacheable;
+import org.springframework.beans.BeanUtils;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
@@ -26,15 +24,13 @@ import java.util.stream.Collectors;
  * @author cst
  */
 @Service
-@CacheConfig(cacheNames = "slide")
 public class SlideServiceImpl implements SlideService {
     private final SlideDAO slideDAO;
+    private final CourseDAO courseDAO;
 
-    private final CourseService courseService;
-
-    public SlideServiceImpl(SlideDAO slideDAO, CourseService courseService) {
+    public SlideServiceImpl(SlideDAO slideDAO, CourseDAO courseDAO) {
         this.slideDAO = slideDAO;
-        this.courseService = courseService;
+        this.courseDAO = courseDAO;
     }
 
     @Override
@@ -42,7 +38,7 @@ public class SlideServiceImpl implements SlideService {
         Page<Slide> slidePage = slideDAO.findByCourseIdAndNameContains(courseId, key, pageable);
 
         return slidePage.getContent().stream()
-                .map(slide -> EntityConvertFactory.convert(slide, SlideVO.class))
+                .map(this::copySlideToSlideVO)
                 .collect(Collectors.toList());
     }
 
@@ -51,15 +47,14 @@ public class SlideServiceImpl implements SlideService {
         Page<Slide> slidePage = slideDAO.findByNameContains(key, pageable);
 
         return slidePage.getContent().stream()
-                .map(slide -> EntityConvertFactory.convert(slide, SlideVO.class))
+                .map(this::copySlideToSlideVO)
                 .collect(Collectors.toList());
     }
 
-    @Cacheable(key = "#slideId")
     @Override
     public SlideVO getOneSlide(int slideId) {
-        Slide slide = findSlideById(slideId);
-        return EntityConvertFactory.convert(slide, SlideVO.class);
+        Slide slide = slideDAO.findSlideById(slideId);
+        return this.copySlideToSlideVO(slide);
     }
 
     @Override
@@ -67,32 +62,61 @@ public class SlideServiceImpl implements SlideService {
         if (slideDAO.existsByName(slideDTO.getName())) {
             throw HelperException.of(HelperException.ExceptionType.CONFLICT, "该幻灯片已存在");
         }
-        Slide slide = DTOConvertFactory.convert(slideDTO);
-        Course course = courseService.findCourseById(slideDTO.getCourseId());
+        Slide slide = new Slide();
+        this.copySlideDTOToSlide(slideDTO, slide);
+        Course course = courseDAO.findCourseById(slideDTO.getCourseId());
         slide.setCourseId(course.getId());
         slide.setCourseName(course.getName());
         slide.setItems(Collections.emptyList());
         slide = slideDAO.save(slide);
-        return EntityConvertFactory.convert(slide, SlideVO.class);
+        return this.copySlideToSlideVO(slide);
     }
 
-    @CachePut(key = "#slideDTO.id")
     @Override
     public SlideVO update(SlideDTO slideDTO) {
-        Slide slide = DTOConvertFactory.convert(slideDTO);
-        slideDAO.save(slide);
-        return EntityConvertFactory.convert(findSlideById(slideDTO.getId()), SlideVO.class);
+        Slide slide = slideDAO.findSlideById(slideDTO.getId());
+        this.copySlideDTOToSlide(slideDTO, slide);
+        slide = slideDAO.save(slide);
+        return this.copySlideToSlideVO(slide);
+    }
+
+    @Override
+    public SlideVO updateState(int slideId, SlideState state) {
+        Slide slide = slideDAO.findSlideById(slideId);
+        slide.setState(state);
+        slide = slideDAO.save(slide);
+        return this.copySlideToSlideVO(slide);
     }
 
-    @CacheEvict(key = "#slideId")
     @Override
     public void delete(int slideId) {
         slideDAO.deleteById(slideId);
     }
 
-    private Slide findSlideById(int slideId) {
-        return slideDAO.findById(slideId).orElseThrow(() -> HelperException.of(
-                HelperException.ExceptionType.NOT_FOUND, "找不到幻灯片")
+
+    private SlideVO copySlideToSlideVO(Slide slide) {
+        SlideVO slideVO = new SlideVO();
+        BeanUtils.copyProperties(slide, slideVO, "items");
+        slideVO.setItems(slide.getItems().stream()
+                .map(this::copyItemToItemVO)
+                .collect(Collectors.toList())
         );
+        return slideVO;
+    }
+
+    private ItemVO copyItemToItemVO(Item item) {
+        ItemVO itemVO = new ItemVO();
+        BeanUtils.copyProperties(item, itemVO);
+        return itemVO;
+    }
+
+    private void copySlideDTOToSlide(SlideDTO slideDTO, Slide slide) {
+        BeanUtils.copyProperties(slideDTO, slide, "courseId", "courseName", "createTime", "updateTime", "items");
+        slide.setItems(slideDTO.getItems().stream()
+                .map(itemDTO -> {
+                    Item item = new Item();
+                    BeanUtils.copyProperties(itemDTO, item);
+                    return item;
+                }).collect(Collectors.toList()));
     }
 }

+ 0 - 18
src/main/java/nju/seec/helper/util/CopyUtils.java

@@ -1,18 +0,0 @@
-package nju.seec.helper.util;
-
-import lombok.SneakyThrows;
-import lombok.experimental.UtilityClass;
-import org.springframework.beans.BeanUtils;
-
-/**
- * @author cst
- */
-@UtilityClass
-public class CopyUtils {
-    @SneakyThrows
-    public <T> T copy(Object source, Class<T> classOfT, String... ignoreProperties) {
-        T t = classOfT.newInstance();
-        BeanUtils.copyProperties(source, t, ignoreProperties);
-        return t;
-    }
-}

+ 1 - 1
src/main/java/nju/seec/helper/util/enums/SlideState.java

@@ -4,5 +4,5 @@ package nju.seec.helper.util.enums;
  * @author cst
  */
 public enum SlideState {
-    DRAFT
+    DRAFT, DISPLAY
 }

+ 5 - 0
src/main/java/nju/seec/helper/util/exception/HelperException.java

@@ -23,4 +23,9 @@ public class HelperException extends RuntimeException {
             this.code = code;
         }
     }
+
+    @Override
+    public String getMessage() {
+        return msg;
+    }
 }

+ 2 - 2
src/main/java/nju/seec/helper/web/controller/CourseController.java

@@ -26,14 +26,14 @@ public class CourseController {
         this.courseService = courseService;
     }
 
-    @ApiOperation(value = "教师获取创建课程", notes = "支持定制化分页排序,例:/course/seec?page=3&size=10&sort=id,asc&sort=name,desc,即以id正向排序再以name倒序排序,请求第3页,返回10条数据")
+    @ApiOperation(value = "教师获取创建课程", notes = "支持定制化分页排序,例:?page=3&size=10&sort=id,asc&sort=name,desc,即以id正向排序再以name倒序排序,请求第3页,返回10条数据")
     @GetMapping("/teacher")
     public PageResourceResponse<CourseVO> getTeacherCourses(@ApiParam(hidden = true) @PageableDefault(size = Integer.MAX_VALUE) Pageable pageable) {
         List<CourseVO> courseVOs = courseService.getTeacherCourses(1, pageable);
         return PageResourceResponse.of(courseVOs, PageResourceResponse.PageInfo.of(pageable.getPageNumber(), courseVOs.size()));
     }
 
-    @ApiOperation(value = "学生获取所选课程", notes = "支持定制化分页排序,例:" + "/course/seec?page=3&size=10&sort=id,asc&sort=name,desc" + ",即以id正向排序再以name倒序排序,请求第3页,返回10条数据")
+    @ApiOperation(value = "学生获取所选课程", notes = "支持定制化分页排序,例:?page=3&size=10&sort=id,asc&sort=name,desc,即以id正向排序再以name倒序排序,请求第3页,返回10条数据")
     @GetMapping("/student")
     public PageResourceResponse<CourseVO> getStudentCourse(@ApiParam(hidden = true) @PageableDefault(size = Integer.MAX_VALUE) Pageable pageable) {
         List<CourseVO> courseVOs = courseService.getStudentCourses(1, pageable);

+ 10 - 3
src/main/java/nju/seec/helper/web/controller/SlideController.java

@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import nju.seec.helper.logic.service.SlideService;
 import nju.seec.helper.logic.vo.SlideVO;
+import nju.seec.helper.util.enums.SlideState;
 import nju.seec.helper.web.dto.SlideDTO;
 import nju.seec.helper.web.response.EmptyResponse;
 import nju.seec.helper.web.response.PageResourceResponse;
@@ -31,7 +32,7 @@ public class SlideController {
         this.slideService = slideService;
     }
 
-    @ApiOperation(value = "根据课程ID和关键字获取创建的幻灯片列表", notes = "支持定制化分页排序,例:/course/seec?page=3&size=10&sort=id,asc&sort=name,desc,即以id正向排序再以name倒序排序,请求第3页,返回10条数据")
+    @ApiOperation(value = "根据课程ID和关键字获取创建的幻灯片列表", notes = "支持定制化分页排序,例:?page=3&size=10&sort=id,asc&sort=name,desc,即以id正向排序再以name倒序排序,请求第3页,返回10条数据")
     @GetMapping("/course/{courseId}")
     public PageResourceResponse<SlideVO> getSlides(@PathVariable String courseId,
                                                    @RequestParam(required = false, defaultValue = "") String key,
@@ -41,7 +42,7 @@ public class SlideController {
     }
 
 
-    @ApiOperation(value = "根据关键字获取创建的幻灯片列表", notes = "支持定制化分页排序,例:/course/seec?page=3&size=10&sort=id,asc&sort=name,desc,即以id正向排序再以name倒序排序,请求第3页,返回10条数据")
+    @ApiOperation(value = "根据关键字获取创建的幻灯片列表", notes = "支持定制化分页排序,例:?page=3&size=10&sort=id,asc&sort=name,desc,即以id正向排序再以name倒序排序,请求第3页,返回10条数据")
     @GetMapping("")
     public PageResourceResponse<SlideVO> getSlides(@RequestParam(required = false, defaultValue = "") String key,
                                                    @ApiParam(hidden = true) @PageableDefault(size = Integer.MAX_VALUE, sort = "updateTime", direction = Sort.Direction.DESC) Pageable pageable) {
@@ -62,12 +63,18 @@ public class SlideController {
         return ResourceResponse.of(slideService.create(slideDTO));
     }
 
-    @ApiOperation(value = "修改幻灯片")
+    @ApiOperation(value = "更新幻灯片")
     @PostMapping("/update")
     public ResourceResponse<SlideVO> update(@RequestBody @Validated SlideDTO slideDTO) {
         return ResourceResponse.of(slideService.update(slideDTO));
     }
 
+    @ApiOperation(value = "更新幻灯片状态")
+    @PostMapping("/updateState/{slideId:\\d+}")
+    public ResourceResponse<SlideVO> updateState(@PathVariable("slideId") int slideId, String state) {
+        return ResourceResponse.of(slideService.updateState(slideId, SlideState.valueOf(state)));
+    }
+
     @ApiOperation(value = "删除幻灯片")
     @PostMapping("/delete/{slideId:\\d+}")
     public EmptyResponse delete(@PathVariable int slideId) {

+ 0 - 1
src/main/java/nju/seec/helper/web/dto/SlideDTO.java

@@ -12,7 +12,6 @@ import java.util.List;
  */
 @Data
 public class SlideDTO {
-    @NotEmpty
     private String courseId;
     private Integer id;
     private SlideState state = SlideState.DRAFT;

+ 2 - 2
src/main/resources/application-dev.yml

@@ -15,6 +15,6 @@ spring:
   http:
     encoding:
       force: true
-server:
-  port: 18080
 
+server:
+  port: 18080