Просмотр исходного кода

Merge remote-tracking branch 'remotes/origin/release_v4.1.0'

deason 3 лет назад
Родитель
Сommit
2694382d82
40 измененных файлов с 1034 добавлено и 1004 удалено
  1. 41 11
      .gitignore
  2. 5 5
      examcloud-core-basic-api-provider/pom.xml
  3. 1 1
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/AppController.java
  4. 1 1
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/AuthController.java
  5. 2 2
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/CourseController.java
  6. 5 3
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/LogController.java
  7. 6 4
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/OrgController.java
  8. 1 1
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/ResourceController.java
  9. 2 2
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/SpecialtyController.java
  10. 2 2
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/StudentController.java
  11. 1 1
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/SystemPropertyController.java
  12. 2 2
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/UserController.java
  13. 36 37
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/provider/OrgCloudServiceProvider.java
  14. 51 45
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/provider/StudentCloudServiceProvider.java
  15. 7 7
      examcloud-core-basic-base/pom.xml
  16. 18 15
      examcloud-core-basic-dao/pom.xml
  17. 119 123
      examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/entity/StudentEntity.java
  18. 10 9
      examcloud-core-basic-service/pom.xml
  19. 5 0
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/OrgService.java
  20. 51 47
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/StudentService.java
  21. 1 1
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/FaceServiceImpl.java
  22. 10 10
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/LoginRuleServiceImpl.java
  23. 16 0
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/OrgServiceImpl.java
  24. 475 461
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/StudentServiceImpl.java
  25. 7 7
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/UserDataRuleServiceImpl.java
  26. 6 6
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/VerifyCodeServiceImpl.java
  27. 3 2
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/report/RocketMqConsumerListener.java
  28. 67 61
      examcloud-core-basic-starter/pom.xml
  29. 1 1
      examcloud-core-basic-starter/shell/start.args
  30. 8 27
      examcloud-core-basic-starter/shell/start.sh
  31. 4 14
      examcloud-core-basic-starter/shell/stop.sh
  32. 5 18
      examcloud-core-basic-starter/src/main/java/cn/com/qmth/examcloud/core/basic/starter/CoreBasicApp.java
  33. 5 5
      examcloud-core-basic-starter/src/main/java/cn/com/qmth/examcloud/core/basic/starter/config/ExamCloudResourceManager.java
  34. 3 2
      examcloud-core-basic-starter/src/main/java/cn/com/qmth/examcloud/core/basic/starter/config/MqConsumerListenerStartup.java
  35. 2 2
      examcloud-core-basic-starter/src/main/java/cn/com/qmth/examcloud/core/basic/starter/config/Swagger2.java
  36. 5 7
      examcloud-core-basic-starter/src/main/resources/application.properties
  37. 0 1
      examcloud-core-basic-starter/src/main/resources/classpath.location
  38. 44 58
      examcloud-core-basic-starter/src/main/resources/log4j2.xml
  39. 4 0
      jenkins.sh
  40. 2 3
      pom.xml

+ 41 - 11
.gitignore

@@ -1,20 +1,50 @@
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
 *.class
+*.log
 
-# Proguard folder generated by ide
-.project
+
+### Eclipse & STS ###
+.apt_generated
 .classpath
-*.springBeans
+.factorypath
+.project
 .settings
-target/
-.idea/
-*.iml
+.springBeans
+.sts4-cache
+
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
 
-# Log Files
-*.log
-*.class
 
+### VS Code ###
+.vscode
+node_modules
+package-lock.json
+yarn.lock
 
-# Package Files #
-*.jar
+
+### Package Files ###
+*.zip
 *.war
 *.ear
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+target/
+
+.flattened-pom.xml
+.DS_Store
+

+ 5 - 5
examcloud-core-basic-api-provider/pom.xml

@@ -6,21 +6,21 @@
     <packaging>jar</packaging>
 
     <parent>
-        <groupId>cn.com.qmth.examcloud.core.basic</groupId>
+        <groupId>cn.com.qmth.examcloud</groupId>
         <artifactId>examcloud-core-basic</artifactId>
-        <version>v4.0.2-RELEASE</version>
+        <version>${revision}</version>
     </parent>
 
     <dependencies>
         <dependency>
             <groupId>cn.com.qmth.examcloud.rpc</groupId>
             <artifactId>examcloud-core-basic-api</artifactId>
-            <version>${examcloud.version}</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
-            <groupId>cn.com.qmth.examcloud.core.basic</groupId>
+            <groupId>cn.com.qmth.examcloud</groupId>
             <artifactId>examcloud-core-basic-service</artifactId>
-            <version>${examcloud.version}</version>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
 

+ 1 - 1
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/AppController.java

@@ -27,7 +27,7 @@ public class AppController extends ControllerSupport {
     @ApiOperation(value = "查询所有应用")
     @GetMapping("getAllApp")
     public List<AppEntity> getAllApp() {
-        Sort sort = new Sort(Sort.Direction.ASC, "id");
+        Sort sort = Sort.by(Sort.Direction.ASC, "id");
         return appRepo.findAll(sort);
     }
 

+ 1 - 1
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/AuthController.java

@@ -86,7 +86,7 @@ public class AuthController extends ControllerSupport {
 
         String isApp = request.getHeader("isApp");
         if (StringUtils.isNotEmpty(isApp) && "true".equals(isApp)) {
-            log.info("App login ... " + loginInfo.getAccountValue());
+            LOGGER.info("App login ... " + loginInfo.getAccountValue());
             user = authService.login(loginInfo, false);
         } else {
             user = authService.login(loginInfo, true);

+ 2 - 2
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/CourseController.java

@@ -105,7 +105,7 @@ public class CourseController extends ControllerSupport {
                                             @RequestParam(required = false) Long specialtyId) {
         User accessUser = getAccessUser();
 
-        PageRequest pageable = PageRequest.of(curPage, pageSize, new Sort(Direction.DESC, "updateTime", "id"));
+        PageRequest pageable = PageRequest.of(curPage, pageSize, Sort.by(Direction.DESC, "updateTime", "id"));
 
         UserDataRule userDataRule = super.getUserDataRule(DataRuleType.COURSE);
         if (userDataRule.assertEmptyQueryResult()) {
@@ -215,7 +215,7 @@ public class CourseController extends ControllerSupport {
             return cb.and(predicates.toArray(new Predicate[predicates.size()]));
         };
 
-        PageRequest pageRequest = PageRequest.of(0, 50, new Sort(Direction.DESC, "updateTime"));
+        PageRequest pageRequest = PageRequest.of(0, 50, Sort.by(Direction.DESC, "updateTime"));
         Page<CourseEntity> page = courseRepo.findAll(specification, pageRequest);
 
         Iterator<CourseEntity> iterator = page.iterator();

+ 5 - 3
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/LogController.java

@@ -32,7 +32,8 @@ public class LogController extends ControllerSupport {
 
     @ApiOperation(value = "学生客户端日志")
     @PostMapping("studentClient/{level}/{code}")
-    public String logByStudentClient(@PathVariable String level, @PathVariable String code,
+    public String logByStudentClient(@PathVariable String level,
+                                     @PathVariable String code,
                                      @RequestBody String info) {
         log("STUDENT_CLIENT_LOGGER", level, code, info);
         return DateUtil.chinaNow();
@@ -49,12 +50,13 @@ public class LogController extends ControllerSupport {
      */
     private void log(String logger, String level, String code, String info) {
         if (!code.matches("\\w{1,2}\\-\\d{6}")) {
-            throw new StatusException("500002",
-                    "code must match regular expression:  \\w{1,2}\\-\\d{6}");
+            throw new StatusException("500002", "code must match regular expression:  \\w{1,2}\\-\\d{6}");
         }
+
         info = RegExUtils.replaceAll(info, "[\n\r]", "  ");
         ExamCloudLog log = getLogger(logger);
         MDC.put("CODE", code);
+
         if ("debug".equalsIgnoreCase(level)) {
             log.debug(info);
         } else if ("info".equalsIgnoreCase(level)) {

+ 6 - 4
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/OrgController.java

@@ -524,7 +524,7 @@ public class OrgController extends ControllerSupport {
             return cb.and(predicates.toArray(new Predicate[predicates.size()]));
         };
 
-        PageRequest pageRequest = PageRequest.of(0, 50, new Sort(Direction.DESC, "updateTime"));
+        PageRequest pageRequest = PageRequest.of(0, 50, Sort.by(Direction.DESC, "updateTime"));
         Page<OrgEntity> page = orgRepo.findAll(specification, pageRequest);
         Iterator<OrgEntity> iterator = page.iterator();
         List<OrgEntity> list = Lists.newArrayList();
@@ -567,7 +567,7 @@ public class OrgController extends ControllerSupport {
             throw new StatusException("001251", "total is larger than 1000");
         }
 
-        Sort sort = new Sort(Direction.ASC, "id");
+        Sort sort = Sort.by(Direction.ASC, "id");
         List<OrgEntity> orgEntityList = orgRepo.findAll(specification, sort);
 
         List<OrgDomain> ret = Lists.newArrayList();
@@ -1409,7 +1409,9 @@ public class OrgController extends ControllerSupport {
         if (null == orgEntity) {
             throw new StatusException("140002", "orgEntity is null");
         }
-        OrgPropertyEntity fileEntity = orgPropertyRepo.findByOrgIdAndKeyId(orgId, 26L);
+        DynamicEnumManager manager = OrgProperty.getDynamicEnumManager();
+        DynamicEnum answersTemplate = manager.getByName("ANSWERS_TEMPLATE");
+        OrgPropertyEntity fileEntity = orgPropertyRepo.findByOrgIdAndKeyId(orgId, answersTemplate.getId());
         if (null == fileEntity || StringUtils.isBlank(fileEntity.getValue())) {
             return "";
         }
@@ -1420,7 +1422,7 @@ public class OrgController extends ControllerSupport {
     @GetMapping("importTemplate")
     public void getDownloadTemplate(HttpServletResponse response) {
         String resoucePath = PathUtil.getResoucePath("templates/subOrgImportTemplate.xlsx");
-        log.info("-------getDownloadTemplate-resoucePath=" + resoucePath);
+        LOGGER.info("-------getDownloadTemplate-resoucePath=" + resoucePath);
         exportFile("学习中心导入模板.xlsx", new File(resoucePath));
     }
 

+ 1 - 1
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/ResourceController.java

@@ -83,7 +83,7 @@ public class ResourceController extends ControllerSupport {
             return cb.and(predicates.toArray(new Predicate[predicates.size()]));
         };
         PageRequest pageRequest = PageRequest.of(pageNo, pageSize,
-                new Sort(Direction.ASC, "isFile").and(new Sort(Direction.DESC, "creationTime")));
+                Sort.by(Direction.ASC, "isFile").and(Sort.by(Direction.DESC, "creationTime")));
 
         Page<ResourceEntity> page = resourceRepo.findAll(specification, pageRequest);
         Iterator<ResourceEntity> iterator = page.iterator();

+ 2 - 2
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/SpecialtyController.java

@@ -124,7 +124,7 @@ public class SpecialtyController extends ControllerSupport {
         };
 
         PageRequest pageRequest = PageRequest.of(curPage, pageSize,
-                new Sort(Direction.DESC, "updateTime", "id"));
+                Sort.by(Direction.DESC, "updateTime", "id"));
 
         Page<SpecialtyEntity> page = specialtyRepo.findAll(specification, pageRequest);
         return page;
@@ -178,7 +178,7 @@ public class SpecialtyController extends ControllerSupport {
         }
 
         List<SpecialtyEntity> list = specialtyRepo.findAll(specification,
-                new Sort(Direction.DESC, "updateTime"));
+                Sort.by(Direction.DESC, "updateTime"));
         return list;
     }
 

+ 2 - 2
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/StudentController.java

@@ -129,7 +129,7 @@ public class StudentController extends ControllerSupport {
         final Long finalRootOrgId = rootOrgId;
 
         PageRequest pageable = PageRequest.of(curPage, pageSize,
-                new Sort(Direction.DESC, "updateTime", "id"));
+                Sort.by(Direction.DESC, "updateTime", "id"));
 
         UserDataRule userDataRule = super.getUserDataRule(DataRuleType.ORG);
         if (userDataRule.assertEmptyQueryResult()) {
@@ -386,7 +386,7 @@ public class StudentController extends ControllerSupport {
         }
 
         List<StudentEntity> studentList = studentRepo.findAll(specification,
-                new Sort(Direction.DESC, "updateTime"));
+                Sort.by(Direction.DESC, "updateTime"));
         this.doExport(studentList);
     }
 

+ 1 - 1
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/SystemPropertyController.java

@@ -82,7 +82,7 @@ public class SystemPropertyController extends ControllerSupport {
         };
 
         PageRequest pageRequest = PageRequest.of(curPage, pageSize,
-                new Sort(Direction.DESC, "updateTime", "propKey"));
+                Sort.by(Direction.DESC, "updateTime", "propKey"));
 
         Page<SystemPropertyEntity> page = systemPropertyRepo.findAll(specification, pageRequest);
 

+ 2 - 2
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/UserController.java

@@ -338,7 +338,7 @@ public class UserController extends ControllerSupport {
             return cb.and(predicates.toArray(new Predicate[predicates.size()]));
         };
 
-        PageRequest pageRequest = PageRequest.of(0, 50, new Sort(Direction.DESC, "updateTime"));
+        PageRequest pageRequest = PageRequest.of(0, 50, Sort.by(Direction.DESC, "updateTime"));
 
         Page<UserEntity> userList = userRepo.findAll(specification, pageRequest);
 
@@ -413,7 +413,7 @@ public class UserController extends ControllerSupport {
             }
 
             if (roleEntity == null) {
-                log.warn("Role not exist, code is " + roleCode);
+                LOGGER.warn("Role not exist, code is " + roleCode);
                 throw new StatusException("500404", "角色不存在");
             }
 

+ 36 - 37
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/provider/OrgCloudServiceProvider.java

@@ -3,19 +3,13 @@ package cn.com.qmth.examcloud.core.basic.api.provider;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.core.basic.api.OrgCloudService;
 import cn.com.qmth.examcloud.core.basic.api.bean.OrgBean;
-import cn.com.qmth.examcloud.core.basic.api.request.GetOrgReq;
-import cn.com.qmth.examcloud.core.basic.api.request.GetOrgsByIdListReq;
-import cn.com.qmth.examcloud.core.basic.api.request.GetOrgsReq;
-import cn.com.qmth.examcloud.core.basic.api.request.SaveOrgReq;
-import cn.com.qmth.examcloud.core.basic.api.response.GetOrgResp;
-import cn.com.qmth.examcloud.core.basic.api.response.GetOrgsByIdListResp;
-import cn.com.qmth.examcloud.core.basic.api.response.GetOrgsResp;
-import cn.com.qmth.examcloud.core.basic.api.response.SaveOrgResp;
+import cn.com.qmth.examcloud.core.basic.api.request.*;
+import cn.com.qmth.examcloud.core.basic.api.response.*;
 import cn.com.qmth.examcloud.core.basic.dao.OrgPropertyRepo;
 import cn.com.qmth.examcloud.core.basic.dao.OrgRepo;
 import cn.com.qmth.examcloud.core.basic.dao.entity.OrgEntity;
+import cn.com.qmth.examcloud.core.basic.service.OrgService;
 import cn.com.qmth.examcloud.core.basic.service.bean.OrgInfo;
-import cn.com.qmth.examcloud.core.basic.service.impl.OrgServiceImpl;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import com.google.common.collect.Lists;
@@ -35,9 +29,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.persistence.criteria.Predicate;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
 
 /**
  * {@link StatusException} 状态码范围:010XXX<br>
@@ -54,7 +46,7 @@ public class OrgCloudServiceProvider extends ControllerSupport implements OrgClo
     private static final long serialVersionUID = -7858439296389761341L;
 
     @Autowired
-    private OrgServiceImpl orgService;
+    private OrgService orgService;
 
     @Autowired
     private OrgRepo orgRepo;
@@ -107,16 +99,8 @@ public class OrgCloudServiceProvider extends ControllerSupport implements OrgClo
             throw new StatusException("150001", "机构不存在");
         }
 
-        OrgBean orgBean = new OrgBean();
-        orgBean.setId(org.getId());
-        orgBean.setName(org.getName());
-        orgBean.setCode(org.getCode());
-        orgBean.setParentId(org.getParentId());
-        orgBean.setRootId(org.getRootId());
-        orgBean.setEnable(org.getEnable());
-
         GetOrgResp resp = new GetOrgResp();
-        resp.setOrg(orgBean);
+        resp.setOrg(toOrgBean(org));
         return resp;
     }
 
@@ -133,14 +117,8 @@ public class OrgCloudServiceProvider extends ControllerSupport implements OrgClo
             if (null == org) {
                 throw new StatusException("010001", "no org. [id=" + cur + "]");
             }
-            OrgBean orgBean = new OrgBean();
-            orgBean.setId(org.getId());
-            orgBean.setName(org.getName());
-            orgBean.setCode(org.getCode());
-            orgBean.setParentId(org.getParentId());
-            orgBean.setRootId(org.getRootId());
-            orgBean.setEnable(org.getEnable());
 
+            OrgBean orgBean = toOrgBean(org);
             orgList.add(orgBean);
         }
         GetOrgsByIdListResp resp = new GetOrgsByIdListResp();
@@ -148,6 +126,22 @@ public class OrgCloudServiceProvider extends ControllerSupport implements OrgClo
         return resp;
     }
 
+    @Override
+    @PostMapping("getOrgMaps")
+    @ApiOperation(value = "根据ID列表获取机构集合")
+    public GetOrgMapsResp getOrgMaps(@RequestBody GetOrgMapsReq req) {
+        Map<Long, OrgEntity> orgs = orgService.getOrgMapsByIds(req.getOrgIds());
+
+        Map<Long, OrgBean> orgMaps = new HashMap<>();
+        for (Map.Entry<Long, OrgEntity> entry : orgs.entrySet()) {
+            orgMaps.put(entry.getKey(), toOrgBean(entry.getValue()));
+        }
+
+        GetOrgMapsResp resp = new GetOrgMapsResp();
+        resp.setOrgMaps(orgMaps);
+        return resp;
+    }
+
     @ApiOperation(value = "查询所有机构")
     @PostMapping("getOrgs")
     @Override
@@ -193,15 +187,9 @@ public class OrgCloudServiceProvider extends ControllerSupport implements OrgClo
         boolean has = false;
         while (iterator.hasNext()) {
             OrgEntity org = iterator.next();
-            OrgBean orgBean = new OrgBean();
-            orgBean.setId(org.getId());
-            orgBean.setName(org.getName());
-            orgBean.setCode(org.getCode());
-            orgBean.setParentId(org.getParentId());
-            orgBean.setRootId(org.getRootId());
-            orgBean.setEnable(org.getEnable());
-
             next = org.getId();
+
+            OrgBean orgBean = toOrgBean(org);
             list.add(orgBean);
             has = true;
         }
@@ -216,4 +204,15 @@ public class OrgCloudServiceProvider extends ControllerSupport implements OrgClo
         return resp;
     }
 
+    private OrgBean toOrgBean(OrgEntity entity) {
+        OrgBean bean = new OrgBean();
+        bean.setId(entity.getId());
+        bean.setParentId(entity.getParentId());
+        bean.setRootId(entity.getRootId());
+        bean.setCode(entity.getCode());
+        bean.setName(entity.getName());
+        bean.setEnable(entity.getEnable());
+        return bean;
+    }
+
 }

+ 51 - 45
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/provider/StudentCloudServiceProvider.java

@@ -1,41 +1,12 @@
 package cn.com.qmth.examcloud.core.basic.api.provider;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.persistence.criteria.Predicate;
-
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.jpa.domain.Specification;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import com.google.common.collect.Lists;
-
 import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.commons.util.ByteUtil;
 import cn.com.qmth.examcloud.commons.util.SHA256;
 import cn.com.qmth.examcloud.core.basic.api.StudentCloudService;
 import cn.com.qmth.examcloud.core.basic.api.bean.StudentBean;
-import cn.com.qmth.examcloud.core.basic.api.request.CountStudentReq;
-import cn.com.qmth.examcloud.core.basic.api.request.GetStudentListByIdsReq;
-import cn.com.qmth.examcloud.core.basic.api.request.GetStudentReq;
-import cn.com.qmth.examcloud.core.basic.api.request.SaveStudentReq;
-import cn.com.qmth.examcloud.core.basic.api.request.UnbindStudentCodeReq;
-import cn.com.qmth.examcloud.core.basic.api.request.UpdatePasswordReq;
-import cn.com.qmth.examcloud.core.basic.api.request.UpdateStudentStatusReq;
-import cn.com.qmth.examcloud.core.basic.api.response.CountStudentResp;
-import cn.com.qmth.examcloud.core.basic.api.response.GetStudentListByIdsResp;
-import cn.com.qmth.examcloud.core.basic.api.response.GetStudentResp;
-import cn.com.qmth.examcloud.core.basic.api.response.SaveStudentResp;
-import cn.com.qmth.examcloud.core.basic.api.response.UnbindStudentCodeResp;
-import cn.com.qmth.examcloud.core.basic.api.response.UpdatePasswordResp;
-import cn.com.qmth.examcloud.core.basic.api.response.UpdateStudentStatusResp;
+import cn.com.qmth.examcloud.core.basic.api.request.*;
+import cn.com.qmth.examcloud.core.basic.api.response.*;
 import cn.com.qmth.examcloud.core.basic.dao.OrgRepo;
 import cn.com.qmth.examcloud.core.basic.dao.StudentRepo;
 import cn.com.qmth.examcloud.core.basic.dao.UserRepo;
@@ -46,8 +17,24 @@ import cn.com.qmth.examcloud.core.basic.service.bean.StudentInfo;
 import cn.com.qmth.examcloud.core.basic.service.cache.StudentCache;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
+import com.google.common.collect.Lists;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.persistence.criteria.Predicate;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * {@link StatusException} 状态码范围:056XXX<br>
@@ -274,7 +261,7 @@ public class StudentCloudServiceProvider extends ControllerSupport implements St
         resp.setCount(count);
         return resp;
     }
-    
+
     @ApiOperation(value = "根据ID获取学生集合")
     @PostMapping("getStudentListByIds")
     @Override
@@ -292,21 +279,10 @@ public class StudentCloudServiceProvider extends ControllerSupport implements St
 
         List<StudentBean> list = Lists.newArrayList();
         for (StudentEntity student : studentEntityList) {
-        	StudentBean studentBean = new StudentBean();
-            studentBean.setId(student.getId());
-            studentBean.setName(student.getName());
-            studentBean.setIdentityNumber(student.getIdentityNumber());
-            studentBean.setRootOrgId(student.getRootOrgId());
-            studentBean.setOrgId(student.getOrgId());
-            studentBean.setPhoneNumber(student.getPhoneNumber());
-            studentBean.setPhotoPath(student.getPhotoPath());
-            studentBean.setRemark(student.getRemark());
-            studentBean.setSecurityPhone(student.getSecurityPhone());
-
-            if (!studentBean.getRootOrgId().equals(rootOrgId)) {
+            if (!student.getRootOrgId().equals(rootOrgId)) {
                 throw new StatusException("500", "params error");
             }
-            list.add(studentBean);
+            list.add(toStudentBean(student));
         }
 
         GetStudentListByIdsResp resp = new GetStudentListByIdsResp();
@@ -315,4 +291,34 @@ public class StudentCloudServiceProvider extends ControllerSupport implements St
         return resp;
     }
 
+    @Override
+    @PostMapping("getStudentMaps")
+    @ApiOperation(value = "根据ID列表获取学生集合")
+    public GetStudentMapsResp getStudentMaps(@RequestBody GetStudentMapsReq req) {
+        Map<Long, StudentEntity> students = studentService.getStudentMapsByIds(req.getStudentIds());
+
+        Map<Long, StudentBean> studentMaps = new HashMap<>();
+        for (Map.Entry<Long, StudentEntity> entry : students.entrySet()) {
+            studentMaps.put(entry.getKey(), toStudentBean(entry.getValue()));
+        }
+
+        GetStudentMapsResp resp = new GetStudentMapsResp();
+        resp.setStudentMaps(studentMaps);
+        return resp;
+    }
+
+    private StudentBean toStudentBean(StudentEntity entity) {
+        StudentBean bean = new StudentBean();
+        bean.setRootOrgId(entity.getRootOrgId());
+        bean.setOrgId(entity.getOrgId());
+        bean.setId(entity.getId());
+        bean.setName(entity.getName());
+        bean.setIdentityNumber(entity.getIdentityNumber());
+        bean.setSecurityPhone(entity.getSecurityPhone());
+        bean.setPhoneNumber(entity.getPhoneNumber());
+        bean.setPhotoPath(entity.getPhotoPath());
+        bean.setRemark(entity.getRemark());
+        return bean;
+    }
+
 }

+ 7 - 7
examcloud-core-basic-base/pom.xml

@@ -6,31 +6,31 @@
     <packaging>jar</packaging>
 
     <parent>
-        <groupId>cn.com.qmth.examcloud.core.basic</groupId>
+        <groupId>cn.com.qmth.examcloud</groupId>
         <artifactId>examcloud-core-basic</artifactId>
-        <version>v4.0.2-RELEASE</version>
+        <version>${revision}</version>
     </parent>
 
     <dependencies>
         <dependency>
             <groupId>cn.com.qmth.examcloud</groupId>
             <artifactId>examcloud-web</artifactId>
-            <version>${examcloud.version}</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>cn.com.qmth.examcloud</groupId>
             <artifactId>examcloud-support</artifactId>
-            <version>${examcloud.version}</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
-            <groupId>cn.com.qmth.examcloud.reports</groupId>
+            <groupId>cn.com.qmth.examcloud</groupId>
             <artifactId>examcloud-reports-commons</artifactId>
-            <version>${examcloud.version}</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>cn.com.qmth.examcloud.starters</groupId>
             <artifactId>examcloud-geetest-starter</artifactId>
-            <version>${examcloud.version}</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>com.github.penggle</groupId>

+ 18 - 15
examcloud-core-basic-dao/pom.xml

@@ -1,19 +1,22 @@
 <?xml version="1.0"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<groupId>cn.com.qmth.examcloud.core.basic</groupId>
-		<artifactId>examcloud-core-basic</artifactId>
-		<version>v4.0.2-RELEASE</version>
-	</parent>
-	<artifactId>examcloud-core-basic-dao</artifactId>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+         xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>examcloud-core-basic-dao</artifactId>
+    <packaging>jar</packaging>
 
-	<dependencies>
-		<dependency>
-			<groupId>cn.com.qmth.examcloud.core.basic</groupId>
-			<artifactId>examcloud-core-basic-base</artifactId>
-			<version>${examcloud.version}</version>
-		</dependency>
-	</dependencies>
+    <parent>
+        <groupId>cn.com.qmth.examcloud</groupId>
+        <artifactId>examcloud-core-basic</artifactId>
+        <version>${revision}</version>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>cn.com.qmth.examcloud</groupId>
+            <artifactId>examcloud-core-basic-base</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
 
 </project>

+ 119 - 123
examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/entity/StudentEntity.java

@@ -1,15 +1,9 @@
 package cn.com.qmth.examcloud.core.basic.dao.entity;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.Index;
-import javax.persistence.Table;
-
 import cn.com.qmth.examcloud.web.jpa.JpaEntity;
 
+import javax.persistence.*;
+
 /**
  * 类注释
  *
@@ -19,155 +13,157 @@ import cn.com.qmth.examcloud.web.jpa.JpaEntity;
  */
 @Entity
 @Table(name = "EC_B_STUDENT", indexes = {
-		@Index(name = "IDX_B_S_002001", columnList = "rootOrgId,identityNumber", unique = true)})
+        @Index(name = "IDX_B_S_002001", columnList = "rootOrgId,identityNumber", unique = true),
+        @Index(name = "IDX_B_S_002002", columnList = "orgId")
+})
 public class StudentEntity extends JpaEntity {
 
-	private static final long serialVersionUID = 757531976286006550L;
+    private static final long serialVersionUID = 757531976286006550L;
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(nullable = false)
+    private String name;
+
+    @Column(nullable = false)
+    private String password;
+
+    @Column(nullable = false)
+    private String identityNumber;
+
+    private String photoPath;
+
+    private String remark;
 
-	@Id
-	@GeneratedValue(strategy = GenerationType.IDENTITY)
-	private Long id;
+    @Column(nullable = false)
+    private Boolean enable;
 
-	@Column(nullable = false)
-	private String name;
+    private Long orgId;
 
-	@Column(nullable = false)
-	private String password;
+    @Column(nullable = false)
+    private Long rootOrgId;
 
-	@Column(nullable = false)
-	private String identityNumber;
+    /**
+     * 手机号码
+     */
+    private String phoneNumber;
 
-	private String photoPath;
+    /**
+     * 安全手机号码(用于登录)
+     */
+    @Column(unique = true, nullable = true)
+    private String securityPhone;
 
-	private String remark;
+    /**
+     * 密码虚弱
+     */
+    @Column(nullable = false)
+    private Boolean passwordWeak;
 
-	@Column(nullable = false)
-	private Boolean enable;
+    public StudentEntity() {
+    }
 
-	private Long orgId;
+    public StudentEntity(Long studentId) {
+        this.id = studentId;
+    }
 
-	@Column(nullable = false)
-	private Long rootOrgId;
+    public Long getId() {
+        return id;
+    }
 
-	/**
-	 * 手机号码
-	 */
-	private String phoneNumber;
+    public void setId(Long id) {
+        this.id = id;
+    }
 
-	/**
-	 * 安全手机号码(用于登录)
-	 */
-	@Column(unique = true, nullable = true)
-	private String securityPhone;
-	
-	/**
-	 * 密码虚弱
-	 */
-	@Column(nullable = false)
-	private Boolean passwordWeak;
+    public String getName() {
+        return name;
+    }
 
-	public StudentEntity() {
-	}
+    public void setName(String name) {
+        this.name = name;
+    }
 
-	public StudentEntity(Long studentId) {
-		this.id = studentId;
-	}
+    public String getPassword() {
+        return password;
+    }
 
-	public Long getId() {
-		return id;
-	}
+    public void setPassword(String password) {
+        this.password = password;
+    }
 
-	public void setId(Long id) {
-		this.id = id;
-	}
+    public String getIdentityNumber() {
+        return identityNumber;
+    }
 
-	public String getName() {
-		return name;
-	}
+    public void setIdentityNumber(String identityNumber) {
+        this.identityNumber = identityNumber;
+    }
 
-	public void setName(String name) {
-		this.name = name;
-	}
+    public String getPhotoPath() {
+        return photoPath;
+    }
 
-	public String getPassword() {
-		return password;
-	}
+    public void setPhotoPath(String photoPath) {
+        this.photoPath = photoPath;
+    }
 
-	public void setPassword(String password) {
-		this.password = password;
-	}
+    public String getRemark() {
+        return remark;
+    }
 
-	public String getIdentityNumber() {
-		return identityNumber;
-	}
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
 
-	public void setIdentityNumber(String identityNumber) {
-		this.identityNumber = identityNumber;
-	}
+    public Boolean getEnable() {
+        return enable;
+    }
 
-	public String getPhotoPath() {
-		return photoPath;
-	}
+    public void setEnable(Boolean enable) {
+        this.enable = enable;
+    }
 
-	public void setPhotoPath(String photoPath) {
-		this.photoPath = photoPath;
-	}
+    public Long getOrgId() {
+        return orgId;
+    }
 
-	public String getRemark() {
-		return remark;
-	}
+    public void setOrgId(Long orgId) {
+        this.orgId = orgId;
+    }
 
-	public void setRemark(String remark) {
-		this.remark = remark;
-	}
+    public Long getRootOrgId() {
+        return rootOrgId;
+    }
 
-	public Boolean getEnable() {
-		return enable;
-	}
+    public void setRootOrgId(Long rootOrgId) {
+        this.rootOrgId = rootOrgId;
+    }
 
-	public void setEnable(Boolean enable) {
-		this.enable = enable;
-	}
+    public String getPhoneNumber() {
+        return phoneNumber;
+    }
 
-	public Long getOrgId() {
-		return orgId;
-	}
+    public void setPhoneNumber(String phoneNumber) {
+        this.phoneNumber = phoneNumber;
+    }
 
-	public void setOrgId(Long orgId) {
-		this.orgId = orgId;
-	}
+    public String getSecurityPhone() {
+        return securityPhone;
+    }
 
-	public Long getRootOrgId() {
-		return rootOrgId;
-	}
+    public void setSecurityPhone(String securityPhone) {
+        this.securityPhone = securityPhone;
+    }
 
-	public void setRootOrgId(Long rootOrgId) {
-		this.rootOrgId = rootOrgId;
-	}
-
-	public String getPhoneNumber() {
-		return phoneNumber;
-	}
-
-	public void setPhoneNumber(String phoneNumber) {
-		this.phoneNumber = phoneNumber;
-	}
-
-	public String getSecurityPhone() {
-		return securityPhone;
-	}
-
-	public void setSecurityPhone(String securityPhone) {
-		this.securityPhone = securityPhone;
-	}
+    public Boolean getPasswordWeak() {
+        return passwordWeak;
+    }
 
-	public Boolean getPasswordWeak() {
-		return passwordWeak;
-	}
+    public void setPasswordWeak(Boolean passwordWeak) {
+        this.passwordWeak = passwordWeak;
+    }
 
-	public void setPasswordWeak(Boolean passwordWeak) {
-		this.passwordWeak = passwordWeak;
-	}
 
-	
 }

+ 10 - 9
examcloud-core-basic-service/pom.xml

@@ -2,37 +2,38 @@
 <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
          xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <modelVersion>4.0.0</modelVersion>
+    <artifactId>examcloud-core-basic-service</artifactId>
+    <packaging>jar</packaging>
+
     <parent>
-        <groupId>cn.com.qmth.examcloud.core.basic</groupId>
+        <groupId>cn.com.qmth.examcloud</groupId>
         <artifactId>examcloud-core-basic</artifactId>
-        <version>v4.0.2-RELEASE</version>
+        <version>${revision}</version>
     </parent>
-    <artifactId>examcloud-core-basic-service</artifactId>
-    <packaging>jar</packaging>
 
     <dependencies>
         <dependency>
-            <groupId>cn.com.qmth.examcloud.core.basic</groupId>
+            <groupId>cn.com.qmth.examcloud</groupId>
             <artifactId>examcloud-core-basic-dao</artifactId>
-            <version>${examcloud.version}</version>
+            <version>${project.version}</version>
         </dependency>
 
         <dependency>
             <groupId>cn.com.qmth.examcloud.rpc</groupId>
             <artifactId>examcloud-exchange-inner-api-client</artifactId>
-            <version>${examcloud.version}</version>
+            <version>${project.version}</version>
         </dependency>
 
         <dependency>
             <groupId>cn.com.qmth.examcloud.rpc</groupId>
             <artifactId>examcloud-task-api-client</artifactId>
-            <version>${examcloud.version}</version>
+            <version>${project.version}</version>
         </dependency>
 
         <dependency>
             <groupId>cn.com.qmth.examcloud.rpc</groupId>
             <artifactId>examcloud-core-examwork-api-client</artifactId>
-            <version>${examcloud.version}</version>
+            <version>${project.version}</version>
         </dependency>
 
     </dependencies>

+ 5 - 0
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/OrgService.java

@@ -62,4 +62,9 @@ public interface OrgService {
      */
     Map<Long, String> findRootOrgNamesByIds(Set<Long> rootOrgIds);
 
+    /**
+     * 根据ID列表获取机构集合
+     */
+    Map<Long, OrgEntity> getOrgMapsByIds(Set<Long> orgIds);
+
 }

+ 51 - 47
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/StudentService.java

@@ -1,10 +1,12 @@
 package cn.com.qmth.examcloud.core.basic.service;
 
-import java.util.List;
-
 import cn.com.qmth.examcloud.core.basic.dao.entity.StudentEntity;
 import cn.com.qmth.examcloud.core.basic.service.bean.StudentInfo;
 
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * 类注释
  *
@@ -14,54 +16,56 @@ import cn.com.qmth.examcloud.core.basic.service.bean.StudentInfo;
  */
 public interface StudentService {
 
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param studentInfo
-	 * @return
-	 */
-	StudentEntity saveStudent(StudentInfo studentInfo);
+    /**
+     * 方法注释
+     *
+     * @param studentInfo
+     * @return
+     * @author WANGWEI
+     */
+    StudentEntity saveStudent(StudentInfo studentInfo);
+
+    /**
+     * 查询
+     *
+     * @param rootOrgId
+     * @param studentId
+     * @param identityNumber
+     * @param studentCode
+     * @param securityPhone
+     * @return
+     * @author WANGWEI
+     */
+    StudentInfo getStudentInfo(Long rootOrgId, Long studentId, String identityNumber,
+                               String studentCode, String securityPhone);
 
-	/**
-	 * 查询
-	 *
-	 * @author WANGWEI
-	 * @param rootOrgId
-	 * @param studentId
-	 * @param identityNumber
-	 * @param studentCode
-	 * @param securityPhone
-	 * @return
-	 */
-	StudentInfo getStudentInfo(Long rootOrgId, Long studentId, String identityNumber,
-			String studentCode, String securityPhone);
+    /**
+     * 解绑学号
+     *
+     * @param studentCode
+     * @param identityNumber
+     * @author WANGWEI
+     */
+    List<Long> unbindStudentCode(Long rootOrgId, String studentCode, String identityNumber);
 
-	/**
-	 * 解绑学号
-	 *
-	 * @author WANGWEI
-	 * @param studentCode
-	 * @param identityNumber
-	 */
-	List<Long> unbindStudentCode(Long rootOrgId, String studentCode, String identityNumber);
+    /**
+     * 解绑安全手机
+     *
+     * @param studentId
+     * @return
+     * @author WANGWEI
+     */
+    public void unbindSecurityPhone(Long studentId);
 
-	/**
-	 * 解绑安全手机
-	 *
-	 * @author WANGWEI
-	 * @param studentId
-	 * @return
-	 */
-	public void unbindSecurityPhone(Long studentId);
+    /**
+     * 手机号码是否被绑定
+     *
+     * @param securityPhone
+     * @return
+     * @author WANGWEI
+     */
+    Boolean hasBeBound(String securityPhone);
 
-	/**
-	 * 手机号码是否被绑定
-	 *
-	 * @author WANGWEI
-	 * @param securityPhone
-	 * @return
-	 */
-	Boolean hasBeBound(String securityPhone);
+    Map<Long, StudentEntity> getStudentMapsByIds(Set<Long> studentIds);
 
 }

+ 1 - 1
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/FaceServiceImpl.java

@@ -150,7 +150,7 @@ public class FaceServiceImpl implements FaceService {
 			return cb.and(predicates.toArray(new Predicate[predicates.size()]));
 		};
 
-		PageRequest pageRequest = PageRequest.of(0, 10, new Sort(Direction.DESC, "updateTime"));
+		PageRequest pageRequest = PageRequest.of(0, 10, Sort.by(Direction.DESC, "updateTime"));
 
 		Page<FacesetEntity> studentList = facesetRepo.findAll(specification, pageRequest);
 

+ 10 - 10
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/LoginRuleServiceImpl.java

@@ -6,8 +6,6 @@
 package cn.com.qmth.examcloud.core.basic.service.impl;
 
 import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
-import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
 import cn.com.qmth.examcloud.commons.util.JsonUtil;
 import cn.com.qmth.examcloud.core.basic.dao.LoginRuleRepo;
 import cn.com.qmth.examcloud.core.basic.dao.entity.LoginRuleEntity;
@@ -23,6 +21,8 @@ import cn.com.qmth.examcloud.web.filestorage.YunPathInfo;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.*;
 import org.springframework.data.jpa.domain.Specification;
@@ -35,7 +35,7 @@ import java.util.stream.Collectors;
 @Service
 public class LoginRuleServiceImpl implements LoginRuleService {
 
-    private static final ExamCloudLog log = ExamCloudLogFactory.getLog("INTERFACE_LOGGER");
+    private static final Logger LOG = LoggerFactory.getLogger(LoginRuleServiceImpl.class);
 
     /**
      * “登录规则”的缓存KEY前缀
@@ -187,7 +187,7 @@ public class LoginRuleServiceImpl implements LoginRuleService {
             this.uploadJsonFile(json);
         }
 
-        log.info("refreshLoginRule " + type.name());
+        LOG.info("refreshLoginRule " + type.name());
     }
 
     private void uploadJsonFile(String json) {
@@ -196,9 +196,9 @@ public class LoginRuleServiceImpl implements LoginRuleService {
             FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
             env.setExt1("geetestConfig");
             YunPathInfo oss = FileStorageUtil.saveFile(LOGIN_RULE_SITE_ID, env, json.getBytes(), true);
-            log.debug(oss.getRelativePath());
+            LOG.debug(oss.getRelativePath());
         } catch (Exception e) {
-            log.error(e.getMessage(), e);
+            LOG.error(e.getMessage(), e);
         }
     }
 
@@ -220,7 +220,7 @@ public class LoginRuleServiceImpl implements LoginRuleService {
         String cacheKey = LOGIN_RULE_CACHE_KEY_PREFIX + type.name();
         Map<String, Boolean> values = redisClient.get(cacheKey, HashMap.class);
         if (MapUtils.isEmpty(values)) {
-            log.warn(String.format("LoginRule not exist, type = %s, rootOrgId = %s", rootOrgId, type.name()));
+            LOG.warn(String.format("LoginRule not exist, type = %s, rootOrgId = %s", rootOrgId, type.name()));
             return true;
         }
 
@@ -231,17 +231,17 @@ public class LoginRuleServiceImpl implements LoginRuleService {
 
         if (globalAllow == null || globalAllow) {
             if (allow == null || allow) {
-                log.info(String.format("LoginRule allow, rootOrgId = %s, type = %s", rootOrgId, type.name()));
+                LOG.info(String.format("LoginRule allow, rootOrgId = %s, type = %s", rootOrgId, type.name()));
                 return true;
             }
         } else {
             if (allow != null && allow) {
-                log.info(String.format("LoginRule allow, rootOrgId = %s, type = %s", rootOrgId, type.name()));
+                LOG.info(String.format("LoginRule allow, rootOrgId = %s, type = %s", rootOrgId, type.name()));
                 return true;
             }
         }
 
-        log.info(String.format("LoginRule unAllow, rootOrgId = %s, type = %s", rootOrgId, type.name()));
+        LOG.info(String.format("LoginRule unAllow, rootOrgId = %s, type = %s", rootOrgId, type.name()));
         return false;
     }
 

+ 16 - 0
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/OrgServiceImpl.java

@@ -470,6 +470,22 @@ public class OrgServiceImpl implements OrgService {
         return entities.stream().collect(Collectors.toMap(v -> v.getId(), v -> v.getName(), (oldValue, newValue) -> newValue));
     }
 
+    @Override
+    public Map<Long, OrgEntity> getOrgMapsByIds(Set<Long> orgIds) {
+        if (CollectionUtils.isEmpty(orgIds)) {
+            return new HashMap<>();
+        }
+
+        Specification<OrgEntity> spec = (root, query, cb) -> {
+            List<Predicate> predicates = new ArrayList<>();
+            predicates.add(root.get("id").in(orgIds));
+            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+        };
+
+        List<OrgEntity> entities = orgRepo.findAll(spec);
+        return entities.stream().collect(Collectors.toMap(v -> v.getId(), v -> v, (k, v) -> v));
+    }
+
     private void createLearnerCenterUser(OrgEntity org) {
         UserEntity user = userRepo.findByRootOrgIdAndLoginName(org.getRootId(), org.getCode());
         if (null != user) {

+ 475 - 461
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/StudentServiceImpl.java

@@ -1,18 +1,5 @@
 package cn.com.qmth.examcloud.core.basic.service.impl;
 
-import java.util.List;
-import java.util.Map;
-
-import javax.transaction.Transactional;
-
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
 import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.commons.util.ByteUtil;
 import cn.com.qmth.examcloud.commons.util.SHA256;
@@ -33,6 +20,18 @@ import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
 import cn.com.qmth.examcloud.task.api.DataSyncCloudService;
 import cn.com.qmth.examcloud.task.api.request.SyncStudentReq;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.criteria.Predicate;
+import javax.transaction.Transactional;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 学生服务类 Created by songyue on 17/1/14.
@@ -40,458 +39,473 @@ import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 @Service
 public class StudentServiceImpl implements StudentService {
 
-	@Autowired
-	StudentRepo studentRepo;
-
-	@Autowired
-	UserRepo userRepo;
-
-	@Autowired
-	StudentCodeRepo studentCodeRepo;
-
-	@Autowired
-	UserService userService;
-
-	@Autowired
-	OrgRepo orgRepo;
-
-	@Autowired
-	OrgServiceImpl orgService;
-
-	@Autowired
-	DataSyncCloudService dataSyncCloudService;
-
-	@Autowired
-	StudentCache studentCache;
-
-	@Autowired
-	OrgCache orgCache;
-
-	/*
-	 * 实现
-	 *
-	 * @author WANGWEI
-	 * 
-	 * @see cn.com.qmth.examcloud.core.basic.service.StudentService#
-	 * insertOrUpdateStudent(cn.com.qmth.examcloud.core.basic.service.bean.
-	 * StudentInfo)
-	 */
-	@Override
-	@Transactional
-	public StudentEntity saveStudent(StudentInfo studentInfo) {
-		Long rootOrgId = studentInfo.getRootOrgId();
-		OrgEntity rootOrg = GlobalHelper.getEntity(orgRepo, rootOrgId, OrgEntity.class);
-
-		if (null == rootOrg || null != rootOrg.getParentId()) {
-			throw new StatusException("160001", "顶级机构错误");
-		}
-
-		String identityNumber = studentInfo.getIdentityNumber();
-		if (StringUtils.isBlank(identityNumber)) {
-			throw new StatusException("160012", "身份证号不能为空");
-		}
-
-		StudentEntity student = studentRepo.findByIdentityNumberAndRootOrgId(identityNumber,
-				rootOrgId);
-
-		OrgEntity org = null;
-		if (null != studentInfo.getOrgId()) {
-			org = GlobalHelper.getEntity(orgRepo, studentInfo.getOrgId(), OrgEntity.class);
-			if (null == org) {
-				throw new StatusException("160050", "orgId is wrong");
-			}
-			if (!org.getRootId().equals(rootOrgId)) {
-				throw new StatusException("160051", "orgId is wrong");
-			}
-			if (null == org.getParentId()) {
-				throw new StatusException("160052", "orgId is wrong");
-			}
-			if (!org.getParentId().equals(rootOrgId)) {
-				throw new StatusException("160053", "orgId is wrong");
-			}
-		} else if (StringUtils.isNotBlank(studentInfo.getOrgCode())) {
-			org = orgRepo.findByRootIdAndCode(rootOrgId, studentInfo.getOrgCode());
-			if (null == org) {
-				String orgName = studentInfo.getOrgName();
-				if (StringUtils.isBlank(orgName)) {
-					throw new StatusException("160003", "orgName is blank");
-				}
-				org = new OrgEntity();
-				org.setParentId(rootOrgId);
-				org.setCode(studentInfo.getOrgCode());
-				org.setName(orgName);
-				org.setEnable(true);
-				org.setRootId(rootOrgId);
-				org = orgRepo.save(org);
-			}
-		} else {
-			if (null != student) {
-				org = GlobalHelper.getEntity(orgRepo, student.getOrgId(), OrgEntity.class);
-			} else {
-				org = orgRepo.findByRootIdAndCode(rootOrgId, BasicConsts.DEFAULT_ORG_COEE);
-				if (null == org) {
-					org = new OrgEntity();
-					org.setParentId(rootOrgId);
-					org.setCode(BasicConsts.DEFAULT_ORG_COEE);
-					org.setName(BasicConsts.DEFAULT_ORG_NAME);
-					org.setEnable(true);
-					org.setRootId(rootOrgId);
-					org = orgRepo.save(org);
-				}
-			}
-		}
-
-		long updateTime = 0L;
-		if (null != student) {
-			if (null != student.getUpdateTime()) {
-				updateTime = student.getUpdateTime().getTime();
-			}
-			if (null == student.getEnable()) {
-				student.setEnable(true);
-			}
-		} else {
-			student = new StudentEntity();
-			student.setPasswordWeak(true);
-			student.setEnable(true);
-			String passwd=null;
+    @Autowired
+    StudentRepo studentRepo;
+
+    @Autowired
+    UserRepo userRepo;
+
+    @Autowired
+    StudentCodeRepo studentCodeRepo;
+
+    @Autowired
+    UserService userService;
+
+    @Autowired
+    OrgRepo orgRepo;
+
+    @Autowired
+    OrgServiceImpl orgService;
+
+    @Autowired
+    DataSyncCloudService dataSyncCloudService;
+
+    @Autowired
+    StudentCache studentCache;
+
+    @Autowired
+    OrgCache orgCache;
+
+    /*
+     * 实现
+     *
+     * @author WANGWEI
+     *
+     * @see cn.com.qmth.examcloud.core.basic.service.StudentService#
+     * insertOrUpdateStudent(cn.com.qmth.examcloud.core.basic.service.bean.
+     * StudentInfo)
+     */
+    @Override
+    @Transactional
+    public StudentEntity saveStudent(StudentInfo studentInfo) {
+        Long rootOrgId = studentInfo.getRootOrgId();
+        OrgEntity rootOrg = GlobalHelper.getEntity(orgRepo, rootOrgId, OrgEntity.class);
+
+        if (null == rootOrg || null != rootOrg.getParentId()) {
+            throw new StatusException("160001", "顶级机构错误");
+        }
+
+        String identityNumber = studentInfo.getIdentityNumber();
+        if (StringUtils.isBlank(identityNumber)) {
+            throw new StatusException("160012", "身份证号不能为空");
+        }
+
+        StudentEntity student = studentRepo.findByIdentityNumberAndRootOrgId(identityNumber,
+                rootOrgId);
+
+        OrgEntity org = null;
+        if (null != studentInfo.getOrgId()) {
+            org = GlobalHelper.getEntity(orgRepo, studentInfo.getOrgId(), OrgEntity.class);
+            if (null == org) {
+                throw new StatusException("160050", "orgId is wrong");
+            }
+            if (!org.getRootId().equals(rootOrgId)) {
+                throw new StatusException("160051", "orgId is wrong");
+            }
+            if (null == org.getParentId()) {
+                throw new StatusException("160052", "orgId is wrong");
+            }
+            if (!org.getParentId().equals(rootOrgId)) {
+                throw new StatusException("160053", "orgId is wrong");
+            }
+        } else if (StringUtils.isNotBlank(studentInfo.getOrgCode())) {
+            org = orgRepo.findByRootIdAndCode(rootOrgId, studentInfo.getOrgCode());
+            if (null == org) {
+                String orgName = studentInfo.getOrgName();
+                if (StringUtils.isBlank(orgName)) {
+                    throw new StatusException("160003", "orgName is blank");
+                }
+                org = new OrgEntity();
+                org.setParentId(rootOrgId);
+                org.setCode(studentInfo.getOrgCode());
+                org.setName(orgName);
+                org.setEnable(true);
+                org.setRootId(rootOrgId);
+                org = orgRepo.save(org);
+            }
+        } else {
+            if (null != student) {
+                org = GlobalHelper.getEntity(orgRepo, student.getOrgId(), OrgEntity.class);
+            } else {
+                org = orgRepo.findByRootIdAndCode(rootOrgId, BasicConsts.DEFAULT_ORG_COEE);
+                if (null == org) {
+                    org = new OrgEntity();
+                    org.setParentId(rootOrgId);
+                    org.setCode(BasicConsts.DEFAULT_ORG_COEE);
+                    org.setName(BasicConsts.DEFAULT_ORG_NAME);
+                    org.setEnable(true);
+                    org.setRootId(rootOrgId);
+                    org = orgRepo.save(org);
+                }
+            }
+        }
+
+        long updateTime = 0L;
+        if (null != student) {
+            if (null != student.getUpdateTime()) {
+                updateTime = student.getUpdateTime().getTime();
+            }
+            if (null == student.getEnable()) {
+                student.setEnable(true);
+            }
+        } else {
+            student = new StudentEntity();
+            student.setPasswordWeak(true);
+            student.setEnable(true);
+            String passwd = null;
             if (StringUtils.isNotEmpty(identityNumber)
                     && identityNumber.matches("[0-9a-zA-Z]{6,}")) {
-            	passwd=StringUtils.substring(identityNumber, -6, identityNumber.length());
+                passwd = StringUtils.substring(identityNumber, -6, identityNumber.length());
             } else {
-            	passwd=BasicConsts.DEFAULT_PASSWORD;
+                passwd = BasicConsts.DEFAULT_PASSWORD;
             }
             byte[] bytes = SHA256.encode(identityNumber + passwd);
-	        String encodePassword = ByteUtil.toHexAscii(bytes);
-	        student.setPassword(encodePassword);
-
-			student.setRootOrgId(rootOrgId);
-			student.setIdentityNumber(identityNumber);
-		}
-
-		student.setOrgId(org.getId());
-		if (null != studentInfo.getName()) {
-			if (StringUtils.isBlank(studentInfo.getName())) {
-				throw new StatusException("160006", "姓名不能为空串");
-			}
-			student.setName(studentInfo.getName());
-		}
-		if (null != studentInfo.getPhotoPath()) {
-			student.setPhotoPath(studentInfo.getPhotoPath());
-		}
-		if (null != studentInfo.getPhoneNumber()) {
-			student.setPhoneNumber(studentInfo.getPhoneNumber());
-		}
-		if (null != studentInfo.getRemark()) {
-			student.setRemark(studentInfo.getRemark());
-		}
-		if (null != studentInfo.getEnable()) {
-			student.setEnable(studentInfo.getEnable());
-		}
-		StudentEntity saved = studentRepo.saveAndFlush(student);
-
-		List<String> studentCodeList = studentInfo.getStudentCodeList();
-		if (CollectionUtils.isNotEmpty(studentCodeList)) {
-
-			if (5 < studentCodeList.size()) {
-				throw new StatusException("160019", "身份证绑定的学号数量不能超过5个");
-			}
-
-			for (String studentCode : studentCodeList) {
-				if (StringUtils.isBlank(studentCode)) {
-					continue;
-				}
-				StudentCodeEntity studentCodeEntity = studentCodeRepo
-						.findByStudentCodeAndRootOrgId(studentCode, rootOrgId);
-
-				if (null != studentCodeEntity) {
-					if (!studentCodeEntity.getIdentityNumber().equalsIgnoreCase(identityNumber)) {
-						throw new StatusException("160008", "学号被占用. 学号: " + studentCode);
-					}
-				} else {
-					studentCodeEntity = new StudentCodeEntity();
-					studentCodeEntity.setIdentityNumber(identityNumber);
-					studentCodeEntity.setRootOrgId(rootOrgId);
-					studentCodeEntity.setStudentCode(studentCode);
-					studentCodeEntity.setStudentId(saved.getId());
-
-					studentCodeRepo.save(studentCodeEntity);
-				}
-
-			}
-		}
-
-		List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo
-				.findByStudentId(saved.getId());
-
-		if (5 < studentCodeEntityList.size()) {
-			throw new StatusException("160018", "身份证绑定的学号数量不能超过5个");
-		}
-
-		List<String> lastStudentCodeList = Lists.newArrayList();
-		for (StudentCodeEntity cur : studentCodeEntityList) {
-			lastStudentCodeList.add(cur.getStudentCode());
-		}
-
-		// 同步操作
-		if (updateTime != saved.getUpdateTime().getTime()) {
-			SyncStudentReq req = new SyncStudentReq();
-			req.setEnable(saved.getEnable());
-			req.setId(saved.getId());
-			req.setIdentityNumber(saved.getIdentityNumber());
-			req.setName(saved.getName());
-			req.setOrgCode(org.getCode());
-			req.setOrgId(org.getId());
-			req.setOrgName(org.getName());
-			req.setPhoneNumber(saved.getPhoneNumber());
-			req.setPhotoPath(saved.getPhotoPath());
-			req.setRootOrgId(saved.getRootOrgId());
-			req.setSecurityPhone(saved.getSecurityPhone());
-			req.setStudentCodeList(lastStudentCodeList);
-
-			req.setSyncType("update");
-
-			dataSyncCloudService.syncStudent(req);
-		}
-
-		studentCache.remove(saved.getId());
-		orgCache.remove(org.getId());
-
-		return saved;
-	}
-
-	/*
-	 * 实现
-	 *
-	 * @author WANGWEI
-	 * 
-	 * @see
-	 * cn.com.qmth.examcloud.core.basic.service.StudentService#getStudentInfo(
-	 * java.lang.Long, java.lang.String, java.lang.String, java.lang.String)
-	 */
-	@Override
-	public StudentInfo getStudentInfo(Long rootOrgId, Long studentId, String identityNumber,
-			String studentCode, String securityPhone) {
-
-		StudentEntity s = null;
-		int count = 0;
-		if (null != studentId) {
-			count++;
-			s = GlobalHelper.getEntity(studentRepo, studentId, StudentEntity.class);
-		} else if (StringUtils.isNotBlank(securityPhone)) {
-			count++;
-			s = studentRepo.findBySecurityPhone(securityPhone);
-		} else if (null == rootOrgId) {
-			throw new StatusException("160250", "rootOrgId is null");
-		}
-
-		if (StringUtils.isNotBlank(identityNumber)) {
-			count++;
-			s = studentRepo.findByIdentityNumberAndRootOrgId(identityNumber, rootOrgId);
-		}
-		if (StringUtils.isNotBlank(studentCode)) {
-			count++;
-
-			StudentCodeEntity studentCodeEntity = studentCodeRepo
-					.findByStudentCodeAndRootOrgId(studentCode, rootOrgId);
-			if (null != studentCodeEntity) {
-				s = GlobalHelper.getEntity(studentRepo, studentCodeEntity.getStudentId(),
-						StudentEntity.class);
-			}
-		}
-
-		if (count > 1) {
-			throw new StatusException("160210",
-					"参数过多,只需要[studentId,identityNumber,studentCode,securityPhone]中的一个");
-		}
-
-		if (null == s) {
-			throw new StatusException("160211", "学生不存在");
-		}
-
-		StudentInfo info = new StudentInfo();
-		info.setId(s.getId());
-		info.setEnable(s.getEnable());
-		info.setIdentityNumber(s.getIdentityNumber());
-		info.setName(s.getName());
-		info.setOrgId(s.getOrgId());
-		if (null != s.getOrgId()) {
-			OrgEntity org = GlobalHelper.getEntity(orgRepo, s.getOrgId(), OrgEntity.class);
-			if (null != org) {
-				info.setOrgCode(org.getCode());
-				info.setOrgName(org.getName());
-			}
-		}
-		info.setPhoneNumber(s.getPhoneNumber());
-
-		if (StringUtils.isNotBlank(s.getPhotoPath())) {
-//			String upyunDomain = PropertyHolder.getString("$upyun.site.1.domain");
-//			if (StringUtils.isBlank(upyunDomain)) {
-//				throw new StatusException("560111",
-//						"property[$upyun.site.1.domain] is not configured");
-//			}
-//			String path = UrlUtil.joinUrl(upyunDomain, "student_base_photo", s.getPhotoPath());
-//			info.setPhotoPath(path);
-			//通用存储
-			info.setPhotoPath(FileStorageUtil.realPath(FileStorageUtil.getIntactPath("student_base_photo", s.getPhotoPath())));
-		}
-
-		info.setRemark(s.getRemark());
-		info.setRootOrgId(s.getRootOrgId());
-		OrgEntity rootOrg = GlobalHelper.getEntity(orgRepo, s.getRootOrgId(), OrgEntity.class);
-		info.setRootOrgName(rootOrg.getName());
-		info.setSecurityPhone(s.getSecurityPhone());
-
-		List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo.findByStudentId(s.getId());
-
-		List<String> studentCodeList = Lists.newArrayList();
-		for (StudentCodeEntity cur : studentCodeEntityList) {
-			studentCodeList.add(cur.getStudentCode());
-		}
-		info.setStudentCodeList(studentCodeList);
-
-		return info;
-	}
-
-	@Override
-	public List<Long> unbindStudentCode(Long rootOrgId, String studentCode, String identityNumber) {
-
-		if (null == rootOrgId) {
-			throw new StatusException("120001", "rootOrgId is null");
-		}
-
-		// 更新的学生集合
-		List<StudentEntity> studentList = Lists.newArrayList();
-		// 解绑的学号集合
-		Map<Long, List<String>> unboundStudentCodeMap = Maps.newHashMap();
-
-		StudentEntity s1 = null;
-		StudentEntity s2 = null;
-		if (null != studentCode) {
-			StudentCodeEntity sc = studentCodeRepo.findByStudentCodeAndRootOrgId(studentCode,
-					rootOrgId);
-			if (null != sc) {
-				studentCodeRepo.delete(sc);
-				s1 = GlobalHelper.getEntity(studentRepo, sc.getStudentId(), StudentEntity.class);
-				studentList.add(s1);
-				List<String> unboundStudentCodeList = Lists.newArrayList();
-				unboundStudentCodeList.add(sc.getStudentCode());
-				unboundStudentCodeMap.put(s1.getId(), unboundStudentCodeList);
-			}
-		}
-
-		if (null != identityNumber) {
-			s2 = studentRepo.findByIdentityNumberAndRootOrgId(identityNumber, rootOrgId);
-			if (null != s2) {
-				if (null == s1 || !s1.getId().equals(s2.getId())) {
-					studentList.add(s2);
-				}
-
-				List<StudentCodeEntity> scList = studentCodeRepo.findByStudentId(s2.getId());
-				studentCodeRepo.deleteAll(scList);
-
-				List<String> unboundStudentCodeList = unboundStudentCodeMap.get(s2.getId());
-				if (null == unboundStudentCodeList) {
-					unboundStudentCodeList = Lists.newArrayList();
-					unboundStudentCodeMap.put(s2.getId(), unboundStudentCodeList);
-				}
-				for (StudentCodeEntity cur : scList) {
-					unboundStudentCodeList.add(cur.getStudentCode());
-				}
-			}
-		}
-
-		List<Long> studentIdList = Lists.newArrayList();
-
-		for (StudentEntity cur : studentList) {
-			studentIdList.add(cur.getId());
-
-			SyncStudentReq req = new SyncStudentReq();
-			req.setEnable(cur.getEnable());
-			req.setId(cur.getId());
-			req.setIdentityNumber(cur.getIdentityNumber());
-			req.setName(cur.getName());
-
-			req.setOrgId(cur.getOrgId());
-			OrgEntity org = GlobalHelper.getEntity(orgRepo, cur.getOrgId(), OrgEntity.class);
-			req.setOrgCode(org.getCode());
-			req.setOrgName(org.getName());
-
-			req.setPhoneNumber(cur.getPhoneNumber());
-			req.setPhotoPath(cur.getPhotoPath());
-			req.setRootOrgId(cur.getRootOrgId());
-			req.setSecurityPhone(cur.getSecurityPhone());
-
-			List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo
-					.findByStudentId(cur.getId());
-
-			List<String> lastStudentCodeList = Lists.newArrayList();
-			for (StudentCodeEntity sc : studentCodeEntityList) {
-				lastStudentCodeList.add(sc.getStudentCode());
-			}
-
-			req.setStudentCodeList(lastStudentCodeList);
-
-			List<String> unboundStudentCodeList = unboundStudentCodeMap.get(cur.getId());
-			req.setUnboundStudentCodeList(unboundStudentCodeList);
-
-			req.setSyncType("update");
-
-			dataSyncCloudService.syncStudent(req);
-		}
-
-		for (Long cur : studentIdList) {
-			studentCache.remove(cur);
-		}
-
-		return studentIdList;
-	}
-
-	@Override
-	public void unbindSecurityPhone(Long studentId) {
-
-		StudentEntity s = GlobalHelper.getEntity(studentRepo, studentId, StudentEntity.class);
-		if (null == s) {
-			throw new StatusException("450110", "学生不存在");
-		}
-		s.setSecurityPhone(null);
-		StudentEntity saved = studentRepo.save(s);
-
-		SyncStudentReq req = new SyncStudentReq();
-		req.setEnable(saved.getEnable());
-		req.setId(saved.getId());
-		req.setIdentityNumber(saved.getIdentityNumber());
-		req.setName(saved.getName());
-
-		req.setOrgId(saved.getOrgId());
-		OrgEntity org = GlobalHelper.getEntity(orgRepo, saved.getOrgId(), OrgEntity.class);
-		req.setOrgCode(org.getCode());
-		req.setOrgName(org.getName());
-
-		req.setPhoneNumber(saved.getPhoneNumber());
-		req.setPhotoPath(saved.getPhotoPath());
-		req.setRootOrgId(saved.getRootOrgId());
-		req.setSecurityPhone(saved.getSecurityPhone());
-
-		List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo
-				.findByStudentId(saved.getId());
-		List<String> lastStudentCodeList = Lists.newArrayList();
-		for (StudentCodeEntity sc : studentCodeEntityList) {
-			lastStudentCodeList.add(sc.getStudentCode());
-		}
-		req.setStudentCodeList(lastStudentCodeList);
-
-		req.setSyncType("update");
-
-		dataSyncCloudService.syncStudent(req);
-
-		studentCache.remove(studentId);
-	}
-
-	@Override
-	public Boolean hasBeBound(String securityPhone) {
-
-		StudentEntity s = studentRepo.findBySecurityPhone(securityPhone);
-		return null != s;
-	}
+            String encodePassword = ByteUtil.toHexAscii(bytes);
+            student.setPassword(encodePassword);
+
+            student.setRootOrgId(rootOrgId);
+            student.setIdentityNumber(identityNumber);
+        }
+
+        student.setOrgId(org.getId());
+        if (null != studentInfo.getName()) {
+            if (StringUtils.isBlank(studentInfo.getName())) {
+                throw new StatusException("160006", "姓名不能为空串");
+            }
+            student.setName(studentInfo.getName());
+        }
+        if (null != studentInfo.getPhotoPath()) {
+            student.setPhotoPath(studentInfo.getPhotoPath());
+        }
+        if (null != studentInfo.getPhoneNumber()) {
+            student.setPhoneNumber(studentInfo.getPhoneNumber());
+        }
+        if (null != studentInfo.getRemark()) {
+            student.setRemark(studentInfo.getRemark());
+        }
+        if (null != studentInfo.getEnable()) {
+            student.setEnable(studentInfo.getEnable());
+        }
+        StudentEntity saved = studentRepo.saveAndFlush(student);
+
+        List<String> studentCodeList = studentInfo.getStudentCodeList();
+        if (CollectionUtils.isNotEmpty(studentCodeList)) {
+
+            if (5 < studentCodeList.size()) {
+                throw new StatusException("160019", "身份证绑定的学号数量不能超过5个");
+            }
+
+            for (String studentCode : studentCodeList) {
+                if (StringUtils.isBlank(studentCode)) {
+                    continue;
+                }
+                StudentCodeEntity studentCodeEntity = studentCodeRepo
+                        .findByStudentCodeAndRootOrgId(studentCode, rootOrgId);
+
+                if (null != studentCodeEntity) {
+                    if (!studentCodeEntity.getIdentityNumber().equalsIgnoreCase(identityNumber)) {
+                        throw new StatusException("160008", "学号被占用. 学号: " + studentCode);
+                    }
+                } else {
+                    studentCodeEntity = new StudentCodeEntity();
+                    studentCodeEntity.setIdentityNumber(identityNumber);
+                    studentCodeEntity.setRootOrgId(rootOrgId);
+                    studentCodeEntity.setStudentCode(studentCode);
+                    studentCodeEntity.setStudentId(saved.getId());
+
+                    studentCodeRepo.save(studentCodeEntity);
+                }
+
+            }
+        }
+
+        List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo
+                .findByStudentId(saved.getId());
+
+        if (5 < studentCodeEntityList.size()) {
+            throw new StatusException("160018", "身份证绑定的学号数量不能超过5个");
+        }
+
+        List<String> lastStudentCodeList = Lists.newArrayList();
+        for (StudentCodeEntity cur : studentCodeEntityList) {
+            lastStudentCodeList.add(cur.getStudentCode());
+        }
+
+        // 同步操作
+        if (updateTime != saved.getUpdateTime().getTime()) {
+            SyncStudentReq req = new SyncStudentReq();
+            req.setEnable(saved.getEnable());
+            req.setId(saved.getId());
+            req.setIdentityNumber(saved.getIdentityNumber());
+            req.setName(saved.getName());
+            req.setOrgCode(org.getCode());
+            req.setOrgId(org.getId());
+            req.setOrgName(org.getName());
+            req.setPhoneNumber(saved.getPhoneNumber());
+            req.setPhotoPath(saved.getPhotoPath());
+            req.setRootOrgId(saved.getRootOrgId());
+            req.setSecurityPhone(saved.getSecurityPhone());
+            req.setStudentCodeList(lastStudentCodeList);
+
+            req.setSyncType("update");
+
+            dataSyncCloudService.syncStudent(req);
+        }
+
+        studentCache.remove(saved.getId());
+        orgCache.remove(org.getId());
+
+        return saved;
+    }
+
+    /*
+     * 实现
+     *
+     * @author WANGWEI
+     *
+     * @see
+     * cn.com.qmth.examcloud.core.basic.service.StudentService#getStudentInfo(
+     * java.lang.Long, java.lang.String, java.lang.String, java.lang.String)
+     */
+    @Override
+    public StudentInfo getStudentInfo(Long rootOrgId, Long studentId, String identityNumber,
+                                      String studentCode, String securityPhone) {
+
+        StudentEntity s = null;
+        int count = 0;
+        if (null != studentId) {
+            count++;
+            s = GlobalHelper.getEntity(studentRepo, studentId, StudentEntity.class);
+        } else if (StringUtils.isNotBlank(securityPhone)) {
+            count++;
+            s = studentRepo.findBySecurityPhone(securityPhone);
+        } else if (null == rootOrgId) {
+            throw new StatusException("160250", "rootOrgId is null");
+        }
+
+        if (StringUtils.isNotBlank(identityNumber)) {
+            count++;
+            s = studentRepo.findByIdentityNumberAndRootOrgId(identityNumber, rootOrgId);
+        }
+        if (StringUtils.isNotBlank(studentCode)) {
+            count++;
+
+            StudentCodeEntity studentCodeEntity = studentCodeRepo
+                    .findByStudentCodeAndRootOrgId(studentCode, rootOrgId);
+            if (null != studentCodeEntity) {
+                s = GlobalHelper.getEntity(studentRepo, studentCodeEntity.getStudentId(),
+                        StudentEntity.class);
+            }
+        }
+
+        if (count > 1) {
+            throw new StatusException("160210",
+                    "参数过多,只需要[studentId,identityNumber,studentCode,securityPhone]中的一个");
+        }
+
+        if (null == s) {
+            throw new StatusException("160211", "学生不存在");
+        }
+
+        StudentInfo info = new StudentInfo();
+        info.setId(s.getId());
+        info.setEnable(s.getEnable());
+        info.setIdentityNumber(s.getIdentityNumber());
+        info.setName(s.getName());
+        info.setOrgId(s.getOrgId());
+        if (null != s.getOrgId()) {
+            OrgEntity org = GlobalHelper.getEntity(orgRepo, s.getOrgId(), OrgEntity.class);
+            if (null != org) {
+                info.setOrgCode(org.getCode());
+                info.setOrgName(org.getName());
+            }
+        }
+        info.setPhoneNumber(s.getPhoneNumber());
+
+        if (StringUtils.isNotBlank(s.getPhotoPath())) {
+            //			String upyunDomain = PropertyHolder.getString("$upyun.site.1.domain");
+            //			if (StringUtils.isBlank(upyunDomain)) {
+            //				throw new StatusException("560111",
+            //						"property[$upyun.site.1.domain] is not configured");
+            //			}
+            //			String path = UrlUtil.joinUrl(upyunDomain, "student_base_photo", s.getPhotoPath());
+            //			info.setPhotoPath(path);
+            //通用存储
+            info.setPhotoPath(FileStorageUtil.realPath(FileStorageUtil.getIntactPath("student_base_photo", s.getPhotoPath())));
+        }
+
+        info.setRemark(s.getRemark());
+        info.setRootOrgId(s.getRootOrgId());
+        OrgEntity rootOrg = GlobalHelper.getEntity(orgRepo, s.getRootOrgId(), OrgEntity.class);
+        info.setRootOrgName(rootOrg.getName());
+        info.setSecurityPhone(s.getSecurityPhone());
+
+        List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo.findByStudentId(s.getId());
+
+        List<String> studentCodeList = Lists.newArrayList();
+        for (StudentCodeEntity cur : studentCodeEntityList) {
+            studentCodeList.add(cur.getStudentCode());
+        }
+        info.setStudentCodeList(studentCodeList);
+
+        return info;
+    }
+
+    @Override
+    public List<Long> unbindStudentCode(Long rootOrgId, String studentCode, String identityNumber) {
+
+        if (null == rootOrgId) {
+            throw new StatusException("120001", "rootOrgId is null");
+        }
+
+        // 更新的学生集合
+        List<StudentEntity> studentList = Lists.newArrayList();
+        // 解绑的学号集合
+        Map<Long, List<String>> unboundStudentCodeMap = Maps.newHashMap();
+
+        StudentEntity s1 = null;
+        StudentEntity s2 = null;
+        if (null != studentCode) {
+            StudentCodeEntity sc = studentCodeRepo.findByStudentCodeAndRootOrgId(studentCode,
+                    rootOrgId);
+            if (null != sc) {
+                studentCodeRepo.delete(sc);
+                s1 = GlobalHelper.getEntity(studentRepo, sc.getStudentId(), StudentEntity.class);
+                studentList.add(s1);
+                List<String> unboundStudentCodeList = Lists.newArrayList();
+                unboundStudentCodeList.add(sc.getStudentCode());
+                unboundStudentCodeMap.put(s1.getId(), unboundStudentCodeList);
+            }
+        }
+
+        if (null != identityNumber) {
+            s2 = studentRepo.findByIdentityNumberAndRootOrgId(identityNumber, rootOrgId);
+            if (null != s2) {
+                if (null == s1 || !s1.getId().equals(s2.getId())) {
+                    studentList.add(s2);
+                }
+
+                List<StudentCodeEntity> scList = studentCodeRepo.findByStudentId(s2.getId());
+                studentCodeRepo.deleteAll(scList);
+
+                List<String> unboundStudentCodeList = unboundStudentCodeMap.get(s2.getId());
+                if (null == unboundStudentCodeList) {
+                    unboundStudentCodeList = Lists.newArrayList();
+                    unboundStudentCodeMap.put(s2.getId(), unboundStudentCodeList);
+                }
+                for (StudentCodeEntity cur : scList) {
+                    unboundStudentCodeList.add(cur.getStudentCode());
+                }
+            }
+        }
+
+        List<Long> studentIdList = Lists.newArrayList();
+
+        for (StudentEntity cur : studentList) {
+            studentIdList.add(cur.getId());
+
+            SyncStudentReq req = new SyncStudentReq();
+            req.setEnable(cur.getEnable());
+            req.setId(cur.getId());
+            req.setIdentityNumber(cur.getIdentityNumber());
+            req.setName(cur.getName());
+
+            req.setOrgId(cur.getOrgId());
+            OrgEntity org = GlobalHelper.getEntity(orgRepo, cur.getOrgId(), OrgEntity.class);
+            req.setOrgCode(org.getCode());
+            req.setOrgName(org.getName());
+
+            req.setPhoneNumber(cur.getPhoneNumber());
+            req.setPhotoPath(cur.getPhotoPath());
+            req.setRootOrgId(cur.getRootOrgId());
+            req.setSecurityPhone(cur.getSecurityPhone());
+
+            List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo
+                    .findByStudentId(cur.getId());
+
+            List<String> lastStudentCodeList = Lists.newArrayList();
+            for (StudentCodeEntity sc : studentCodeEntityList) {
+                lastStudentCodeList.add(sc.getStudentCode());
+            }
+
+            req.setStudentCodeList(lastStudentCodeList);
+
+            List<String> unboundStudentCodeList = unboundStudentCodeMap.get(cur.getId());
+            req.setUnboundStudentCodeList(unboundStudentCodeList);
+
+            req.setSyncType("update");
+
+            dataSyncCloudService.syncStudent(req);
+        }
+
+        for (Long cur : studentIdList) {
+            studentCache.remove(cur);
+        }
+
+        return studentIdList;
+    }
+
+    @Override
+    public void unbindSecurityPhone(Long studentId) {
+
+        StudentEntity s = GlobalHelper.getEntity(studentRepo, studentId, StudentEntity.class);
+        if (null == s) {
+            throw new StatusException("450110", "学生不存在");
+        }
+        s.setSecurityPhone(null);
+        StudentEntity saved = studentRepo.save(s);
+
+        SyncStudentReq req = new SyncStudentReq();
+        req.setEnable(saved.getEnable());
+        req.setId(saved.getId());
+        req.setIdentityNumber(saved.getIdentityNumber());
+        req.setName(saved.getName());
+
+        req.setOrgId(saved.getOrgId());
+        OrgEntity org = GlobalHelper.getEntity(orgRepo, saved.getOrgId(), OrgEntity.class);
+        req.setOrgCode(org.getCode());
+        req.setOrgName(org.getName());
+
+        req.setPhoneNumber(saved.getPhoneNumber());
+        req.setPhotoPath(saved.getPhotoPath());
+        req.setRootOrgId(saved.getRootOrgId());
+        req.setSecurityPhone(saved.getSecurityPhone());
+
+        List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo
+                .findByStudentId(saved.getId());
+        List<String> lastStudentCodeList = Lists.newArrayList();
+        for (StudentCodeEntity sc : studentCodeEntityList) {
+            lastStudentCodeList.add(sc.getStudentCode());
+        }
+        req.setStudentCodeList(lastStudentCodeList);
+
+        req.setSyncType("update");
+
+        dataSyncCloudService.syncStudent(req);
+
+        studentCache.remove(studentId);
+    }
+
+    @Override
+    public Boolean hasBeBound(String securityPhone) {
+        StudentEntity s = studentRepo.findBySecurityPhone(securityPhone);
+        return null != s;
+    }
+
+    @Override
+    public Map<Long, StudentEntity> getStudentMapsByIds(Set<Long> studentIds) {
+        if (CollectionUtils.isEmpty(studentIds)) {
+            return new HashMap<>();
+        }
+
+        Specification<StudentEntity> spec = (root, query, cb) -> {
+            List<Predicate> predicates = new ArrayList<>();
+            predicates.add(root.get("id").in(studentIds));
+            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
+        };
+
+        List<StudentEntity> entities = studentRepo.findAll(spec);
+        return entities.stream().collect(Collectors.toMap(v -> v.getId(), v -> v, (k, v) -> v));
+    }
 
 }

+ 7 - 7
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/UserDataRuleServiceImpl.java

@@ -3,8 +3,6 @@ package cn.com.qmth.examcloud.core.basic.service.impl;
 import cn.com.qmth.examcloud.api.commons.enums.DataRuleType;
 import cn.com.qmth.examcloud.api.commons.security.enums.RoleMeta;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
-import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
 import cn.com.qmth.examcloud.core.basic.dao.CourseRepo;
 import cn.com.qmth.examcloud.core.basic.dao.OrgRepo;
 import cn.com.qmth.examcloud.core.basic.dao.UserDataRuleRepo;
@@ -24,6 +22,8 @@ import cn.com.qmth.examcloud.examwork.api.response.GetExamMapsResp;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.*;
 import org.springframework.data.jpa.domain.Specification;
@@ -36,7 +36,7 @@ import java.util.stream.Collectors;
 @Service
 public class UserDataRuleServiceImpl implements UserDataRuleService {
 
-    private static final ExamCloudLog log = ExamCloudLogFactory.getLog("INTERFACE_LOGGER");
+    private static final Logger LOG = LoggerFactory.getLogger(UserDataRuleServiceImpl.class);
 
     private static final String DATA_RULE_CACHE_KEY = "$DATA_RULE:%s_%s";//“数据权限”的缓存KEY规则
 
@@ -257,13 +257,13 @@ public class UserDataRuleServiceImpl implements UserDataRuleService {
         Map<Long, Long> targetUserMaps = new HashMap<>();
         for (Long targetUserId : req.getTargetUserIds()) {
             if (targetUserId.equals(req.getSourceUserId())) {
-                log.warn(String.format("跳过复制,targetUserId与sourceUserId相同... id = %s", targetUserId));
+                LOG.warn(String.format("跳过复制,targetUserId与sourceUserId相同... id = %s", targetUserId));
                 continue;
             }
 
             Optional<UserEntity> targetUser = userRepo.findById(targetUserId);
             if (!targetUser.isPresent()) {
-                log.warn(String.format("User is not exist... targetUserId = %s", targetUserId));
+                LOG.warn(String.format("User is not exist... targetUserId = %s", targetUserId));
                 continue;
             }
 
@@ -438,8 +438,8 @@ public class UserDataRuleServiceImpl implements UserDataRuleService {
             refIds.add(rule.getRefId());
         }
 
-        if (log.isInfoEnabled()) {
-            log.info(String.format("userId = %s, dataRuleType = %s, globalStatus = %s, refIds = [%s]",
+        if (LOG.isInfoEnabled()) {
+            LOG.info(String.format("userId = %s, dataRuleType = %s, globalStatus = %s, refIds = [%s]",
                     userId, type.name(), cacheBean.getGlobalStatus(), StringUtils.join(refIds, ",")));
         }
 

+ 6 - 6
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/VerifyCodeServiceImpl.java

@@ -3,8 +3,6 @@ package cn.com.qmth.examcloud.core.basic.service.impl;
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
 import cn.com.qmth.examcloud.api.commons.security.bean.UserType;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
-import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
 import cn.com.qmth.examcloud.commons.util.UUID;
 import cn.com.qmth.examcloud.core.basic.base.util.VerifyCode;
 import cn.com.qmth.examcloud.core.basic.dao.enums.LoginRuleType;
@@ -22,6 +20,8 @@ import cn.com.qmth.examcloud.reports.commons.util.ReportsUtil;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -31,7 +31,7 @@ import org.springframework.stereotype.Service;
 @Service
 public class VerifyCodeServiceImpl implements VerifyCodeService {
 
-    private static final ExamCloudLog log = ExamCloudLogFactory.getLog("INTERFACE_LOGGER");
+    private static final Logger LOG = LoggerFactory.getLogger(VerifyCodeServiceImpl.class);
 
     private static final String CACHE_KEY_VERIFY_CODE = "B_VERIFY_CODE:%s_%s";// “验证码”缓存KEY
 
@@ -110,7 +110,7 @@ public class VerifyCodeServiceImpl implements VerifyCodeService {
         String base64 = Base64.encodeBase64String(bytes);
         String uuid = UUID.randomUUID();
 
-        log.info(String.format("accountValue = %s, uuid = %s, verifyCode = %s", accountValue, uuid, result.getResult()));
+        LOG.info(String.format("accountValue = %s, uuid = %s, verifyCode = %s", accountValue, uuid, result.getResult()));
         VerifyCodeCacheBean cacheBean = new VerifyCodeCacheBean();
         cacheBean.setUuid(uuid);
         cacheBean.setVerifyCode(result.getResult());
@@ -159,7 +159,7 @@ public class VerifyCodeServiceImpl implements VerifyCodeService {
         final String cacheKeyVerifyCodeResource = String.format(CACHE_KEY_VERIFY_CODE_RESOURCE, cacheBean.getUuid());
         Boolean resource = redisClient.get(cacheKeyVerifyCodeResource, Boolean.class);
         if (resource == null) {
-            log.warn(String.format("accountValue = %s, uuid = %s, Real uuid = %s", info.getAccountValue(), info.getUuid(), cacheBean.getUuid()));
+            LOG.warn(String.format("accountValue = %s, uuid = %s, Real uuid = %s", info.getAccountValue(), info.getUuid(), cacheBean.getUuid()));
             throw new StatusException("400", "验证码请求无效,请重试!");
         }
 
@@ -195,7 +195,7 @@ public class VerifyCodeServiceImpl implements VerifyCodeService {
     @Override
     public void verifyCodeResource(String uuid) {
         if (StringUtils.isBlank(uuid) || uuid.length() != 32) {
-            log.debug("Invalid uuid... " + uuid);
+            LOG.debug("Invalid uuid... " + uuid);
             return;
         }
 

+ 3 - 2
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/report/RocketMqConsumerListener.java

@@ -22,7 +22,8 @@ import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
 import cn.com.qmth.examcloud.web.support.SpringContextHolder;
 
 public class RocketMqConsumerListener {
-    private final static Logger logger = LoggerFactory.getLogger(RocketMqConsumerListener.class);
+    private static final Logger LOG = LoggerFactory.getLogger(RocketMqConsumerListener.class);
+
     private static AdminOperateService adminOperateService = SpringContextHolder.getBean(AdminOperateService.class);
     private static Properties properties = new Properties();
 
@@ -55,7 +56,7 @@ public class RocketMqConsumerListener {
                     onMessageAdminOperate(msg,message.getMsgID());
                     return Action.CommitMessage;
                 } catch (Exception e) {
-                    logger.error("consumer failed MsgID:" + message.getMsgID(), e);
+                    LOG.error("consumer failed MsgID:" + message.getMsgID(), e);
                     return Action.ReconsumeLater;
                 }
             }

+ 67 - 61
examcloud-core-basic-starter/pom.xml

@@ -1,67 +1,73 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<groupId>cn.com.qmth.examcloud.core.basic</groupId>
-		<artifactId>examcloud-core-basic</artifactId>
-		<version>v4.0.2-RELEASE</version>
-	</parent>
-	<artifactId>examcloud-core-basic-starter</artifactId>
-	<packaging>jar</packaging>
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>examcloud-core-basic-starter</artifactId>
+    <packaging>jar</packaging>
 
-	<dependencies>
-		<dependency>
-			<groupId>cn.com.qmth.examcloud.core.basic</groupId>
-			<artifactId>examcloud-core-basic-api-provider</artifactId>
-			<version>${examcloud.version}</version>
-		</dependency>
-	</dependencies>
+    <parent>
+        <groupId>cn.com.qmth.examcloud</groupId>
+        <artifactId>examcloud-core-basic</artifactId>
+        <version>${revision}</version>
+    </parent>
 
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-jar-plugin</artifactId>
-				<configuration>
-					<archive>
-						<manifest>
-							<mainClass>cn.com.qmth.examcloud.core.basic.starter.CoreBasicApp</mainClass>
-							<addClasspath>true</addClasspath>
-							<classpathPrefix>./</classpathPrefix>
-						</manifest>
-						<manifestEntries>
-							<Class-Path>../config/</Class-Path>
-						</manifestEntries>
-					</archive>
-					<excludes>
-						<exclude>templates/*</exclude>
-						<exclude>*.properties</exclude>
-						<exclude>*.xml </exclude>
-						<exclude>classpath.location</exclude>
-					</excludes>
-				</configuration>
-			</plugin>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-assembly-plugin</artifactId>
-				<configuration>
-					<finalName>examcloud-core-basic</finalName>
-					<descriptors>
-						<descriptor>assembly.xml</descriptor>
-					</descriptors>
-				</configuration>
-				<executions>
-					<execution>
-						<id>make-assembly</id>
-						<phase>install</phase>
-						<goals>
-							<goal>assembly</goal>
-						</goals>
-					</execution>
-				</executions>
-			</plugin>
-		</plugins>
-	</build>
+    <dependencies>
+        <dependency>
+            <groupId>cn.com.qmth.examcloud</groupId>
+            <artifactId>examcloud-core-basic-api-provider</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>cn.com.qmth.examcloud.core.basic.starter.CoreBasicApp</mainClass>
+                            <addClasspath>true</addClasspath>
+                            <classpathPrefix>./</classpathPrefix>
+                        </manifest>
+                        <manifestEntries>
+                            <Class-Path>../config/</Class-Path>
+                        </manifestEntries>
+                    </archive>
+                    <excludes>
+                        <exclude>templates/*</exclude>
+                        <exclude>*.properties</exclude>
+                        <exclude>*.xml</exclude>
+                        <exclude>classpath.location</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <finalName>examcloud-core-basic</finalName>
+                    <descriptors>
+                        <descriptor>assembly.xml</descriptor>
+                    </descriptors>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>make-assembly</id>
+                        <phase>install</phase>
+                        <goals>
+                            <goal>assembly</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>

+ 1 - 1
examcloud-core-basic-starter/shell/start.args

@@ -1 +1 @@
---spring.profiles.active=dev --examcloud.startup.configCenterHost=192.168.10.39
+--spring.profiles.active=dev --sys.config.center.address=192.168.10.39:8888

+ 8 - 27
examcloud-core-basic-starter/shell/start.sh

@@ -1,38 +1,19 @@
 #!/bin/bash
 
-FILE_PATH=$(cd `dirname $0`; pwd)
+PROJECT_JAR="examcloud-core-basic-starter-v4.1.0-SNAPSHOT.jar"
 
-APP_MAIN_JAR="examcloud-core-basic-starter-v4.0.2-RELEASE.jar"
+PROJECT_JVM_ARGS=`cat start.vmoptions`
 
-JAVA_OPTS=`cat $FILE_PATH/start.vmoptions`
-APP_ARGS=`cat $FILE_PATH/start.args`
+PROJECT_ARGS=`cat start.args`
 
-PID_LIST=`ps -ef|grep $APP_MAIN_JAR|grep java|awk '{print $2}'`
+PROJECT_ARGS=$PROJECT_ARGS" --sys.config.center.secretKey="$1
 
+PID_LIST=`ps -ef | grep $PROJECT_JAR | grep java | awk '{print $2}'`
 if [ ! -z "$PID_LIST" ]; then
-    echo "[ERROR] : APP is already running!"
+    echo "$PROJECT_JAR is already running..."
     exit -1
 fi
 
-if [ "$1" ];then
-    echo "startupCode:"$1;
-else
-    echo "[ERROR] : no arguments"
-    exit -1
-fi
-
-APP_ARGS=$APP_ARGS" --examcloud.startup.startupCode="$1
-
-echo "java options:"
-echo "$JAVA_OPTS"
-echo "args:"
-echo "$APP_ARGS"
-    
-nohup java $JAVA_OPTS -jar $FILE_PATH/lib/$APP_MAIN_JAR $APP_ARGS >/dev/null 2>&1 &
-
-echo "starting......"
-
-exit 0
-
-
+nohup java $PROJECT_JVM_ARGS -jar lib/$PROJECT_JAR $PROJECT_ARGS >/dev/null 2>&1 &
 
+echo "$PROJECT_JAR start..."

+ 4 - 14
examcloud-core-basic-starter/shell/stop.sh

@@ -1,18 +1,8 @@
 #!/bin/bash
 
-FILE_PATH=$(cd `dirname $0`; pwd)
+PROJECT_JAR="examcloud-core-basic-starter-v4.1.0-SNAPSHOT.jar"
 
-APP_MAIN_JAR="examcloud-core-basic-starter-v4.0.2-RELEASE.jar"
+ps -ef | grep $PROJECT_JAR | grep java | awk '{printf("kill -15 %s\n",$2)}' | sh
+BUILD_ID=DONTKILLME
 
-PID_LIST=`ps -ef|grep $APP_MAIN_JAR|grep java|awk '{print $2}'`
-
-if [ ! -z "$PID_LIST" ]; then
-    echo "Runnable jar is $APP_MAIN_JAR."
-    for PID in $PID_LIST 
-    do
-        kill -9 $PID
-    done
-    echo "stopped !"
-fi
-
-exit 0
+echo "$PROJECT_JAR stop..."

+ 5 - 18
examcloud-core-basic-starter/src/main/java/cn/com/qmth/examcloud/core/basic/starter/CoreBasicApp.java

@@ -5,11 +5,10 @@ import cn.com.qmth.examcloud.core.basic.dao.enums.OrgProperty;
 import cn.com.qmth.examcloud.core.basic.service.LoginRuleService;
 import cn.com.qmth.examcloud.core.basic.service.cache.AppCache;
 import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
-import cn.com.qmth.examcloud.web.bootstrap.AppBootstrap;
 import cn.com.qmth.examcloud.web.jpa.DataIntegrityViolationTransverter;
 import cn.com.qmth.examcloud.web.support.SpringContextHolder;
 import org.apache.logging.log4j.ThreadContext;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.domain.EntityScan;
 import org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration;
@@ -24,7 +23,6 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
 import org.springframework.web.multipart.MultipartResolver;
 import org.springframework.web.multipart.commons.CommonsMultipartResolver;
 
-@SpringBootApplication
 @Configuration
 @EnableJpaAuditing
 @EnableTransactionManagement
@@ -33,12 +31,11 @@ import org.springframework.web.multipart.commons.CommonsMultipartResolver;
 @ComponentScan(basePackages = {"cn.com.qmth"})
 @EntityScan(basePackages = {"cn.com.qmth"})
 @EnableJpaRepositories(basePackages = {"cn.com.qmth"})
-@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
+@SpringBootApplication(exclude = {MultipartAutoConfiguration.class})
 public class CoreBasicApp {
 
     static {
-        String runtimeLevel = System.getProperty("log.commonLevel");
-        if (null == runtimeLevel) {
+        if (System.getProperty("log.commonLevel") == null) {
             System.setProperty("log.commonLevel", "INFO");
         }
         System.setProperty("hibernate.dialect.storage_engine", "innodb");
@@ -55,22 +52,12 @@ public class CoreBasicApp {
      * @author WANGWEI
      */
     public static void main(String[] args) throws Exception {
-        AppBootstrap.run(CoreBasicApp.class, args);
+        // AppBootstrap.run(CoreBasicApp.class, args);
+        SpringApplication.run(CoreBasicApp.class, args);
 
         initCache();
         FileStorageUtil.initYunSite();
         FileStorageUtil.initYunClient();
-        // test();
-    }
-
-    /**
-     * 测试方法
-     *
-     * @author WANGWEI
-     */
-    private static void test() {
-        Tester tester = SpringContextHolder.getBean(Tester.class);
-        tester.test();
     }
 
     /**

+ 5 - 5
examcloud-core-basic-starter/src/main/java/cn/com/qmth/examcloud/core/basic/starter/config/ExamCloudResourceManager.java

@@ -3,7 +3,6 @@ package cn.com.qmth.examcloud.core.basic.starter.config;
 import cn.com.qmth.examcloud.api.commons.enums.DataRuleType;
 import cn.com.qmth.examcloud.api.commons.security.bean.*;
 import cn.com.qmth.examcloud.api.commons.security.enums.RoleMeta;
-import cn.com.qmth.examcloud.commons.util.PropertiesUtil;
 import cn.com.qmth.examcloud.commons.util.RegExpUtil;
 import cn.com.qmth.examcloud.core.basic.api.UserDataRuleCloudService;
 import cn.com.qmth.examcloud.core.basic.api.request.QueryUserDataRuleReq;
@@ -12,6 +11,7 @@ import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.AppCacheBean;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
 import cn.com.qmth.examcloud.web.security.ResourceManager;
+import cn.com.qmth.examcloud.web.security.SecurityProperty;
 import cn.com.qmth.examcloud.web.support.ApiInfo;
 import com.google.common.collect.Sets;
 import org.apache.commons.collections4.CollectionUtils;
@@ -39,7 +39,7 @@ public class ExamCloudResourceManager implements ResourceManager {
     UserDataRuleCloudService userDataRuleCloudService;
 
     static {
-        PropertiesUtil.loadFromResource("security.properties");
+        SecurityProperty.loadProperties("security.properties");
     }
 
     @Override
@@ -82,7 +82,7 @@ public class ExamCloudResourceManager implements ResourceManager {
         // 学生鉴权
         if (user.getUserType().equals(UserType.STUDENT)) {
             String key = "[s]" + mapping;
-            return PropertiesUtil.getBoolean(key, false);
+            return SecurityProperty.getBooleanProperty(key, false);
         }
 
         List<Role> roleList = user.getRoleList();
@@ -98,8 +98,8 @@ public class ExamCloudResourceManager implements ResourceManager {
         }
 
         // 权限组集合
-        String privilegeGroups = PropertiesUtil.getString(mapping);
-        if (StringUtils.isBlank(privilegeGroups)) {
+        String privilegeGroups = SecurityProperty.getProperty(mapping);
+        if (StringUtils.isEmpty(privilegeGroups)) {
             return true;
         }
 

+ 3 - 2
examcloud-core-basic-starter/src/main/java/cn/com/qmth/examcloud/core/basic/starter/config/MqConsumerListenerStartup.java

@@ -14,7 +14,8 @@ import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
 @Component
 @Order(999)
 public class MqConsumerListenerStartup implements ApplicationRunner {
-	private final static Logger logger = LoggerFactory.getLogger(MqConsumerListenerStartup.class);
+	private static final Logger LOG = LoggerFactory.getLogger(MqConsumerListenerStartup.class);
+
 	private void startConsumerListener() {
 
 		String mqType = PropertyHolder.getString("$report.mq-type");
@@ -25,7 +26,7 @@ public class MqConsumerListenerStartup implements ApplicationRunner {
 			if(MqType.ROCKETMQ.getCode().equals(mqType)) {
 				RocketMqConsumerListener.start();
 			}else {
-				logger.error("no $report.mq-type property config!");
+				LOG.error("no $report.mq-type property config!");
 			}
 		}
 

+ 2 - 2
examcloud-core-basic-starter/src/main/java/cn/com/qmth/examcloud/core/basic/starter/config/Swagger2.java

@@ -10,10 +10,10 @@ import springfox.documentation.service.ApiInfo;
 import springfox.documentation.service.Contact;
 import springfox.documentation.spi.DocumentationType;
 import springfox.documentation.spring.web.plugins.Docket;
-import springfox.documentation.swagger2.annotations.EnableSwagger2;
+import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
 
 @Configuration
-@EnableSwagger2
+@EnableSwagger2WebMvc
 public class Swagger2 {
 
 	@Bean

+ 5 - 7
examcloud-core-basic-starter/src/main/resources/application.properties

@@ -1,8 +1,6 @@
 spring.profiles.active=dev
-
-examcloud.startup.startupCode=8000
-examcloud.startup.configCenterHost=192.168.10.39
-examcloud.startup.configCenterPort=9999
-examcloud.startup.appCode=B
-
-
+sys.config.center.enabled=true
+sys.config.center.address=192.168.10.39:8888
+sys.config.center.namespace=examcloud
+sys.config.center.appCode=B
+sys.config.center.secretKey=

+ 0 - 1
examcloud-core-basic-starter/src/main/resources/classpath.location

@@ -1 +0,0 @@
-classpath 定位文件

+ 44 - 58
examcloud-core-basic-starter/src/main/resources/log4j2.xml

@@ -2,47 +2,32 @@
 <Configuration status="WARN" monitorInterval="30">
 
     <Properties>
-        <Property name="commonLevel" value="${sys:log.commonLevel}"/>
-        <Property name="logPattern">
+        <Property name="LOG_LEVEL" value="${sys:log.commonLevel}"/>
+        <Property name="LOG_DIR" value="../logs/examcloud-core-basic"/>
+        <Property name="STUDENT_CLIENT_LOG_DIR" value="../logs/student-client"/>
+        <Property name="LOG_PATTERN">
             %d{yyyy-MM-dd HH:mm:ss.SSS} | %clr{%level} | %X{TRACE_ID} %X{CALLER} | %clr{%c{1.1}:%L}{cyan} | %m%n
         </Property>
     </Properties>
 
     <Appenders>
-        <!-- 控制台 日志 -->
-        <Console name="Console" target="SYSTEM_OUT">
-            <PatternLayout pattern="${logPattern}" charset="UTF-8"/>
+        <Console name="CONSOLE_APPENDER" target="SYSTEM_OUT">
+            <PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
         </Console>
 
-        <!-- debug 日志 -->
-        <RollingFile name="DEBUG_APPENDER"
-                     fileName="./logs/debug/debug.log"
-                     filePattern="./logs/debug/debug-%d{yyyy.MM.dd.HH}-%i.log">
-            <PatternLayout pattern="${logPattern}" charset="UTF-8"/>
-            <Policies>
-                <TimeBasedTriggeringPolicy interval="1" modulate="false"/>
-                <SizeBasedTriggeringPolicy size="100 MB"/>
-            </Policies>
-            <DefaultRolloverStrategy max="1000">
-                <Delete basePath="./logs/debug" maxDepth="1">
-                    <IfFileName glob="debug-*.log">
-                        <IfAccumulatedFileSize exceeds="2 GB"/>
-                    </IfFileName>
-                </Delete>
-            </DefaultRolloverStrategy>
-        </RollingFile>
+        <RollingFile name="FILE_APPENDER"
+                     fileName="${LOG_DIR}/debug.log"
+                     filePattern="${LOG_DIR}/debug-%d{yyyyMMdd}-%i.log">
+            <PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
 
-        <!-- 接口日志 -->
-        <RollingFile name="INTERFACE_APPENDER" fileName="./logs/interface/interface.log"
-                     filePattern="./logs/interface/interface-%d{yyyy.MM.dd.HH}-%i.log">
-            <PatternLayout pattern="${logPattern}" charset="UTF-8"/>
             <Policies>
                 <TimeBasedTriggeringPolicy interval="1" modulate="false"/>
                 <SizeBasedTriggeringPolicy size="100 MB"/>
             </Policies>
+
             <DefaultRolloverStrategy max="1000">
-                <Delete basePath="./logs/interface" maxDepth="1">
-                    <IfFileName glob="interface-*.log">
+                <Delete basePath="${LOG_DIR}" maxDepth="1">
+                    <IfFileName glob="debug-*.log">
                         <IfAccumulatedFileSize exceeds="10 GB"/>
                     </IfFileName>
                 </Delete>
@@ -50,17 +35,20 @@
         </RollingFile>
 
         <!-- 考生客户端日志 -->
-        <RollingFile name="STUDENT_CLIENT_APPENDER" fileName="./logs/student_client/student_client.log"
-                     filePattern="./logs/student_client/student_client-%d{yyyy.MM.dd}-%i.log">
-            <PatternLayout pattern="${logPattern}" charset="UTF-8"/>
+        <RollingFile name="STUDENT_CLIENT_APPENDER"
+                     fileName="${STUDENT_CLIENT_LOG_DIR}/debug.log"
+                     filePattern="${STUDENT_CLIENT_LOG_DIR}/debug-%d{yyyyMMdd}-%i.log">
+            <PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
+
             <Policies>
                 <TimeBasedTriggeringPolicy interval="1" modulate="false"/>
                 <SizeBasedTriggeringPolicy size="100 MB"/>
             </Policies>
+
             <DefaultRolloverStrategy max="1000">
-                <Delete basePath="./logs/student_client" maxDepth="1">
-                    <IfFileName glob="student_client-*.log">
-                        <IfAccumulatedFileSize exceeds="5 GB"/>
+                <Delete basePath="${STUDENT_CLIENT_LOG_DIR}" maxDepth="1">
+                    <IfFileName glob="debug-*.log">
+                        <IfAccumulatedFileSize exceeds="10 GB"/>
                     </IfFileName>
                 </Delete>
             </DefaultRolloverStrategy>
@@ -68,40 +56,38 @@
     </Appenders>
 
     <Loggers>
-        <logger name="springfox.documentation" level="ERROR"/>
-        <logger name="org.springframework" level="ERROR"/>
-        <logger name="org.hibernate" level="ERROR"/>
-        <logger name="org.apache" level="ERROR"/>
-        <logger name="org.quartz" level="ERROR"/>
-        <logger name="org.docx4j" level="ERROR"/>
-        <logger name="cn.afterturn" level="ERROR"/>
-        <logger name="com.netflix" level="ERROR"/>
-        <logger name="com.aliyun" level="ERROR"/>
-        <logger name="io.lettuce" level="ERROR"/>
-        <logger name="io.netty" level="ERROR"/>
+        <logger name="springfox.documentation" level="WARN"/>
+        <logger name="org.springframework" level="WARN"/>
+        <logger name="org.hibernate" level="WARN"/>
+        <logger name="org.apache" level="WARN"/>
+        <logger name="org.quartz" level="WARN"/>
+        <logger name="org.docx4j" level="WARN"/>
+        <logger name="cn.afterturn" level="WARN"/>
+        <logger name="com.netflix" level="WARN"/>
+        <logger name="com.aliyun" level="WARN"/>
+        <logger name="io.lettuce" level="WARN"/>
+        <logger name="io.netty" level="WARN"/>
 
+        <!--<Logger name="org.hibernate.SQL" level="DEBUG"/>-->
+        <!--<Logger name="org.hibernate.engine.transaction" level="DEBUG"/>-->
+        <!--<Logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>-->
         <!--<logger name="org.springframework.jdbc.core.JdbcTemplate" level="DEBUG"/>-->
         <!--<logger name="org.springframework.data.mongodb" level="DEBUG"/>-->
         <!--<logger name="org.springframework.data.redis" level="DEBUG"/>-->
 
-        <Logger name="cn.com.qmth" level="${commonLevel}" additivity="false">
-            <AppenderRef ref="DEBUG_APPENDER"/>
-            <AppenderRef ref="Console"/>
-        </Logger>
-
-        <Logger name="INTERFACE_LOGGER" level="${commonLevel}" additivity="false">
-            <AppenderRef ref="INTERFACE_APPENDER"/>
-            <AppenderRef ref="Console"/>
+        <Logger name="cn.com.qmth" level="${LOG_LEVEL}" additivity="false">
+            <AppenderRef ref="CONSOLE_APPENDER"/>
+            <AppenderRef ref="FILE_APPENDER"/>
         </Logger>
 
-        <Logger name="STUDENT_CLIENT_LOGGER" level="${commonLevel}" additivity="false">
+        <Logger name="STUDENT_CLIENT_LOGGER" level="INFO" additivity="false">
+            <AppenderRef ref="CONSOLE_APPENDER"/>
             <AppenderRef ref="STUDENT_CLIENT_APPENDER"/>
-            <AppenderRef ref="Console"/>
         </Logger>
 
-        <Root level="${commonLevel}">
-            <AppenderRef ref="Console"/>
-            <AppenderRef ref="DEBUG_APPENDER"/>
+        <Root level="${LOG_LEVEL}">
+            <AppenderRef ref="CONSOLE_APPENDER"/>
+            <AppenderRef ref="FILE_APPENDER"/>
         </Root>
     </Loggers>
 

+ 4 - 0
jenkins-prod.sh → jenkins.sh

@@ -1,4 +1,8 @@
 #!/bin/bash
+
 pwd
+mkdir -p ~/packages
 
 cp examcloud-core-basic-starter/target/examcloud-core-basic-distribution.zip ~/packages
+
+echo "finished..."

+ 2 - 3
pom.xml

@@ -2,15 +2,14 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
-    <groupId>cn.com.qmth.examcloud.core.basic</groupId>
     <artifactId>examcloud-core-basic</artifactId>
-    <version>v4.0.2-RELEASE</version>
     <packaging>pom</packaging>
 
     <parent>
         <groupId>cn.com.qmth.examcloud</groupId>
         <artifactId>examcloud-parent</artifactId>
-        <version>v4.0.2-RELEASE</version>
+        <version>${revision}</version>
+        <relativePath>../examcloud-parent/pom.xml</relativePath>
     </parent>
 
     <modules>