shenhao 5 years ago
parent
commit
0d25a050e2
100 changed files with 13326 additions and 0 deletions
  1. 26 0
      src/main/java/com/aijia/KmtApp.java
  2. 55 0
      src/main/java/com/aijia/basic/common/bean/Page.java
  3. 462 0
      src/main/java/com/aijia/basic/common/bean/SplitPage.java
  4. 56 0
      src/main/java/com/aijia/basic/config/bean/VersionConfig.java
  5. 133 0
      src/main/java/com/aijia/basic/utils/ByteUtil.java
  6. 930 0
      src/main/java/com/aijia/basic/utils/DateHelper.java
  7. 157 0
      src/main/java/com/aijia/basic/utils/EncryptUtil.java
  8. 58 0
      src/main/java/com/aijia/basic/utils/ExceptionUtil.java
  9. 56 0
      src/main/java/com/aijia/basic/utils/MD5.java
  10. 28 0
      src/main/java/com/aijia/basic/utils/PhoneVerifyUtil.java
  11. 71 0
      src/main/java/com/aijia/basic/utils/SHACoder.java
  12. 205 0
      src/main/java/com/aijia/basic/utils/StringUtils.java
  13. 13 0
      src/main/java/com/aijia/contants/AuthConstants.java
  14. 13 0
      src/main/java/com/aijia/core/security/exception/CommonException.java
  15. 20 0
      src/main/java/com/aijia/core/security/exception/ConchException.java
  16. 144 0
      src/main/java/com/aijia/core/utils/CastUtil.java
  17. 134 0
      src/main/java/com/aijia/core/utils/CodecUtil.java
  18. 381 0
      src/main/java/com/aijia/core/utils/Constant.java
  19. 249 0
      src/main/java/com/aijia/core/utils/HttpRemote.java
  20. 200 0
      src/main/java/com/aijia/core/utils/MapGetterTool.java
  21. 54 0
      src/main/java/com/aijia/core/utils/RedisConstants.java
  22. 52 0
      src/main/java/com/aijia/core/utils/StringUtil.java
  23. 90 0
      src/main/java/com/aijia/core/web/BaseController.java
  24. 24 0
      src/main/java/com/aijia/core/web/BaseRequest.java
  25. 40 0
      src/main/java/com/aijia/core/web/MyResponseConstant.java
  26. 153 0
      src/main/java/com/aijia/core/web/MyResponseEntity.java
  27. 94 0
      src/main/java/com/aijia/core/web/ResponseConstant.java
  28. 150 0
      src/main/java/com/aijia/core/web/ResponseEntity.java
  29. 21 0
      src/main/java/com/aijia/core/web/exception/RequestsException.java
  30. 22 0
      src/main/java/com/aijia/core/web/exception/TokenException.java
  31. 15 0
      src/main/java/com/aijia/kmt/annotation/IgnoreSecurity.java
  32. 15 0
      src/main/java/com/aijia/kmt/annotation/ModifySecurity.java
  33. 57 0
      src/main/java/com/aijia/kmt/common/DruidConfiguration.java
  34. 70 0
      src/main/java/com/aijia/kmt/common/EntityResultTransformer.java
  35. 132 0
      src/main/java/com/aijia/kmt/common/ExceptionAdvice.java
  36. 125 0
      src/main/java/com/aijia/kmt/common/GlobalExceptionHandler.java
  37. 36 0
      src/main/java/com/aijia/kmt/common/MapResultTransformer.java
  38. 281 0
      src/main/java/com/aijia/kmt/common/MybatisMapperRefresh.java
  39. 70 0
      src/main/java/com/aijia/kmt/common/MybatisPlusConfig.java
  40. 309 0
      src/main/java/com/aijia/kmt/common/PagingHibernateJdbcDao.java
  41. 63 0
      src/main/java/com/aijia/kmt/common/RedisConfig.java
  42. 820 0
      src/main/java/com/aijia/kmt/common/RedisTokenManager.java
  43. 65 0
      src/main/java/com/aijia/kmt/common/SpringContextHolder.java
  44. 64 0
      src/main/java/com/aijia/kmt/common/WebMvcConfig.java
  45. 191 0
      src/main/java/com/aijia/kmt/common/constant/Constant.java
  46. 182 0
      src/main/java/com/aijia/kmt/common/constant/CourseConstant.java
  47. 222 0
      src/main/java/com/aijia/kmt/common/constant/ImageTools.java
  48. 94 0
      src/main/java/com/aijia/kmt/common/constant/Knowledge2.java
  49. 13 0
      src/main/java/com/aijia/kmt/common/constant/KnowledgeConfig.java
  50. 163 0
      src/main/java/com/aijia/kmt/common/constant/KnowledgeVersion.java
  51. 54 0
      src/main/java/com/aijia/kmt/common/constant/RedisConstants.java
  52. 134 0
      src/main/java/com/aijia/kmt/common/excel/j2se/RandomUtils.java
  53. 273 0
      src/main/java/com/aijia/kmt/common/excel/j2se/ReflectUtils.java
  54. 184 0
      src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/BeanToExcel.java
  55. 483 0
      src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/CustomizeToExcel.java
  56. 34 0
      src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/Excel.java
  57. 94 0
      src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/ExcelColumn.java
  58. 27 0
      src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/ExcelDataFormatter.java
  59. 248 0
      src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/ExcelToBean.java
  60. 554 0
      src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/ExcelUtils.java
  61. 39 0
      src/main/java/com/aijia/kmt/common/excel/thirdparty/gson/GsonExclusion.java
  62. 41 0
      src/main/java/com/aijia/kmt/common/excel/thirdparty/gson/GsonKeyRename.java
  63. 113 0
      src/main/java/com/aijia/kmt/common/excel/thirdparty/gson/GsonTools.java
  64. 123 0
      src/main/java/com/aijia/kmt/common/excel/thirdparty/http/CookieUtils.java
  65. 144 0
      src/main/java/com/aijia/kmt/common/excel/thirdparty/http/HttpServletUtils.java
  66. 55 0
      src/main/java/com/aijia/kmt/common/swagger/Swagger2Config.java
  67. 57 0
      src/main/java/com/aijia/kmt/common/taskthread/AijiaThreadPool.java
  68. 34 0
      src/main/java/com/aijia/kmt/common/taskthread/Task.java
  69. 166 0
      src/main/java/com/aijia/kmt/common/taskthread/ThreadPool.java
  70. 90 0
      src/main/java/com/aijia/kmt/common/weixin/LoginWxUtil.java
  71. 74 0
      src/main/java/com/aijia/kmt/common/weixin/WeixinOauth2Token.java
  72. 253 0
      src/main/java/com/aijia/kmt/common/weixin/WeixinUtil.java
  73. 265 0
      src/main/java/com/aijia/kmt/controller/KmtExerciseController.java
  74. 51 0
      src/main/java/com/aijia/kmt/controller/KmtExerciseQuestionListController.java
  75. 94 0
      src/main/java/com/aijia/kmt/controller/KmtKnowledgeController.java
  76. 181 0
      src/main/java/com/aijia/kmt/dto/AnswerProofreadExerciseBookDTO.java
  77. 221 0
      src/main/java/com/aijia/kmt/dto/ApplyRegisterTeacherDto.java
  78. 58 0
      src/main/java/com/aijia/kmt/dto/BookDTO.java
  79. 116 0
      src/main/java/com/aijia/kmt/dto/CheckTeacherDetailDto.java
  80. 269 0
      src/main/java/com/aijia/kmt/dto/DistributionExerciseBookDTO.java
  81. 98 0
      src/main/java/com/aijia/kmt/dto/DistributionTeacherDTO.java
  82. 119 0
      src/main/java/com/aijia/kmt/dto/Exercise1Dto.java
  83. 295 0
      src/main/java/com/aijia/kmt/dto/Exercise2Dto.java
  84. 136 0
      src/main/java/com/aijia/kmt/dto/Exercise3Dto.java
  85. 36 0
      src/main/java/com/aijia/kmt/dto/Exercise4Dto.java
  86. 59 0
      src/main/java/com/aijia/kmt/dto/Exercise5Dto.java
  87. 34 0
      src/main/java/com/aijia/kmt/dto/ExerciseBaseDto.java
  88. 40 0
      src/main/java/com/aijia/kmt/dto/ExerciseBookBaseDto.java
  89. 84 0
      src/main/java/com/aijia/kmt/dto/ExerciseBookCountDTO.java
  90. 78 0
      src/main/java/com/aijia/kmt/dto/ExerciseBookCountSubjectDetailDTO.java
  91. 62 0
      src/main/java/com/aijia/kmt/dto/ExerciseBookCourseClassDto.java
  92. 111 0
      src/main/java/com/aijia/kmt/dto/ExerciseBookCourseDTO.java
  93. 191 0
      src/main/java/com/aijia/kmt/dto/ExerciseBookDto.java
  94. 34 0
      src/main/java/com/aijia/kmt/dto/ExerciseBookUnitDto.java
  95. 56 0
      src/main/java/com/aijia/kmt/dto/ExerciseDistributionCountDTO.java
  96. 55 0
      src/main/java/com/aijia/kmt/dto/ExercisePriorityDto.java
  97. 32 0
      src/main/java/com/aijia/kmt/dto/ExerciseQuestionAnswer4CorrectDTO.java
  98. 25 0
      src/main/java/com/aijia/kmt/dto/ExerciseQuestionAnswerDto.java
  99. 174 0
      src/main/java/com/aijia/kmt/dto/ExerciseQuestionDto.java
  100. 0 0
      src/main/java/com/aijia/kmt/dto/ExerciseQuestionNumberDto.java

+ 26 - 0
src/main/java/com/aijia/KmtApp.java

@@ -0,0 +1,26 @@
+package com.aijia;
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.ServletComponentScan;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+/**
+ *
+ */
+@SpringBootApplication
+@EnableDubbo
+@EnableJpaRepositories
+@ServletComponentScan(basePackages = "com.aijia.core.filter")
+class KmtApp extends SpringBootServletInitializer {
+    public static void main(String[] args) throws InterruptedException {
+        SpringApplication.run(KmtApp.class);
+    }
+
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
+        return builder.sources(KmtApp.class);
+    }
+}

+ 55 - 0
src/main/java/com/aijia/basic/common/bean/Page.java

@@ -0,0 +1,55 @@
+package com.aijia.basic.common.bean;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class Page<T> implements Serializable{
+
+    private static final long serialVersionUID = -328518255199109069L;
+
+    private long pageNo;
+    private long pageSize;
+    private long rowCnt;
+    private long pages;
+    private List<T> list;
+
+    public long getPageNo() {
+        return pageNo;
+    }
+
+    public void setPageNo(long pageNo) {
+        this.pageNo = pageNo;
+    }
+
+    public long getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(long pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    public long getRowCnt() {
+        return rowCnt;
+    }
+
+    public void setRowCnt(long rowCnt) {
+        this.rowCnt = rowCnt;
+    }
+
+    public long getPages() {
+        return pages;
+    }
+
+    public void setPages(long pages) {
+        this.pages = pages;
+    }
+
+    public List<T> getList() {
+        return list;
+    }
+
+    public void setList(List<T> list) {
+        this.list = list;
+    }
+}

+ 462 - 0
src/main/java/com/aijia/basic/common/bean/SplitPage.java

@@ -0,0 +1,462 @@
+package com.aijia.basic.common.bean;
+
+import java.io.Serializable;
+import java.util.Map;
+
+public class SplitPage implements Serializable{
+    /**
+	 * 
+	 */
+	private static final long serialVersionUID = -2823281440247472516L;
+	private int pageNo = 1;
+    private int pageSize = 10;
+    private int rowCnt = 0;
+    private int pages = 0; // 总页数
+    private String action = null;
+    private Map<String, Object> params = null;
+
+    public int getPageNo() {
+        return pageNo;
+    }
+
+    public void setPageNo(int pageNo) {
+        this.pageNo = pageNo;
+    }
+
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(int pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    public long getRowCnt() {
+        return rowCnt;
+    }
+
+    public void setRowCnt(int rowCnt) {
+        this.rowCnt = rowCnt;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public int getStartNum() {
+        return (this.pageNo - 1) * this.pageSize + 1;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public Map<String, Object> getParams() {
+        return params;
+    }
+
+    public void setParams(Map<String, Object> params) {
+        this.params = params;
+    }
+
+    public void setPages(int pages) {
+        this.pages = pages;
+    }
+
+    public int getPages() {
+        if ((rowCnt % pageSize) == 0) {
+            pages = rowCnt / pageSize;
+        } else {
+            pages = (rowCnt / pageSize) + 1;
+        }
+        return pages;
+    }
+
+    /**
+     * 生成分页导航条
+     * @return
+     */
+    public String getSplitHtml() {
+        if (rowCnt <= 0) {
+            return "";
+        }
+        StringBuffer html = new StringBuffer();
+        int pageCnt = 0;// :一共有多少页
+        if ((rowCnt % pageSize) == 0) {
+            pageCnt = rowCnt / pageSize;
+        } else {
+            pageCnt = (rowCnt / pageSize) + 1;
+        }
+
+        int prePageNo = 1; //上一页页码
+        if (pageNo > 1) {
+            prePageNo = pageNo - 1;
+        }
+
+        int nextPageNo = pageCnt; //下一页页码
+        if (pageNo < pageCnt) {
+            nextPageNo = pageNo + 1;
+        }
+
+        html.append("<form id=\"splitFrom\" name=\"splitFrom\" method=\"post\" action=\"" + action + "\">\n");
+
+        //页面参数封装
+        html.append("<input type='hidden' id='pageNo' name='pageNo' value='").append(pageNo).append("'>\n");
+        html.append("<input type='hidden' id='pageSize' name='pageSize' value='").append(pageSize).append("'>\n");
+
+        if (params != null) {
+            for (Map.Entry<String, Object> entry : params.entrySet()) {
+                if (!("pageNo".equals(entry.getKey()) || "pageSize".equals(entry.getKey()))) {
+                    html.append("<input type=\"hidden\" name=\"" + entry.getKey() + "\" value=\"").append(entry.getValue()).append("\">\n");
+                }
+            }
+        }
+
+        html.append("<ul class='pagination'>\n");
+
+        //添加首页 --- bryan add 2016-01-21
+        if (pageCnt > 0) {
+            if (pageNo == 1) {
+                html.append("<li><a href='javascript:;' onclick='listData(1); return false;' aria-label='First'><span aria-hidden='true'>|&laquo;</span></a></li>\n");
+            } else {
+                html.append("<li><a href='javascript:;' onclick='listData(1);' aria-label='First'><span aria-hidden='true'>|&laquo;</span></a></li>\n");
+            }
+        }
+
+        html.append("<li><a href='javascript:;' onclick='listData(").append(prePageNo).append(");' aria-label='Previous'><span aria-hidden='true'>&laquo;</span></a></li>\n");
+
+        if (pageCnt > 7) { //大于7页时才采取计算[左右为首尾页,中间5页]
+            //取得中间显示的那页
+            int centerPage = pageNo;
+            if (pageNo < 4) { //如果当前页小于4,就一直以4为中心   
+                centerPage = 4;
+            } else if (pageNo + 3 > pageCnt) { //如果当前页快接近尾页,则以尾页减3为中心
+                centerPage = pageCnt - 3;
+            }
+
+            //中间5页中的左2页
+            if (centerPage > 4) { //如果中心页大于4,则表示前面与首页分开了
+                //先添加首页
+                html.append(generatePagerNum(1, 1, pageNo));
+
+                html.append("<li><a href=\"#\" onclick=\"javascript:return false;\">...</a></li>\n");
+                html.append(generatePagerNum(centerPage - 2, centerPage - 1, pageNo));
+            } else {
+                html.append(generatePagerNum(1, centerPage - 1, pageNo));
+            }
+
+            //产生中心页
+            html.append(generatePagerNum(centerPage, centerPage, pageNo));
+
+            //中间5页中的右2页
+            if (centerPage + 3 < pageCnt) { //如果中心页离尾页超过3页,则表示与尾页分开了
+                html.append(generatePagerNum(centerPage + 1, centerPage + 2, pageNo));
+                html.append("<li><a href=\"#\" onclick=\"javascript:return false;\">...</a></li>\n");
+
+                //添加尾页
+                html.append(generatePagerNum(pageCnt, pageCnt, pageNo));
+            } else {
+                html.append(generatePagerNum(centerPage + 1, pageCnt, pageNo));
+            }
+        } else {
+            html.append(generatePagerNum(1, pageCnt, pageNo));
+        }
+
+        html.append("<li><a href='javascript:;' onclick='listData(").append(nextPageNo).append(");' aria-label='Next'><span aria-hidden='true'>&raquo;</span></a></li>\n");
+
+        //添加尾页 --- bryan add 2016-01-21
+        if (pageCnt > 0) {
+            if (pageNo == pageCnt) {
+                html.append("<li><a href='javascript:;' onclick='listData(" + pageCnt + "); return false;' aria-label='Last'><span aria-hidden='true'>&raquo;|</span></a></li>\n");
+            } else {
+                html.append("<li><a href='javascript:;' onclick='listData(" + pageCnt + ");' aria-label='Last'><span aria-hidden='true'>&raquo;|</span></a></li>\n");
+            }
+        }
+
+        html.append("</ul>\n");
+        html.append("</form>");
+        return html.toString();
+    }
+
+    /*
+     * 循环产生分页的标签
+     */
+    private String generatePagerNum(int startNum, int endNum, int currentpage) {
+        StringBuffer htmlStr = new StringBuffer();
+        for (int i = startNum; i <= endNum; i++) {
+            if (i == currentpage) {
+                htmlStr.append("<li class=\"active\"><a href='javascript:;' onclick='listData(" + i + "); return false;'>" + i + "</a></li>\n");
+            } else {
+                htmlStr.append("<li><a href='javascript:;' onclick='listData(" + i + ");'>" + i + "</a></li>\n");
+            }
+        }
+        return htmlStr.toString();
+    }
+
+    /**
+     * 生成后台分页导航条
+     * @return
+     */
+    public String getSysPaginHtml() {
+        if (rowCnt <= 0) {
+            return "";
+        }
+        StringBuffer html = new StringBuffer();
+        int pageCnt = 0;// :一共有多少页
+        if ((rowCnt % pageSize) == 0) {
+            pageCnt = rowCnt / pageSize;
+        } else {
+            pageCnt = (rowCnt / pageSize) + 1;
+        }
+
+        int prePageNo = 1; //上一页页码
+        if (pageNo > 1) {
+            prePageNo = pageNo - 1;
+        }
+
+        int nextPageNo = pageCnt; //下一页页码
+        if (pageNo < pageCnt) {
+            nextPageNo = pageNo + 1;
+        }
+
+        html.append("<form id=\"splitFrom\" name=\"splitFrom\" method=\"post\" action=\"" + action + "\">\n");
+
+        //页面参数封装
+        html.append("<input type='hidden' id='pageNo' name='pageNo' value='").append(pageNo).append("'>\n");
+        html.append("<input type='hidden' id='pageSize' name='pageSize' value='").append(pageSize).append("'>\n");
+        html.append("<input type='hidden' id='attr1' name='attr1' value=''>\n");
+        html.append("<input type='hidden' id='attr2' name='attr2' value=''>\n");
+
+        if (params != null) {
+            for (Map.Entry<String, Object> entry : params.entrySet()) {
+                if (!("pageNo".equals(entry.getKey()) || "pageSize".equals(entry.getKey()))) {
+                    html.append("<input type=\"hidden\" name=\"" + entry.getKey() + "\" value=\"").append(entry.getValue()).append("\">\n");
+                }
+            }
+        }
+
+        html.append("<ul class='paginList'>\n");
+        if (pageCnt > 1) {
+            html.append("<li class='paginItem'><a href='javascript:;' onclick='listData(").append(prePageNo).append(");'><span class='pagepre'></span></a></li>\n");
+        }
+        if (pageCnt > 7) { //大于7页时才采取计算[左右为首尾页,中间5页]
+            //取得中间显示的那页
+            int centerPage = pageNo;
+            if (pageNo < 4) { //如果当前页小于4,就一直以4为中心   
+                centerPage = 4;
+            } else if (pageNo + 3 > pageCnt) { //如果当前页快接近尾页,则以尾页减3为中心
+                centerPage = pageCnt - 3;
+            }
+
+            //中间5页中的左2页
+            if (centerPage > 4) { //如果中心页大于4,则表示前面与首页分开了
+                //先添加首页
+                html.append(generateSysPaginNum(1, 1, pageNo));
+
+                html.append("<li class='paginItem more'><a href='javascript:;'>...</a></li>\n");
+                html.append(generateSysPaginNum(centerPage - 2, centerPage - 1, pageNo));
+            } else {
+                html.append(generateSysPaginNum(1, centerPage - 1, pageNo));
+            }
+
+            //产生中心页
+            html.append(generateSysPaginNum(centerPage, centerPage, pageNo));
+
+            //中间5页中的右2页
+            if (centerPage + 3 < pageCnt) { //如果中心页离尾页超过3页,则表示与尾页分开了
+                html.append(generateSysPaginNum(centerPage + 1, centerPage + 2, pageNo));
+                html.append("<li class='paginItem more'><a href='javascript:;'>...</a></li>\n");
+
+                //添加尾页
+                html.append(generateSysPaginNum(pageCnt, pageCnt, pageNo));
+            } else {
+                html.append(generateSysPaginNum(centerPage + 1, pageCnt, pageNo));
+            }
+        } else {
+            html.append(generateSysPaginNum(1, pageCnt, pageNo));
+        }
+        if (pageCnt > 1) {
+            html.append("<li class='paginItem'><a href='javascript:;' onclick='listData(").append(nextPageNo).append(");'><span class='pagenxt'></span></a></li>\n");
+        }
+        html.append("</ul>\n");
+        html.append("</form>");
+        return html.toString();
+    }
+    
+    /*
+     * 循环产生后台分页的标签
+     */
+    private String generateSysPaginNum(int startNum, int endNum, int currentpage) {
+        StringBuffer htmlStr = new StringBuffer();
+        for (int i = startNum; i <= endNum; i++) {
+            if (i == currentpage) {
+                htmlStr.append("<li class='paginItem current'><a href='javascript:;'>" + i + "</a></li>\n");
+            } else {
+                htmlStr.append("<li class='paginItem'><a href='javascript:;' onclick=\"javascript:listData('" + i + "');return false;\">" + i + "</a></li>\n");
+            }
+        }
+        return htmlStr.toString();
+    }
+    
+    /**
+     * 获取人间分页html
+     * @return
+     */
+    public String getJobPageHtml() {
+        if (rowCnt <= 0) {
+            return "";
+        }
+        StringBuffer html = new StringBuffer();
+        int pageCnt = 0;// :一共有多少页
+        if ((rowCnt % pageSize) == 0) {
+            pageCnt = rowCnt / pageSize;
+        } else {
+            pageCnt = (rowCnt / pageSize) + 1;
+        }
+
+        int prePageNo = 1; //上一页页码
+        if (pageNo > 1) {
+            prePageNo = pageNo - 1;
+        }
+
+        int nextPageNo = pageCnt; //下一页页码
+        if (pageNo < pageCnt) {
+            nextPageNo = pageNo + 1;
+        }
+        html.append("<form id=\"jobSpFrom\" name=\"jobSpFrom\" method=\"get\" action=\"" + action + "\">\n");
+
+        //页面参数封装
+        html.append("<input type=\"hidden\" id=\"pageNo\" name=\"p\" value=\"").append(pageNo).append("\">\n");
+
+        if (params != null) {
+            for (Map.Entry<String, Object> entry : params.entrySet()) {
+                if (!("p".equals(entry.getKey()) || "pageSize".equals(entry.getKey()))) {
+                    html.append("<input type=\"hidden\" name=\"" + entry.getKey() + "\" value=\"").append(entry.getValue()).append("\">\n");
+                }
+            }
+        }
+        
+        if (pageNo == 1) {
+            html.append("<a id=\"rtPrev\" class=\"dicon\" href=\"javascript:;\"></a>\n");
+        } else {
+            html.append("<a id=\"rtPrev\" class=\"dicon on\" href=\"javascript:;\" onclick=\"javascript:jobListData(").append(prePageNo).append(");\"></a>\n");
+        }
+        
+        html.append("<span class=\"se_c_orange\">").append(pageNo).append("</span>/").append(pageCnt).append("\n");
+        
+        if (pageNo == pageCnt) {
+            html.append("<a id=\"rtNext\" class=\"dicon off\" href=\"javascript:;\"></a>\n");
+        } else {
+            html.append("<a id=\"rtNext\" class=\"dicon on\" href=\"javascript:;\" onclick=\"javascript:jobListData(").append(nextPageNo).append(");\"></a>\n");
+        }
+        html.append("</form>");
+        return html.toString();
+    }
+
+    /**
+     * 生成分页导航条
+     * @return
+     */
+    public String getCourseHtml() {
+        if (rowCnt <= 0) {
+            return "";
+        }
+        StringBuffer html = new StringBuffer();
+        int pageCnt = 0;// :一共有多少页
+        if ((rowCnt % pageSize) == 0) {
+            pageCnt = rowCnt / pageSize;
+        } else {
+            pageCnt = (rowCnt / pageSize) + 1;
+        }
+
+        int prePageNo = 1; //上一页页码
+        if (pageNo > 1) {
+            prePageNo = pageNo - 1;
+        }
+
+        int nextPageNo = pageCnt; //下一页页码
+        if (pageNo < pageCnt) {
+            nextPageNo = pageNo + 1;
+        }
+
+        html.append("<form id=\"splitFrom\" name=\"splitFrom\" method=\"post\" action=\"" + action + "\">\n");
+
+        //页面参数封装
+        html.append("<input type='hidden' id='pageNo' name='pageNo' value='").append(pageNo).append("'>\n");
+        html.append("<input type='hidden' id='pageSize' name='pageSize' value='").append(pageSize).append("'>\n");
+
+        if (params != null) {
+            for (Map.Entry<String, Object> entry : params.entrySet()) {
+                if (!("pageNo".equals(entry.getKey()) || "pageSize".equals(entry.getKey()))) {
+                    html.append("<input type=\"hidden\" name=\"" + entry.getKey() + "\" value=\"").append(entry.getValue()).append("\">\n");
+                }
+            }
+        }
+
+        html.append("<ul class='pagination pull-right'>\n");
+
+        //添加首页 --- bryan add 2016-01-21
+        if (pageCnt > 0) {
+            if (pageNo == 1) {
+            	html.append("<li><a href='javascript:;' onclick='listData(1);' aria-label='Previous' class='previous'><span aria-hidden='true'>上一页</span></a></li>\n");
+            } else {
+            	html.append("<li><a href='javascript:;' onclick='listData(").append(prePageNo).append(");' aria-label='Previous' class='previous'><span aria-hidden='true'>上一页</span></a></li>\n");
+            }
+        }
+
+        
+
+        if (pageCnt > 7) { //大于7页时才采取计算[左右为首尾页,中间5页]
+            //取得中间显示的那页
+            int centerPage = pageNo;
+            if (pageNo < 4) { //如果当前页小于4,就一直以4为中心   
+                centerPage = 4;
+            } else if (pageNo + 3 > pageCnt) { //如果当前页快接近尾页,则以尾页减3为中心
+                centerPage = pageCnt - 3;
+            }
+
+            //中间5页中的左2页
+            if (centerPage > 4) { //如果中心页大于4,则表示前面与首页分开了
+                //先添加首页
+                html.append(generatePagerNum(1, 1, pageNo));
+
+                html.append("<li><a href=\"#\" onclick=\"javascript:return false;\">...</a></li>\n");
+                html.append(generatePagerNum(centerPage - 2, centerPage - 1, pageNo));
+            } else {
+                html.append(generatePagerNum(1, centerPage - 1, pageNo));
+            }
+
+            //产生中心页
+            html.append(generatePagerNum(centerPage, centerPage, pageNo));
+
+            //中间5页中的右2页
+            if (centerPage + 3 < pageCnt) { //如果中心页离尾页超过3页,则表示与尾页分开了
+                html.append(generatePagerNum(centerPage + 1, centerPage + 2, pageNo));
+                html.append("<li><a href=\"#\" onclick=\"javascript:return false;\">...</a></li>\n");
+
+                //添加尾页
+                html.append(generatePagerNum(pageCnt, pageCnt, pageNo));
+            } else {
+                html.append(generatePagerNum(centerPage + 1, pageCnt, pageNo));
+            }
+        } else {
+            html.append(generatePagerNum(1, pageCnt, pageNo));
+        }
+
+       
+
+        //添加尾页 --- bryan add 2016-01-21
+        if (pageCnt > 0) {
+            if (pageNo == pageCnt) {
+                html.append("<li><a href='javascript:;' onclick='listData(").append(pageCnt).append(");' aria-label='Next'  class='next'><span aria-hidden='true'>下一页</span></a></li>\n");
+            } else {
+                html.append("<li><a href='javascript:;' onclick='listData(").append(nextPageNo).append(");' aria-label='Next'  class='next'><span aria-hidden='true'>下一页</span></a></li>\n");
+            }
+        }
+
+        html.append("</ul>\n");
+        html.append("</form>");
+        return html.toString();
+    }
+    
+}

+ 56 - 0
src/main/java/com/aijia/basic/config/bean/VersionConfig.java

@@ -0,0 +1,56 @@
+package com.aijia.basic.config.bean;
+
+import java.io.Serializable;
+
+public class VersionConfig  implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+    
+    //科目
+    private String courseName;
+    
+//	  版本 
+//   value="1" />北师大
+//	 value="2" />人教版
+//	 value="5" />江苏版
+//	 value="6" />思维拓展
+//	
+//	 value="2" />人教(部编)
+//	
+//	 value="2" />教科版
+//	 value="3" />沪教版(新)
+//	 value="7" />朗文版
+//	 value="8" />人教版(PEP)
+//	 value="9" />牛津版
+//	 value="10" />外研版
+    private Integer versionType;
+    
+    private String versionName;
+
+	public String getCourseName() {
+		return courseName;
+	}
+
+	public void setCourseName(String courseName) {
+		this.courseName = courseName;
+	}
+
+	public Integer getVersionType() {
+		return versionType;
+	}
+
+	public void setVersionType(Integer versionType) {
+		this.versionType = versionType;
+	}
+
+	public String getVersionName() {
+		return versionName;
+	}
+
+	public void setVersionName(String versionName) {
+		this.versionName = versionName;
+	}
+    
+   
+
+}

+ 133 - 0
src/main/java/com/aijia/basic/utils/ByteUtil.java

@@ -0,0 +1,133 @@
+package com.aijia.basic.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ByteUtil {
+	/*public static final InputStream byte2Input(byte[] buf) {
+		return new ByteArrayInputStream(buf);
+	}*/
+
+	public static final byte[] input2byte(InputStream inStream) throws IOException {
+		ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
+		byte[] buff = new byte[100];
+		int rc = 0;
+		while ((rc = inStream.read(buff, 0, 100)) > 0) {
+			swapStream.write(buff, 0, rc);
+		}
+		byte[] in2b = swapStream.toByteArray();
+		return in2b;
+	}
+	
+	/**
+     * 获得指定文件的byte数组
+     */
+    /*public static byte[] getBytes(File file) {
+        byte[] buffer = null;
+        FileInputStream fis = null;
+        ByteArrayOutputStream bos = null;
+        try {
+            fis = new FileInputStream(file);
+            bos = new ByteArrayOutputStream(1000);
+            byte[] b = new byte[1000];
+            int n;
+            while ((n = fis.read(b)) != -1) {
+                bos.write(b, 0, n);
+            }
+            buffer = bos.toByteArray();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (fis != null) {
+                try {
+                    fis.close();
+                } catch (Exception e) {
+                }
+            }
+            if (bos != null) {
+                try {
+                    bos.close();
+                } catch (Exception e) {
+                }
+            }
+        }
+        return buffer;
+    }
+
+	*//**
+	 * 获得指定文件的byte数组
+	 *//*
+	public static byte[] getBytes(String filePath) {
+		byte[] buffer = null;
+		FileInputStream fis = null;
+		ByteArrayOutputStream bos = null;
+		try {
+			File file = new File(filePath);
+			fis = new FileInputStream(file);
+			bos = new ByteArrayOutputStream(1000);
+			byte[] b = new byte[1000];
+			int n;
+			while ((n = fis.read(b)) != -1) {
+				bos.write(b, 0, n);
+			}
+			buffer = bos.toByteArray();
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		} finally {
+			if (fis != null) {
+				try {
+					fis.close();
+				} catch (Exception e) {
+				}
+			}
+			if (bos != null) {
+				try {
+					bos.close();
+				} catch (Exception e) {
+				}
+			}
+		}
+		return buffer;
+	}
+
+	*//**
+	 * 根据byte数组,生成文件
+	 *//*
+	public static void getFile(byte[] bfile, String filePath, String fileName) {
+		BufferedOutputStream bos = null;
+		FileOutputStream fos = null;
+		File file = null;
+		try {
+			File dir = new File(filePath);
+			if (!dir.exists() && dir.isDirectory()) {// 判断文件目录是否存在
+				dir.mkdirs();
+			}
+			file = new File(filePath + "/" + fileName);
+			fos = new FileOutputStream(file);
+			bos = new BufferedOutputStream(fos);
+			bos.write(bfile);
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			if (bos != null) {
+				try {
+					bos.close();
+				} catch (IOException e1) {
+					e1.printStackTrace();
+				}
+			}
+			if (fos != null) {
+				try {
+					fos.close();
+				} catch (IOException e1) {
+					e1.printStackTrace();
+				}
+			}
+		}
+	}*/
+}

+ 930 - 0
src/main/java/com/aijia/basic/utils/DateHelper.java

@@ -0,0 +1,930 @@
+package com.aijia.basic.utils;
+
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+
+public class DateHelper {
+
+
+    private static final long ONE_MINUTE = 60;
+    private static final long ONE_HOUR = 3600;
+    private static final long ONE_DAY = 86400;
+    static String[] weekDays = {"日", "一", "二", "三", "四", "五", "六"};
+    static Integer[] weekDay = {7, 1, 2, 3, 4, 5, 6};
+
+    /**
+     * 根据用户传入的时间表示格式,返回当前时间的格式 如果是yyyyMMdd,注意字母y不能大写。
+     *
+     * @param sformat yyyyMMddhhmmss
+     * @return
+     */
+    public static String getUserDate(String sformat) {
+        Date currentTime = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat(sformat);
+        String dateString = formatter.format(currentTime);
+        return dateString;
+    }
+
+    public static String getOrderNo(int k) {
+
+        return getUserDate("yyyyMMddHHmmss") + getRandom(k);
+    }
+
+
+    /**
+     * 返回一个随机数
+     *
+     * @param i
+     * @return
+     */
+    public static String getRandom(int i) {
+        Random jjj = new Random();
+        if (i == 0){
+            return "";
+        }
+        String jj = "";
+        for (int k = 0; k < i; k++) {
+            jj = jj + jjj.nextInt(9);
+        }
+        return jj;
+    }
+
+
+    public static String formatDateByFormat(Date date, String format) {
+        String result = "";
+        if (date != null) {
+            try {
+                SimpleDateFormat sdf = new SimpleDateFormat(format);
+                result = sdf.format(date);
+                result = "/" + result;
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+        return result;
+    }
+
+    public static Date parseDate(String dateStr, String format) {
+        Date date = null;
+        try {
+            DateFormat df = new SimpleDateFormat(format);
+            String dt = dateStr;
+            if ((!"".equals(dt)) && (dt.length() < format.length())) {
+                dt = dt + format.substring(dt.length()).replaceAll("[YyMmDdHhSs]", "0");
+            }
+            date = df.parse(dt);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return date;
+    }
+
+    public static String format(String dateStr) throws Exception {
+
+        Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateStr);
+        SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日");
+        return format.format(date.getTime());
+    }
+
+
+    public static String format(Date date, String format) {
+        String result = "";
+        try {
+            if (date != null) {
+                DateFormat df = new SimpleDateFormat(format);
+                result = df.format(date);
+            }
+        } catch (Exception localException) {
+
+        }
+        return result;
+    }
+
+
+    public static String getDate(Date date) {
+        return format(date, "yyyy/MM/dd");
+    }
+
+
+    public static String getDateTime(Date date) {
+        return format(date, "yyyy-MM-dd HH:mm:ss");
+    }
+
+
+    /**
+     * 获取好友的时间显示,如 5分钟前
+     *
+     * @param
+     * @return
+     */
+    public static String getTimeDes(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+
+        long time = date.getTime() / 1000;
+        long now = System.currentTimeMillis() / 1000;
+        long ago = now - time;
+        if ( ONE_HOUR >=ago ) {
+            return ago / ONE_MINUTE + "分钟前";
+        } else if (ONE_DAY >=ago) {
+            return ago / ONE_HOUR + "小时前";
+        } else if ( ONE_DAY * 2 >=ago ) {
+            return "昨天";
+        } else if ( ONE_DAY * 3  >=ago) {
+            return "前天";
+        } else {
+            return ago / ONE_DAY + "天前";
+        }
+
+    }
+
+    public static String getDays(Date date, int i) throws Exception {
+        int days = daysOfTwo(date, new Date());
+        SimpleDateFormat format = new SimpleDateFormat("MM月dd日");
+        String time = "";
+        if (i == 1) {
+            time = "<br/>" + format.format(date.getTime());
+        }
+        if (days == 0) {
+            return "今天" + time;
+        } else if (days == 1) {
+            return "昨天" + time;
+        } else if (days == 2) {
+            return "前天" + time;
+        } else if (days <= 7 && days >= 3) {
+            return numToUpper(days - 1) + "天前" + time;
+        } else if (days < 0) {
+            if (days == -1) {
+                return "明天" + time;
+            } else if (days == -2) {
+                return "后天" + time;
+            }
+            return Math.abs(days) + "天" + time;
+        } else {
+            if (days / 7 > 3) {
+                return numToUpper(days / 30) + "月前" + time;
+            }
+            return numToUpper(days / 7) + "周前" + time;
+        }
+
+    }
+
+    public static String numToUpper(int num) {
+        String[] u = {"上", "两", "三", "四", "五", "六", "七", "八", "九"};
+        char[] str = String.valueOf(num).toCharArray();
+        String rstr = "";
+        for (int i = 0; i < str.length; i++) {
+            rstr = rstr + u[Integer.parseInt(str[i] + "")];
+        }
+        return rstr;
+    }
+
+
+
+
+    /**
+     * 将时间转换为标准的天+小时+分+秒格式
+     */
+    public static  String getStandardTime(long diff){
+        String DateTimes = null;
+        long hours = (diff % ( 60 * 60 * 24)) / (60 * 60);
+        long minutes = (diff % ( 60 * 60)) /60;
+        long seconds = diff % 60;
+        if(hours>0){
+            DateTimes=hours + ":" + minutes + ":"    + seconds;
+        }else if(minutes>0){
+            DateTimes="00"+":"+minutes + ":"    + seconds;
+        }else{
+            DateTimes="00"+":"+"00"+":"+seconds;
+        }  return DateTimes;
+
+
+    }
+
+
+    public static String getDifferenceTime(Date one, Date two) {
+        String DateTimes = null;
+        long day = 0;
+        long hour = 0;
+        long min = 0;
+        long sec = 0;
+        long time1 = one.getTime();
+        long time2 = two.getTime();
+        long diff;
+        if (time1 < time2) {
+            diff = (time2 - time1);
+        } else {
+            diff = (time1 - time2);
+        }
+        long days = diff / (1000 * 60 * 60 * 24);
+        long hours = (diff-days*(1000 * 60 * 60 * 24))/(1000* 60 * 60);
+        long minutes = (diff-days*(1000 * 60 * 60 * 24)-hours*(1000* 60 * 60))/(1000* 60);
+        long seconds=(diff/1000-days*24*60*60-hours*60*60-minutes*60);//获取秒
+        long addHour=hours+days*24;
+        if(addHour>0){
+            DateTimes=addHour + ":" + minutes + ":"    + seconds;
+        }else if(minutes>0){
+            DateTimes="00"+":"+minutes + ":"    + seconds;
+        }else{
+            DateTimes="00"+":"+"00"+":"+seconds;
+        }  return DateTimes;
+    }
+
+    public static String getCostTime(Date one, Date two) {
+        long time1 = one.getTime();
+        long time2 = two.getTime();
+        long diff;
+        if (time1 < time2) {
+            diff = time2 - time1;
+        } else {
+            diff = time1 - time2;
+        }
+        long min = diff / (60 * 1000);
+        return Long.toString(min);
+    }
+
+    public static Date getNextDay(Date date, int days) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(Calendar.DAY_OF_MONTH, days);
+        date = calendar.getTime();
+        return date;
+    }
+
+    /**
+     * 获取上月的第一天
+     *
+     * @param date
+     * @param
+     * @return 创建人:ZhangCaibao
+     * 2018年2月1日 上午9:55:52
+     * @Date
+     */
+    public static Date getLastMonthFirstDay(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(Calendar.MONTH, -1);
+        calendar.set(Calendar.DAY_OF_MONTH, 1);
+        date = calendar.getTime();
+        return date;
+    }
+
+    /**
+     * 获取下月的第一天
+     *
+     * @param date
+     * @param
+     * @return 创建人:ZhangCaibao
+     * 2018年2月1日 上午9:55:52
+     * @Date
+     */
+    public static Date getNextMonthFirstDay(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(Calendar.MONTH, 1);
+        calendar.set(Calendar.DAY_OF_MONTH, 1);
+        date = calendar.getTime();
+        return date;
+    }
+
+    public static Date getTheMonthFirstDay() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.add(Calendar.MONTH, 0);
+        calendar.set(Calendar.DAY_OF_MONTH, 1);
+        return calendar.getTime();
+    }
+
+    /**
+     * 获取上月的最后一天
+     *
+     * @param date
+     * @param
+     * @return 创建人:ZhangCaibao
+     * 2018年2月1日 上午9:55:52
+     * @Date
+     */
+    public static Date getLastMonthLastDay(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.set(Calendar.DAY_OF_MONTH, 0);
+        date = calendar.getTime();
+        return date;
+    }
+
+    public static int getMonth(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        int month = calendar.get(Calendar.MONTH) + 1;
+        return month;
+    }
+
+
+
+
+
+    /**
+     * @param
+     * @return 根据开学时间,和当前时间,相差几周。
+     * @throws Exception
+     * @Integer
+     */
+    public static Integer diffWeeks(String date) throws Exception {
+        Date startDate = parseDate(date, "yyyy-MM-dd");
+        Date endDate = new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
+        Long weekNum = ((endDate.getTime() / 1000 - startDate.getTime() / 1000) % 604800) > 0 ? (endDate.getTime() / 1000 - startDate.getTime() / 1000) / 604800 + 1 : (endDate.getTime() / 1000 - startDate.getTime() / 1000) / 604800;
+        return weekNum.intValue();
+    }
+
+    public static Integer diffWeeks(String date, Date start) throws Exception {
+        Date startDate = parseDate(date, "yyyy-MM-dd");
+        Date endDate = new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(start));
+        Long weekNum = ((endDate.getTime() / 1000 - startDate.getTime() / 1000) % 604800) > 0 ? (endDate.getTime() / 1000 - startDate.getTime() / 1000) / 604800 + 1 : (endDate.getTime() / 1000 - startDate.getTime() / 1000) / 604800;
+        return weekNum.intValue();
+    }
+
+    /**
+     * 判断当前时间是不是大于活动结束时间
+     *
+     * @param
+     * @param date
+     * @return
+     * @throws Exception
+     */
+    public static boolean isInDate(Date date, String strDateBegin,
+                                   String strDateEnd) {
+        try {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+            Date beginDate = sdf.parse(strDateBegin);
+            Date endDate = sdf.parse(strDateEnd);
+            if (date.getTime() >= beginDate.getTime() && date.getTime() <= endDate.getTime()) {
+                return true;
+            }
+
+        } catch (Exception e) {
+            return false;
+        }
+        return false;
+    }
+
+    public static boolean isInDate(Date date, Date beginDate,
+                                   Date endDate) {
+        try {
+            if (date.getTime() >= beginDate.getTime() && date.getTime() <= endDate.getTime()) {
+                return true;
+            }
+
+        } catch (Exception e) {
+            return false;
+        }
+        return false;
+    }
+
+
+    /**
+     * 根据日期字符串判断周几
+     *
+     * @param
+     * @return
+     * @throws Exception
+     */
+    public static int getday(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        //第几天,从周日开始
+        int day = calendar.get(Calendar.DAY_OF_WEEK);
+        return day;
+    }
+
+    public static String getWeekDays(Date date) {
+        int day = getday(date);
+        return weekDays[day - 1];
+    }
+
+    public static Integer getWeekDay(Date date) {
+        int day = getday(date);
+        return weekDay[day - 1];
+    }
+
+
+    /**
+     * @param date         当前时间
+     * @param week_of_year 第几周 下周(1),下下周(2)
+     * @param day_of_week  周几,周日(1),周一(2),周六(7)
+     * @return
+     */
+    public static Date getNextTuesday(Date date, int week_of_year, int day_of_week) {
+        Calendar cal = Calendar.getInstance();
+
+        cal.setTime(date);
+        cal.add(Calendar.WEEK_OF_YEAR, week_of_year);
+        cal.set(Calendar.DAY_OF_WEEK, day_of_week);
+
+        return cal.getTime();
+    }
+
+    public static String getPercentage(int num1, int num2) {
+        // 创建一个数值格式化对象
+
+        NumberFormat numberFormat = NumberFormat.getInstance();
+
+        // 设置精确到小数点后2位  
+
+        numberFormat.setMaximumFractionDigits(2);
+
+        String result = numberFormat.format((float) num1 / (float) num2 * 100);
+        return result + "%";
+    }
+
+    /**
+     * 比较两个日期相差的天数
+     *
+     * @param
+     * @param
+     * @return
+     * @throws Exception
+     */
+    public static int daysOfTwo(Date smdate, Date bdate) throws Exception {
+
+        smdate = new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(smdate));
+        bdate = new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(bdate));
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(smdate);
+        long time1 = cal.getTimeInMillis();
+        cal.setTime(bdate);
+        long time2 = cal.getTimeInMillis();
+        long between_days = (time2 - time1) / (1000 * 3600 * 24);
+
+        return daysOfTian(smdate,bdate);
+
+    }
+    public static LocalDate date2LocalDate(Date date) {
+        Instant instant = date.toInstant();
+        ZoneId zoneId = ZoneId.systemDefault();
+        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
+        return localDate;
+    }
+
+    public static int daysOfTian(Date date1, Date date2) {
+
+        if (date1 == null || date2 == null) {
+            throw new RuntimeException("日期不能为空");
+        }
+        LocalDate localDate1 = date2LocalDate(date1);
+        LocalDate localDate2 = date2LocalDate(date2);
+
+        return  (int) (localDate2.toEpochDay() - localDate1.toEpochDay());
+    }
+
+    /**
+     * 获取相差的天数
+     *
+     * @param
+     * @param
+     * @return
+     * @throws Exception 创建人:ZhangCaibao
+     *                   2017年4月19日 下午4:27:42
+     * @int
+     */
+    public static int daysDiffer(String startdate, String enddate) throws Exception {
+
+        Date smdate = new SimpleDateFormat("yyyy-MM-dd").parse(startdate);
+        Date bdate = new SimpleDateFormat("yyyy-MM-dd").parse(enddate);
+        return  daysOfTian(smdate,bdate);
+
+    }
+
+    public static String dateFormatString(String dateStr, int days) throws Exception {
+        Date smdate = new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);
+        if (days > 90) {
+            return format(smdate, "MM月dd日");
+        } else {
+            return format(smdate, "YYYY年MM月dd日");
+        }
+
+    }
+
+    /**
+     * 根据时间来拼接
+     *
+     * @param
+     * @param hhmmss
+     * @return
+     */
+    public static Date timeStitching(Date date, String hhmmss) throws Exception {
+        String yyyyMMdd = new SimpleDateFormat("yyyy-MM-dd").format(date);
+        Date datefor = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(yyyyMMdd + " " + hhmmss);
+        return datefor;
+    }
+
+
+
+
+    //判断选择的日期是否是本月
+    public static boolean isThisMonth(Date date) {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
+        String param = sdf.format(date);//参数时间
+        String now = sdf.format(new Date());//当前时间
+        if (param.equals(now)) {
+            return true;
+        }
+        return false;
+    }
+
+    public static Date getMonthDate(Date smdate, int month) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(smdate);
+        cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + month);
+        return cal.getTime();
+    }
+
+    public static Date getYearDate(Date smdate, int year) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(smdate);
+        cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + year);
+        return cal.getTime();
+    }
+
+
+
+    public static Map<String, Object> getDifferenceTimeHourMap(Date one, Date two) {
+        Map<String, Object> map = new HashMap<String, Object>();
+        long day = 0;
+        long hour = 0;
+        long min = 0;
+        long sec = 0;
+        long time1 = one.getTime();
+        long time2 = two.getTime();
+        long diff;
+        if (time1 < time2) {
+            diff = time2 - time1;
+        } else {
+            diff = time1 - time2;
+        }
+        day = diff / (24 * 60 * 60 * 1000);
+        hour = (diff / (60 * 60 * 1000) - day * 24);
+        min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
+        sec = (diff / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
+        map.put("day", day < 10 ? "0" + day : day);
+        map.put("hour", hour < 10 ? "0" + hour : hour);
+        map.put("min", min < 10 ? "0" + min : min);
+        map.put("sec", sec < 10 ? "0" + sec : sec);
+        map.put("millisecond", diff);
+        return map;
+    }
+
+    //两时间差
+    public static long getDifferenceTimeNum(Date one, Date two) {
+        long time1 = one.getTime();
+        long time2 = two.getTime();
+        long diff;
+        if (time1 < time2) {
+            diff = time2 - time1;
+        } else {
+            diff = time1 - time2;
+        }
+        return diff;
+
+    }
+
+
+
+    public static boolean isSameDate(Date date1, Date date2) {
+        Calendar cal1 = Calendar.getInstance();
+        cal1.setTime(date1);
+        Calendar cal2 = Calendar.getInstance();
+        cal2.setTime(date2);
+        boolean isSameYear = cal1.get(Calendar.YEAR) == cal2
+                .get(Calendar.YEAR);
+        boolean isSameMonth = isSameYear
+                && cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH);
+        boolean isSameDate = isSameMonth
+                && cal1.get(Calendar.DAY_OF_MONTH) == cal2
+                .get(Calendar.DAY_OF_MONTH);
+        return isSameDate;
+    }
+
+    /**
+     * @param sformat   时间格式
+     * @param beforeDay 如果为负数即当前时间前beforeDay天,如果为正数则为当前时间后beforeDay天
+     * @return 方法说明:
+     * <p>
+     * 创立日期:2018年5月16日 下午3:51:09
+     * 创建人:yangcan
+     */
+    public static String getBeforeDate(String sformat, int beforeDay) {
+        Calendar calendar = Calendar.getInstance(); //得到日历
+        calendar.setTime(new Date());//把当前时间赋给日历
+        calendar.add(Calendar.DAY_OF_MONTH, beforeDay);  //设置为当前时间前beforeDay天
+        SimpleDateFormat formatter = new SimpleDateFormat(sformat);
+        String dateString = formatter.format(calendar.getTime());
+        return dateString;
+    }
+
+
+    /**
+     * @param date   传入时间
+     * @param hour   传入时间加小时
+     * @param minute 传入时间加分钟
+     * @return 方法说明:返回传入时间加小时,分钟后的时间
+     * <p>
+     * 创立日期:2018年6月10日 下午3:19:32
+     * 创建人:yangcan
+     */
+    public static Date getAddHour(Date date, int hour, int minute) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.add(Calendar.HOUR, hour);
+        cal.add(Calendar.MINUTE, minute);
+        return cal.getTime();
+    }
+
+    public static List<Map<String, Object>> nearWeek() {
+        List<Map<String, Object>> mlist = new ArrayList<Map<String, Object>>();
+        String[] weekDays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
+        for (int i = -6; i <= 0; i++) {
+            Map<String, Object> map = new HashMap<>();
+            Calendar cal = Calendar.getInstance();
+            cal.add(5, i);
+            int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
+            if (w < 0){
+                w = 0;
+            }
+            if (i == 0) {
+                map.put("dateTime", "今");
+            } else {
+                map.put("dateTime", new SimpleDateFormat("dd").format(cal.getTime()));
+            }
+            map.put("time", new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime()));
+            map.put("dateWeek", weekDays[w]);
+            mlist.add(map);
+        }
+        return mlist;
+    }
+
+    public static int diffDate(java.util.Date endDate, java.util.Date startDate) {
+        return (int) ((getMillis(endDate) - getMillis(startDate)) / 86400000L);
+    }
+
+    public static long getMillis(java.util.Date date) {
+        Calendar c = Calendar.getInstance();
+        c.setTime(date);
+        return c.getTimeInMillis();
+    }
+
+    /**
+     * 计算两个日期之间相差的天数
+     *
+     * @param smdate 较小的时间
+     * @param bdate  较大的时间
+     * @return 相差天数
+     * @throws ParseException
+     */
+    public static int daysBetween(Date smdate, Date bdate) throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        smdate = sdf.parse(sdf.format(smdate));
+        bdate = sdf.parse(sdf.format(bdate));
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(smdate);
+        long time1 = cal.getTimeInMillis();
+        cal.setTime(bdate);
+        long time2 = cal.getTimeInMillis();
+        long between_days = (time2 - time1) / (1000 * 3600 * 24);
+
+        return Integer.parseInt(String.valueOf(between_days));
+    }
+
+    /**
+     * 计算两段日期重叠的天数
+     *
+     * 这里共有2个时间段(b1-----e1)【b2-----e2】,4个时间点;
+     * 相当于两条线段(b代表起点,e代表端点,b<=e),4个端点。
+     * 可分3种情况:
+     * 1.不相交。(b1-----e1)【b2-----e2】(b1-----e1)。if(e1<b2||b1>e2)此时,重合天数为零。
+     * 2.相交。
+     * 情况一:(b1---【b2---e1)----e2】          if(b1<b2&&e1<e2&&e1>b2)
+     * 情况二:【b2---(b1---e2】----e1)	   if(b1>b2&&b1<e2&&e2<e1)
+     * 3.包含:计算较短的时间段日期长度。
+     * (b1---【b2-----e2】--e1)			   if(b1<b2&&e1>e2)
+     * 【b2---(b1-----e1)--e2】			   if(b1>b2&&e1<e2)
+     *
+     * @param begindate1     开始日期
+     * @param enddate1       结束日期
+     * @param begindate2     开始日期
+     * @param enddate2       结束日期
+     * @return
+     */
+    public static Integer getDayCoincidence(Date begindate1, Date enddate1, Date begindate2, Date enddate2) throws ParseException {
+        //转换为天判断
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        begindate1 = sdf.parse(sdf.format(begindate1));
+        enddate1 = sdf.parse(sdf.format(enddate1));
+        begindate2 = sdf.parse(sdf.format(begindate2));
+        enddate2 = sdf.parse(sdf.format(enddate2));
+        long b1 = begindate1.getTime();
+        long e1 = enddate1.getTime();
+        long b2 = begindate2.getTime();
+        long e2 = enddate2.getTime();
+        assert (b1 < e1 && b2 < e2);
+        Integer coincidenceDay;
+        if (b1 <= b2 && e1 >= e2) {
+            System.out.println("1包含2:(b1---【b2-----e2】--e1)");
+            coincidenceDay = daysBetween(begindate2, enddate2) + 1;
+        } else if (b1 >= b2 && e1 <= e2) {
+            System.out.println("2包含1:【b2---(b1-----e1)--e2】");
+            coincidenceDay = daysBetween(begindate1, enddate1) + 1;
+        } else if (b1 >= b2 && b1 <= e2 && e2 <= e1) {
+            System.out.println("相交:【b2---(b1---e2】----e1)");
+            coincidenceDay = daysBetween(begindate1, enddate2) + 1;
+        } else if (b1 <= b2 && e1 <= e2 && e1 >= b2) {
+            System.out.println("相交:(b1---【b2---e1)----e2】");
+            coincidenceDay = daysBetween(begindate2, enddate1) + 1;
+        } else if (e1 < b2 || b1 > e2) {
+            coincidenceDay = 0;
+        } else {
+            System.out.println("意料外的日期组合,无法计算重合天数!");
+            coincidenceDay = null;
+        }
+        //取绝对值
+        return coincidenceDay != null ? Math.abs(coincidenceDay) : null;
+    }
+
+    /**
+     * 比较两个日期大小(只精确到日)
+     *
+     * @param smallDate 小日期
+     * @param bigDate 大日期
+     * @return
+     */
+    public static boolean compareTwoDate(Date smallDate, Date bigDate) {
+        String smallString = DateFormatUtils.format(smallDate, "yyyy-MM-dd");
+        String bigString = DateFormatUtils.format(bigDate, "yyyy-MM-dd");
+        if (smallString.compareTo(bigString) <= 0) {
+            return true;
+        }
+        return false;
+    }
+
+
+    /**
+     * 获取当前日期是星期几
+     *
+     * @param date
+     * @param style
+     * @return 当前日期是星期几
+     */
+    public static String getWeekOfDate(Date date, int style) {
+        String[] weekZhouDays = {"周天", "周一", "周二", "周三", "周四", "周五", "周六"};
+        String[] weekXingqiDays = {"星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
+        if (w < 0) {
+            w = 0;
+        }
+        if (1 == style) {
+            return weekZhouDays[w];
+        } else {
+            return weekXingqiDays[w];
+        }
+    }
+
+    /**
+     * 给定月份,得到当月最后一天的零点
+     */
+    public static  String getLastTime(String date) throws Exception{
+        Calendar cal=Calendar.getInstance();
+        cal.setTime(new SimpleDateFormat("yyyy-MM").parse(date));
+        int lastDay=cal.getActualMaximum(Calendar.DAY_OF_MONTH);
+        cal.set(Calendar.DAY_OF_MONTH,lastDay);
+        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
+        String time=sdf.format(cal.getTime())+" 24:00:00";
+        return time;
+
+    }
+
+    /**
+     * 给定月份,得到当月第一天一天的零点
+     */
+    public static  String getBeginTime(String date) throws Exception{
+        Calendar cal=Calendar.getInstance();
+        cal.setTime(new SimpleDateFormat("yyyy-MM").parse(date));
+        cal.set(Calendar.DAY_OF_MONTH,1);
+        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
+        String time=sdf.format(cal.getTime())+" 00:00:00";
+        return time;
+
+    }
+
+  
+
+    
+    
+    //得到日历列表,包含周几
+    public static List<String[]> nextCalendarList() {
+        List<String[]> calendarList=new ArrayList<String[]>();
+	    Date d = nextMonthFirstDate(); 
+        Date date = getMonthStart(d);
+        Date monthEnd = getMonthEnd(d);
+        while (!date.after(monthEnd)) {
+           String[] dataStrs={DateHelper.format(date, "yyyy-MM-dd"),dateToWeek(date)};
+           calendarList.add(dataStrs);
+           date = getNext(date);
+        }
+    	return calendarList;
+    }
+    
+
+    
+   //取得上个月的1号
+    public static Date theMonthFirstDate(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.set(Calendar.DAY_OF_MONTH, 1);
+        calendar.add(Calendar.MONTH, -1);
+        return calendar.getTime();
+    }
+    
+    
+    //取得下个月的1号
+    public static Date nextMonthFirstDate() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.DAY_OF_MONTH, 1);
+        calendar.add(Calendar.MONTH, 1);
+        return calendar.getTime();
+    }
+ 
+    //当月的开始日期
+    public static Date getMonthStart(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        int index = calendar.get(Calendar.DAY_OF_MONTH);
+        calendar.add(Calendar.DATE, (1 - index));
+        return calendar.getTime();
+    }
+    //当月的结束日期
+    private static Date getMonthEnd(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(Calendar.MONTH, 1);
+        int index = calendar.get(Calendar.DAY_OF_MONTH);
+        calendar.add(Calendar.DATE, (-index));
+        return calendar.getTime();
+    }
+    //下一个日期
+    private static Date getNext(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(Calendar.DATE, 1);
+        return calendar.getTime();
+    }
+ 
+    //周几
+    public static String dateToWeek(Date date) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
+        return String.valueOf(weekDay[w]) ;
+    }
+    
+    //时间戳转换为标准日期
+
+    public  static  String getStandTime(Date date){
+        SimpleDateFormat format =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        return format.format(date);
+    }
+    
+	
+	 public static boolean dateQualsByMonth(Date dateOne, Date dateTwo) {
+       Calendar calendarOne = Calendar.getInstance();
+       calendarOne.setTime(dateOne);
+       Calendar calendarTwo = Calendar.getInstance();
+       calendarTwo.setTime(dateTwo);
+       return calendarOne.get(Calendar.YEAR) == calendarTwo.get(Calendar.YEAR) && calendarOne.get(Calendar.MONTH) == calendarTwo.get(Calendar.MONTH);
+	  } 
+	 
+	 public static boolean isLastDayOfMonth(Date curMonthDate,Date date) {
+	    Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		
+		Calendar maxCalendar = Calendar.getInstance();
+		maxCalendar.setTime(curMonthDate);
+		return calendar.get(Calendar.DAY_OF_MONTH) == maxCalendar
+				.getActualMaximum(Calendar.DAY_OF_MONTH);
+	 }
+
+    public static String getNextYear(int num) {
+        LocalDate today = LocalDate.now();
+        LocalDate nextYear = today.plus(num, ChronoUnit.YEARS);
+        return nextYear.getYear() + "";
+    }
+
+}

+ 157 - 0
src/main/java/com/aijia/basic/utils/EncryptUtil.java

@@ -0,0 +1,157 @@
+package com.aijia.basic.utils;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.UUID;
+
+/**
+ * 
+ * 类名称:EncryptUtil<br>
+ * 类描述:加密工具类<br>
+ * @version v1.0
+ *
+ */
+public class EncryptUtil {
+    private static final Logger logger = LoggerFactory.getLogger(EncryptUtil.class);
+    protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+    protected static MessageDigest messagedigest = null;
+    static {
+        try {
+            messagedigest = MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException e) {
+            logger.error("MD5FileUtil messagedigest初始化失败", e);
+        }
+    }
+
+    /**
+     * 获取文件的MD5值
+     * @param file
+     * @return
+     */
+    public static String getFileMD5String(File file) {
+        String fileMD5 = "未知";
+        FileInputStream in = null;
+        try {
+            in = new FileInputStream(file);
+            FileChannel ch = in.getChannel();
+            MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
+            messagedigest.update(byteBuffer);
+            fileMD5 = bufferToHex(messagedigest.digest());
+            IOUtils.closeQuietly(in);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            IOUtils.closeQuietly(in);
+        }
+        return fileMD5;
+    }
+
+    /**
+     * 获取文件的MD5值
+     * @param file
+     * @return
+     */
+    public static String getFileMD5String(MultipartFile fileItem) {
+        String fileMD5 = "未知";
+        try {
+            byte[] uploadBytes = fileItem.getBytes();
+            byte[] digest = messagedigest.digest(uploadBytes);
+            String hashString = new BigInteger(1, digest).toString(32);
+            fileMD5 = hashString.toUpperCase();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return fileMD5;
+    }
+
+    /**
+     * 通过字符串生成MD5
+     * @param s
+     * @return
+     */
+    public static String getMD5String(String s) {
+        return getMD5String(s.getBytes());
+    }
+
+    /**
+     * 获取一个字符串UUID
+     * @return
+     */
+    public static String getUUIDString() {
+        String uuid = UUID.randomUUID().toString();
+        // 去掉“-”符号
+        return uuid.replace("-", "");
+    }
+
+
+
+    /**
+     * 通过byte[]生成MD5
+     * @param s
+     * @return
+     */
+    public static String getMD5String(byte[] bytes) {
+        messagedigest.update(bytes);
+        return bufferToHex(messagedigest.digest());
+    }
+
+    /**
+     * 通过byte生成MD5
+     * @param s
+     * @return
+     */
+    private static String bufferToHex(byte bytes[]) {
+        return bufferToHex(bytes, 0, bytes.length);
+    }
+
+    private static String bufferToHex(byte bytes[], int m, int n) {
+        StringBuffer stringbuffer = new StringBuffer(2 * n);
+        int k = m + n;
+        for (int l = m; l < k; l++) {
+            appendHexPair(bytes[l], stringbuffer);
+        }
+        return stringbuffer.toString();
+    }
+
+    private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
+        char c0 = hexDigits[(bt & 0xf0) >> 4];
+        char c1 = hexDigits[bt & 0xf];
+        stringbuffer.append(c0);
+        stringbuffer.append(c1);
+    }
+
+    /**
+     * SHA1 加密
+     * @param input
+     * @return
+     * @throws NoSuchAlgorithmException
+     */
+    public static String SHA1(String input) {
+        StringBuffer sb = new StringBuffer();
+        try {
+            MessageDigest mDigest = MessageDigest.getInstance("SHA1");
+            byte[] result = mDigest.digest(input.getBytes());
+            for (int i = 0; i < result.length; i++) {
+                sb.append(Integer.toString((result[i] & 0xff) + 0x100, 16).substring(1));
+            }
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        }
+        return sb.toString();
+    }
+}
+

+ 58 - 0
src/main/java/com/aijia/basic/utils/ExceptionUtil.java

@@ -0,0 +1,58 @@
+package com.aijia.basic.utils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * 
+ * 类名称:ExceptionUtil<br>
+ * 类描述: 关于异常的工具类<br>
+ * 创建人:qinjiaxue<br>
+ * 创建时间:2015年12月17日 上午9:35:16<br>  
+ * @version v1.0
+ *
+ */
+public class ExceptionUtil {
+
+    /**
+     * 将CheckedException转换为UncheckedException
+     * @param e
+     * @return
+     */
+   /* public static RuntimeException unchecked(Exception e) {
+        if (e instanceof RuntimeException) {
+            return (RuntimeException) e;
+        } else {
+            return new RuntimeException(e);
+        }
+    }*/
+
+    /**
+     * 将ErrorStack转化为String
+     * @param e
+     * @return
+     */
+    public static String getStackTraceAsString(Exception e) {
+        StringWriter stringWriter = new StringWriter();
+        e.printStackTrace(new PrintWriter(stringWriter));
+        return "\r\n" + stringWriter.toString() + "\r\n";
+    }
+
+    /**
+     * 判断异常是否由某些底层的异常引起
+     * @param ex
+     * @param causeExceptionClasses
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+	public static boolean isCausedBy(Exception ex, Class<? extends Exception>... causeExceptionClasses) {
+        Throwable cause = ex.getCause();
+        while (cause != null) {
+            for (Class<? extends Exception> causeClass : causeExceptionClasses) {
+                if (causeClass.isInstance(cause)) { return true; }
+            }
+            cause = cause.getCause();
+        }
+        return false;
+    }
+}

+ 56 - 0
src/main/java/com/aijia/basic/utils/MD5.java

@@ -0,0 +1,56 @@
+package com.aijia.basic.utils;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MD5 {
+
+	private static final Logger logger = LoggerFactory.getLogger(MD5.class);
+
+	/** 
+	* MD5的算法在RFC1321 中定义 
+	* 在RFC 1321中,给出了Test suite用来检验你的实现是否正确: 
+	* MD5 ("") = d41d8cd98f00b204e9800998ecf8427e 
+	* MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661 
+	* MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72 
+	* MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0 
+	* MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b 
+	* 
+	* @author haogj 
+	* 
+	* 传入参数:一个字节数组 
+	* 传出参数:字节数组的 MD5 结果字符串 
+	*/ 
+
+	public static String getMD5(byte[] source) { 
+		String s = null; 
+		char hexDigits[] = { // 用来将字节转换成 16 进制表示的字符 
+		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 
+		try 
+		{ 
+			java.security.MessageDigest md = java.security.MessageDigest.getInstance( "MD5" ); 
+			md.update( source ); 
+			byte tmp[] = md.digest(); // MD5 的计算结果是一个 128 位的长整数, 
+			// 用字节表示就是 16 个字节 
+			char str[] = new char[16 * 2]; // 每个字节用 16 进制表示的话,使用两个字符, 
+			// 所以表示成 16 进制需要 32 个字符 
+			int k = 0; // 表示转换结果中对应的字符位置 
+			for (int i = 0; i < 16; i++) { // 从第一个字节开始,对 MD5 的每一个字节 
+			// 转换成 16 进制字符的转换 
+			byte byte0 = tmp[i]; // 取第 i 个字节 
+			str[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换, 
+			// >>> 为逻辑右移,将符号位一起右移 
+			str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换 
+			} 
+			s = new String(str); // 换后的结果转换为字符串
+	
+		}catch( Exception e ) 
+		{ 
+			logger.error("异常", e);
+		} 
+		return s; 
+	}
+	
+	
+}

+ 28 - 0
src/main/java/com/aijia/basic/utils/PhoneVerifyUtil.java

@@ -0,0 +1,28 @@
+package com.aijia.basic.utils;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author yanghuan
+ * @title: PhoneVerifyUtil
+ * @projectName ssj
+ * @description: 手机号校验
+ * @date 2020/4/9 16:12
+ */
+public class PhoneVerifyUtil {
+
+    public static boolean vertifyPhone(String phone){
+        boolean flag=true;
+        String regex="^((\\+86)|(86))?(1[2,3,4,5,6,7,8,9][0-9])\\d{8}$";
+        Pattern p = Pattern.compile(regex);
+        Matcher m = p.matcher(phone);
+        boolean isMatch = m.matches();
+        if(!isMatch){
+            flag=false;
+
+        }
+        return flag;
+
+    }
+}

+ 71 - 0
src/main/java/com/aijia/basic/utils/SHACoder.java

@@ -0,0 +1,71 @@
+package com.aijia.basic.utils;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+public class SHACoder {
+	/**
+	 * SHA-1消息摘要算法,返回字节数组
+	 *//*
+	@SuppressWarnings("deprecation")
+	public static byte[] encodeSHA(byte[] data) throws Exception {
+		return DigestUtils.sha(data);
+	}
+	
+	*//**
+	 * SHA-1消息摘要算法,返回十六进制字符串
+	 *//*
+	@SuppressWarnings("deprecation")
+	public static String encodeSHAHex(byte[] data) throws Exception {
+		return DigestUtils.shaHex(data);
+	}
+*/
+	/**
+	 * SHA-256消息摘要算法,返回字节数组
+	 */
+	public static byte[] encodeSHA256(byte[] data) throws Exception {
+		return DigestUtils.sha256(data);
+	}
+	
+	/**
+	 * SHA-256消息摘要算法,返回十六进制字符串
+	 */
+	public static String encodeSHA256Hex(byte[] data) throws Exception {
+		return DigestUtils.sha256Hex(data);
+	}
+
+	/**
+	 * SHA-384消息摘要算法,返回字节数组
+	 *//*
+	public static byte[] encodeSHA384(byte[] data) throws Exception {
+		return DigestUtils.sha384(data);
+	}
+	
+	*//**
+	 * SHA-384消息摘要算法,返回十六进制字符串
+	 *//*
+	public static String encodeSHA384Hex(byte[] data) throws Exception {
+		return DigestUtils.sha384Hex(data);
+	}
+	
+	*//**
+	 * SHA-512消息摘要算法,返回字节数组
+	 *//*
+	public static byte[] encodeSHA512(byte[] data) throws Exception {
+		return DigestUtils.sha512(data);
+	}
+	
+	*//**
+	 * SHA-512消息摘要算法,返回十六进制字符串
+	 * (更能确保唯一,但效率更低)
+	 *//*
+	public static String encodeSHA512Hex(byte[] data) throws Exception {
+		return DigestUtils.sha512Hex(data);
+	}
+	
+	
+	public static String encoderToMD5(String str) throws Exception {
+        //MessageDigest md5 = DigestUtils.getMd5Digest();
+        String newStr = DigestUtils.md5Hex(str);
+        return newStr;
+    }*/
+}

+ 205 - 0
src/main/java/com/aijia/basic/utils/StringUtils.java

@@ -0,0 +1,205 @@
+package com.aijia.basic.utils;
+
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 
+ * 类名称:StringUtils<br>
+ * 类描述:字符串工具类, 继承org.apache.commons.lang3.StringUtils类<br>
+ * @version v1.0
+ * 
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils {
+
+    /**
+     * 替换掉HTML标签方法
+     */
+    public static String replaceHtml(String html) {
+        if (isBlank(html)) {
+            return "";
+        }
+        // . 匹配除换行符以外的任意字符
+        // + 重复一次或更多次
+        // ? 重复零次或一次
+        String regEx = "<.+?>";
+        Pattern p = Pattern.compile(regEx);
+        Matcher m = p.matcher(html);
+        String s = m.replaceAll("");
+        return s;
+    }
+
+    /**
+     * 缩略字符串(不区分中英文字符)
+     * @param str 目标字符串
+     * @param length 截取长度
+     * @return
+     */
+    public static String abbr(String str, int length) {
+        if (str == null) {
+            return "";
+        }
+        try {
+            StringBuilder sb = new StringBuilder();
+            int currentLength = 0;
+            for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) {
+                currentLength += String.valueOf(c).getBytes("GBK").length;
+                if (currentLength <= length - 3) {
+                    sb.append(c);
+                } else {
+                    sb.append("...");
+                    break;
+                }
+            }
+            return sb.toString();
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+
+    /**
+     * 缩略字符串(替换html)
+     * @param str 目标字符串
+     * @param length 截取长度
+     * @return
+     */
+    public static String rabbr(String str, int length) {
+        return abbr(replaceHtml(str), length);
+    }
+
+    // 将首字母改成小写
+    public static String lowerFirst(String str) {
+        if (StringUtils.isBlank(str)) {
+            return "";
+        } else {
+            return str.substring(0, 1).toLowerCase() + str.substring(1);
+        }
+    }
+    // 将首字母改成大写
+    public static String upperFirst(String str) {
+        if (StringUtils.isBlank(str)) {
+            return "";
+        } else {
+            return str.substring(0, 1).toUpperCase() + str.substring(1);
+        }
+    }
+
+
+    /**
+     * 判断字符串是否为数字
+     */
+    public static boolean isNumeric(String str) {
+        return NumberUtils.isDigits(str);
+    }
+
+    /**
+     * 正向查找指定字符串
+     */
+    public static int indexOf(String str, String searchStr, boolean ignoreCase) {
+        if (ignoreCase) {
+            return StringUtils.indexOfIgnoreCase(str, searchStr);
+        } else {
+            return str.indexOf(searchStr);
+        }
+    }
+
+    /**
+     * 反向查找指定字符串
+     */
+    public static int lastIndexOf(String str, String searchStr, boolean ignoreCase) {
+        if (ignoreCase) {
+            return StringUtils.lastIndexOfIgnoreCase(str, searchStr);
+        } else {
+            return str.lastIndexOf(searchStr);
+        }
+    }
+
+    /**
+     * 将用分隔符分隔的字符串转换为list
+     * 
+     * @param str 字符串
+     * @param separator 分隔符,如","
+     * @return
+     */
+    public static List<String> splits(String str, String separator) {
+        String[] arr = str.split(separator);
+        return Arrays.asList(arr);
+    }
+
+    /**
+     * 将列表List<String>,转成字符串逗号隔开,前后带"'"
+     * 
+     * @param list
+     * @return
+     */
+    public static String join(List<String> list) {
+        String str = "";
+        for (int i = 0; i < list.size(); i++) {
+            if (i > 0) {
+                str += ",";
+            }
+            str += "'" + list.get(i) + "'";
+        }
+        return str;
+    }
+
+    /**
+     * 将列表List<String>,转成字符串逗号隔开
+     * 
+     * @param list
+     * @return
+     */
+    public static String join(List<String> list, String separator) {
+        String str = "";
+        for (int i = 0; i < list.size(); i++) {
+            if (i > 0) {
+                str += separator;
+            }
+            str += list.get(i);
+        }
+        return str;
+    }
+
+    /**
+     * 对url进行编码
+     */
+    public static String encodeURL(String url) {
+        try {
+            return URLEncoder.encode(url, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 对url进行解码
+     * @param url
+     * @return
+     */
+    public static String decodeURL(String url) {
+        try {
+            return URLDecoder.decode(url, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    
+    public static String pass2NormalStr (String str){
+        if (StringUtils.isEmpty(str) || "null".equals(str.toLowerCase())){
+            str = "";
+        }
+        return str;
+    }
+
+}

+ 13 - 0
src/main/java/com/aijia/contants/AuthConstants.java

@@ -0,0 +1,13 @@
+package com.aijia.contants;
+
+/**
+ * 自定义的常量
+ * 
+ * @author cc
+ *
+ */
+public interface AuthConstants {
+	public String tokenSuccess = "OK";
+	public String defaultValue = "1";// 随便设置的一个默认值,用于判断请求过于频繁
+	public int expireSeconds = 1;// 1秒过期时间
+}

+ 13 - 0
src/main/java/com/aijia/core/security/exception/CommonException.java

@@ -0,0 +1,13 @@
+package com.aijia.core.security.exception;
+
+/**
+ * 用于当出现异常用户操作时抛出,如参数错误、校验不通过等,给用户相应提示
+ */
+public class CommonException extends RuntimeException{
+
+	private static final long serialVersionUID = 3830014639818075432L;
+
+	public CommonException(String message) {
+        super(message);
+    }
+}

+ 20 - 0
src/main/java/com/aijia/core/security/exception/ConchException.java

@@ -0,0 +1,20 @@
+package com.aijia.core.security.exception;
+/** 
+ * @author  ZhangCaibao 
+ * @version 2018年4月11日 下午3:14:53 
+ * 类说明 
+ */
+public class ConchException extends RuntimeException{
+
+
+	private static final long serialVersionUID = -4473011039166845613L;
+
+		/**
+	     * 
+	     * 创建一个新的实例 ConchException.     
+	     * @param message
+	     */
+	    public ConchException(String message) {
+	        super(message);
+	    }
+}

+ 144 - 0
src/main/java/com/aijia/core/utils/CastUtil.java

@@ -0,0 +1,144 @@
+package com.aijia.core.utils;
+
+
+/**
+ * 
+ * 类名称:CastUtil<br>
+ * 类描述:转型操作工具类<br>
+ * @version v1.0
+ *
+ */
+public final class CastUtil {
+
+    /**
+     * 转为 String 型
+     * @param obj
+     * @return
+     */
+    public static String castString(Object obj) {
+        return CastUtil.castString(obj, "");
+    }
+
+    /**
+     * 转为 String 型(提供默认值)
+     * @param obj
+     * @param defaultValue
+     * @return
+     */
+    public static String castString(Object obj, String defaultValue) {
+        return obj != null ? String.valueOf(obj) : defaultValue;
+    }
+
+    /**
+     * 转为 double 型
+     * @param obj
+     * @return
+     */
+    public static double castDouble(Object obj) {
+        return CastUtil.castDouble(obj, 0);
+    }
+
+    /**
+     * 转为 double 型(提供默认值)
+     * @param obj
+     * @param defaultValue
+     * @return
+     */
+    public static double castDouble(Object obj, double defaultValue) {
+        double doubleValue = defaultValue;
+        if (obj != null) {
+            String strValue = castString(obj);
+            if (org.apache.commons.lang3.StringUtils.isNotEmpty(strValue)) {
+                try {
+                    doubleValue = Double.parseDouble(strValue);
+                } catch (NumberFormatException e) {
+                    doubleValue = defaultValue;
+                }
+            }
+        }
+        return doubleValue;
+    }
+
+    /**
+     * 转为 long 型
+     * @param obj
+     * @return
+     */
+    public static long castLong(Object obj) {
+        return CastUtil.castLong(obj, 0);
+    }
+
+    /**
+     * 转为 long 型
+     * @param obj
+     * @param defaultValue
+     * @return
+     */
+    public static long castLong(Object obj, long defaultValue) {
+        long longValue = defaultValue;
+        if (obj != null) {
+            String strValue = castString(obj);
+            if (org.apache.commons.lang3.StringUtils.isNotEmpty(strValue)) {
+                try {
+                    longValue = Long.parseLong(strValue);
+                } catch (NumberFormatException e) {
+                    longValue = defaultValue;
+                }
+            }
+        }
+        return longValue;
+    }
+
+    /**
+     * 转为 int 型
+     * @param obj
+     * @return
+     */
+    public static int castInt(Object obj) {
+        return CastUtil.castInt(obj, 0);
+    }
+
+    /**
+     * 转为 int 型(提供默认值)
+     * @param obj
+     * @param defaultValue
+     * @return
+     */
+    public static int castInt(Object obj, int defaultValue) {
+        int intValue = defaultValue;
+        if (obj != null) {
+            String strValue = castString(obj);
+            if (org.apache.commons.lang3.StringUtils.isNotEmpty(strValue)) {
+                try {
+                    intValue = Integer.parseInt(strValue);
+                } catch (NumberFormatException e) {
+                    intValue = defaultValue;
+                }
+            }
+        }
+        return intValue;
+    }
+
+    /**
+     * 转为 boolean 型
+     * @param obj
+     * @return
+     */
+    public static boolean castBoolean(Object obj) {
+        return CastUtil.castBoolean(obj, false);
+    }
+
+    /**
+     * 转为 boolean 型(提供默认值)
+     * @param obj
+     * @param defaultValue
+     * @return
+     */
+    public static boolean castBoolean(Object obj, boolean defaultValue) {
+        boolean booleanValue = defaultValue;
+        if (obj != null) {
+            booleanValue = Boolean.parseBoolean(castString(obj));
+        }
+        return booleanValue;
+    }
+}

+ 134 - 0
src/main/java/com/aijia/core/utils/CodecUtil.java

@@ -0,0 +1,134 @@
+package com.aijia.core.utils;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.UUID;
+/**
+ * 
+ * 类名称:CodecUtil<br>
+ * 类描述:编码与解码操作工具类<br>
+ * @version v1.0
+ *
+ */
+public class CodecUtil {
+
+    private static Logger logger = LoggerFactory.getLogger(CodecUtil.class);
+
+    /**
+     * 将 URL 编码
+     */
+    public static String encodeURL(String str) {
+        String target;
+        try {
+            target = URLEncoder.encode(str, "UTF-8");
+        } catch (Exception e) {
+            logger.error("编码出错!", e);
+            throw new RuntimeException(e);
+        }
+        return target;
+    }
+
+    /**
+     * 将 URL 解码
+     */
+    public static String decodeURL(String str) {
+        String target;
+        try {
+            target = URLDecoder.decode(str, "UTF-8");
+        } catch (Exception e) {
+            logger.error("解码出错!", e);
+            throw new RuntimeException(e);
+        }
+        return target;
+    }
+
+    /**
+     * 将字符串 Base64 编码
+     */
+    public static String encodeBASE64(String str) {
+        String target;
+        try {
+            target = Base64.encodeBase64URLSafeString(str.getBytes("UTF-8"));
+        } catch (UnsupportedEncodingException e) {
+            logger.error("编码出错!", e);
+            throw new RuntimeException(e);
+        }
+        return target;
+    }
+
+    /**
+     * 将字符串 Base64 解码
+     */
+    public static String decodeBASE64(String str) {
+        String target;
+        try {
+            target = new String(Base64.decodeBase64(str), "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            logger.error("解码出错!", e);
+            throw new RuntimeException(e);
+        }
+        return target;
+    }
+
+    /**
+     * 将字符串 MD5 加密
+     */
+    public static String encryptMD5(String str) {
+        return DigestUtils.md5Hex(str);
+    }
+
+    /**
+     *
+     * @param str 加密数据
+     * @param key 密钥
+     * @return
+     */
+    public static String encryptMD5(String str, String key) {
+        return DigestUtils.md5Hex("SSJ"+str+key);
+    }
+    /**
+     * MD5验证方法
+     *
+     * @param str 明文
+     * @param key 密钥
+     * @param md5 密文
+     * @return true/false
+     */
+    public static boolean verifyMD5(String str, String key, String md5) {
+        //根据传入的密钥进行验证
+        String md5Text = encryptMD5(str, key);
+        if (md5Text.equalsIgnoreCase(md5)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 将字符串 SHA 加密
+     */
+    public static String encryptSHA(String str) {
+        return DigestUtils.sha1Hex(str);
+    }
+
+    /**
+     * 创建随机数
+     */
+    public static String createRandom(int count) {
+       return RandomStringUtils.randomNumeric(count);
+    }
+ 
+    /**
+     * 获取 UUID(32位)
+     */
+    public static String createUUID() {
+        return UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
+    }
+
+}

+ 381 - 0
src/main/java/com/aijia/core/utils/Constant.java

@@ -0,0 +1,381 @@
+package com.aijia.core.utils;
+
+import java.util.*;
+
+public class Constant {
+	/**
+	 * 作业批注超时时间,30分钟
+	 */
+	public static final int HOME_WORK_OUTTIME = 30;
+
+	/**
+	 * 难题解答超时时间,20分钟
+	 */
+	public static final int PROBLEM_OUTTIME = 20;
+
+	/**
+	 * tb_lib_manager中校长的类别
+	 */
+	public static final int SCHOOL_MASTER_TYPE = 6;
+
+	/**
+	 * tb_lib_manager中馆长的类别
+	 */
+	public static final int CURATOR = 4;
+
+	/**
+	 * tb_lib_manager中在馆老师的类别
+	 */
+	public static final int TEACHER_TYPE = 2;
+
+	/**
+	 * tb_lib_manager一对一的老师类别
+	 */
+	public static final int KMT_121_TEACHER_TYPE = 7;
+
+	/**
+	 * tb_lib_manager中线上老师,和kmt 的老师
+	 */
+	public static final int KMT_122_TEACHER_TYPE = 8;
+
+	/**
+	 * tb_lib_manager小课老师的type
+	 */
+	public static final int GROUP_TEACHER_TYPE = 9;
+
+	/**
+	 * tb_lib_manager中学科老师的类别
+	 */
+	public static final int ORG_TEACHER_TYPE = 10;
+
+	/**
+	 * tb_lib_manager中管理员的类别
+	 */
+	public static final int CORRECT_MANAGER = 11;
+
+	/**
+	 * tb_lib_manager中批注质检员的类别
+	 */
+	public static final int CORRECT_CHECKER = 50;
+
+
+	/**
+	 * tb_lib_manager中超级管理员的类别
+	 */
+	public static final int CORRECT_SUPER_MANAGER = 12;
+
+	/**
+	 * tb_lib_manager中匹配知识点老师的类别
+	 */
+	public static final int KNOW_MATCH_TYPE = 13;
+
+	/**
+	 * 质检员类别
+	 */
+	public static final int HOMEWORK_CHECK_TYPE = 14;
+
+	/**
+	 * tb_lib_manager 机构作业自批注老师
+	 */
+	public static final int LIB_TEACHER_TYPE = 15;
+
+	/**
+	 * 作业批注
+	 */
+	public static final int TEACHER_TASK_HOMEWORK = 1;
+
+	/**
+	 * 难题反馈
+	 */
+	public static final int TEACHER_TASK_RPOBLEM = 2;
+
+	/**
+	 * 作业批注
+	 */
+	public static final int TEACHER_TASK_WORKFEEDBACK = 3;
+
+	/**
+	 * 年级
+	 */
+	public static final List<String> GRADE_LIST = Arrays.asList("一年级", "二年级", "三年级", "四年级", "五年级", "六年级");
+
+	/**
+	 * 学期
+	 */
+	public static final List<Integer> SEMESTER_LIST = Arrays.asList(1, 2);
+
+	/**
+	 * 知识点类型
+	 */
+	public static final List<Integer> SEMESTER_REVIEW_KNOWLEDGE_TYPE_LIST = Arrays.asList(-1, 0, 1);
+
+	/**
+	 * 服务列表
+	 */
+	public static final Map<String, String> SERVICE_MAP = new HashMap<String, String>();
+	/**
+	 * 录入
+	 */
+	public static final String CMB_DF_STATUS_I = "I";
+	/**
+	 * 成功
+	 */
+	public static final String CMB_DF_STATUS_S = "S";
+	/**
+	 * 失败
+	 */
+	public static final String CMB_DF_STATUS_F = "F";
+
+	/**
+	 * 正在获取状态
+	 */
+	public static final String CMB_DF_STATUS_C = "C";
+
+	/**
+	 * 录入
+	 */
+	public static final String WITHDRAWAL_STATUS_INIT = "INIT";
+	/**
+	 * 重新
+	 */
+	public static final String WITHDRAWAL_STATUS_REINIT = "REINIT";
+	/**
+	 * 错误
+	 */
+	public static final String WITHDRAWAL_STATUS_ERROR = "ERROR";
+	/**
+	 * 成功
+	 */
+	public static final String WITHDRAWAL_STATUS_SUCCESS = "SUCCESS";
+	/**
+	 * 失败
+	 */
+	public static final String WITHDRAWAL_STATUS_FAIL = "FAIL";
+
+	/**
+	 * 注册老师
+	 */
+	public static final String REGISTER_TEACHER = "注册老师";
+
+	/**
+	 * 资深老师
+	 */
+	public static final String SENIOR_TEACHER = "资深老师";
+	/**
+	 * 明星老师
+	 */
+	public static final String STAR_TEACHER = "明星老师";
+	/**
+	 * 学霸老师
+	 */
+	public static final String SUPER_TEACHER = "学霸老师";
+
+	/**
+	 * 小课老师
+	 */
+	public static final String GROUP_TEACHER = "小课老师";
+
+	/**
+	 * redis中已离开馆学生键值对的key的前缀,完整key为:key的前缀+馆id
+	 */
+	public static final String EXITED_STUDENT_PREFIX = "EXITED_STUDENT_";
+
+	/**
+	 * redis中同步锁key的前缀,完整key为:key的前缀+学生id
+	 */
+	public static final String SIGN_LOCK_PREFIX = "SIGN_LOCK_";
+
+	/**
+	 * redis中es保存出错的题目id的key
+	 */
+	public static final String ES_SAVE_ERROR_QUESTIONS = "ES_SAVE_ERROR_QUESTIONS";
+
+	/**
+	 * 各端app平台类型
+	 */
+	public static final Integer CONCH_PLATFORM_TYPE = 1;
+	public static final Integer PARENT_PLATFORM_TYPE = 2;
+	public static final Integer STUDENT_PLATFORM_TYPE = 3;
+	public static final Integer TEACHER_PLATFORM_TYPE = 4;
+	public static final Integer SCHOOL_MASTER_PLATFORM_TYPE = 5;
+
+	public static final String PREVIOUS50_HOMEWORK_RANK = "PREVIOUS50_HOMEWORK_RANK";
+
+	/**
+	 * 提分训练,推题时排除这些考点
+	 */
+	public static final String EXCLUDED_KD_ID_OF_TRAIN_RECOMMEND = "EXCLUDED_KD_ID_OF_TRAIN_RECOMMEND";
+
+	/**
+	 * 提分训练,推题时排除这些知识点
+	 */
+	public static final String EXCLUDED_HOW_DETAIL_ID_OF_TRAIN_RECOMMEND = "EXCLUDED_HOW_DETAIL_ID_OF_TRAIN_RECOMMEND";
+
+	public static final Map<String, String> ZYB_CARD_TYPE = new HashMap<String, String>();
+
+	public static final String TEACHERAPP_URL = "https://img.sharingschool.com/aijiaH5/SSJAPPDownload/teacher.html";
+
+	public static final String PARENTAPP_URL = "https://img.sharingschool.com/aijiaH5/SSJAPPDownload/user.html";
+
+	/**
+	 * 练习册最大数量
+	 */
+	public static final int MAX_ROWS_COUNT = 5000;
+
+//    /**
+//     * 题目类型
+//     */
+//    public static final List<QuestionSubjectAttribute> QUESTION_TYPES = JSONArray.parseArray(PropertiesUtil.getValue("QUESTION_TYPES"), QuestionSubjectAttribute.class);
+//
+//    /**
+//     * 难度级别
+//     */
+//    public static final List<KnowledgeBaseDto> DIFFICULTY_LEVELS = JSONArray.parseArray(PropertiesUtil.getValue("DIFFICULTY_LEVELS"), KnowledgeBaseDto.class);
+//
+//    /**
+//     * 真题例题练习题
+//     */
+//    public static final List<KnowledgeBaseDto> REAL_EXAM_TYPE = JSONArray.parseArray(PropertiesUtil.getValue("REAL_EXAM_TYPE"), KnowledgeBaseDto.class);
+//
+//    /**
+//     * 能力
+//     */
+//    public static final List<QuestionSubjectAttribute> TRAINING_SKILL =  JSONArray.parseArray(PropertiesUtil.getValue("TRAINING_SKILL"), QuestionSubjectAttribute.class);
+
+
+	/**
+	 * 保存文件所在路径的key,eg.FILE_MD5:1243jkalsjflkwaejklgjawe
+	 */
+	public static final String FILE_MD5_KEY = "FILE_MD5:";
+	/**
+	 * 保存上传文件的状态
+	 */
+	public static final String FILE_UPLOAD_STATUS = "FILE_UPLOAD_STATUS";
+
+	/**
+	 * 练习册题目类型
+	 */
+	public static final Map<Integer, String> QUESTION_TYPE_MAP = new HashMap<>();
+
+	static {
+		SERVICE_MAP.put("S003", "作业吧");
+		SERVICE_MAP.put("S010", "一对一");
+
+		ZYB_CARD_TYPE.put("C001", "年卡");
+		ZYB_CARD_TYPE.put("C002", "半年卡");
+		ZYB_CARD_TYPE.put("C003", "月卡");
+		ZYB_CARD_TYPE.put("C004", "作业吧月卡");
+		ZYB_CARD_TYPE.put("C005", "作业吧半年卡");
+		ZYB_CARD_TYPE.put("C006", "作业吧年卡");
+		ZYB_CARD_TYPE.put("C015", "季度卡");
+
+		QUESTION_TYPE_MAP.put(1, "选择题");
+		QUESTION_TYPE_MAP.put(2, "多选项");
+		QUESTION_TYPE_MAP.put(3, "填空题");
+		QUESTION_TYPE_MAP.put(4, "简答题");
+		QUESTION_TYPE_MAP.put(6, "计算题");
+		QUESTION_TYPE_MAP.put(7, "作文题");
+		QUESTION_TYPE_MAP.put(8, "判断题");
+		QUESTION_TYPE_MAP.put(9, "连线题");
+		QUESTION_TYPE_MAP.put(10, "翻译题");
+		QUESTION_TYPE_MAP.put(11, "匹配题");
+		QUESTION_TYPE_MAP.put(12, "阅读题");
+		QUESTION_TYPE_MAP.put(13, "语音题");
+		QUESTION_TYPE_MAP.put(14, "操作题");
+		QUESTION_TYPE_MAP.put(16, "课外阅读题");
+		QUESTION_TYPE_MAP.put(17, "解决问题");
+		QUESTION_TYPE_MAP.put(18, "看图列式");
+		QUESTION_TYPE_MAP.put(19, "情景交际");
+		QUESTION_TYPE_MAP.put(20, "听力题");
+		QUESTION_TYPE_MAP.put(21, "口语题");
+		QUESTION_TYPE_MAP.put(22, "课内阅读题");
+		QUESTION_TYPE_MAP.put(23, "朗读背诵题");
+	}
+
+	public static final String getSubjectFromRequest(String subject) {
+		if ("YUWEN".equals(subject)) {
+			subject = "语文";
+		} else if ("YINGYU".equals(subject)) {
+			subject = "英语";
+		} else if ("SHUXUE".equals(subject)) {
+			subject = "数学";
+		}
+		return subject;
+	}
+
+	/**
+	 * 获取中文汉字数字
+	 * @param num
+	 * @return
+	 */
+	public static String getChineseNumberByNumber (int num){
+		String[] chinese = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
+		String[] unit = { "十", "百", "千", "万", "十", "百", "千", "亿", "十", "百", "千" };
+		if (num > 0){
+			char[] numChar = (num + "").toCharArray();
+			StringBuffer sb = new StringBuffer();
+			int size = numChar.length;
+			for (int i = 0; i < numChar.length; i++) {
+				int tempNum = Integer.parseInt(String.valueOf(numChar[i]));
+				if(i != 0){
+					if (sb.length() > 0 && "零".equals(sb.substring(sb.length() - 1, sb.length()))){
+						if (tempNum != 0){
+							sb.append(chinese[tempNum]);
+						}
+					} else {
+						sb.append(unit[size-i-1]+chinese[tempNum]);
+					}
+				} else {
+					sb.append(chinese[tempNum]);
+				}
+			}
+			if (sb.length() > 2 && "一十".equals(sb.substring(0, 2))){
+				sb.deleteCharAt(0);
+			}
+			if (sb.length() > 0 && "零".equals(sb.substring(sb.length() - 1, sb.length()))){
+				sb.deleteCharAt(sb.length() - 1);
+			}
+			return sb.toString();
+		} else {
+			return "";
+		}
+	}
+
+	/**
+	 * 把解析json转成html
+	 * 
+	 * @return
+	 */
+	public static final String changeAnalysisJson2AnalysisHtml(List<Map> arr) {
+		String result = null;
+		if (arr != null && arr.size() > 0) {
+			List<String> htmlList = new ArrayList<>();
+			for (Map<String, Object> a : arr) {
+				List<Map<String, Object>> list = (List<Map<String, Object>>) a.get("list");
+				List<String> htmlLi = new ArrayList<>();
+				for (Map<String, Object> c : list) {
+					Map<String, Object> style = (Map<String, Object>) c.get("style");
+					String value = (String) c.get("value");
+					int type = (int) c.get("type");
+					int width = (int) style.get("width");
+					int height = (int) style.get("height");
+					if (type == 1) {
+						htmlLi.add("<span>" + value + "</span>");
+					} else if (type == 2) {
+						htmlLi.add("<img src=\"" + value + "\" style=\"width: " + width + "px; height: " + height
+								+ "px;\" alt=\"题目解析\"/>");
+					}
+				}
+				if (htmlLi.size() > 0) {
+					htmlList.add(
+							"<div style=\"display: -webkit-flex; display: flex; -webkit-flex-direction: row; flex-direction: row; -webkit-flex-wrap: wrap; flex-wrap: wrap; -webkit-justify-content: flex-start; justify-content: flex-start; -webkit-align-items: flex-start; align-items: flex-start; margin: 0 50px 25px 0;\">"
+									+ StringUtil.join(htmlLi, "") + "</div>");
+				}
+			}
+			result = "<div style=\"width: 100%; display: -webkit-flex; display: flex; -webkit-flex-direction: column; flex-direction: column; -webkit-flex-wrap: wrap; flex-wrap: wrap; -webkit-justify-content: flex-start; justify-content: flex-start; -webkit-align-items: flex-start; align-items: flex-start;\">"
+					+ StringUtil.join(htmlList, "") + "</div>";
+		}
+		return result;
+	}
+
+}

+ 249 - 0
src/main/java/com/aijia/core/utils/HttpRemote.java

@@ -0,0 +1,249 @@
+package com.aijia.core.utils;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.entity.BufferedHttpEntity;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.message.BasicNameValuePair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * 
+ * 类名称:Remote<br>
+ * 类描述: HttpClient 远程请求访问类<br>
+ * @version v1.0
+ * 
+ */
+public class HttpRemote {
+
+    private static final Logger logger = LoggerFactory.getLogger(HttpRemote.class);
+    
+
+    /**
+     * 以Post方法访问 字符串拼接到后面的URL
+     * @param url 请求地址
+     * @param argsMap 携带的参数
+     * @return String 返回结果
+     * @throws Exception
+     */
+    public static String POSTMethod(String url, Map<String, Object> argsMap) throws Exception {
+        byte[] dataByte = null;
+
+        // DefaultHttpClient已作废
+        // HttpClient httpClient=new DefaultHttpClient();
+
+        // 创建HttpClientBuilder
+        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
+        // HttpClient
+        CloseableHttpClient httpClient = httpClientBuilder.build();
+
+        HttpPost httpPost = new HttpPost(url);
+        // 设置参数
+        UrlEncodedFormEntity encodedFormEntity = new UrlEncodedFormEntity(setHttpParams(argsMap), "UTF-8");
+        logger.debug("POST请求参数为:" + IOUtils.toString(encodedFormEntity.getContent()));
+        httpPost.setEntity(encodedFormEntity);
+        // 执行请求
+        HttpResponse httpResponse = httpClient.execute(httpPost);
+        // 获取返回的数据
+        HttpEntity httpEntity = httpResponse.getEntity();
+        if (httpEntity != null) {
+            byte[] responseBytes = getData(httpEntity);
+            dataByte = responseBytes;
+            httpPost.abort();
+        }
+        // 将字节数组转换成为字符串
+        String result = bytesToString(dataByte);
+        return result;
+    }
+    /**
+     * header 'Content-Type: application/json' --header 'Accept: application/json'
+     * 以body方式提交json数据
+    * @param url
+    * @param body
+    * @return
+    * @throws Exception
+    * 创建人:ZhangCaibao 
+    * 2018年4月24日 下午2:22:14 
+    * @String
+     */
+    public static String POSTMethod(String url, String body) throws Exception {
+    	byte[] dataByte = null;
+    	
+    	
+    	// 创建HttpClientBuilder
+    	HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
+    	// HttpClient
+    	CloseableHttpClient httpClient = httpClientBuilder.build();
+    	
+    	HttpPost httpPost = new HttpPost(url);
+    	httpPost.addHeader("Content-Type", "application/json");
+    	// 设置参数
+    	logger.debug("POST请求参数为:" + body);
+    	httpPost.setEntity(new StringEntity(body, "utf-8"));
+    	// 执行请求
+    	HttpResponse httpResponse = httpClient.execute(httpPost);
+    	// 获取返回的数据
+    	HttpEntity httpEntity = httpResponse.getEntity();
+    	if (httpEntity != null) {
+    		byte[] responseBytes = getData(httpEntity);
+    		dataByte = responseBytes;
+    		httpPost.abort();
+    	}
+    	// 将字节数组转换成为字符串
+    	String result = bytesToString(dataByte);
+    	return result;
+    }
+
+    /**
+     * iopooooooliil 以Get方法访问
+     * @param url 请求地址
+     * @return String
+     * @throws Exception
+     */
+    public static String GETMethod(String url, Map<String, Object> argsMap) throws Exception {
+        byte[] dataByte = null;
+        // 创建HttpClientBuilder
+        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
+        // HttpClient
+        CloseableHttpClient httpClient = httpClientBuilder.build();
+        // 为GET请求链接构造参数
+        url = formatGetParameter(url, argsMap);
+        HttpGet httpGet = new HttpGet(url);
+        httpGet.addHeader("Content-Type", "application/json");
+        HttpResponse httpResponse = httpClient.execute(httpGet);
+        HttpEntity httpEntity = httpResponse.getEntity();
+        if (httpEntity != null) {
+            byte[] responseBytes = getData(httpEntity);
+            dataByte = responseBytes;
+            httpGet.abort();
+        }
+        // 将字节数组转换成为字符串
+        String result = bytesToString(dataByte);
+        return result;
+    }
+
+    /**
+     * 以Put方法访问
+     * @param url 请求地址
+     * @param argsMap 携带的参数
+     * @return String
+     * @throws Exception
+     */
+    public static String PUTMethod(String url, Map<String, Object> argsMap) throws Exception {
+        byte[] dataByte = null;
+        // 创建HttpClientBuilder
+        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
+        // HttpClient
+        CloseableHttpClient httpClient = httpClientBuilder.build();
+        HttpPut httpPut = new HttpPut(url);
+        // 设置参数
+        UrlEncodedFormEntity encodedFormEntity = new UrlEncodedFormEntity(setHttpParams(argsMap), "UTF-8");
+        httpPut.setEntity(encodedFormEntity);
+        // 执行请求
+        HttpResponse httpResponse = httpClient.execute(httpPut);
+        // 获取返回的数据
+        HttpEntity httpEntity = httpResponse.getEntity();
+        if (httpEntity != null) {
+            byte[] responseBytes = getData(httpEntity);
+            dataByte = responseBytes;
+            httpPut.abort();
+        }
+        // 将字节数组转换成为字符串
+        String result = bytesToString(dataByte);
+        return result;
+    }
+
+    /**
+     * 构造GET请求地址的参数拼接
+     * @param url
+     * @param argsMap
+     * @return String
+     */
+    private static String formatGetParameter(String url, Map<String, Object> argsMap) {
+        if (url != null && url.length() > 0) {
+            if (!url.endsWith("?")) {
+                url = url + "?";
+            }
+
+            if (argsMap != null && !argsMap.isEmpty()) {
+                Set<Entry<String, Object>> entrySet = argsMap.entrySet();
+                Iterator<Entry<String, Object>> iterator = entrySet.iterator();
+                while (iterator.hasNext()) {
+                    Entry<String, Object> entry = iterator.next();
+                    if (entry != null) {
+                        String key = entry.getKey();
+                        String value = (String) entry.getValue();
+                        url = url + key + "=" + value;
+                        if (iterator.hasNext()) {
+                            url = url + "&";
+                        }
+                    }
+                }
+            }
+        }
+        return url;
+    }
+
+    /**
+     * 获取数据
+     * @param httpEntity
+     * @return
+     * @throws Exception
+     */
+    private static byte[] getData(HttpEntity httpEntity) throws Exception {
+        BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(httpEntity);
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        bufferedHttpEntity.writeTo(byteArrayOutputStream);
+        byte[] responseBytes = byteArrayOutputStream.toByteArray();
+        return responseBytes;
+    }
+
+    /**
+     * 设置HttpPost请求参数
+     * @param argsMap
+     * @return BasicHttpParams
+     */
+    private static List<BasicNameValuePair> setHttpParams(Map<String, Object> argsMap) {
+        List<BasicNameValuePair> nameValuePairList = new ArrayList<BasicNameValuePair>();
+        // 设置请求参数
+        if (argsMap != null && !argsMap.isEmpty()) {
+            Set<Entry<String, Object>> set = argsMap.entrySet();
+            Iterator<Entry<String, Object>> iterator = set.iterator();
+            while (iterator.hasNext()) {
+                Entry<String, Object> entry = iterator.next();
+                String key = entry.getKey();
+                String value = CastUtil.castString(entry.getValue());
+                BasicNameValuePair basicNameValuePair = new BasicNameValuePair(key, value);
+                nameValuePairList.add(basicNameValuePair);
+            }
+        }
+        return nameValuePairList;
+    }
+
+    /**
+     * 将字节数组转换成字符串
+     * @param bytes
+     * @return
+     * @throws UnsupportedEncodingException
+     */
+    private static String bytesToString(byte[] bytes) throws UnsupportedEncodingException {
+        if (bytes != null) {
+            String returnStr = new String(bytes, "utf-8");
+            return returnStr;
+        }
+        return null;
+    }
+}

+ 200 - 0
src/main/java/com/aijia/core/utils/MapGetterTool.java

@@ -0,0 +1,200 @@
+package com.aijia.core.utils;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * Map取值方法,其中取得多种值,避免null值转换
+ *
+ * @author Mount Liu
+ * @date 2019/5/23
+ */
+public class MapGetterTool {
+
+    private Map<String, Object> map;
+
+    public MapGetterTool(Map<String, Object> map) {
+        this.map = map;
+    }
+
+    /**
+     * 根据Key返回一个Double型
+     *
+     * @param key
+     * @return
+     */
+    public Double getDouble(String key) {
+        if (map.get(key) != null) {
+            if (map.get(key) instanceof Double) {
+                return (Double) map.get(key);
+            } else {
+                return 0.0;
+            }
+        } else {
+            return 0.00;
+        }
+    }
+
+    /**
+     * 根据Key返回一个Double型
+     *
+     * @param key
+     * @return
+     */
+    public Long getLong(String key) {
+        if (map.get(key) != null) {
+            if (map.get(key) instanceof Long) {
+                return (Long) map.get(key);
+            } else {
+                return 0L;
+            }
+        } else {
+            return 0L;
+        }
+    }
+
+    /**
+     * 根据Key返回一个String
+     *
+     * @param key
+     * @return String
+     */
+    public String getString(String key) {
+        if (map.get(key) != null) {
+            if (map.get(key) instanceof String) {
+                return (String) map.get(key);
+            } else {
+                return null;
+            }
+        } else {
+            return "";
+        }
+    }
+
+    public String getStringNoNull(String key) {
+        if (map.get(key) != null) {
+            if (map.get(key) instanceof String) {
+                String result = (String) map.get(key);
+                return result != null ? result : "";
+            } else {
+                return "";
+            }
+        } else {
+            return "";
+        }
+    }
+
+    /**
+     * 根据Key返回一个Date
+     *
+     * @param key
+     * @return Date
+     */
+    public Date getDate(String key) {
+        if (map.get(key) != null) {
+            if (map.get(key) instanceof Date) {
+                return (Date) map.get(key);
+            } else {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 根据Key返回一个Integer
+     *
+     * @param key
+     * @return Integer
+     */
+    public Integer getInteger(String key) {
+        if (map.get(key) != null) {
+            if (map.get(key) instanceof Integer) {
+                return (Integer) map.get(key);
+            } else if (map.get(key) instanceof BigInteger) {
+                return ((BigInteger) map.get(key)).intValue();
+            } else {
+                return null;
+            }
+        } else {
+            return 0;
+        }
+    }
+
+    /**
+     * 根据Key返回一个BigInteger
+     *
+     * @param key
+     * @return BigInteger
+     */
+    public BigInteger getBigInteger(String key) {
+        if (map.get(key) != null) {
+            if (map.get(key) instanceof BigInteger) {
+                return (BigInteger) map.get(key);
+            } else {
+                return null;
+            }
+        } else {
+            return BigInteger.valueOf(0);
+        }
+    }
+
+    /**
+     * 根据一个Key返回一个Map<String,String>
+     *
+     * @param key
+     * @return Map<String, String>
+     */
+    @SuppressWarnings("unchecked")
+    public Map<String, String> getMap(String key) {
+        if (map.get(key) != null) {
+            if (map.get(key) instanceof Map) {
+                return (Map<String, String>) map.get(key);
+            } else {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 根据key返回BigDecimal
+     * 如果为null,则返回 new BigDecimal(0)
+     *
+     * @param key
+     * @return BigDecimal
+     */
+    public BigDecimal getBigDecimal(String key) {
+        if (map.containsKey(key)) {
+            if (map.get(key) instanceof BigDecimal) {
+                return (BigDecimal) map.get(key);
+            } else {
+                return new BigDecimal(0);
+            }
+        } else {
+            return new BigDecimal(0);
+        }
+    }
+
+    /**
+     * 获取布尔类型的值
+     * @param key
+     * @return
+     */
+    public Boolean getBoolean(String key) {
+        if (map.containsKey(key)) {
+            if (map.get(key) instanceof Boolean) {
+                return (Boolean) map.get(key);
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+}

+ 54 - 0
src/main/java/com/aijia/core/utils/RedisConstants.java

@@ -0,0 +1,54 @@
+package com.aijia.core.utils;
+
+
+public class RedisConstants {
+	
+	public static final String spilt=":";
+
+	/**
+	 * redis库1  保存档案树
+	 */
+	public static final Integer datebase1=1;
+
+	/**
+	 * 1.redis库2 保存档案表格
+	 * 2.保存分页码
+	 */
+	public static final Integer datebase2=2;
+
+	/**
+	 * redis库3 保存档案image url
+	 */
+	public static final Integer datebase3=3;
+
+	/**
+	 * 1.redis库4 保存手机验证码
+	 *
+	 */
+	public static final Integer datebase4=4;
+
+	/**
+	 * redis库5 保存身份认证信息
+	 */
+	public static final Integer datebase5=5;
+
+	/**
+	 * redis库6 记录身份认证次数
+	 */
+	public static final Integer datebase6=6;
+
+	/**
+	 * redis库7 记录重发次数
+	 */
+	public static final Integer datebase7=7;
+
+	/**
+	 * redis库8 记录任务参数
+	 */
+	public static final Integer datebase8=8;
+
+	
+	public RedisConstants() {
+
+	}
+}

+ 52 - 0
src/main/java/com/aijia/core/utils/StringUtil.java

@@ -0,0 +1,52 @@
+package com.aijia.core.utils;
+
+import java.util.Collection;
+import java.util.Map;
+
+
+
+public class StringUtil extends  org.apache.commons.lang3.StringUtils {
+	
+	
+
+	
+    public static <T> boolean isEmpty(T[] obj) {
+        return (obj == null) || (obj.length == 0);
+    }
+
+    public static boolean isEmpty(Object obj) {
+        if (obj == null) {
+            return true;
+        }
+        if ((obj instanceof String)) {
+            return (String.valueOf(obj)).trim().isEmpty();
+        }
+        if (obj instanceof CharSequence) {
+            return ((CharSequence) obj).length() == 0;
+        }
+        if (obj instanceof Number) {
+            return false;
+        }
+        return false;
+    }
+    public static String formateStr (String str){
+        if (isEmpty(str)){
+            return "";
+        } else {
+            return str;
+        }
+    }
+    @SuppressWarnings("rawtypes")
+    public static boolean isEmpty(Collection obj) {
+        return (obj == null) || (obj.isEmpty());
+    }
+
+    @SuppressWarnings("rawtypes")
+    public static boolean isEmpty(Map obj) {
+        return (obj == null) || (obj.isEmpty());
+    }
+
+
+   
+
+}

+ 90 - 0
src/main/java/com/aijia/core/web/BaseController.java

@@ -0,0 +1,90 @@
+package com.aijia.core.web;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * 
+ * 类名称:BaseController<br>
+ * 类描述: Controller基类<br>
+ * 
+ * @version v1.0
+ *
+ */
+public abstract class BaseController {
+
+//	 protected Logger logger = LoggerFactory.getLogger("aijia");
+
+	@Autowired
+	protected HttpServletRequest request;
+
+	@Autowired
+	protected HttpServletResponse response;
+
+
+
+	/**
+	 * 初始化分页查询参数Page
+	 *
+	 * @param pageNo
+	 * @param pageSize
+	 * @return
+	 */
+	protected Pageable initPage(Integer pageNo, Integer pageSize) {
+		// @RequestParam在处理不存在的参数时,赋值为null,基本类型无法为null,改为包装类型
+		if (pageNo == null) {
+			pageNo = 0;
+		}
+		if (pageSize == null) {
+			pageSize = 0;
+		}
+		pageNo = pageNo == 0 ? 0 : pageNo - 1;
+		pageSize = pageSize == 0 ? 10 : pageSize;
+		Pageable page = new PageRequest(pageNo, pageSize);
+		return page;
+	}
+
+	/**
+	 * 初始化分页查询参数Page
+	 *
+	 * @param pageNo
+	 * @param pageSize
+	 * @param direction
+	 * @param properties
+	 * @return
+	 */
+	protected Pageable initPage(Integer pageNo, Integer pageSize, Sort.Direction direction, String... properties) {
+		if (pageNo == null) {
+			pageNo = 0;
+		}
+		if (pageSize == null) {
+			pageSize = 0;
+		}
+		pageNo = pageNo == 0 ? 0 : pageNo - 1;
+		pageSize = pageSize == 0 ? 10 : pageSize;
+		Pageable page = new PageRequest(pageNo, pageSize, direction, properties);
+		return page;
+	}
+
+	protected Map<String, Object> getPageResultMap(Page page) {
+		Map<String, Object> resultMap = new HashMap<>();
+		if (page != null) {
+			resultMap.put("pages", page.getTotalPages());
+			resultMap.put("pageNo", page.getNumber() + 1);
+			resultMap.put("pageSize", page.getSize());
+			resultMap.put("list", page.getContent());
+		}
+		return resultMap;
+	}
+
+
+}

+ 24 - 0
src/main/java/com/aijia/core/web/BaseRequest.java

@@ -0,0 +1,24 @@
+package com.aijia.core.web;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.serializer.SerializeConfig;
+import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ *
+ */
+public class BaseRequest implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	@Override
+	public String toString() {
+		SerializeConfig mapping = new SerializeConfig();
+		mapping.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
+		return JSON.toJSONString(this);
+	}
+
+}

+ 40 - 0
src/main/java/com/aijia/core/web/MyResponseConstant.java

@@ -0,0 +1,40 @@
+package com.aijia.core.web;
+
+/**
+ * 
+ * 类名称:ResponseCode<br>
+ * 类描述:返回常量<br>
+ * @version v1.0
+ *
+ */
+public class MyResponseConstant {
+
+    public static final int CODE_OK = 0;
+    
+    public static final String MSG_OK = "OK";
+
+    /**
+     * 401 Unauthorized
+     */
+    public static final int CODE_401 = 401;
+    
+    /**
+     * 403 Forbidden
+     */
+    public static final int CODE_403 = 403;
+    
+    /**
+     * 404 Not Found
+     */
+    public static final int CODE_404 = 404;
+    
+    /**
+     * 服务器问题
+     */
+    public static final int CODE_500 = 500;
+    /**
+     * 请求太频繁
+     */
+    public static final int CODE_503 = 503;
+    
+}

+ 153 - 0
src/main/java/com/aijia/core/web/MyResponseEntity.java

@@ -0,0 +1,153 @@
+package com.aijia.core.web;
+
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.util.*;
+ 
+public class MyResponseEntity extends HashMap<String, Object> {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -6725416360588540451L;
+
+	public static MyResponseEntity success(String msg){
+        MyResponseEntity response = new MyResponseEntity();
+        response.setCode(MyResponseConstant.CODE_OK);
+        response.setMsg(msg);
+        return response;
+    }
+	
+	public static MyResponseEntity success(int code,String msg){
+        MyResponseEntity response = new MyResponseEntity();
+        response.setCode(code);
+        response.setMsg(msg);
+        return response;
+    }
+ 
+    public static MyResponseEntity failure(String msg){
+        MyResponseEntity response = new MyResponseEntity();
+        response.setCode(MyResponseConstant.CODE_500);
+        response.setMsg(msg);
+        return response;
+    }
+    
+    public static MyResponseEntity failure(int code,String msg){
+        MyResponseEntity response = new MyResponseEntity();
+        response.setCode(code);
+        response.setMsg(msg);
+        return response;
+    }
+    
+	public static MyResponseEntity success(String key, Object value){
+        MyResponseEntity response = new MyResponseEntity();
+        response.setCode(MyResponseConstant.CODE_OK);
+        response.setMsg(MyResponseConstant.MSG_OK);
+        response.setAny(key, value);
+        return response;
+    }
+	
+	public static MyResponseEntity success(Map<String,Object> map){
+        MyResponseEntity response = new MyResponseEntity();
+        response.setCode(MyResponseConstant.CODE_OK);
+        response.setMsg(MyResponseConstant.MSG_OK);
+        response.putAll(map);
+        return response;
+    }
+	
+	public static MyResponseEntity success(List<Map<String,Object>> queueList){
+        MyResponseEntity response = new MyResponseEntity();
+        response.setCode(MyResponseConstant.CODE_OK);
+        response.setMsg(MyResponseConstant.MSG_OK);
+        response.setAny("queueList", queueList);
+        return response;
+    }
+	
+	public static MyResponseEntity success(List<Map<String,Object>> queueList,int totalSize){
+        MyResponseEntity response = new MyResponseEntity();
+        response.setCode(MyResponseConstant.CODE_OK);
+        response.setMsg(MyResponseConstant.MSG_OK);
+        response.setAny("queueList", queueList);
+        response.setAny("totalSize", totalSize);
+        return response;
+    }
+	
+	public static MyResponseEntity success(Object bean){
+		if(bean instanceof Map) {
+			return success((Map<String,Object>)bean);
+		}
+		
+		MyResponseEntity response = new MyResponseEntity();
+	    response.setCode(MyResponseConstant.CODE_OK);
+	    response.setMsg(MyResponseConstant.MSG_OK);
+	        
+	    response.beanToMap(bean,false);
+        return response;
+    }
+	
+	/** 如果returnNull=true,表示对象属性为null也输出
+	 * @param bean
+	 * @param returnNull
+	 * @return
+	 */
+	public static MyResponseEntity success(Object bean,boolean returnNull){
+		if(bean instanceof Map) {
+			return success((Map<String,Object>)bean);
+		}
+		
+		MyResponseEntity response = new MyResponseEntity();
+	    response.setCode(MyResponseConstant.CODE_OK);
+	    response.setMsg(MyResponseConstant.MSG_OK);
+	        
+	    response.beanToMap(bean,returnNull);
+		
+        return response;
+    }
+	
+    public MyResponseEntity append(String key, Object value) {
+        if (key != null && value != null) put(key, value);
+        return this;
+    }
+ 
+    private MyResponseEntity setCode(int code) {
+        put("code", code);
+        return this;
+    }
+ 
+    private MyResponseEntity setMsg(String msg) {
+        put("msg", msg);
+        return this;
+    }
+ 
+    private MyResponseEntity setAny(String key, Object value) {
+        if (key != null && value != null) put(key, value);
+        return this;
+    }
+    
+    private void beanToMap(Object bean,boolean returnNull ) {
+	    try {
+	        Arrays.asList(Introspector.getBeanInfo(bean.getClass(), Object.class)
+	                                          .getPropertyDescriptors())
+	                      .stream()
+	                      // filter out properties with setters only
+	                      .filter(pd -> Objects.nonNull(pd.getReadMethod()))
+	                      .forEach(pd -> { // invoke method to get value
+	                          try {
+	                              Object value = pd.getReadMethod().invoke(bean);
+	                              if(returnNull) {
+	                            	  put(pd.getName(), value);
+	                              }else{
+	                            	  if (value != null) {
+	                            		  put(pd.getName(), value);
+	                            	  }
+	                              }
+	                          } catch (Exception e) {
+	                             e.printStackTrace();
+	                          }
+	                      });
+	    } catch (IntrospectionException e) {
+	        	 e.printStackTrace();
+	    }
+    }
+}

+ 94 - 0
src/main/java/com/aijia/core/web/ResponseConstant.java

@@ -0,0 +1,94 @@
+package com.aijia.core.web;
+
+/**
+ * 
+ * 类名称:ResponseCode<br>
+ * 类描述:返回常量<br>
+ * @version v1.0
+ *
+ */
+public class ResponseConstant {
+
+    /**
+     * 成功状态
+     */
+    public static final String CODE_999 = "999";
+
+    /**
+     * 用户名不存在
+     */
+    public static final String CODE_000 = "000";
+
+    /**
+     * 用户名和密码不匹配
+     */
+    public static final String CODE_001 = "001";
+
+    /**
+     * 用户密码不符合规范,需要重置密码
+     */
+    public static final String CODE_011 = "011";
+
+    /**
+     * 网络问题
+     */
+    public static final String CODE_002 = "002";
+    /**
+     * 会员卡为空
+     */
+    public static final String CODE_004 = "004";
+    /**
+     *图书isbn编号为空
+     */
+    public static final String CODE_005 = "005";
+    /**
+     *图书馆ID为空
+     */
+    public static final String CODE_006 = "006";
+    /**
+     *图书库存不足
+     */
+    public static final String CODE_007 = "007";
+    /**
+     *图书不存在
+     */
+    public static final String CODE_008 = "008";
+    
+    /**
+     * 401 Unauthorized
+     */
+    public static final String CODE_401 = "401";
+    
+    /**
+     * 403 Forbidden
+     */
+    public static final String CODE_403 = "403";
+    
+    /**
+     * 404 Not Found
+     */
+    public static final String CODE_404 = "404";
+    
+    /**
+     * 服务器问题
+     */
+    public static final String CODE_500 = "500";
+    /**
+     * 没有服务
+     */
+    public static final String CODE_003 = "003";
+    /**
+     * 请求太频繁
+     */
+    public static final String CODE_503 = "503";
+    /**
+     * 小程序根据code获取不到uninoid
+     */
+    public static final String CODE_888 = "888";
+
+    /**
+     * 校区服务已到期, 节假日提示, 可用在前端返回提示信息的状态码
+     */
+    public static final String CODE_009 = "009";
+    
+}

+ 150 - 0
src/main/java/com/aijia/core/web/ResponseEntity.java

@@ -0,0 +1,150 @@
+package com.aijia.core.web;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ *
+ * 类名称:Response<br>
+ * 类描述:Response 类<br>
+ * @version v1.0
+ *
+ */
+public class ResponseEntity implements Serializable{
+    /**
+	 * 
+	 */
+	private static final long serialVersionUID = 8731218855844435111L;
+	private static final String ERROR = "error";
+    private static final String SUCCESS = "success";
+
+    private String status;
+    private String code;
+    private String msg;
+    private Object data;
+
+    public ResponseEntity success() {
+        this.status = SUCCESS;
+        this.msg = "成功";
+        this.code = ResponseConstant.CODE_999;
+        return this;
+    }
+
+    public ResponseEntity success(String msg) {
+        this.status = SUCCESS;
+        this.msg = msg;
+        this.code = ResponseConstant.CODE_999;
+        return this;
+    }
+
+    public ResponseEntity success(String code, String msg) {
+        this.status = SUCCESS;
+        this.code = code;
+        this.msg = msg;
+        return this;
+    }
+
+    public ResponseEntity success(Map<String, Object> data, String msg) {
+        this.status = SUCCESS;
+        this.code = ResponseConstant.CODE_999;
+        this.msg = msg;
+        this.data = data;
+        return this;
+    }
+
+    public ResponseEntity success(Object data, String msg) {
+        this.status = SUCCESS;
+        this.code = ResponseConstant.CODE_999;
+        this.msg = msg;
+        this.data = data;
+        return this;
+    }
+
+    public ResponseEntity success(String code, String msg, Map<String, Object> data) {
+        this.status = SUCCESS;
+        this.code = code;
+        this.msg = msg;
+        this.data = data;
+        return this;
+    }
+
+    public ResponseEntity failure(String code, String msg) {
+        this.status = ERROR;
+        this.code = code;
+        this.msg = msg;
+        return this;
+    }
+
+    public ResponseEntity failure(String msg) {
+        this.status = ERROR;
+        this.code = ResponseConstant.CODE_000;
+        this.msg = msg;
+        return this;
+    }
+
+    public ResponseEntity failure(Object data, String msg) {
+        this.status = ERROR;
+        this.code = ResponseConstant.CODE_000;
+        this.msg = msg;
+        this.data = data;
+        return this;
+    }
+
+    public ResponseEntity failure(String code, String msg, Object data) {
+        this.status = ERROR;
+        this.code = code;
+        this.msg = msg;
+        this.data = data;
+        return this;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public Object getData() {
+        return data;
+    }
+
+    public void setData(ResponseData data) {
+        this.data = data;
+    }
+
+    public class ResponseData implements Serializable{
+        /**
+		 * 
+		 */
+		private static final long serialVersionUID = 4460263954067427230L;
+		private Map<String, Object> data;
+
+        public ResponseData() {
+            super();
+        }
+
+        public ResponseData(Map<String, Object> data) {
+            super();
+            this.data = data;
+        }
+
+        public Map<String, Object> getData() {
+            return data;
+        }
+
+        public void setData(Map<String, Object> data) {
+            this.data = data;
+        }
+    }
+
+}

+ 21 - 0
src/main/java/com/aijia/core/web/exception/RequestsException.java

@@ -0,0 +1,21 @@
+package com.aijia.core.web.exception;
+/** 
+ * @author  ZhangCaibao 
+ * @version 2018年7月26日 上午11:33:52 
+ * 类说明 
+ */
+public class RequestsException extends RuntimeException{
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -5782852372678913439L;
+	/**
+     * 
+     * 创建一个新的实例 ConchException.     
+     * @param message
+     */
+    public RequestsException(String message) {
+        super(message);
+    }
+}

+ 22 - 0
src/main/java/com/aijia/core/web/exception/TokenException.java

@@ -0,0 +1,22 @@
+package com.aijia.core.web.exception;
+
+/**
+ * 
+ * 类名称:TokenException<br>
+ * 类描述:令牌异常<br>
+ * @version v1.0
+ *
+ */
+public class TokenException extends RuntimeException {
+
+    private static final long serialVersionUID = 8391869486329200571L;
+
+    /**
+     * 
+     * 创建一个新的实例 TokenException.     
+     * @param message
+     */
+    public TokenException(String message) {
+        super(message);
+    }
+}

+ 15 - 0
src/main/java/com/aijia/kmt/annotation/IgnoreSecurity.java

@@ -0,0 +1,15 @@
+package com.aijia.kmt.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 
+ * 类名称:IgnoreSecurity<br>
+ * 类描述:忽略安全性检查<br>
+ * @version v1.0
+ *
+ */
+@Documented
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface IgnoreSecurity {}

+ 15 - 0
src/main/java/com/aijia/kmt/annotation/ModifySecurity.java

@@ -0,0 +1,15 @@
+package com.aijia.kmt.annotation;
+
+import java.lang.annotation.*;
+
+/** 
+ * @author  ZhangCaibao 
+ * @version 2018年7月26日 下午2:57:53 
+ *  类描述:修改安全性检查
+ */
+@Documented
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ModifySecurity {
+
+}

+ 57 - 0
src/main/java/com/aijia/kmt/common/DruidConfiguration.java

@@ -0,0 +1,57 @@
+package com.aijia.kmt.common;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.druid.support.http.StatViewServlet;
+import com.alibaba.druid.support.http.WebStatFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+
+/**
+ * @author yangcan
+ * 类描述:阿里数据库连接池 Druid配置http://localhost/druid/index.html druid管理平台
+ * 创建时间:2019年5月15日 下午3:41:27
+
+ */
+@Configuration
+public class DruidConfiguration {
+	private static final Logger logger = LoggerFactory.getLogger(DruidConfiguration.class);
+	private static final String DB_PREFIX = "spring.datasource";
+
+	@Bean
+	public ServletRegistrationBean druidServlet() {
+		logger.info("init Druid Servlet Configuration ");
+		ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),
+				"/druid/*");
+		// IP白名单 (没有配置或者为空,则允许所有访问)
+		servletRegistrationBean.addInitParameter("allow", "");
+		// IP黑名单(共同存在时,deny优先于allow)
+		// servletRegistrationBean.addInitParameter("deny", "192.168.1.100");
+		// 控制台管理用户
+		servletRegistrationBean.addInitParameter("loginUsername", "admin");
+		servletRegistrationBean.addInitParameter("loginPassword", "aijia123456");
+		// 是否能够重置数据 禁用HTML页面上的“Reset All”功能
+		servletRegistrationBean.addInitParameter("resetEnable", "false");
+		return servletRegistrationBean;
+	}
+
+	@Bean
+	public FilterRegistrationBean filterRegistrationBean() {
+		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
+		filterRegistrationBean.addUrlPatterns("/*");
+		filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
+		return filterRegistrationBean;
+	}
+
+	@Bean
+	@ConfigurationProperties(prefix = "spring.datasource")
+	public DataSource druidDataSource() {
+		return new DruidDataSource();
+	}
+}

+ 70 - 0
src/main/java/com/aijia/kmt/common/EntityResultTransformer.java

@@ -0,0 +1,70 @@
+package com.aijia.kmt.common;
+
+import org.apache.commons.lang3.StringUtils;
+import org.hibernate.transform.ResultTransformer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * 
+ * 类名称:EntityResultTransformer<br>
+ * 类描述:数据库查询结果集映射,将ResultSet转换为Entity
+ * <p>
+ * Hibernate自带的Transformers.aliasToBean(class)方法不能识别继承属性<br>
+ * 本类改用BeanUtils来实现<br>
+ * @version v1.0
+ *
+ */
+public class EntityResultTransformer implements ResultTransformer {
+
+    private static final long serialVersionUID = 2362750655253391124L;
+
+    private static final Logger logger = LoggerFactory.getLogger(EntityResultTransformer.class);
+
+    private Class<?> targetClass;
+
+    public EntityResultTransformer(Class<?> targetClass) {
+        if (targetClass == null) { throw new IllegalArgumentException("targetClass参数不能为空"); }
+        this.targetClass = targetClass;
+    }
+
+    @Override
+    public Object transformTuple(Object[] tuple, String[] aliases) {
+        try {
+            Object result = targetClass.newInstance();
+            for (int i = 0; i < aliases.length; i++) {
+                String alias = camelPropertyName(aliases[i]);
+//                try {
+//                    if (result instanceof String) {
+//                        return tuple[i];
+//                    } else {
+//                        BeanUtils.copyProperty(result, alias, tuple[i]);
+//                    }
+//                } catch (InvocationTargetException e) {
+//                    logger.warn(targetClass.getSimpleName() + "类中没有" + alias + "属性");
+//                }
+            }
+            return result;
+        } catch (InstantiationException | IllegalAccessException e) {
+            throw new IllegalStateException(targetClass.getSimpleName() + "不能实例化");
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public List transformList(List list) {
+        return list;
+    }
+
+    // 将数据库字段名转换为JavaBean中的属性名,遵循驼峰命名法
+    private String camelPropertyName(String propName) {
+        String[] arr = propName.toLowerCase().split("_");
+        String chr = arr[0];
+        for (int i = 1; i < arr.length; i++) {
+            chr += StringUtils.capitalize(arr[i]);
+        }
+        return chr;
+    }
+}

+ 132 - 0
src/main/java/com/aijia/kmt/common/ExceptionAdvice.java

@@ -0,0 +1,132 @@
+package com.aijia.kmt.common;
+
+import com.aijia.core.security.exception.CommonException;
+import com.aijia.core.web.ResponseConstant;
+import com.aijia.core.web.ResponseEntity;
+import com.aijia.core.web.exception.RequestsException;
+import com.aijia.core.web.exception.TokenException;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.validation.FieldError;
+import org.springframework.web.HttpMediaTypeNotSupportedException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 
+ * 类名称:ExceptionAdvice<br>
+ * 类描述:异常处理<br>
+ * @version v1.0
+ *
+ */
+@ControllerAdvice
+@ResponseBody
+public class ExceptionAdvice {
+
+    private static final Logger logger = LoggerFactory.getLogger("exceptionAdvice");
+
+    /**
+     * 400 - Bad Request
+     */
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(HttpMessageNotReadableException.class)
+    public ResponseEntity handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
+        logger.error("参数解析失败", e);
+        return new ResponseEntity().failure(ResponseConstant.CODE_000, "无法解析JSON");
+    }
+    @ResponseStatus(HttpStatus.EXPECTATION_FAILED)
+    @ExceptionHandler(RequestsException.class)
+    public ResponseEntity handleRequestsException(RequestsException e) {
+    	logger.error("请求太频繁,稍后再试", e);
+    	return new ResponseEntity().failure(ResponseConstant.CODE_503, "请求太频繁,稍后再试");
+    }
+
+    /**
+     * 401 - Unauthorized Request
+     */
+    @ResponseStatus(HttpStatus.UNAUTHORIZED)
+    @ExceptionHandler(TokenException.class)
+    public ResponseEntity handleTokenException(TokenException e) {
+        ResponseEntity responseEntity = new ResponseEntity();
+        String message = e.getMessage();
+        Map<String, Object> data = null;
+        if (StringUtils.isNotBlank(message)) {
+            //失效的token
+            int startIndex = message.indexOf("{");
+            int endIndex = message.indexOf("}");
+            if (startIndex > -1 && endIndex > -1) {
+                String type = message.substring(startIndex + 1, endIndex);
+                data = new HashMap<>(16);
+                //告诉前端失效的原因:(1:被管理员强制下线,2:被其他超级管理员挤下线)
+                data.put("type", type);
+            }
+        }
+        logger.error("登录信息失效,请重新登录", e);
+        return responseEntity.failure(ResponseConstant.CODE_401, "登录信息失效,请重新登录", data);
+    }
+
+    /**
+     * 405 - Method Not Allowed
+     */
+    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
+    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+    public ResponseEntity handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
+        logger.error("不支持当前请求方法", e);
+        return new ResponseEntity().failure(ResponseConstant.CODE_000, "不支持当前请求方法");
+    }
+
+    /**
+     * 415 - Unsupported Media Type
+     */
+    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
+    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
+    public ResponseEntity handleHttpMediaTypeNotSupportedException(Exception e) {
+        logger.error("不支持当前媒体类型", e);
+        return new ResponseEntity().failure(ResponseConstant.CODE_000, "不支持的内容类型");
+    }
+
+    /**
+     * 500 - Internal Server Error
+     */
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(Exception.class)
+    public ResponseEntity handleException(Exception e) {
+        logger.error("服务运行异常", e);
+        return new ResponseEntity().failure(ResponseConstant.CODE_000, "暂未加载到数据,请稍后再试");
+    }
+
+    /**
+     * 500 - Internal Server Error
+     * 用于给用户提示时抛出,如:操作失败的原因
+     */
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(CommonException.class)
+    public ResponseEntity handleCommonException(CommonException e) {
+        return new ResponseEntity().failure(ResponseConstant.CODE_000, e.getMessage());
+    }
+
+    /**
+     * 500 - Internal Server Error
+     * 参数校验失败时抛出,如:非空属性的值为空
+     */
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
+        StringBuilder errorInfo = new StringBuilder();
+        List<FieldError> fieldErrorList = e.getBindingResult().getFieldErrors();
+        fieldErrorList.forEach(fieldError -> errorInfo.append(fieldError.getField()).append(" ").append(fieldError.getDefaultMessage()).append(","));
+        errorInfo.deleteCharAt(errorInfo.length() - 1);
+        return new ResponseEntity().failure(ResponseConstant.CODE_000, errorInfo.toString());
+    }
+}

+ 125 - 0
src/main/java/com/aijia/kmt/common/GlobalExceptionHandler.java

@@ -0,0 +1,125 @@
+package com.aijia.kmt.common;
+
+import com.aijia.core.base.ResponseEntity;
+import com.aijia.core.security.exception.CommonException;
+import com.aijia.core.web.ResponseConstant;
+import com.aijia.core.web.exception.RequestsException;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.validation.FieldError;
+import org.springframework.web.HttpMediaTypeNotSupportedException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.util.ContentCachingRequestWrapper;
+
+
+import javax.servlet.http.HttpServletRequest;
+import java.nio.charset.Charset;
+import java.util.List;
+
+/**
+ * 
+ * 类名称:ExceptionAdvice<br>
+ * 类描述:异常处理<br>
+ * @author yrf
+ * @version v1.0
+ */
+@ControllerAdvice
+@ResponseBody
+public class GlobalExceptionHandler {
+
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    /**
+     * 400 - Bad Request
+     */
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(HttpMessageNotReadableException.class)
+    public ResponseEntity handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
+        logger.error("参数解析失败", e);
+        return  ResponseEntity.failure("无法解析JSON");
+    }
+
+    @ResponseStatus(HttpStatus.EXPECTATION_FAILED)
+    @ExceptionHandler(RequestsException.class)
+    public ResponseEntity handleRequestsException(RequestsException e) {
+    	logger.warn("请求太频繁,稍后再试", e);
+    	return ResponseEntity.failure("请求太频繁,稍后再试");
+    }
+    
+    /**
+     * 405 - Method Not Allowed
+     */
+    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
+    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+    public ResponseEntity handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
+        logger.error("不支持当前请求方法", e);
+        return ResponseEntity.failure("不支持当前请求方法");
+    }
+
+    /**
+     * 415 - Unsupported Media Type
+     */
+    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
+    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
+    public ResponseEntity handleHttpMediaTypeNotSupportedException(Exception e) {
+        logger.error("不支持当前媒体类型", e);
+        return ResponseEntity.failure("不支持的内容类型");
+    }
+
+    /**
+     * 500 - Internal Server Error
+     */
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(Exception.class)
+    public ResponseEntity handleException(HttpServletRequest request, Exception e) throws Exception{
+        String bodyStr = null;
+        if (request instanceof ContentCachingRequestWrapper) {
+            ContentCachingRequestWrapper contentCachingRequestWrapper = (ContentCachingRequestWrapper) request;
+            bodyStr = StringUtils.toEncodedString(contentCachingRequestWrapper.getContentAsByteArray(), Charset.forName(contentCachingRequestWrapper.getCharacterEncoding()));
+        }
+        logger.error(String.format("服务运行异常,uri = [%s] \n请求参数 body = %s", request.getRequestURI(), bodyStr), e);
+        return ResponseEntity.failure();
+    }
+
+    /**
+     * 500 - Internal Server Error
+     * 用于给用户提示时抛出,如:操作失败的原因
+     */
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(CommonException.class)
+    public ResponseEntity handleCommonException(CommonException e) {
+        return ResponseEntity.failure(ResponseConstant.CODE_000, e.getMessage());
+    }
+
+    /**
+     * 500 - Internal Server Error
+     * 用于处理断言抛出的异常提示
+     */
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(IllegalArgumentException.class)
+    public ResponseEntity handleIllegalArgumentExceptionException(IllegalArgumentException e) {
+        return ResponseEntity.failure(e.getMessage());
+    }
+
+    /**
+     * 500 - Internal Server Error
+     * 参数校验失败时抛出,如:非空属性的值为空
+     */
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
+        StringBuilder errorInfo = new StringBuilder();
+        List<FieldError> fieldErrorList = e.getBindingResult().getFieldErrors();
+        fieldErrorList.forEach(fieldError -> errorInfo.append(fieldError.getDefaultMessage()).append(","));
+        errorInfo.deleteCharAt(errorInfo.length() - 1);
+        return ResponseEntity.failure(ResponseConstant.CODE_000, errorInfo.toString());
+    }
+}

+ 36 - 0
src/main/java/com/aijia/kmt/common/MapResultTransformer.java

@@ -0,0 +1,36 @@
+package com.aijia.kmt.common;
+
+import org.hibernate.transform.ResultTransformer;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 
+ * 类名称:MapResultTransformer<br>
+ * 类描述:数据库查询结果集映射,将ResultSet转换为Map<br>
+ * @version v1.0
+ *
+ */
+public class MapResultTransformer implements ResultTransformer {
+
+    private static final long serialVersionUID = 189347373937529641L;
+
+    @Override
+    public Object transformTuple(Object[] tuple, String[] aliases) {
+        Map<String, Object> result = new HashMap<>();
+        for (int i = 0; i < aliases.length; i++) {
+            // key为小写
+            result.put(aliases[i].toLowerCase(), tuple[i]);
+        }
+        return result;
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public List transformList(List list) {
+        return list;
+    }
+
+}

+ 281 - 0
src/main/java/com/aijia/kmt/common/MybatisMapperRefresh.java

@@ -0,0 +1,281 @@
+package com.aijia.kmt.common;
+
+import com.baomidou.mybatisplus.core.toolkit.SystemClock;
+import com.google.common.collect.Lists;
+import org.apache.ibatis.binding.MapperRegistry;
+import org.apache.ibatis.builder.xml.XMLMapperBuilder;
+import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
+import org.apache.ibatis.executor.ErrorContext;
+import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
+import org.apache.ibatis.io.Resources;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.parsing.XNode;
+import org.apache.ibatis.parsing.XPathParser;
+import org.apache.ibatis.session.Configuration;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.util.ResourceUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.*;
+
+/**
+ * @author yrf
+ * @description
+ * @time 2019/9/16 16:55
+ */
+public class MybatisMapperRefresh implements Runnable {
+
+    private static final Logger logger = LoggerFactory.getLogger(MybatisMapperRefresh.class);
+
+    /**
+     * 记录jar包存在的mapper
+     */
+    private static final Map<String, List<Resource>> jarMapper = new HashMap<>();
+
+    private SqlSessionFactory sqlSessionFactory;
+    private Resource[] mapperLocations;
+    private Long beforeTime = 0L;
+    private Configuration configuration;
+    /**
+     * 是否开启刷新mapper
+     */
+    private boolean enabled;
+    /**
+     * xml文件目录
+     */
+    private Set<String> fileSet;
+    /**
+     * 延迟加载时间
+     */
+    private int delaySeconds = 10;
+    /**
+     * 刷新间隔时间
+     */
+    private int sleepSeconds = 5;
+
+    public MybatisMapperRefresh(Resource[] mapperLocations, SqlSessionFactory sqlSessionFactory, int delaySeconds,
+                                int sleepSeconds, boolean enabled) {
+        this.mapperLocations = mapperLocations.clone();
+        this.sqlSessionFactory = sqlSessionFactory;
+        this.delaySeconds = delaySeconds;
+        this.enabled = enabled;
+        this.sleepSeconds = sleepSeconds;
+        this.configuration = sqlSessionFactory.getConfiguration();
+        this.run();
+    }
+
+    public MybatisMapperRefresh(Resource[] mapperLocations, SqlSessionFactory sqlSessionFactory, boolean enabled) {
+        this.mapperLocations = mapperLocations.clone();
+        this.sqlSessionFactory = sqlSessionFactory;
+        this.enabled = enabled;
+        this.configuration = sqlSessionFactory.getConfiguration();
+        this.run();
+    }
+
+    @Override
+    public void run() {
+        /*
+         * 启动 XML 热加载
+         */
+        if (enabled) {
+            beforeTime = SystemClock.now();
+            final MybatisMapperRefresh runnable = this;
+            new Thread(() -> {
+                if (fileSet == null) {
+                    fileSet = new HashSet<>();
+                    if (mapperLocations != null) {
+                        for (Resource mapperLocation : mapperLocations) {
+                            try {
+                                if (ResourceUtils.isJarURL(mapperLocation.getURL())) {
+                                    String key = new UrlResource(ResourceUtils.extractJarFileURL(mapperLocation.getURL()))
+                                            .getFile().getPath();
+                                    fileSet.add(key);
+                                    if (jarMapper.get(key) != null) {
+                                        jarMapper.get(key).add(mapperLocation);
+                                    } else {
+                                        List<Resource> resourcesList = new ArrayList<>();
+                                        resourcesList.add(mapperLocation);
+                                        jarMapper.put(key, resourcesList);
+                                    }
+                                } else {
+                                    fileSet.add(mapperLocation.getFile().getPath());
+                                }
+                            } catch (IOException ioException) {
+                                logger.error("读取mapper异常", ioException);
+                            }
+                        }
+                    }
+                }
+                try {
+                    Thread.sleep(delaySeconds * 1000);
+                } catch (InterruptedException interruptedException) {
+                    logger.error("延迟异常", interruptedException);
+                }
+                do {
+                    try {
+                        for (String filePath : fileSet) {
+                            File file = new File(filePath);
+                            if (file.isFile() && file.lastModified() > beforeTime) {
+                                List<Resource> removeList = jarMapper.get(filePath);
+                                if (removeList != null && !removeList.isEmpty()) {
+                                    for (Resource resource : removeList) {
+                                        runnable.refresh(resource);
+                                    }
+                                } else {
+                                    runnable.refresh(new FileSystemResource(file));
+                                }
+                            }
+                        }
+                    } catch (Exception exception) {
+                        logger.error("刷新mapper异常", exception);
+                    }
+                    try {
+                        Thread.sleep(sleepSeconds * 1000);
+                    } catch (InterruptedException interruptedException) {
+                        logger.error("延迟2异常", interruptedException);
+                    }
+
+                } while (true);
+            }, "mybatis-plus MapperRefresh").start();
+        }
+    }
+
+    /**
+     * 刷新mapper
+     *
+     * @throws Exception
+     */
+    @SuppressWarnings("rawtypes")
+    private void refresh(Resource resource) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
+        this.configuration = sqlSessionFactory.getConfiguration();
+        boolean isSupper = configuration.getClass().getSuperclass() == Configuration.class;
+        try {
+            Field loadedResourcesField = isSupper ? configuration.getClass().getSuperclass().getDeclaredField("loadedResources")
+                    : configuration.getClass().getDeclaredField("loadedResources");
+            loadedResourcesField.setAccessible(true);
+            Set loadedResourcesSet = ((Set) loadedResourcesField.get(configuration));
+            XPathParser xPathParser = new XPathParser(resource.getInputStream(), true, configuration.getVariables(),
+                    new XMLMapperEntityResolver());
+            XNode context = xPathParser.evalNode("/mapper");
+            String namespace = context.getStringAttribute("namespace");
+            Field field = MapperRegistry.class.getDeclaredField("knownMappers");
+            field.setAccessible(true);
+            Map mapConfig = (Map) field.get(configuration.getMapperRegistry());
+
+            mapConfig.remove(Resources.classForName(namespace));
+            loadedResourcesSet.remove(resource.toString());
+            configuration.getCacheNames().remove(namespace);
+
+            cleanParameterMap(context.evalNodes("/mapper/parameterMap"), namespace);
+            cleanResultMap(context.evalNodes("/mapper/resultMap"), namespace);
+            cleanKeyGenerators(context.evalNodes("insert|update|select"), namespace);
+            cleanSqlElement(context.evalNodes("/mapper/sql"), namespace);
+            XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resource.getInputStream(),
+                    sqlSessionFactory.getConfiguration(),
+                    resource.toString(), sqlSessionFactory.getConfiguration().getSqlFragments());
+            xmlMapperBuilder.parse();
+            beforeTime = new Date().getTime();
+            logger.debug("refresh: '" + resource + "', success!");
+        } catch (IOException e) {
+            logger.error("Refresh IOException :" + e.getMessage());
+        } finally {
+            ErrorContext.instance().reset();
+        }
+    }
+
+    /**
+     * 清理parameterMap
+     *
+     * @param list
+     * @param namespace
+     */
+    private void cleanParameterMap(List<XNode> list, String namespace) {
+        for (XNode parameterMapNode : list) {
+            String id = parameterMapNode.getStringAttribute("id");
+            configuration.getParameterMaps().removeIf(it -> Objects.equals(it.getId(), namespace + "." + id));
+        }
+    }
+
+    /**
+     * 清理resultMap
+     *
+     * @param list
+     * @param namespace
+     */
+    private void cleanResultMap(List<XNode> list, String namespace) {
+        for (XNode resultMapNode : list) {
+            String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier());
+            configuration.getResultMapNames().remove(id);
+            configuration.getResultMapNames().remove(namespace + "." + id);
+            clearResultMap(resultMapNode, namespace);
+        }
+    }
+
+    private void clearResultMap(XNode xNode, String namespace) {
+        for (XNode resultChild : xNode.getChildren()) {
+            if ("association".equals(resultChild.getName()) || "collection".equals(resultChild.getName())
+                    || "case".equals(resultChild.getName())) {
+                if (resultChild.getStringAttribute("select") == null) {
+                    configuration.getResultMapNames().remove(
+                            resultChild.getStringAttribute("id", resultChild.getValueBasedIdentifier()));
+                    configuration.getResultMapNames().remove(
+                            namespace + "." + resultChild.getStringAttribute("id", resultChild.getValueBasedIdentifier()));
+                    if (resultChild.getChildren() != null && !resultChild.getChildren().isEmpty()) {
+                        clearResultMap(resultChild, namespace);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 清理selectKey
+     *
+     * @param list
+     * @param namespace
+     */
+    private void cleanKeyGenerators(List<XNode> list, String namespace) {
+        for (XNode context : list) {
+            String id = context.getStringAttribute("id");
+            configuration.getKeyGeneratorNames().remove(id + SelectKeyGenerator.SELECT_KEY_SUFFIX);
+            configuration.getKeyGeneratorNames().remove(namespace + "." + id + SelectKeyGenerator.SELECT_KEY_SUFFIX);
+
+            Collection<String> mappedStatementNames = configuration.getMappedStatementNames();
+            List<MappedStatement> objects = Lists.newArrayList();
+            for (String mappedStatementName : mappedStatementNames) {
+                if (Objects.equals(mappedStatementName, namespace + "." + id)) {
+                    objects.add(configuration.getMappedStatement(mappedStatementName));
+                }
+            }
+//            Collection<MappedStatement> mappedStatements = configuration.getMappedStatements();
+//            for (MappedStatement mappedStatement : mappedStatements) {
+//                if (mappedStatement.getId().equals(namespace + "." + id)) {
+//                    objects.add(mappedStatement);
+//                }
+//            }
+            configuration.getMappedStatements().removeAll(objects);
+//            mappedStatements.removeAll(objects);
+        }
+    }
+
+    /**
+     * 清理sql节点缓存
+     *
+     * @param list
+     * @param namespace
+     */
+    private void cleanSqlElement(List<XNode> list, String namespace) {
+        for (XNode context : list) {
+            String id = context.getStringAttribute("id");
+            configuration.getSqlFragments().remove(id);
+            configuration.getSqlFragments().remove(namespace + "." + id);
+        }
+    }
+}

+ 70 - 0
src/main/java/com/aijia/kmt/common/MybatisPlusConfig.java

@@ -0,0 +1,70 @@
+package com.aijia.kmt.common;
+
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternResolver;
+
+import java.io.IOException;
+
+/**
+ * @author yrf
+ * @description
+ * @time 2019/9/16 16:51
+ */
+@Configuration
+@AutoConfigureAfter(SqlSessionFactory.class)
+public class MybatisPlusConfig {
+
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Value("${mybatis-plus.mapper-locations}")
+    private String mapperLocations;
+
+    @Value("${mybatis-plus.refresh-mapper}")
+    private Boolean refreshMapper;
+
+    private static final ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
+
+    /*
+     * 分页插件,自动识别数据库类型
+     * 多租户,请参考官网【插件扩展】
+     */
+    @Bean
+    public PaginationInterceptor paginationInterceptor() {
+        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
+        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
+        // paginationInterceptor.setOverflow(false);
+        // 设置最大单页限制数量,默认 500 条,-1 不受限制
+         paginationInterceptor.setLimit(-1);
+        // 开启 count 的 join 优化,只针对部分 left join
+        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
+        return paginationInterceptor;
+    }
+
+
+    /**
+     * mapper.xml 热加载
+     * @return
+     */
+    @Bean
+    public MybatisMapperRefresh mybatisMapperRefresh(){
+        SqlSessionFactory sqlSessionFactory = SpringContextHolder.getBean("sqlSessionFactory");
+        Resource[] resources = new Resource[0];
+        try {
+            resources = resourceResolver.getResources(mapperLocations);
+        } catch (IOException e) {
+            logger.error("获取mapper source异常", e);
+        }
+        return new MybatisMapperRefresh(resources,sqlSessionFactory,10,5,refreshMapper);
+    }
+
+}

+ 309 - 0
src/main/java/com/aijia/kmt/common/PagingHibernateJdbcDao.java

@@ -0,0 +1,309 @@
+package com.aijia.kmt.common;
+
+import com.aijia.core.utils.CastUtil;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 
+ * 类名称:PagingHibernateJdbcDao<br>
+ * 类描述:基于Hibernate的原生sql分页查询支持多数据库<br>
+ * @version v1.0
+ *
+ */
+@Repository
+public class PagingHibernateJdbcDao {
+
+    @PersistenceContext
+    private EntityManager em;
+
+    // 避免影响遗留代码,开放此方法
+    public Query createSQLQuery(String sql) {
+        // 得到Hibernate Session
+        Session session = em.unwrap(Session.class);
+        return session.createSQLQuery(sql);
+    }
+
+
+    /**
+     * 批量插入
+     * @param list
+     */
+	 @Transactional
+	 public void batchInsert(@SuppressWarnings("rawtypes") List list){
+		 for (int i = 0; i < list.size(); i++) {
+			 em.persist(list.get(i));
+			 if (i % 30 == 0) {
+				 em.flush();
+				 em.clear();
+			 }
+		  }
+	 }
+	 @Transactional
+	 public void batchInsertObject(Object object){
+			 em.persist(object);
+	 }
+
+	 /**
+	  * 批量更新
+	  * @param list
+	  */
+	 @Transactional
+	 public void batchUpdate(@SuppressWarnings("rawtypes") List list){
+		 for (int i = 0; i < list.size(); i++) {
+			 em.merge(list.get(i));
+			 if (i % 30 == 0) {
+				 em.flush();
+				 em.clear();
+			 }
+		 }
+	 }
+
+    /**
+     * count查询
+     * 
+     * @param sql 查询语句
+     * @return 结果集行数
+     */
+    public long count(String sql) {
+        sql = createCountSql(sql);
+        return count(createSQLQuery(sql));
+    }
+
+    /**
+     * 带参数count查询
+     * 
+     * @param sql 查询语句,参数用 ? 代替
+     * @param args 查询参数
+     * @return 结果集行数
+     */
+    public long count(String sql, Object[] args) {
+        sql = createCountSql(sql);
+        Query query = createSQLQuery(sql);
+        query = setParameters(query, args);
+        return count(query);
+    }
+
+    /**
+     * 查询结果集
+     *
+     * @param sql 查询语句
+     * @param clazz 返回domain实体的class
+     * @return 分页实体
+     */
+    @SuppressWarnings("unchecked")
+    public <T> List<T> findList(String sql, Class<T> clazz) {
+        List<T> results;
+        Query query = createSQLQuery(sql);
+        query.setResultTransformer(new EntityResultTransformer(clazz));
+        results = query.list();
+        return results;
+    }
+    @SuppressWarnings("unchecked")
+    public <T> List<T> findList(String sql , Object[] args, Class<T> clazz){
+    	Query query = createSQLQuery(sql);
+    	 query = setParameters(query, args);
+    	 query.setResultTransformer(new EntityResultTransformer(clazz));
+    	List<T> results =query.list();
+    	return results;
+    }
+
+    /**
+     * 分页查询:查询结果集
+     * 
+     * @param sql 查询语句
+     * @param page 分页条件
+     * @param clazz 返回domain实体的class
+     * @return 分页实体
+     */
+    @SuppressWarnings("unchecked")
+    public <T> Page<T> findPage(String sql, Pageable page, Class<T> clazz) {
+        long count = count(sql);
+        List<T> results;
+        if (count == 0) {
+            results = null;
+        } else {
+            Query query = createSQLQuery(sql);
+            query = setPageable(query, page);
+            query.setResultTransformer(new EntityResultTransformer(clazz));
+            results = query.list();
+        }
+        return wrapResult(results, page, count);
+    }
+
+    /**
+     * 分页查询:查询结果集
+     * 
+     * @param sql 查询语句,参数用 ? 代替
+     * @param args 查询参数
+     * @param page 分页条件
+     * @param clazz 返回domain实体的class
+     * @return 分页实体
+     */
+    @SuppressWarnings("unchecked")
+    public <T> Page<T> findPage(String sql, Object[] args, Pageable page, Class<T> clazz) {
+        long count = count(sql, args);
+        List<T> results;
+        if (count == 0) {
+            results = null;
+        } else {
+            Query query = createSQLQuery(sql);
+            query = setParameters(query, args);
+            query = setPageable(query, page);
+            query.setResultTransformer(new EntityResultTransformer(clazz));
+            results = query.list();
+        }
+        return wrapResult(results, page, count);
+    }
+
+    /**
+     * 分页查询:查询结果集
+     * 
+     * @param sql 查询语句
+     * @param page 分页条件
+     * @return 分页实体
+     */
+    @SuppressWarnings("unchecked")
+    public Page<Map<String, Object>> findPage(String sql, Pageable page) {
+        long count = count(sql);
+        List<Map<String, Object>> results;
+        if (count == 0) {
+            results = null;
+        }
+        Query query = createSQLQuery(sql);
+        query = setPageable(query, page);
+        query.setResultTransformer(new MapResultTransformer());
+        results = query.list();
+        return wrapResult(results, page, count);
+    }
+
+    /**
+     * 分页查询:查询结果集
+     * @param sql 查询语句
+     * @param countSql 查询总数语句
+     * @param page 分页条件
+     * @return 分页实体
+     */
+    @SuppressWarnings("unchecked")
+    public Page<Map<String, Object>> findByPage(String sql, String countSql, Pageable page) {
+        long count = count(countSql);
+        List<Map<String, Object>> results;
+        if (count == 0) {
+            results = null;
+        }
+        Query query = createSQLQuery(sql);
+        query = setPageable(query, page);
+        query.setResultTransformer(new MapResultTransformer());
+        results = query.list();
+        return wrapResult(results, page, count);
+    }
+
+    /**
+     * 分页查询:查询结果集
+     * 
+     * @param sql 查询语句,参数用 ? 代替
+     * @param args 查询参数
+     * @param page 分页条件
+     * @return 分页实体
+     */
+    @SuppressWarnings("unchecked")
+    public Page<Map<String, Object>> findPage(String sql, Object[] args, Pageable page) {
+        long count = count(sql, args);
+        List<Map<String, Object>> results;
+        if (count == 0) {
+            results = null;
+        } else {
+            Query query = createSQLQuery(sql);
+            query = setPageable(query, page);
+            query = setParameters(query, args);
+            query.setResultTransformer(new MapResultTransformer());
+            results = query.list();
+        }
+        return wrapResult(results, page, count);
+    }
+    @SuppressWarnings("unchecked")
+    public List<Map<String, Object>> findMap(String sql, Object[] args) {
+    	  List<Map<String, Object>> results;
+    		Query query = createSQLQuery(sql);
+    		query = setParameters(query, args);
+    		query.setResultTransformer(new MapResultTransformer());
+    		results = query.list();
+    	return results;
+    }
+
+    // 创建count语句
+    private String createCountSql(String sql) {
+        StringBuilder countSql = new StringBuilder();
+        countSql.append("select count(1) from (");
+        countSql.append(sql);
+        countSql.append(") t");
+        return countSql.toString();
+    }
+
+    // 简单封装count查询
+    private long count(Query query) {
+        return CastUtil.castLong(query.uniqueResult());
+    }
+
+    // 设置查询参数
+    private Query setParameters(Query query, Object[] args) {
+        if (args != null && args.length != 0) {
+            for (int i = 0; i < args.length; i++) {
+                query.setParameter(i, args[i]);
+            }
+        }
+        return query;
+    }
+
+    // 设置分页参数
+    private Query setPageable(Query query, Pageable page) {
+        query.setFirstResult((int)page.getOffset());
+        query.setMaxResults(page.getPageSize());
+        return query;
+    }
+
+    // 将查询结果集封装为标准格式
+    private <T> Page<T> wrapResult(List<T> result, Pageable page, long count) {
+        if (result == null) {
+            result = Collections.emptyList();
+        }
+        Page<T> thisPage = new PageImpl<>(result, page, count);
+        return thisPage;
+    }
+
+    /**
+     *
+     * @param list 实体列表
+     * @param batchSize 每次插入数据量
+     */
+    @Transactional
+    public void batchInsert(@SuppressWarnings("rawtypes") List list, int batchSize) {
+        int temp = 0;
+
+        for (int i = 0; i < list.size(); i++) {
+            em.persist(list.get(i));
+            temp ++;
+            if (i % batchSize == 0) {
+                em.flush();
+                em.clear();
+                temp = 0;
+            }
+        }
+
+        if (temp % batchSize != 0) {
+            em.flush();
+            em.clear();
+        }
+    }
+}

+ 63 - 0
src/main/java/com/aijia/kmt/common/RedisConfig.java

@@ -0,0 +1,63 @@
+package com.aijia.kmt.common;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
+import redis.clients.jedis.HostAndPort;
+import redis.clients.jedis.JedisCluster;
+import redis.clients.jedis.JedisPoolConfig;
+
+import java.util.HashSet;
+
+@Configuration
+@EnableRedisHttpSession  
+public class RedisConfig {
+
+
+
+    @Value("${spring.redis.timeout}")
+    private int timeout;
+
+    @Value("${spring.redis.cluster.pool.max-idle}")
+    private int maxIdle;
+
+    @Value("${spring.redis.cluster.pool.max-wait}")
+    private long maxWaitMillis;
+
+
+    @Value("${spring.redis.block-when-exhausted}")
+    private boolean  blockWhenExhausted;
+
+    @Value("${spring.redis.cluster.nodes}")
+    private String clusterNodes;
+    @Value("${spring.redis.password}")
+    private String password;
+    @Value("${spring.redis.cluster.pool.total}")
+    private int total;
+
+    @Bean
+    public JedisCluster redisPoolFactory() {
+        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
+        jedisPoolConfig.setMaxIdle(maxIdle);
+        jedisPoolConfig.setMaxTotal(total);
+        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
+        // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
+        jedisPoolConfig.setBlockWhenExhausted(blockWhenExhausted);
+        // 是否启用pool的jmx管理功能, 默认true
+        jedisPoolConfig.setJmxEnabled(true);
+        String[] cNodes = clusterNodes.split(",");
+        HashSet<HostAndPort> nodes = new HashSet<>();
+        //分割集群节点
+        for (String node : cNodes) {
+            String[] hp = node.split(":");
+            nodes.add(new HostAndPort(hp[0], Integer.parseInt(hp[1])));
+        }
+        //创建集群对象
+       // JedisCluster jedisCluster = new JedisCluster(nodes, timeout, jedisPoolConfig);
+
+        return  new JedisCluster(nodes,timeout,timeout,5,password, jedisPoolConfig);
+      //  return  new JedisCluster(nodes, timeout, jedisPoolConfig);
+    }
+
+}

+ 820 - 0
src/main/java/com/aijia/kmt/common/RedisTokenManager.java

@@ -0,0 +1,820 @@
+package com.aijia.kmt.common;
+
+
+import com.aijia.core.utils.CodecUtil;
+import com.aijia.core.utils.StringUtil;
+import com.aijia.kmt.common.weixin.WeixinUtil;
+import com.aijia.kmt.service.TokenManager;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisCluster;
+import redis.clients.jedis.JedisPool;
+
+import java.util.*;
+
+/**
+ *
+ * 类名称:RedisTokenManager<br>
+ * 类描述:基于 Redis 的令牌管理器<br>
+ * @version v1.0
+ *
+ */
+@Service
+@Primary
+public class RedisTokenManager implements TokenManager {
+
+    private static final Logger logger = LoggerFactory.getLogger(RedisTokenManager.class);
+
+    /**
+     * Redis中key是userId  value 是token
+     */
+    private static final String REDIS_TOKEN_TOKEN_PREFIX = "TOKEN_TOKEN_";
+
+    /**
+     * Redis中key是token  value 是      userId
+     */
+    private static final String REDIS_TOKEN_USERID_PREFIX = "TOKEN_USERID_";
+
+
+    /**
+     * Redis中key是token value 是       openId
+     */
+    private static final String REDIS_TOKEN_OPENID_PREFIX = "TOKEN_OPENID_";
+    /**
+     * Redis中key是token value 是       sessionkey
+     */
+    private static final String REDIS_TOKEN_SESSION_KEY = "TOKEN_SESSION_Key_";
+
+    /**
+     * 订单明细前缀
+     */
+    private static final String ORDERDATA = "ORDERDATA:";
+
+    /**
+     * 周末止前缀
+     */
+    private static final String WEEKENDVIP = "WEEKENDVIP";
+
+    /**
+     * 小程序token失效时间,默认2小时
+     */
+    private static final int WX_SECONDS = 1 * 3600;
+
+    /**
+     * token失效时间,默认7天
+     */
+    private static final int DEFAULT_SECONDS = 7 * 24 * 3600;
+
+    /**
+     * 信鸽推送ID的前缀
+     */
+
+    private static final String REDIS_XINGE = "XINGE_";
+    /**
+     * 私塾家微信token
+     */
+    private static final String SSJ_WX_TOKEN = "SSJ_WX_TOKEN";
+    /**
+     * 私塾家微信JStoken
+     */
+    private static final String SSJ_JSWX_TOKEN = "SSJ_JSWX_TOKEN";
+    /**
+     * 私塾家openId
+     */
+    private static final String SSJ_OPEN_ID = "SSJ_OPEN_ID";
+
+    private static final String EASEMOBNAME = "easemobName";
+    /**
+     * 私塾家token失效时间,默认2小时
+     */
+    private static final int SSJ_SECONDS = 7000;
+    @Autowired
+    private JedisCluster jedisPool;
+    private int seconds = DEFAULT_SECONDS;
+    private int wxseconds = WX_SECONDS;
+    private int ssjseconds = SSJ_SECONDS;
+
+
+
+
+    public void setSeconds(int seconds) {
+        this.seconds = seconds;
+    }
+
+    @Override
+    public String createToken(String token, String userId, String type) {
+        if(StringUtil.isBlank(token)){
+            token= CodecUtil.createUUID();
+        }
+        String oldToken = get(formatTokenToken(userId+type));
+        if (StringUtil.isNotBlank(oldToken)) {
+            removeToken(oldToken,type);
+        }
+        set(formatTokenUserId(token), userId, seconds);
+        set(formatTokenToken(userId+type), token, seconds);
+
+        return token;
+    }
+
+    @Override
+    public String createToken(String token, String userId, int seconds, String type) {
+        if(StringUtil.isBlank(token)){
+            token=CodecUtil.createUUID();
+        }
+        String oldToken = get(formatTokenToken(userId+type));
+        if (StringUtil.isNotBlank(oldToken)) {
+            removeToken(oldToken,type);
+        }
+        set(formatTokenUserId(token), userId, seconds);
+        set(formatTokenToken(userId+type), token, seconds);
+
+        return token;
+    }
+
+    @Override
+    public String createToken(String token, String userId, String openId, int source, String sessionKey, String type) {
+        if(StringUtil.isBlank(token)){
+            token=CodecUtil.createUUID();
+        }
+        String oldToken = get(formatTokenToken(userId+type));
+        if (StringUtil.isNotBlank(oldToken)) {
+            removeToken(oldToken,userId,openId,type);
+        }
+        set(formatTokenUserId(token), userId, seconds);
+        set(formatTokenToken(userId+type), token, seconds);//单独存放是为了后台了删除
+
+        set(formatTokenOpenid(token),openId, seconds);
+        set(formatTokenSessionKey(token),sessionKey, seconds);
+        return token;
+    }
+    @Override
+    public String createToken(String token, String userId, String openId, int source, String sessionKey, int seconds, String type) {
+        if(StringUtil.isBlank(token)){
+            token=CodecUtil.createUUID();
+        }
+        String oldToken = get(formatTokenToken(userId+type));
+        if (StringUtil.isNotBlank(oldToken)) {
+            removeToken(oldToken,userId,openId,type);
+        }
+        set(formatTokenUserId(token), userId, seconds);
+        set(formatTokenToken(userId+type), token, seconds);//单独存放是为了后台了删除
+        set(formatTokenOpenid(token),openId, seconds);
+        set(formatTokenSessionKey(token),sessionKey, seconds);
+        return token;
+    }
+
+
+    @Override
+    public void removeToken(String token, String userId, String openId, String type){
+        delete(formatTokenUserId(token));
+        delete(formatTokenOpenid(token));
+        delete(formatTokenSessionKey(token));
+        delete(formatTokenToken(userId+type));
+    }
+    @Override
+    public void delToken(String userId){
+        List<String> list = getToken(userId);
+        for (String token : list) {
+            if(token!=null){
+                delete(formatTokenUserId(token));
+                delete(formatTokenOpenid(token));
+                delete(formatTokenSessionKey(token));
+            }
+
+        }
+        delete(formatTokenToken(userId+"WX"));
+        delete(formatTokenToken(userId+"APP"));
+        delete(formatTokenToken(userId+"APP_TEACHER"));
+        delete(formatTokenToken(userId+"IPAD"));
+        delete(formatTokenToken(userId+"PC"));
+
+    }
+
+    @Override
+    public void removeToken(String token) {
+        if(StringUtil.isNotEmpty(token)){
+            String userId =get(formatTokenUserId(token));
+            delToken(userId);
+        }
+
+    }
+    @Override
+    public void removeToken(String token, String type) {
+        if(StringUtil.isEmpty(token)){
+            return ;
+
+        }
+
+        String replaceOpenid= get(formatTokenOpenid(token));
+        if(replaceOpenid!=null){
+            delete(formatTokenOpenid(token));
+        }
+
+        String replaceSessionKey= get(formatTokenSessionKey(token));
+        if(replaceSessionKey!=null){
+            delete(formatTokenSessionKey(token));
+        }
+
+        String replaceUserId =get(formatTokenUserId(token));
+        if(replaceUserId!=null){
+            delete(formatTokenToken(replaceUserId+type));
+        }
+
+        delete(formatTokenUserId(token));
+    }
+
+    @Override
+    public boolean checkToken(String token) {
+        boolean result = exists(formatTokenUserId(token));
+        if (result) {
+            refreshToken(token);
+        }
+        return result;
+    }
+
+    private void refreshToken(String token) {
+        try {
+
+
+            Long pptl=pttl(formatTokenUserId(token));
+            if(pptl > 259200000){
+                return;
+            }
+
+            String userId = get(formatTokenUserId(token));
+
+
+            boolean result = exists(formatTokenToken(userId + "PC"));
+            if (result) {
+                String redisToken = get(formatTokenToken(userId + "PC"));
+                if (token.equals(redisToken)) {
+                    expire(formatTokenUserId(token), seconds);
+                    expire(formatTokenToken(userId + "PC"), seconds);
+                }
+            }
+            result = exists(formatTokenToken(userId + "APP"));
+            if (result) {
+                String redisToken = get(formatTokenToken(userId + "APP"));
+                if (token.equals(redisToken)) {
+                    expire(formatTokenUserId(token), seconds);
+                    expire(formatTokenToken(userId + "APP"), seconds);
+                    expire(formatTokenOpenid(token), seconds);
+                    expire(formatTokenSessionKey(token), seconds);
+                }
+            }
+            result = exists(formatTokenToken(userId + "APP_TEACHER"));
+            if (result) {
+                String redisToken = get(formatTokenToken(userId + "APP_TEACHER"));
+                if (token.equals(redisToken)) {
+                    expire(formatTokenUserId(token), seconds);
+                    expire(formatTokenToken(userId + "APP_TEACHER"), seconds);
+                    expire(formatTokenOpenid(token), seconds);
+                    expire(formatTokenSessionKey(token), seconds);
+                }
+            }
+            result = exists(formatTokenToken(userId + "WX"));
+            if (result) {
+                String redisToken = get(formatTokenToken(userId + "WX"));
+                if (token.equals(redisToken)) {
+                    expire(formatTokenUserId(token), seconds);
+                    expire(formatTokenToken(userId + "WX"), seconds);
+                    expire(formatTokenOpenid(token), seconds);
+                    expire(formatTokenSessionKey(token), seconds);
+                }
+            }
+
+            result = exists(formatTokenToken(userId + "IPAD"));
+            if (result) {
+                String redisToken = get(formatTokenToken(userId + "IPAD"));
+                if (token.equals(redisToken)) {
+                    expire(formatTokenUserId(token), seconds);
+                    expire(formatTokenToken(userId + "IPAD"), seconds);
+                    expire(formatTokenOpenid(token), seconds);
+                    expire(formatTokenSessionKey(token), seconds);
+                }
+            }
+
+
+        } catch (Exception e) {
+            logger.error("刷新token失效时间发生异常", e);
+        }
+    }
+
+    @Override
+    public boolean checkToken(String token, String userId) {
+        boolean result = exists(formatTokenUserId(token));
+        logger.info("result="+result);
+        if (!userId.equals(get(formatTokenUserId(token)))) {
+            result = false;
+        }else{
+            refreshToken(token);
+        }
+
+        return result;
+    }
+
+    /*
+     * (non-Javadoc)
+     */
+    public String getUserId(String token) {
+        return get(formatTokenUserId(token));
+    }
+    public String getOpenId(String token) {
+        return get(formatTokenOpenid(token));
+    }
+    public String getSessionKey(String token) {
+        return get(formatTokenSessionKey(token));
+    }
+    public List<String> getToken(String userId){
+        List<String> list =new ArrayList<String>();
+        String token =getToken( userId,"WX");
+        if(token!=null){
+            list.add(token);
+        }
+        token =getToken( userId,"APP");
+        if(token!=null){
+            list.add(token);
+        }
+        token =getToken( userId,"APP_TEACHER");
+        if(token!=null){
+            list.add(token);
+        }
+        token =getToken( userId,"IPAD");
+        if(token!=null){
+            list.add(token);
+        }
+        token =getToken( userId,"PC");
+        if(token!=null){
+            list.add(token);
+        }
+
+        return list;
+    }
+    public String getToken(String userId, String type) {
+        return get(formatTokenToken(userId+type));
+    }
+
+    private String get(String key) {
+
+        return jedisPool.get(key);
+
+    }
+
+    public  <T> List<T> getList(String key, Class<T> clazz){
+
+
+        String value = jedisPool.get(key);
+        if(value!=null){
+            return JSON.parseArray(value, clazz);
+        }
+        return null;
+
+    }
+
+    private String set(String key, String value, int expireSeconds) {
+
+        return jedisPool.setex(key, expireSeconds, value);
+
+    }
+
+    public boolean exists(String key) {
+        return jedisPool.exists(key);
+
+    }
+
+    private void expire(String key, int seconds) {
+        jedisPool.expire(key, seconds);
+    }
+
+    private void delete(String keys) {
+        jedisPool.del(keys);
+    }
+
+    public  <T> T get(String key, Class<T> clazz){
+
+        String value = jedisPool.get(key);
+        if(value!=null){
+            return JSON.parseObject(value, clazz);
+        }
+        return null;
+    }
+
+    public String set(String key, Object value, int expireSeconds) {
+
+        String objectJson = JSON.toJSONString(value);
+        return jedisPool.setex(key, expireSeconds, objectJson);
+
+    }
+
+    public String setAt(String key, long expireUnitTime, Object value) {
+
+        String objectJson = JSON.toJSONString(value);
+        String result = jedisPool.set(key, objectJson);
+        jedisPool.expireAt(key, expireUnitTime);
+        return result;
+    }
+
+    public String set(String key, Object value) {
+
+        String objectJson = JSON.toJSONString(value);
+        return jedisPool.setex(key, DEFAULT_SECONDS, objectJson);
+
+    }
+
+
+    private Long pttl(String key) {
+            return jedisPool.pttl(key);
+    }
+
+    public Long setnx(String key, String value) {
+
+        return jedisPool.setnx(key, value);
+
+    }
+    @Override
+    public void hset(String key, Map<String, String> value) {
+
+        jedisPool.hmset(key, value);
+        jedisPool.expire(key, DEFAULT_SECONDS);
+
+    }
+
+    @Override
+    public void hset(String key, Map<String, String> value, int expireSeconds) {
+
+        jedisPool.hmset(key, value);
+        jedisPool.expire(key, expireSeconds);
+
+    }
+
+    @Override
+    public Map<String, String> hget(String key) {
+
+        return jedisPool.hgetAll(key);
+
+    }
+
+    @Override
+    public String setString(String key, String value, int expireSeconds) {
+        return set(key, value, expireSeconds);
+    }
+
+    @Override
+    public String setString(String key, String value) {
+        return set(key, value,DEFAULT_SECONDS);
+    }
+    @Override
+    public void delString(String key) {
+        delete(key);
+    }
+    @Override
+    public String getString(String key) {
+        return get(key);
+    }
+
+    private String formatTokenToken(String key) {
+        return REDIS_TOKEN_TOKEN_PREFIX.concat(key);
+    }
+
+    private String formatTokenUserId(String userId) {
+        return REDIS_TOKEN_USERID_PREFIX.concat(userId);
+    }
+
+    private String formatTokenOpenid(String openid) {
+        return REDIS_TOKEN_OPENID_PREFIX.concat(openid);
+    }
+    private String formatTokenSessionKey(String sessionKey) {
+        return REDIS_TOKEN_SESSION_KEY.concat(sessionKey);
+    }
+    private String formatXingeKey(String key) {
+        return REDIS_XINGE.concat(key);
+    }
+    /**
+     * 私塾家公众号开始
+     */
+    @Override
+    public String createSSJAccessToken(String wxToken, int seconds) {
+        seconds = seconds >0 ? seconds:ssjseconds;
+        set(SSJ_WX_TOKEN, wxToken, seconds);
+        return wxToken;
+    }
+
+    @Override
+    public String createSSJJSAccessToken(String wxToken, int seconds) {
+        seconds = seconds >0 ? seconds:ssjseconds;
+        set(SSJ_JSWX_TOKEN, wxToken, seconds);
+        return wxToken;
+    }
+    private String formatOpenId(String key) {
+        return SSJ_OPEN_ID.concat(key);
+    }
+    @Override
+    public String createSSJOpenId(String openId, String subscribe) {
+        String oldOpenId = get(formatOpenId(openId));
+        if(oldOpenId !=null ){
+            delete(formatOpenId(openId));
+        }
+        set(formatOpenId(openId), subscribe, DEFAULT_SECONDS);
+        return openId;
+    }
+
+    @Override
+    public String getSSJAccessToken() {
+        String accessToken=get(SSJ_WX_TOKEN);
+        if(accessToken ==null){
+            int seconds  = 0;
+            try {
+                JSONObject json =new WeixinUtil().getAccessToken();
+                accessToken=json.getString("access_token");
+                seconds=json.getInteger("expires_in");
+            } catch (Exception e) {
+                logger.info("发生异常SSJAccessToken:" + e.getMessage());
+                e.printStackTrace();
+            }
+            createSSJAccessToken(accessToken,seconds);
+        }
+        return accessToken;
+    }
+
+    @Override
+    public String getSSJJSAccessToken() {
+        String jsAccessToken=get(SSJ_JSWX_TOKEN);
+        if(jsAccessToken ==null){
+            int seconds  = 0;
+            try {
+                JSONObject json =new WeixinUtil().getJsApiTicket(this.getSSJAccessToken());
+                jsAccessToken=json.getString("ticket");
+                seconds=json.getInteger("expires_in");
+            } catch (Exception e) {
+                logger.info("发生异常:JsapiTicket" + e.getMessage());
+                e.printStackTrace();
+            }
+
+            createSSJJSAccessToken(jsAccessToken,seconds);
+        }
+        return jsAccessToken;
+    }
+
+
+
+    @Override
+    public String createWxOpenId(String openId, String subscribe) {
+        String oldOpenId = get(formatOpenId(openId));
+        if(oldOpenId !=null ){
+            delete(formatOpenId(openId));
+        }
+        set(formatOpenId(openId), subscribe, DEFAULT_SECONDS);
+        return openId;
+    }
+
+    @Override
+    public String getWxOpenId(String openId) {
+        return get(formatOpenId(openId));
+    }
+
+    @Override
+    public String getLibWeather(String libKey, String city) {
+        return get(libKey);
+    }
+
+    public String createWeather(String libValue, String libKey, int times){
+        times = times >0 ? times:ssjseconds;
+        set(libKey, libValue, times);
+        return libValue;
+    }
+
+    @Override
+    public String createPayOrderData(String orderNo, String orderdata) {
+        String order=get(ORDERDATA+orderNo);
+        if(order !=null){
+            delete(ORDERDATA+orderNo);
+        }
+        set(ORDERDATA+orderNo, orderdata, wxseconds);
+        return get(ORDERDATA+orderNo);
+    }
+
+    @Override
+    public String getPayOrderData(String orderNo) {
+        String order=get(ORDERDATA+orderNo);
+        return order;
+    }
+
+    @Override
+    public String getCurWeekendVipCode() {
+        if(exists(WEEKENDVIP)){
+            return get(WEEKENDVIP);
+        }else{
+            return "0";
+        }
+
+    }
+
+    @Override
+    public String createCurWeekendVipCode(String vipCode) {
+        String weekend=get(WEEKENDVIP);
+        if(weekend !=null){
+            delete(WEEKENDVIP);
+        }
+        set(WEEKENDVIP, vipCode, 365 * 24 * 3600);
+        return get(WEEKENDVIP);
+    }
+
+    @Override
+    public String createManageType(String userId, String type) {
+        String old_userId=get(userId);
+        if(old_userId !=null){
+            delete(userId);
+        }
+        set(userId,type, DEFAULT_SECONDS);
+        return get(userId);
+    }
+
+    @Override
+    public String getManageType(String userId) {
+        if(exists(userId)){
+            return get(userId);
+        }else{
+            return "-1";
+        }
+    }
+
+    @Override
+    public void deleteManageType(String userId) {
+        String old_userId=get(userId);
+        if(old_userId !=null){
+            delete(userId);
+        }
+    }
+
+    @Override
+    public String createServiceCount(String vipIdAndLibId, String type) {
+        String old_vipIdAndLibId=get(vipIdAndLibId);
+        if(old_vipIdAndLibId !=null){
+            delete(vipIdAndLibId);
+        }
+        set(vipIdAndLibId,type, 12 * 3600);
+        return get(vipIdAndLibId);
+    }
+
+    @Override
+    public String getServiceCount(String vipIdAndLibId) {
+        if(exists(vipIdAndLibId)){
+            return get(vipIdAndLibId);
+        }else{
+            return "-1";
+        }
+    }
+
+    @Override
+    public String getGrWord(String wordKey, int grade) {
+
+        return get(wordKey);
+    }
+
+    public String createGrWord(String wordKey, String wordValue, int times){
+        times = times >0 ? times:ssjseconds;
+        set(wordKey, wordValue, times);
+        return wordValue;
+    }
+
+
+    @Override
+    public String setXingeAlias(String userId, String alias) {
+        String oldAlias = get(formatXingeKey(userId));
+        if (oldAlias != null) {
+            delete(formatXingeKey(userId));
+        }
+        set(formatXingeKey(userId), alias, 365 * 24 * 3600);
+        return alias;
+    }
+
+    @Override
+    public String getXingeAlias(String userId) {
+        return get(formatXingeKey(userId));
+    }
+
+    @Override
+    public String setXinge(String derver, String xinge) {
+        String oldAlias = get(formatXingeKey(derver));
+        if (oldAlias != null) {
+            delete(formatXingeKey(derver));
+        }
+        set(formatXingeKey(derver), xinge, 365 * 24 * 3600);
+        return xinge;
+    }
+
+    @Override
+    public String getXinge(String derver) {
+        return get(formatXingeKey(derver));
+    }
+
+    @Override
+    public boolean addLock(String key, String requestId, int expireSeconds) {
+//        String result = jedisPool.set(key, requestId, "NX", "EX", expireSeconds);
+//        return "OK".equals(result);
+        return true;
+    }
+
+    @Override
+    public boolean unLock(String key, String requestId) {
+        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
+        Object result = jedisPool.eval(script, Collections.singletonList(key), Collections.singletonList(requestId));
+        return Objects.equals(1L, result);
+    }
+
+    @Override
+    public int recordPasswordWrong(String userAccount, String clientType) {
+        jedisPool.setex("LOGIN_" + userAccount + "_" + clientType + "_" + System.currentTimeMillis(), 30 * 60, "1");
+        Set<String> keySet = this.getKeys("LOGIN_" + userAccount + "_" + clientType + "_*");
+        if (keySet.size() >= 5) {
+            jedisPool.setex("LOGIN_LOCK_" + userAccount + "_" + clientType + "_" + System.currentTimeMillis(), 30 * 60,
+                    String.valueOf(System.currentTimeMillis()));
+        }
+        return keySet.size();
+    }
+
+    private Set<String> getKeys(String pattern) {
+        Set<String> keySet = new HashSet<>();
+        Map<String, JedisPool> clusterNodes = jedisPool.getClusterNodes();
+        JedisPool tempJedisPool;
+        for(String k : clusterNodes.keySet()){
+            tempJedisPool = clusterNodes.get(k);
+            try (Jedis connection = tempJedisPool.getResource()) {
+                keySet.addAll(connection.keys(pattern));
+            } catch (Exception e) {
+                logger.error("Getting keys error", e);
+            }
+        }
+
+        return keySet;
+    }
+
+    @Override
+    public void clearPasswordWrongRecord(String userAccount) {
+        this.batchDel("LOGIN_" + userAccount + "_*");
+    }
+
+    @Override
+    public void batchDel(String key) {
+
+
+        TreeSet<String> keys = new TreeSet<>();
+        Map<String, JedisPool> clusterNodes = jedisPool.getClusterNodes();
+        for(String k : clusterNodes.keySet()){
+            logger.debug("Getting keys from: {}", k);
+            JedisPool jp = clusterNodes.get(k);
+            Jedis connection = jp.getResource();
+            try {
+                keys.addAll(connection.keys(key));
+            } catch(Exception e){
+                logger.error("Getting keys error: {}", e);
+            } finally{
+                logger.debug("Connection closed.");
+                connection.close();//用完一定要close这个链接!!!
+            }
+        }
+        Iterator<String> it = keys.iterator();
+        while(it.hasNext()){
+            String keyStr = it.next();
+            jedisPool.del(keyStr);
+        }
+    }
+
+    @Override
+    public String setEasemob(String derver, String easemobName) {
+        logger.info("reids-derver="+derver);
+        logger.info("reids-easemobName="+easemobName);
+        String oldEasemobName = get(EASEMOBNAME+derver);
+        if (oldEasemobName != null) {
+            logger.info("reids-oldeasemobName="+oldEasemobName);
+            delete(EASEMOBNAME+derver);
+        }
+        set(EASEMOBNAME+derver, easemobName,10 * 365* 24 * 3600);
+        return easemobName;
+    }
+
+    @Override
+    public String getEasemob(String derver) {
+        return get(EASEMOBNAME+derver);
+    }
+
+    @Override
+    public Long incrKey(String key){
+        return  jedisPool.incr(key);
+    }
+    @Override
+    public Long incrByLong(String key, Long incrAmout){
+        return  jedisPool.incrBy(key,incrAmout);
+    }
+
+    @Override
+    public void refreshExpireTime(String key, int expireSeconds) {
+        jedisPool.expire(key, expireSeconds);
+    }
+}

+ 65 - 0
src/main/java/com/aijia/kmt/common/SpringContextHolder.java

@@ -0,0 +1,65 @@
+package com.aijia.kmt.common;
+
+import org.apache.dubbo.config.annotation.Service;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+
+import java.util.Map;
+
+/**
+ * @author yrf
+ * @description
+ * @time 2019/9/16 17:37
+ */
+@Service
+@Lazy(false)
+@Configuration
+public class SpringContextHolder implements ApplicationContextAware {
+
+    private static ApplicationContext applicationContext;
+
+
+    //实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) {
+        SpringContextHolder.applicationContext = applicationContext;
+    }
+
+
+    //取得存储在静态变量中的ApplicationContext.
+    public static ApplicationContext getApplicationContext() {
+        checkApplicationContext();
+        return applicationContext;
+    }
+
+    //从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String name) {
+        checkApplicationContext();
+        return (T) applicationContext.getBean(name);
+    }
+
+
+    //从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
+    //如果有多个Bean符合Class, 取出第一个.
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(Class<T> clazz) {
+        checkApplicationContext();
+        @SuppressWarnings("rawtypes")
+        Map beanMaps = applicationContext.getBeansOfType(clazz);
+        if (beanMaps!=null && !beanMaps.isEmpty()) {
+            return (T) beanMaps.values().iterator().next();
+        } else{
+            return null;
+        }
+    }
+
+    private static void checkApplicationContext() {
+        if (applicationContext == null) {
+            throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");
+        }
+    }
+
+}

+ 64 - 0
src/main/java/com/aijia/kmt/common/WebMvcConfig.java

@@ -0,0 +1,64 @@
+package com.aijia.kmt.common;
+
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.alibaba.fastjson.support.config.FastJsonConfig;
+import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
+import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.nio.charset.Charset;
+
+/**
+ * 类名称:CustomObjectMapper<br>
+ *
+ * @version v1.0
+ */
+@Configuration
+public class WebMvcConfig implements WebMvcConfigurer {
+
+    @Bean
+    public HttpMessageConverters fastJsonHttpMessageConverters() {
+        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
+        FastJsonConfig fastJsonConfig = new FastJsonConfig();
+
+        fastJsonConfig.setSerializerFeatures(
+                // 输出空置字段
+                SerializerFeature.WriteMapNullValue,
+                // list字段如果为null,输出为[],而不是null
+                SerializerFeature.WriteNullListAsEmpty,
+                // 数值字段如果为null,输出为0,而不是null
+                SerializerFeature.WriteNullNumberAsZero,
+                // Boolean字段如果为null,输出为false,而不是null
+                SerializerFeature.WriteNullBooleanAsFalse,
+                // 字符类型字段如果为null,输出为"",而不是null
+                SerializerFeature.WriteNullStringAsEmpty,
+                SerializerFeature.WriteDateUseDateFormat,
+                // 禁用 fastjson 循环引用检测
+                SerializerFeature.DisableCircularReferenceDetect);
+
+        fastJsonConfig.setCharset(Charset.forName("UTF-8"));
+//        fastJsonConfig.setDateFormat("yyyy-MM-dd hh:mm:ss");
+        fastConverter.setFastJsonConfig(fastJsonConfig);
+        HttpMessageConverter<?> converter = fastConverter;
+        return new HttpMessageConverters(converter);
+    }
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler("swagger-ui.html")
+                .addResourceLocations("classpath:/META-INF/resources/");
+
+        registry.addResourceHandler("/webjars/**")
+                .addResourceLocations("classpath:/META-INF/resources/webjars/");
+
+        registry.addResourceHandler("/favicon.ico")
+                .addResourceLocations("classpath:/META-INF/resources/favicon.ico");
+
+        registry.addResourceHandler("/wifi/**").addResourceLocations("classpath:/META-INF/resources/wifi/");
+    }
+
+}

+ 191 - 0
src/main/java/com/aijia/kmt/common/constant/Constant.java

@@ -0,0 +1,191 @@
+package com.aijia.kmt.common.constant;
+
+import com.aijia.kmt.dto.exercise.QuestionSubjectAttribute;
+import com.aijia.kmt.dto.knowledge.KnowledgeBaseDto;
+import com.aijia.kmt.utils.PropertiesUtil;
+import com.alibaba.fastjson.JSONArray;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Constant {
+    /**
+     * 作业批注超时时间,30分钟
+     */
+    public static final int HOME_WORK_OUTTIME = 30;
+
+    /**
+     * 难题解答超时时间,20分钟
+     */
+    public static final int PROBLEM_OUTTIME = 20;
+
+    /**
+     * tb_lib_manager中校长的类别
+     */
+    public static final int SCHOOL_MASTER_TYPE = 6;
+
+    /**
+     * tb_lib_manager中在馆老师的类别
+     */
+    public static final int TEACHER_TYPE = 2;
+
+    /**
+     * tb_lib_manager一对一的老师类别
+     */
+    public static final int KMT_121_TEACHER_TYPE = 7;  
+
+    
+    /**
+     * tb_lib_manager中线上老师,和kmt 的老师
+     */
+    public static final int KMT_122_TEACHER_TYPE = 8;
+
+    /**
+     * tb_lib_manager小课老师的type
+     */
+    public static final int GROUP_TEACHER_TYPE = 9;
+
+    /**
+     * tb_lib_manager机构老师的type
+     */
+    public static final int ORG_TEACHER_TYPE = 10;
+    /**
+     * tb_lib_manager校区群管理员的type
+     */
+    public static final int CORRECT_MANAGER_TYPE = 11;
+    /**
+     * tb_lib_manager超级管理员的type
+     */
+    public static final int CORRECT_SUPER_MANAGER_TYPE = 12;
+    /**
+     * tb_lib_manager匹配知识点老师的type
+     */
+    public static final int CORRECT_KNOW_TYPE = 13;
+    /**
+     * 质检员
+     */
+    public static final int CORRECT_CHECKER = 14;
+
+    /**
+     * 质检员
+     */
+    public static final int SELF_CORRECT_TYPE = 15;
+    /**
+     * 作业批注
+     */
+    public static final int TEACHER_TASK_HOMEWORK = 1;
+
+    /**
+     * 难题反馈
+     */
+    public static final int TEACHER_TASK_RPOBLEM = 2;
+
+    /**
+     * 作业批注
+     */
+    public static final int TEACHER_TASK_WORKFEEDBACK = 3;
+
+    /**
+     * 服务列表
+     */
+    public static final Map<String, String>  SERVICE_MAP = new HashMap<String, String>();
+    /**
+     * 录入
+     */
+    public static final String   CMB_DF_STATUS_I                         = "I";
+    /**
+     * 成功
+     */
+    public static final String   CMB_DF_STATUS_S                         = "S";
+    /**
+     * 失败
+     */
+    public static final String   CMB_DF_STATUS_F                         = "F";
+
+    /**
+     * 正在获取状态
+     */
+    public static final String   CMB_DF_STATUS_C                         = "C";
+    
+    /**
+     * 录入
+     */
+    public static final String   WITHDRAWAL_STATUS_INIT                  = "INIT";
+    /**
+     * 重新
+     */
+    public static final String   WITHDRAWAL_STATUS_REINIT                = "REINIT";
+    /**
+     * 错误
+     */
+    public static final String   WITHDRAWAL_STATUS_ERROR                 = "ERROR";
+    /**
+     * 成功
+     */
+    public static final String   WITHDRAWAL_STATUS_SUCCESS               = "SUCCESS";
+    /**
+     * 失败
+     */
+    public static final String   WITHDRAWAL_STATUS_FAIL                  = "FAIL";
+    
+    /**
+     * 注册老师
+     */
+    public static final String   REGISTER_TEACHER                  = "注册老师";
+    
+    /**
+     * 资深老师
+     */
+    public static final String	SENIOR_TEACHER               = "资深老师";
+    /**
+     * 明星老师
+     */
+    public static final String   STAR_TEACHER                  = "明星老师";
+    /**
+     * 学霸老师
+     */
+    public static final String   SUPER_TEACHER                  = "学霸老师";
+
+    /**
+     * 小课老师
+     */
+    public static final String   GROUP_TEACHER                  = "小课老师";
+
+    public static final Map<String, String> ZYB_CARD_TYPE      = new HashMap<String, String>();
+
+    /**
+     * 题目类型
+     */
+    public static final List<QuestionSubjectAttribute> QUESTION_TYPES = JSONArray.parseArray(PropertiesUtil.getValue("QUESTION_TYPES"), QuestionSubjectAttribute.class);
+
+    /**
+     * 难度级别
+     */
+    public static final List<KnowledgeBaseDto> DIFFICULTY_LEVELS = JSONArray.parseArray(PropertiesUtil.getValue("DIFFICULTY_LEVELS"), KnowledgeBaseDto.class);
+
+    /**
+     * 真题例题练习题
+     */
+    public static final List<KnowledgeBaseDto> REAL_EXAM_TYPE = JSONArray.parseArray(PropertiesUtil.getValue("REAL_EXAM_TYPE"), KnowledgeBaseDto.class);
+
+    /**
+     * 能力
+     */
+    public static final List<QuestionSubjectAttribute> TRAINING_SKILL =  JSONArray.parseArray(PropertiesUtil.getValue("TRAINING_SKILL"), QuestionSubjectAttribute.class);
+
+    static {
+        SERVICE_MAP.put("S003", "作业吧");
+        SERVICE_MAP.put("S010", "一对一");
+
+        ZYB_CARD_TYPE.put("C001", "年卡");
+        ZYB_CARD_TYPE.put("C002", "半年卡");
+        ZYB_CARD_TYPE.put("C003", "月卡");
+        ZYB_CARD_TYPE.put("C004", "作业吧月卡");
+        ZYB_CARD_TYPE.put("C005", "作业吧半年卡");
+        ZYB_CARD_TYPE.put("C006", "作业吧年卡");
+        ZYB_CARD_TYPE.put("C015", "季度卡");
+
+    }
+
+}

+ 182 - 0
src/main/java/com/aijia/kmt/common/constant/CourseConstant.java

@@ -0,0 +1,182 @@
+package com.aijia.kmt.common.constant;
+
+import com.aijia.kmt.enums.GradeEnum;
+import com.aijia.kmt.utils.PropertiesUtil;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CourseConstant implements Serializable{
+    /**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+
+	/**
+     * 全学科列表
+     */
+    public final static List<String> subjectList = new ArrayList<>();
+
+
+    /**
+     * 全学科列表
+     */
+    public final static List<String> MAIN_SUBJECT_LIST = new ArrayList<>();
+
+    /**
+     * 排行榜显示top几
+     */
+    public final static int RANKING_COUNT = 50;
+
+    /**
+     * 同学圈排行榜基础分值
+     */
+    public final static Map<String, Integer> RANKING_BASE = new HashMap<>();
+
+    /**
+     * 学生学习状态及其对应分数
+     */
+    public final static List<Map<String, Object>> LABEL_SCORE = new ArrayList<>();
+
+
+    /**
+     * 作业状态名称
+     */
+    public final static List<String> LABEL_NAME_LIST = new ArrayList<>();
+
+    /**
+     * 各科作业的内容名称
+     */
+    public final static List<Map<String, Object>> SUBJECT_ITEM_TITLE = new ArrayList<>();
+
+    /**
+     * 题目类型
+     */
+    public final static String QUESTION_TYPES_STR = PropertiesUtil.getValue("QUESTION_TYPES");
+
+    /**
+     * 难易程度
+     */
+    public final static String DIFFICULTY_LEVELS_STR = PropertiesUtil.getValue("DIFFICULTY_LEVELS");
+
+    /**
+     * 真题例题类型
+     */
+    public final static String REAL_EXAM_TYPE_STR = PropertiesUtil.getValue("REAL_EXAM_TYPE");
+
+    /**
+     * 训练能力
+     */
+    public final static String TRAINING_SKILL_STR =  PropertiesUtil.getValue("TRAINING_SKILL");
+
+    /**
+     * 发布时间,用于作业反馈报告的查询
+     */
+    public final static String publishDate = "2018-10-31";
+
+
+
+    static {
+        initSubjectList();
+        initRankingBase();
+        initLabelScore();
+        initLabelName();
+        initSubjectItemTitle();
+    }
+
+    public static void initSubjectList (){
+        subjectList.add("语文");
+        subjectList.add("数学");
+        subjectList.add("英语");
+        subjectList.add("物理");
+        subjectList.add("化学");
+
+        MAIN_SUBJECT_LIST.add("语文");
+        MAIN_SUBJECT_LIST.add("数学");
+        MAIN_SUBJECT_LIST.add("英语");
+    }
+
+    public static void initRankingBase () {
+        //点赞
+        RANKING_BASE.put("1", 1);
+        //被点赞
+        RANKING_BASE.put("2", 2);
+        //发消息
+        RANKING_BASE.put("3", 4);
+        //评论
+        RANKING_BASE.put("4", 2);
+        //被采纳
+        RANKING_BASE.put("5", 4);
+    }
+
+    public static void initLabelScore (){
+        Map<String, Object> item = new HashMap<>();
+        item.put("name", "欠佳");
+        item.put("score", 1);
+        LABEL_SCORE.add(item);
+
+        item = new HashMap<>();
+        item.put("name", "一般");
+        item.put("score", 2);
+        LABEL_SCORE.add(item);
+
+        item = new HashMap<>();
+        item.put("name", "好");
+        item.put("score", 3);
+        LABEL_SCORE.add(item);
+    }
+
+    public static void initLabelName(){
+        LABEL_NAME_LIST.add("作业速度");
+        LABEL_NAME_LIST.add("自律性");
+        LABEL_NAME_LIST.add("积极性");
+        LABEL_NAME_LIST.add("专注度");
+    }
+
+    public static void initSubjectItemTitle () {
+        Map<String, Object> subject  = new HashMap<>();
+        String[] chineseItem = {"拼音抄写", "新字词抄写", "笔画认识", "笔顺认识", "造句", "听写", "默写", "课文朗读", "背诵", "阅读", "看图写作", "好词好句摘抄", "其他"};
+        String[] mathItem = {"数字书写练习", "口算题", "计算题", "应用题", "画图题", "填空题", "判断题", "常识题", "图形认识", "拓展题", "其他"};
+        String[] englishItem = {"字母书写练习", "语法", "单项选择", "单词填空题", "阅读判断", "问答题", "课文朗读", "单词听写", "拓展题", "其他"};
+
+        subject.put("subject", "语文");
+        subject.put("list", chineseItem);
+        SUBJECT_ITEM_TITLE.add(subject);
+
+        subject = new HashMap<>();
+        subject.put("subject", "数学");
+        subject.put("list", mathItem);
+        SUBJECT_ITEM_TITLE.add(subject);
+
+        subject = new HashMap<>();
+        subject.put("subject", "英语");
+        subject.put("list", englishItem);
+        SUBJECT_ITEM_TITLE.add(subject);
+    }
+
+    /**
+     * 根据年级获取科目列表, 低年级只能是语数英
+     * @param grade
+     * @return
+     */
+    public static List<String> getSubjectList (String grade) {
+        if (StringUtils.isBlank(grade)) {
+            return MAIN_SUBJECT_LIST;
+        }
+        int gradeNum = GradeEnum.getIndexByGrade(grade);
+        if (gradeNum < 7){
+            return MAIN_SUBJECT_LIST;
+        }  else {
+            return subjectList;
+        }
+    }
+
+    public static List<String>  getAllSubjectList (){
+        return subjectList;
+    }
+}

+ 222 - 0
src/main/java/com/aijia/kmt/common/constant/ImageTools.java

@@ -0,0 +1,222 @@
+package com.aijia.kmt.common.constant;
+
+//import com.aijia.aiservice.provider.utils.OSSUtils;
+//import com.aijia.aiservice.provider.utils.PropertiesUtil;
+import com.aijia.kmt.po.base.IdWorker;
+import com.aijia.kmt.utils.OSSUtils;
+import com.aijia.kmt.utils.PropertiesUtil;
+import com.aijia.utils.DateUtil;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * 
+ * 类名称:ImageTools<br>
+ * 类描述:图片工具类<br>
+ * @version v1.0
+ *
+ */
+public class ImageTools {
+    protected static Logger logger = LoggerFactory.getLogger(ImageTools.class);
+    /**
+     * jpg后缀
+     */
+    public static final String SUFF_JPG = ".jpg";
+
+    /**
+     * png后缀
+     */
+    public static final String SUFF_PNG = ".png";
+
+    /**
+     * gif后缀
+     */
+    public static final String SUFF_GIF = ".gif";
+
+    /**
+     * 保存来自base64的图片,返回参数不为空保存成功
+     * @param base64String
+     * @return
+     */
+    public static String savePic4Base64(String base64String) {
+        String saveFileName = IdWorker.generateId() + getPicExtension(base64String);
+
+        //判断是否为base64字符串,不是要处理
+        if (!Base64.isBase64(base64String)) {
+            String[] base64Strs = base64String.split(",");
+            if (base64Strs.length > 1) {
+                base64String = base64Strs[1];
+            }
+        }
+        byte[] bytes = Base64.decodeBase64(base64String);
+
+        for (int i = 0; i < bytes.length; ++i) {
+            if (bytes[i] < 0) {//调整异常数据  
+                bytes[i] += 256;
+            }
+        }
+
+        String imgFilePath = getSavePath() + "/" +  saveFileName;//图片保存路径
+
+        try {
+            IOUtils.write(bytes, new FileOutputStream(imgFilePath));
+            String ps= OSSUtils.uploadFile(imgFilePath,
+                    imgFilePath.replaceAll(PropertiesUtil.getValue("file_save_path"),""));
+            logger.info("阿里oss返回的路径="+ps);
+
+        } catch (IOException e) {
+            e.printStackTrace();
+            imgFilePath = null;
+        }
+        return imgFilePath;
+    }
+
+
+
+
+    public static String[] uploadFile(Map<String, MultipartFile> fileList) {
+        String[] filePaths = new String[fileList.size()];
+
+        String imgFilePath = getSavePath() + "/" ;
+        int i = 0;
+        for (Map.Entry<String, MultipartFile> entity : fileList.entrySet()) {
+            MultipartFile fileItem = entity.getValue();
+
+            //图片保存文件名
+            String saveFileName =IdWorker.generateId() + "." + FilenameUtils.getExtension(fileItem.getName());
+            FileOutputStream outputStream = null;
+            try {
+                outputStream = new FileOutputStream(imgFilePath + saveFileName);
+                IOUtils.write(fileItem.getBytes(), outputStream);
+
+                filePaths[i] = imgFilePath + saveFileName;
+            } catch (IOException e) {
+                e.printStackTrace();
+            }finally  {
+                IOUtils.closeQuietly(outputStream);
+            }
+            i++;
+        }
+        return filePaths;
+    }
+    
+    public static String[] uploadFile(List<MultipartFile> fileList) {
+        String imgFilePath = getSavePath() + "/" ;
+        return uploadFile(imgFilePath, fileList);
+    }
+
+
+    public static String[] uploadFile(String imgFilePath, List<MultipartFile> fileList) {
+        String[] filePaths = new String[fileList.size()];
+        int i = 0;
+        for (MultipartFile fileItem : fileList) {
+
+            //图片保存文件名
+            String originalFile = fileItem.getOriginalFilename();
+            String ext = originalFile.substring(originalFile.lastIndexOf("."));
+            if(ext !=null && ext.contains("image%")){
+                ext =SUFF_JPG;
+            }
+            String saveFileName = IdWorker.generateId() + ext;
+            FileOutputStream outputStream = null;
+            try {
+                outputStream = new FileOutputStream(imgFilePath + saveFileName);
+                IOUtils.write(fileItem.getBytes(), outputStream);
+
+
+                String ps= OSSUtils.uploadInputStream(fileItem.getInputStream(),
+                        (imgFilePath + saveFileName).replaceAll(PropertiesUtil.getValue("file_save_path"),""));
+                logger.info("阿里oss返回的路径="+ps);
+
+
+
+                filePaths[i] = imgFilePath + saveFileName;
+            } catch (IOException e) {
+                e.printStackTrace();
+            }finally  {
+                IOUtils.closeQuietly(outputStream);
+            }
+            i++;
+        }
+
+        return filePaths;
+    }
+
+    public static void uploadFile(String absFileName, MultipartFile file) {
+        //图片保存文件名
+        FileOutputStream outputStream = null;
+        try {
+            outputStream = new FileOutputStream(absFileName);
+            IOUtils.write(file.getBytes(), outputStream);
+//            String ps= OSSUtils.uploadInputStream(file.getInputStream(),
+//                    absFileName.replaceAll(PropertiesUtil.getValue("file_save_path"),""));
+//            logger.info("阿里oss返回的路径="+ps);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }finally  {
+            IOUtils.closeQuietly(outputStream);
+        }
+    }
+
+    public static void uploadFilePd(MultipartFile files, String imgFilePath) {
+        FileOutputStream outputStream = null;
+            try {
+                outputStream = new FileOutputStream(imgFilePath);
+                IOUtils.write(files.getBytes(), outputStream);
+
+                String ps= OSSUtils.uploadInputStream(files.getInputStream(),
+                        imgFilePath.replaceFirst(PropertiesUtil.getValue("file_save_path"),""));
+                logger.info("上海培典上传深圳阿里oss返回的路径="+ps);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }finally  {
+                IOUtils.closeQuietly(outputStream);
+            }
+    }
+
+    /**
+     * 获取保存目录 按年/月/日 区分
+     */
+    public static String getSavePath() {
+        String savePath = PropertiesUtil.getValue("file_save_path");
+        // 当前日期(按月保存)
+        String date = DateUtil.format(System.currentTimeMillis(), "yyyy/MM/dd");
+        savePath = savePath +  date;
+        // 创建文件夹
+        File f = new File(savePath);
+        if (!f.exists()) {
+            f.mkdirs();
+        }
+        return savePath;
+    }
+
+    /**
+     * 从base64字符串中获取图片后缀
+     * @return
+     */
+    private static String getPicExtension(String base64String) {
+        //默认使用jpg
+        if (base64String.contains("image/jpg")) {
+            return SUFF_JPG;
+        } else if (base64String.contains("image/png")) {
+            return SUFF_PNG;
+        } else if (base64String.contains("image/gif")) {
+            return SUFF_GIF;
+        } else {
+            return SUFF_JPG;
+        }
+    }
+
+
+}

+ 94 - 0
src/main/java/com/aijia/kmt/common/constant/Knowledge2.java

@@ -0,0 +1,94 @@
+package com.aijia.kmt.common.constant;
+
+import com.aijia.kmt.dto.knowledge.KnowledgeBaseDto;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class Knowledge2 {
+    private List<KnowledgeBaseDto> chineseList = new ArrayList<>();
+
+    private List<KnowledgeBaseDto> mathList = new ArrayList<>();
+
+    private List<KnowledgeBaseDto> englishList = new ArrayList<>();
+
+    public void init() {
+        initChineseList();
+        initMathList();
+        initEnglishList();
+    }
+
+    public void destroy () {
+
+    }
+
+    /**
+     * 初始化语文版本
+     */
+    public void initChineseList () {
+        KnowledgeBaseDto temp = new KnowledgeBaseDto(2, "人教(部编)");
+        this.chineseList.add(temp);
+    }
+
+    /**
+     * 初始化数学版本
+     */
+    public void initMathList () {
+        KnowledgeBaseDto renTemp = new KnowledgeBaseDto(2, "人教版");
+        this.mathList.add(renTemp);
+    }
+
+    /**
+     * 初始化英语版本
+     */
+    public void initEnglishList () {
+        KnowledgeBaseDto peopleEducationEdition = new KnowledgeBaseDto(8, "人教版(PEP)");
+        this.englishList.add(peopleEducationEdition);
+    }
+
+
+
+    /**
+     * 根据科目返回版本列表
+     * @param subject
+     * @return
+     */
+    public List<KnowledgeBaseDto> getVersionListBySubject (String subject) {
+        List<KnowledgeBaseDto> result;
+        switch (subject){
+            case "语文": result = this.chineseList; break;
+            case "数学": result = this.mathList; break;
+            case "英语": result = this.englishList; break;
+            default: result = this.chineseList;
+        }
+        return result;
+    }
+
+    /**
+     * 根据科目和版本号获取版本名
+     */
+    public String getVersionNameBySubjectAndVersionNum(String subject, Integer versionNum) {
+        List<KnowledgeBaseDto> knowledgeBaseDtoList = getVersionListBySubject(subject);
+        for (KnowledgeBaseDto knowledgeBaseDto : knowledgeBaseDtoList) {
+            if (Objects.equals(versionNum, knowledgeBaseDto.getType())) {
+                return knowledgeBaseDto.getName();
+            }
+        }
+
+        return "未知的版本";
+    }
+
+    /**
+     * 根据科目和版本名获取版本号
+     */
+    public Integer getVersionNumBySubjectAndVersionName(String subject, String versionName) {
+        List<KnowledgeBaseDto> knowledgeBaseDtoList = getVersionListBySubject(subject);
+        for (KnowledgeBaseDto knowledgeBaseDto : knowledgeBaseDtoList) {
+            if (Objects.equals(versionName, knowledgeBaseDto.getName())) {
+                return knowledgeBaseDto.getType();
+            }
+        }
+        return 0;
+    }
+}

+ 13 - 0
src/main/java/com/aijia/kmt/common/constant/KnowledgeConfig.java

@@ -0,0 +1,13 @@
+package com.aijia.kmt.common.constant;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class KnowledgeConfig {
+
+    @Bean(initMethod = "init", destroyMethod = "destroy")
+    public KnowledgeVersion knowledgeVersion(){
+        return new KnowledgeVersion();
+    }
+}

+ 163 - 0
src/main/java/com/aijia/kmt/common/constant/KnowledgeVersion.java

@@ -0,0 +1,163 @@
+package com.aijia.kmt.common.constant;
+
+
+
+
+import com.aijia.kmt.dto.knowledge.KnowledgeBaseDto;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class KnowledgeVersion {
+
+    private List<KnowledgeBaseDto> chineseList = new ArrayList<>();
+
+    private List<KnowledgeBaseDto> mathList = new ArrayList<>();
+
+    private List<KnowledgeBaseDto> englishList = new ArrayList<>();
+
+    private List<KnowledgeBaseDto> physicsList = new ArrayList<>();
+
+    private List<KnowledgeBaseDto> chemistryList = new ArrayList<>();
+
+    public void init() {
+        initChineseList();
+        initMathList();
+        initEnglishList();
+        initPhysicsList();
+        initChemistryList();
+    }
+
+    public void destroy () {
+
+    }
+
+    /**
+     * 初始化语文版本
+     */
+    public void initChineseList () {
+        KnowledgeBaseDto temp = new KnowledgeBaseDto(1, "人教版");
+        this.chineseList.add(temp);
+        temp = new KnowledgeBaseDto(2, "人教(部编)");
+        this.chineseList.add(temp);
+        temp = new KnowledgeBaseDto(3, "人教(部编旧)");
+        this.chineseList.add(temp);
+    }
+
+    /**
+     * 初始化数学版本
+     */
+    public void initMathList () {
+        KnowledgeBaseDto northTemp = new KnowledgeBaseDto(1, "北师大版");
+        this.mathList.add(northTemp);
+        KnowledgeBaseDto renTemp = new KnowledgeBaseDto(2, "人教版");
+        this.mathList.add(renTemp);
+        KnowledgeBaseDto suTTemp = new KnowledgeBaseDto(5, "苏教版");
+        this.mathList.add(suTTemp);
+        KnowledgeBaseDto siTemp = new KnowledgeBaseDto(6, "思维拓展");
+        this.mathList.add(siTemp);
+    }
+
+    /**
+     * 初始化英语版本
+     */
+    public void initEnglishList () {
+        KnowledgeBaseDto temp = new KnowledgeBaseDto(3, "沪教版(新)");
+        this.englishList.add(temp);
+
+        KnowledgeBaseDto longmanEdition = new KnowledgeBaseDto(7, "朗文版");
+        this.englishList.add(longmanEdition);
+
+        KnowledgeBaseDto peopleEducationEdition = new KnowledgeBaseDto(8, "人教版(PEP)");
+        this.englishList.add(peopleEducationEdition);
+
+        KnowledgeBaseDto teachingVersion = new KnowledgeBaseDto(2, "教科版");
+        this.englishList.add(teachingVersion);
+
+        KnowledgeBaseDto oxford = new KnowledgeBaseDto(9, "牛津版");
+        this.englishList.add(oxford);
+
+        KnowledgeBaseDto externalResearchEdition = new KnowledgeBaseDto(10, "外研版(JOIN IN)");
+        this.englishList.add(externalResearchEdition);
+
+        temp = new KnowledgeBaseDto(11, "广东人民版");
+        this.englishList.add(temp);
+
+        temp = new KnowledgeBaseDto(12, "牛津上海版");
+        this.englishList.add(temp);
+
+        temp = new KnowledgeBaseDto(14, "译林版");
+        this.englishList.add(temp);
+
+        temp = new KnowledgeBaseDto(15, "外研版(三起点)");
+        this.englishList.add(temp);
+
+        temp = new KnowledgeBaseDto(16, "湘少版");
+        this.englishList.add(temp);
+
+        temp = new KnowledgeBaseDto(17, "闽教版");
+        this.englishList.add(temp);
+    }
+
+    /**
+     * 初始化物理版本
+     */
+    public void initPhysicsList () {
+        KnowledgeBaseDto temp = new KnowledgeBaseDto(2, "人教版");
+        this.physicsList.add(temp);
+    }
+
+    /**
+     * 初始化化学版本
+     */
+    public void initChemistryList () {
+        KnowledgeBaseDto temp = new KnowledgeBaseDto(2, "人教版");
+        this.chemistryList.add(temp);
+    }
+
+
+    /**
+     * 根据科目返回版本列表
+     * @param subject
+     * @return
+     */
+    public List<KnowledgeBaseDto> getVersionListBySubject (String subject) {
+        List<KnowledgeBaseDto> result;
+        switch (subject){
+            case "语文": result = this.chineseList; break;
+            case "数学": result = this.mathList; break;
+            case "英语": result = this.englishList; break;
+            default: result = this.physicsList;
+        }
+        return result;
+    }
+
+    /**
+     * 根据科目和版本号获取版本名
+     */
+    public String getVersionNameBySubjectAndVersionNum(String subject, Integer versionNum) {
+        List<KnowledgeBaseDto> knowledgeBaseDtoList = getVersionListBySubject(subject);
+        for (KnowledgeBaseDto knowledgeBaseDto : knowledgeBaseDtoList) {
+            if (Objects.equals(versionNum, knowledgeBaseDto.getType())) {
+                return knowledgeBaseDto.getName();
+            }
+        }
+
+        return "未知的版本";
+    }
+
+    /**
+     * 根据科目和版本名获取版本号
+     */
+    public Integer getVersionNumBySubjectAndVersionName(String subject, String versionName) {
+        List<KnowledgeBaseDto> knowledgeBaseDtoList = getVersionListBySubject(subject);
+        for (KnowledgeBaseDto knowledgeBaseDto : knowledgeBaseDtoList) {
+            if (Objects.equals(versionName, knowledgeBaseDto.getName())) {
+                return knowledgeBaseDto.getType();
+            }
+        }
+        return 0;
+    }
+
+}

+ 54 - 0
src/main/java/com/aijia/kmt/common/constant/RedisConstants.java

@@ -0,0 +1,54 @@
+package com.aijia.kmt.common.constant;
+
+
+public class RedisConstants {
+	
+	public static final String spilt=":";
+
+	/**
+	 * redis库1  保存档案树
+	 */
+	public static final Integer datebase1=1;
+
+	/**
+	 * 1.redis库2 保存档案表格
+	 * 2.保存分页码
+	 */
+	public static final Integer datebase2=2;
+
+	/**
+	 * redis库3 保存档案image url
+	 */
+	public static final Integer datebase3=3;
+
+	/**
+	 * 1.redis库4 保存手机验证码
+	 *
+	 */
+	public static final Integer datebase4=4;
+
+	/**
+	 * redis库5 保存身份认证信息
+	 */
+	public static final Integer datebase5=5;
+
+	/**
+	 * redis库6 记录身份认证次数
+	 */
+	public static final Integer datebase6=6;
+
+	/**
+	 * redis库7 记录重发次数
+	 */
+	public static final Integer datebase7=7;
+
+	/**
+	 * redis库8 记录任务参数
+	 */
+	public static final Integer datebase8=8;
+
+	
+	public RedisConstants() {
+
+	}
+}

+ 134 - 0
src/main/java/com/aijia/kmt/common/excel/j2se/RandomUtils.java

@@ -0,0 +1,134 @@
+package com.aijia.kmt.common.excel.j2se;
+
+import java.util.Random;
+import java.util.UUID;
+
+/**
+ * 随机数工具类
+ * 
+ * @author <a href="http://www.xdemo.org/">http://www.xdemo.org/</a>
+ *         252878950@qq.com
+ */
+public class RandomUtils {
+
+	public static final char[] n = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
+	public static final char[] c = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'Z', 'Y', 'Z' };
+	public static final char[] s = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P','Q', 'R', 'S', 'T', 'U', 'V', 'W', 'Z', 'Y', 'Z' };
+	public static final char[] sc = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P','Q', 'R', 'S', 'T', 'U', 'V', 'W', 'Z', 'Y', 'Z', '=', '/', '+', '-', '*', '_', '~', '!', '#', '@', '%', '^', '&', '(', ')', '|', '.', '`', ':' };
+	//去掉了I O 0
+	public static final char[] s1 = { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P','Q', 'R', 'S', 'T', 'U', 'V', 'W', 'Z', 'Y', 'Z' };
+
+
+	/**
+	 * 获取一个固定长度的随机整数
+	 * 
+	 * @param size
+	 *            数字长度
+	 * @return String
+	 */
+	public static String getRandomNumber(int size) {
+		StringBuffer sb = new StringBuffer();
+		Random rd = new Random();
+		for (int i = 0; i < size; i++) {
+			sb.append(n[rd.nextInt(n.length)]);
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * 获取一个随机的字符串
+	 * 
+	 * @param size
+	 *            字符串长度
+	 * @param withNumber
+	 *            是否包含数字
+	 * @return String
+	 */
+	public static String getRandomString(int size, boolean withNumber) {
+		StringBuffer sb = new StringBuffer();
+		Random rd = new Random();
+		if (withNumber) {
+			for (int i = 0; i < size; i++) {
+				sb.append(s[rd.nextInt(s.length)]);
+			}
+		} else {
+			for (int i = 0; i < size; i++) {
+				sb.append(c[rd.nextInt(c.length)]);
+			}
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * 获取一个随机的字符串(数字+大写,去掉了I O 0)
+	 *
+	 * @param size 字符串长度
+	 * @return String
+	 */
+	public static String getRandomSpecialString(int size) {
+		StringBuffer sb = new StringBuffer();
+		Random rd = new Random();
+		for (int i = 0; i < size; i++) {
+			sb.append(s1[rd.nextInt(s1.length)]);
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * 获取一个随机的字符串,含有特殊字符
+	 * @param size 字符串长度
+	 * @return String
+	 */
+	public static String getRandomStringWithSpecialChar(int size) {
+		StringBuffer sb = new StringBuffer();
+		Random rd = new Random();
+		for (int i = 0; i < size; i++) {
+			sb.append(sc[rd.nextInt(sc.length)]);
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * 获取一个双精度随机数
+	 * 
+	 * @return Double
+	 */
+	public static Double getRandomDouble() {
+		return Math.random();
+	}
+
+	/**
+	 * 获取UUID
+	 * 
+	 * @return String
+	 */
+	public static String uuid() {
+		UUID uuid = UUID.randomUUID();
+		return uuid.toString();
+	}
+
+	/**
+	 * 获取某个区间的整形
+	 * 
+	 * @param min
+	 *            最小值
+	 * @param max
+	 *            最大值
+	 * @return int
+	 */
+	public static int getRandomInt(int min, int max) {
+		Random random = new Random();
+		return random.nextInt(max) % (max - min + 1) + min;
+	}
+
+	/**
+	 * 获取一个随机整形值
+	 * 
+	 * @return int
+	 */
+	public static int getRandomInt() {
+		Random random = new Random();
+		return random.nextInt();
+	}
+
+}

+ 273 - 0
src/main/java/com/aijia/kmt/common/excel/j2se/ReflectUtils.java

@@ -0,0 +1,273 @@
+package com.aijia.kmt.common.excel.j2se;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+
+/**
+ * Java反射工具类
+ * 
+ * @author <a href="xdemo.org">xdemo.org</a>
+ * 
+ */
+public class ReflectUtils {
+
+	/**
+	 * 获取成员变量的修饰符
+	 * 
+	 * @param clazz
+	 * @param field
+	 * @return
+	 * @throws Exception
+	 */
+	public static <T> int getFieldModifier(Class<T> clazz, String field) throws Exception {
+		// getDeclaredFields可以获取所有修饰符的成员变量,包括private,protected等getFields则不可以
+		Field[] fields = clazz.getDeclaredFields();
+
+		for (int i = 0; i < fields.length; i++) {
+			if (fields[i].getName().equals(field)) {
+				return fields[i].getModifiers();
+			}
+		}
+		throw new Exception(clazz + " has no field \"" + field + "\"");
+	}
+
+	/**
+	 * 获取成员方法的修饰符
+	 * 
+	 * @param clazz
+	 * @param method
+	 * @return
+	 * @throws Exception
+	 */
+	public static <T> int getMethodModifier(Class<T> clazz, String method) throws Exception {
+
+		// getDeclaredMethods可以获取所有修饰符的成员方法,包括private,protected等getMethods则不可以
+		Method[] m = clazz.getDeclaredMethods();
+
+		for (int i = 0; i < m.length; i++) {
+			if (m[i].getName().equals(m)) {
+				return m[i].getModifiers();
+			}
+		}
+		throw new Exception(clazz + " has no method \"" + m + "\"");
+	}
+
+	/**
+	 * [对象]根据成员变量名称获取其值
+	 * 
+	 * @param clazzInstance
+	 * @param field
+	 * @return
+	 * @throws NoSuchFieldException
+	 * @throws SecurityException
+	 * @throws IllegalArgumentException
+	 * @throws IllegalAccessException
+	 */
+	public static <T> Object getFieldValue(Object clazzInstance, Object field) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
+
+		Field[] fields = clazzInstance.getClass().getDeclaredFields();
+
+		for (int i = 0; i < fields.length; i++) {
+			if (fields[i].getName().equals(field)) {
+				// 对于私有变量的访问权限,在这里设置,这样即可访问Private修饰的变量
+				fields[i].setAccessible(true);
+				return fields[i].get(clazzInstance);
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * [类]根据成员变量名称获取其值(默认值)
+	 * 
+	 * @param clazz
+	 * @param field
+	 * @return
+	 * @throws NoSuchFieldException
+	 * @throws SecurityException
+	 * @throws IllegalArgumentException
+	 * @throws IllegalAccessException
+	 * @throws InstantiationException
+	 */
+	public static <T> Object getFieldValue(Class<T> clazz, String field) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {
+
+		Field[] fields = clazz.getDeclaredFields();
+
+		for (int i = 0; i < fields.length; i++) {
+			if (fields[i].getName().equals(field)) {
+				// 对于私有变量的访问权限,在这里设置,这样即可访问Private修饰的变量
+				fields[i].setAccessible(true);
+				return fields[i].get(clazz.newInstance());
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * 获取所有的成员变量
+	 * 
+	 * @param clazz
+	 * @return
+	 */
+	public static <T> String[] getFields(Class<T> clazz) {
+
+		Field[] fields = clazz.getDeclaredFields();
+
+		String[] fieldsArray = new String[fields.length];
+
+		for (int i = 0; i < fields.length; i++) {
+			fieldsArray[i] = fields[i].getName();
+		}
+
+		return fieldsArray;
+	}
+
+	/**
+	 * 获取所有的成员变量,包括父类
+	 * 
+	 * @param clazz
+	 * @param superClass
+	 *            是否包括父类
+	 * @return
+	 * @throws Exception
+	 */
+	public static <T> Field[] getFields(Class<T> clazz, boolean superClass) throws Exception {
+
+		Field[] fields = clazz.getDeclaredFields();
+		Field[] superFields = null;
+		if (superClass) {
+			Class superClazz = clazz.getSuperclass();
+			if (superClazz != null) {
+				superFields = superClazz.getDeclaredFields();
+			}
+		}
+
+		Field[] allFields = null;
+
+		if (superFields == null || superFields.length == 0) {
+			allFields = fields;
+		} else {
+			allFields = new Field[fields.length + superFields.length];
+			for (int i = 0; i < fields.length; i++) {
+				allFields[i] = fields[i];
+			}
+			for (int i = 0; i < superFields.length; i++) {
+				allFields[fields.length + i] = superFields[i];
+			}
+		}
+
+		return allFields;
+	}
+
+	/**
+	 * 获取所有的成员变量,包括父类
+	 * 
+	 * @param clazz
+	 * @return
+	 * @throws Exception
+	 */
+	public static <T> Field[] getClassFieldsAndSuperClassFields(Class<T> clazz) throws Exception {
+
+		Field[] fields = clazz.getDeclaredFields();
+
+		if (clazz.getSuperclass() == null) {
+			throw new Exception(clazz.getName() + "没有父类");
+		}
+
+		Field[] superFields = clazz.getSuperclass().getDeclaredFields();
+
+		Field[] allFields = new Field[fields.length + superFields.length];
+
+		for (int i = 0; i < fields.length; i++) {
+			allFields[i] = fields[i];
+		}
+		for (int i = 0; i < superFields.length; i++) {
+			allFields[fields.length + i] = superFields[i];
+		}
+
+		return allFields;
+	}
+
+	/**
+	 * 指定类,调用指定的无参方法
+	 * 
+	 * @param clazz
+	 * @param method
+	 * @throws NoSuchMethodException
+	 * @throws SecurityException
+	 * @throws IllegalAccessException
+	 * @throws IllegalArgumentException
+	 * @throws InvocationTargetException
+	 * @throws InstantiationException
+	 */
+	public static <T> Object invoke(Class<T> clazz, String method) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
+		Object instance = clazz.newInstance();
+		Method m = clazz.getMethod(method, new Class[] {});
+		return m.invoke(instance, new Object[] {});
+	}
+
+	/**
+	 * 通过对象,访问其方法
+	 * 
+	 * @param clazzInstance
+	 * @param method
+	 * @return
+	 * @throws NoSuchMethodException
+	 * @throws SecurityException
+	 * @throws IllegalAccessException
+	 * @throws IllegalArgumentException
+	 * @throws InvocationTargetException
+	 * @throws InstantiationException
+	 */
+	public static <T> Object invoke(Object clazzInstance, String method) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
+		Method m = clazzInstance.getClass().getMethod(method, new Class[] {});
+		return m.invoke(clazzInstance, new Object[] {});
+	}
+
+	/**
+	 * 指定类,调用指定的方法
+	 * 
+	 * @param clazz
+	 * @param method
+	 * @param paramClasses
+	 * @param params
+	 * @return Object
+	 * @throws InstantiationException
+	 * @throws IllegalAccessException
+	 * @throws NoSuchMethodException
+	 * @throws SecurityException
+	 * @throws IllegalArgumentException
+	 * @throws InvocationTargetException
+	 */
+	public static <T> Object invoke(Class<T> clazz, String method, Class<T>[] paramClasses, Object[] params) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
+		Object instance = clazz.newInstance();
+		Method _m = clazz.getMethod(method, paramClasses);
+		return _m.invoke(instance, params);
+	}
+
+	/**
+	 * 通过类的实例,调用指定的方法
+	 * 
+	 * @param clazzInstance
+	 * @param method
+	 * @param paramClasses
+	 * @param params
+	 * @return
+	 * @throws InstantiationException
+	 * @throws IllegalAccessException
+	 * @throws NoSuchMethodException
+	 * @throws SecurityException
+	 * @throws IllegalArgumentException
+	 * @throws InvocationTargetException
+	 */
+	public static <T> Object invoke(Object clazzInstance, String method, Class<T>[] paramClasses, Object[] params) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
+		Method _m = clazzInstance.getClass().getMethod(method, paramClasses);
+		return _m.invoke(clazzInstance, params);
+	}
+
+
+}

+ 184 - 0
src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/BeanToExcel.java

@@ -0,0 +1,184 @@
+package com.aijia.kmt.common.excel.thirdparty.excel;
+
+import com.aijia.kmt.common.excel.j2se.ReflectUtils;
+import org.apache.poi.hssf.util.HSSFColor;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+
+import java.io.FileOutputStream;
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * 根据Bean上的Excel注解写入到Excel
+ * @author Goofy 2015/9/16 ReWrite
+ */
+public class BeanToExcel {
+	/**
+	 * 获得Workbook对象
+	 * 
+	 * @param list
+	 *            数据集合
+	 * @return Workbook
+	 * @throws Exception
+	 */
+	public static <T> Workbook getWorkBook(List<T> list, ExcelDataFormatter edf) throws Exception {
+		// 创建工作簿
+		Workbook wb = new SXSSFWorkbook();
+
+		if (list == null || list.size() == 0){
+			return wb;
+		}
+
+
+		// 创建一个工作表sheet
+		Sheet sheet = wb.createSheet();
+		// 申明行
+		Row row = sheet.createRow(0);
+		// 申明单元格
+		Cell cell = null;
+
+		CreationHelper createHelper = wb.getCreationHelper();
+
+		Field[] fields = ReflectUtils.getClassFieldsAndSuperClassFields(list.get(0).getClass());
+
+		XSSFCellStyle titleStyle = (XSSFCellStyle) wb.createCellStyle();
+		titleStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
+		// 设置前景色
+		titleStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(159, 213, 183)));
+		titleStyle.setAlignment(CellStyle.ALIGN_CENTER);
+
+		Font font = wb.createFont();
+		font.setColor(HSSFColor.BROWN.index);
+		font.setBoldweight(Font.BOLDWEIGHT_BOLD);
+		// 设置字体
+		titleStyle.setFont(font);
+
+		int columnIndex = 0;
+		Excel excel = null;
+		for (Field field : fields) {
+			field.setAccessible(true);
+			excel = field.getAnnotation(Excel.class);
+			if (excel == null || excel.skip() == true) {
+				continue;
+			}
+			// 列宽注意乘256
+			sheet.setColumnWidth(columnIndex, excel.width() * 256);
+			// 写入标题
+			cell = row.createCell(columnIndex);
+			cell.setCellStyle(titleStyle);
+			cell.setCellValue(excel.name());
+
+			columnIndex++;
+		}
+
+		int rowIndex = 1;
+
+		CellStyle cs = wb.createCellStyle();
+
+		for (T t : list) {
+			row = sheet.createRow(rowIndex);
+			columnIndex = 0;
+			Object o = null;
+			for (Field field : fields) {
+
+				field.setAccessible(true);
+
+				// 忽略标记skip的字段
+				excel = field.getAnnotation(Excel.class);
+				if (excel == null || excel.skip() == true) {
+					continue;
+				}
+				// 数据
+				cell = row.createCell(columnIndex);
+
+				o = field.get(t);
+				// 如果数据为空,跳过
+				if (o == null) {
+					continue;
+				}
+
+
+				// 处理日期类型
+				if (o instanceof Date) {
+					// excel.dateFormat()获取注解的日期格式,默认yyyy-MM-dd HH:mm:ss
+					cs.setDataFormat(createHelper.createDataFormat().getFormat(excel.dateFormat()));
+					cell.setCellStyle(cs);
+					cell.setCellValue((Date) field.get(t));
+				} else if (o instanceof Double || o instanceof Float) {// 浮点数
+					cell.setCellValue(field.get(t).toString());
+					if (excel.precision() != -1) {
+						cell.setCellValue(new BigDecimal(field.get(t).toString()).setScale(excel.precision(), excel.round() == true ? BigDecimal.ROUND_HALF_UP : BigDecimal.ROUND_FLOOR).toString());
+					}
+				} else if (o instanceof BigDecimal) {// BigDecimal
+					cell.setCellValue((field.get(t).toString()));
+					if (excel.precision() != -1) {
+						cell.setCellValue(new BigDecimal(field.get(t).toString()).setScale(excel.precision(), excel.round() == true ? BigDecimal.ROUND_HALF_UP : BigDecimal.ROUND_FLOOR).toString());
+					}
+				} else if (o instanceof Boolean) {// 布尔类型
+					Boolean bool = (Boolean) field.get(t);
+					if (edf == null) {
+						cell.setCellValue(bool);
+					} else {
+						Map<String, String> map = edf.get(field.getName());
+						if (map == null) {
+							cell.setCellValue(bool);
+						} else {
+							cell.setCellValue(map.get(bool.toString().toLowerCase()));
+						}
+					}
+
+				} else if (o instanceof Integer) {// 整型
+
+					Integer intValue = (Integer) field.get(t);
+
+					if (edf == null) {
+						cell.setCellValue(intValue);
+					} else {
+						Map<String, String> map = edf.get(field.getName());
+						if (map == null) {
+							cell.setCellValue(intValue);
+						} else {
+							cell.setCellValue(map.get(intValue.toString()));
+						}
+					}
+				} else {
+					cell.setCellValue(field.get(t).toString());
+				}
+
+				columnIndex++;
+			}
+
+			rowIndex++;
+		}
+
+		return wb;
+	}
+
+	/**
+	 * 将数据写入到EXCEL文档
+	 * 
+	 * @param list
+	 *            数据集合
+	 * @param edf
+	 *            数据格式化,比如有些数字代表的状态,像是0:女,1:男,或者0:正常,1:锁定,变成可读的文字
+	 *            该字段仅仅针对Boolean,Integer两种类型作处理
+	 * @param filePath
+	 *            文件路径
+	 * @throws Exception
+	 */
+	public static <T> void writeToFile(List<T> list, ExcelDataFormatter edf, String filePath) throws Exception {
+		// 创建并获取工作簿对象
+		Workbook wb = getWorkBook(list, edf);
+		// 写入到文件
+		FileOutputStream out = new FileOutputStream(filePath);
+		wb.write(out);
+		out.close();
+	}
+}

+ 483 - 0
src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/CustomizeToExcel.java

@@ -0,0 +1,483 @@
+package com.aijia.kmt.common.excel.thirdparty.excel;
+
+import com.aijia.kmt.common.excel.j2se.RandomUtils;
+import com.aijia.kmt.common.excel.thirdparty.gson.GsonTools;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+import org.apache.poi.xssf.usermodel.XSSFFont;
+
+import javax.servlet.ServletOutputStream;
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * 自定义
+ * 
+ * @author Goofy 自定义表头的Excel
+ */
+public class CustomizeToExcel {
+
+	// 创建工作簿
+	private static Workbook wb = new SXSSFWorkbook();
+	// 创建一个工作表sheet
+	private static Sheet sheet = wb.createSheet();
+
+	private static List<String> fields = new ArrayList<String>();
+
+	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+	/**
+	 * 获取工作簿对象
+	 * 
+	 * @param columns
+	 *            List<ExcelColumn> 列定义
+	 * @param list
+	 *            List<Map<String, Object>> 数据
+	 * @return Workbook
+	 * @throws IOException
+	 */
+	public static Workbook getWorkbook(List<ExcelColumn> columns, List<Map<String, Object>> list) throws IOException {
+		GsonTools gt = new GsonTools(false, null, null, null);
+		return getWorkbook(gt.toJson(columns), list);
+	}
+
+	/**
+	 * 获取工作簿对象
+	 * 
+	 * @param columnsJsonArray
+	 *            String 列定义
+	 * @param list
+	 *            List<Map<String, Object>> 数据
+	 * @return Workbook
+	 * @throws IOException
+	 */
+	public static Workbook getWorkbook(String columnsJsonArray, List<Map<String, Object>> list) throws IOException {
+		init();
+		JsonArray array = new JsonArray();
+		JsonParser parser = new JsonParser();
+		array = parser.parse(columnsJsonArray).getAsJsonArray();
+		// 写标题
+		writeTitles(array, 0, null);
+		// 合并列
+		mergeColumns();
+		// 合并行
+		mergeRows();
+		// 写入行分隔符
+		writeDelimiter();
+		// 冻结表头
+		freezeTitle();
+		// 写数据
+		writeData(list);
+
+		return wb;
+	}
+
+	/**
+	 * 写入到文件
+	 * 
+	 * @param columns
+	 *            List<ExcelColumn> 列定义
+	 * @param list
+	 *            List<Map<String, Object>> 数据
+	 * @param filePath
+	 *            文件路径
+	 * @throws Exception
+	 */
+	public static void toFile(List<ExcelColumn> columns, List<Map<String, Object>> list, String filePath) throws Exception {
+		GsonTools gt = new GsonTools(false, null, null, null);
+		toFile(gt.toJson(columns), list, filePath);
+	}
+
+	/**
+	 * 冻结表头
+	 */
+	private static void freezeTitle() {
+		int rowsCount = sheet.getPhysicalNumberOfRows();
+		sheet.createFreezePane(0, rowsCount - 1);
+	}
+	
+	/**
+	 * 初始化workbook,sheet,fields对象,防止多次连续调用发生错误
+	 */
+	private static void init() {
+		wb = new SXSSFWorkbook();
+		sheet = wb.createSheet();
+		fields = new ArrayList<String>();
+	}
+
+	/**
+	 * 写入到文件
+	 * 
+	 * @param columnsJsonArray
+	 *            String 列定义
+	 * @param list
+	 *            List<Map<String, Object>> 数据
+	 * @param filePath
+	 *            文件路径
+	 * @throws Exception
+	 */
+	public static void toFile(String columnsJsonArray, List<Map<String, Object>> list, String filePath) throws Exception {
+		FileOutputStream out = null;
+		try {
+			getWorkbook(columnsJsonArray, list);
+			out = new FileOutputStream(filePath);
+			wb.write(out);
+			out.close();
+		} catch (Exception e) {
+			throw e;
+		} finally {
+			if (out != null) {
+				out.close();
+			}
+		}
+	}
+	
+	/**
+	 * 写入到文件
+	 * 
+	 * @param columns
+	 *            List<ExcelColumn> 列定义
+	 * @param list
+	 *            List<Map<String, Object>> 数据
+	 * @param filePath
+	 *            文件路径
+	 * @throws Exception
+	 */
+	public static void downFile(List<ExcelColumn> columns, List<Map<String, Object>> list, ServletOutputStream outputStream) throws Exception {
+		GsonTools gt = new GsonTools(false, null, null, null);
+		downFile(gt.toJson(columns), list, outputStream);
+	}
+	
+	public static void downFile(String columnsJsonArray, List<Map<String, Object>> list, ServletOutputStream outputStream) throws Exception{
+        
+		try {
+			getWorkbook(columnsJsonArray, list);
+			wb.write(outputStream);
+		} catch (Exception e) {
+			throw e;
+		} finally {
+			
+			if (outputStream != null) {
+				outputStream.flush();
+				outputStream.close();
+			}
+		}
+	}
+
+	/**
+	 * 写入行数据
+	 * 
+	 * @param list
+	 */
+	private static void writeData(List<Map<String, Object>> list) {
+		// 行数
+		int rowsCount = sheet.getPhysicalNumberOfRows();
+		// 列数
+		int colsCount = sheet.getRow(0).getPhysicalNumberOfCells();
+		Row row;
+		Cell cell;
+		CellStyle csTop = wb.createCellStyle();
+		csTop.setBorderTop(HSSFCellStyle.BORDER_MEDIUM_DASHED);
+		CellStyle csBottom = wb.createCellStyle();
+		csBottom.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM_DASHED);
+		Map<String, Object> map = new HashMap<String, Object>();
+		for (int r = 0; r < list.size(); r++) {
+			row = sheet.createRow(r + rowsCount - 1);
+			map = list.get(r);
+			for (int c = 0; c < colsCount; c++) {
+				cell = row.createCell(c);
+				if (r == 0) {
+					cell.setCellStyle(csTop);
+				}
+				if (r == list.size() - 1) {
+					cell.setCellStyle(csBottom);
+				}
+				Object v = map.get(fields.get(c));
+				if (v == null) {
+					cell.setCellValue("");
+				} else {
+					if (v.getClass().equals(Date.class)) {
+						cell.setCellValue(sdf.format((Date) v));
+					} else {
+						cell.setCellValue(v.toString());
+					}
+
+				}
+
+			}
+		}
+	}
+
+	/**
+	 * 写入列头下分隔符
+	 */
+	private static void writeDelimiter() {
+
+		// 行数
+		int rowsCount = sheet.getPhysicalNumberOfRows();
+		// 列数
+		int colsCount = sheet.getRow(0).getPhysicalNumberOfCells();
+		Cell cell;
+		CellStyle cs = wb.createCellStyle();
+		Row row = sheet.createRow(rowsCount);
+		for (int c = 0; c < colsCount; c++) {
+			cell = row.createCell(c);
+			cs.setBorderTop(HSSFCellStyle.BORDER_MEDIUM_DASHED);
+			cell.setCellStyle(cs);
+		}
+
+	}
+
+	/**
+	 * 合并行
+	 */
+	private static void mergeRows() {
+		// 行数
+		int rowsCount = sheet.getPhysicalNumberOfRows();
+		// 列数
+		int colsCount = sheet.getRow(0).getPhysicalNumberOfCells();
+		Row row = null;
+
+		Cell cell = null;
+		int rowSpan = 0;
+		for (int c = 0; c < colsCount; c++) {
+			rowSpan = 0;
+			for (int r = rowsCount - 1; r > -1; r--) {
+
+				row = sheet.getRow(r);
+
+				cell = row.getCell(c);
+
+				if (cell != null && r == rowsCount - 1) {
+					break;
+				} else if (cell != null && r != rowsCount - 1) {
+					// 合并列
+					sheet.addMergedRegion(new CellRangeAddress(rowsCount - rowSpan - 1, rowsCount - 1, c, c));
+					break;
+				} else {
+					// 行合并数+1
+					rowSpan++;
+				}
+			}
+		}
+	}
+
+	/**
+	 * 合并列
+	 */
+	private static void mergeColumns() {
+		// 行数
+		int rowsCount = sheet.getPhysicalNumberOfRows();
+		// 列数
+		int colsCount = sheet.getRow(0).getPhysicalNumberOfCells();
+
+		Row row = null;
+		Cell cell1 = null;
+		Cell cell2 = null;
+
+		int colSpan = 0;
+
+		for (int r = 0; r < rowsCount; r++) {
+			row = sheet.getRow(r);
+			// 重置
+			colSpan = 0;
+			row = sheet.getRow(r);
+			for (int c = 0; c < colsCount; c++) {
+				cell1 = row.getCell(c);
+				cell2 = row.getCell(c + 1);
+				if (cell1 == null) {// 如果当前单元格是空的,跳过,继续当前行的后一个单元格查找
+					if (c == colsCount - 1) {
+						break;
+					} else {
+						continue;
+					}
+				}
+				if (cell2 == null) {// 说明当前行已经到最后一个单元格了
+					if (colSpan >= 1) {// 判断colSpan是否大于等于1,大于1就要合并了
+						// 合并行中连续相同的值的单元格
+						sheet.addMergedRegion(new CellRangeAddress(r, r, c - colSpan, c));
+						break;
+					}
+				}
+
+				if (cell1 != null && cell2 != null) {
+					// 如果当前单元格和下一个单元格内容相同,那么colSpan加1
+					if (cell1.getStringCellValue().equals(cell2.getStringCellValue())) {
+						colSpan++;
+					} else {
+						// 如果当前单元格和下一个不等,那么判断colSpan是否大于等于1
+						if (colSpan >= 1) {
+							// 合并行中连续相同的值的单元格
+							sheet.addMergedRegion(new CellRangeAddress(r, r, c - colSpan, c));
+							// 合并后重置colSpan
+							colSpan = 0;
+							continue;
+						}
+					}
+				}
+
+			}
+		}
+
+	}
+
+	/**
+	 * 写入标题
+	 * 
+	 * @param array
+	 *            JSON数组
+	 * @param rowIndex
+	 *            行号
+	 * @param parentTitle
+	 *            父节点名称
+	 */
+	private static void writeTitles(JsonArray array, int rowIndex, String parentTitle) {
+		Iterator<JsonElement> it = array.iterator();
+		Row row = sheet.getRow(rowIndex) == null ? sheet.createRow(rowIndex) : sheet.getRow(rowIndex);
+		Row lastRow = rowIndex == 0 ? null : sheet.getRow(rowIndex - 1);
+
+		int _colIndex = -1;
+		// 遍历当前行,获取行最多的单元格的个数,因为如果之前行之前有单元格是空的,会对列索引造成问题
+		int currentMaxColumns = 0;
+		for (int x = 0; x < rowIndex; x++) {
+			Row rr = sheet.getRow(x);
+			if (rr.getPhysicalNumberOfCells() > currentMaxColumns) {
+				currentMaxColumns = rr.getPhysicalNumberOfCells();
+			}
+		}
+
+		// 查找上一级的列开始位置
+		if (lastRow != null && parentTitle != null) {
+			for (int i = 0; i < currentMaxColumns; i++) {
+				if (lastRow.getCell(i) != null && lastRow.getCell(i).getStringCellValue() != null && lastRow.getCell(i).getStringCellValue().equals(parentTitle)) {
+					_colIndex = i;
+					break;
+				}
+			}
+		}
+		_colIndex = _colIndex == -1 ? 0 : _colIndex;
+
+		Cell cell;
+
+		while (it.hasNext()) {
+
+			JsonElement e = it.next();
+			// 是否是叶子节点
+			boolean isLeaf = false;
+			// 获取子节点数量
+			int count = getSubNodesCount(e);
+			// 没有子节点就是叶子节点,如果子节点为0,将count设置为1,是为了能够让下面的for循环执行一次,将标题写入
+			if (count == 0) {
+				count = 1;
+				isLeaf = true;
+			} else {
+				isLeaf = false;
+			}
+
+			XSSFCellStyle cs = (XSSFCellStyle) wb.createCellStyle();
+			// 水平居中
+			cs.setAlignment(CellStyle.ALIGN_CENTER);
+			// 垂直居中
+			cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+
+			cs.setFillPattern(CellStyle.SOLID_FOREGROUND);
+			// 设置前景色
+			cs.setFillForegroundColor(new XSSFColor(new java.awt.Color(RandomUtils.getRandomInt(0, 255), 185, RandomUtils.getRandomInt(0, 255))));
+
+			// 字体样式
+			Font font = wb.createFont();
+			// 粗体
+			font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
+			// 设置字体
+			cs.setFont(font);
+
+			// 根据子节点的数量,写入相应数量的父节点的名称,待完成后合并列
+			for (int i = 0; i < count; i++) {
+				cell = row.createCell(_colIndex++);
+				if (isLeaf) {
+
+					// 如果没有子节点,就是浅红色的
+					cs.setFillForegroundColor(new XSSFColor(new java.awt.Color(255, 199, 206)));
+					if (e.getAsJsonObject().get("width") != null && e.getAsJsonObject().get("width").getAsInt() != 0) {
+
+						fields.add(e.getAsJsonObject().get("field").getAsString());
+
+						// 设置列宽,列宽是根据叶子节点来的,其他地方定义不生效,l列索引由于上面已经+1了,所以这里要减1
+						sheet.setColumnWidth(_colIndex - 1, e.getAsJsonObject().get("width").getAsInt() * 256);
+					}
+				}
+
+				cell.setCellStyle(cs);
+				cell.setCellValue(e.getAsJsonObject().get("title").getAsString());
+				// 判断是否写到最后一个父节点名称
+				if (i == count - 1) {
+					// 如果有子节点,递归写入子节点
+					if (e.getAsJsonObject().get("children") != null && e.getAsJsonObject().get("children").getAsJsonArray().size() != 0) {
+						writeTitles(e.getAsJsonObject().get("children").getAsJsonArray(), rowIndex + 1, e.getAsJsonObject().get("title").getAsString());
+					}
+				}
+
+			}
+
+		}
+	}
+
+	/**
+	 * 获取当前节点的子节点数量
+	 * 
+	 * @param e
+	 * @return
+	 */
+	private static int getSubNodesCount(JsonElement e) {
+		JsonArray array = e.getAsJsonObject().get("children") == null ? null : e.getAsJsonObject().get("children").getAsJsonArray();
+		if (array == null)
+			return 0;
+
+		Iterator<JsonElement> it = array.iterator();
+		int count = array.size();
+		while (it.hasNext()) {
+			int c = getSubNodesCount(it.next());
+			count += c > 0 ? c - 1 : c;
+		}
+		return count;
+	}
+	
+	
+	public static List<Map<String, Object>> objectToMap(List<?> list) throws Exception {
+		if (list == null)
+			return null;
+		List<Map<String, Object>> maps=new ArrayList<Map<String,Object>>();
+		Map<String, Object> map = new HashMap<String, Object>();
+		for (Object obj : list) {
+			BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
+			PropertyDescriptor[] propertyDescriptors = beanInfo
+					.getPropertyDescriptors();
+			for (PropertyDescriptor property : propertyDescriptors) {
+				String key = property.getName();
+				if (key.compareToIgnoreCase("class") == 0) {
+					continue;
+				}
+				Method getter = property.getReadMethod();
+				Object value = getter != null ? getter.invoke(obj) : null;
+				map.put(key, value);
+			}
+			maps.add(map);
+		}
+		return maps;
+	}
+
+
+}

+ 34 - 0
src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/Excel.java

@@ -0,0 +1,34 @@
+package com.aijia.kmt.common.excel.thirdparty.excel;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author Goofy
+ * Excel注解,用以生成Excel表格文件
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD,ElementType.TYPE})
+public @interface Excel {
+	
+	//列名
+	String name() default "";
+	
+	//宽度
+	int width() default 20;
+
+	//忽略该字段
+	boolean skip() default false;
+	
+	//日期格式化
+	String dateFormat() default "yyyy-MM-dd HH:mm:ss";
+	
+	//浮点数的精度
+	int precision() default -1;
+	
+	//四舍五入
+	boolean round() default true;
+	
+}

+ 94 - 0
src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/ExcelColumn.java

@@ -0,0 +1,94 @@
+package com.aijia.kmt.common.excel.thirdparty.excel;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * Excel列定义
+ * @author Goofy
+ */
+public class ExcelColumn implements Serializable{
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 5111066450199929978L;
+	//列名
+	private String title;
+	//列对应的数据中的field
+	private String field;
+	//列宽
+	private int width=0;
+	//子列
+	private List<ExcelColumn> children;
+
+	public ExcelColumn(){}
+	
+	public ExcelColumn(String title, String field, int width) {
+		super();
+		this.title = title;
+		this.field = field;
+		this.width = width;
+	}
+
+	/**
+	 * @return the title
+	 */
+	public String getTitle() {
+		return title;
+	}
+
+	/**
+	 * @param title
+	 *            the title to set
+	 */
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	/**
+	 * @return the field
+	 */
+	public String getField() {
+		return field;
+	}
+
+	/**
+	 * @param field
+	 *            the field to set
+	 */
+	public void setField(String field) {
+		this.field = field;
+	}
+
+	/**
+	 * @return the width
+	 */
+	public int getWidth() {
+		return width;
+	}
+
+	/**
+	 * @param width
+	 *            the width to set
+	 */
+	public void setWidth(int width) {
+		this.width = width;
+	}
+
+	/**
+	 * @return the children
+	 */
+	public List<ExcelColumn> getChildren() {
+		return children;
+	}
+
+	/**
+	 * @param children
+	 *            the children to set
+	 */
+	public void setChildren(List<ExcelColumn> children) {
+		this.children = children;
+	}
+
+}

+ 27 - 0
src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/ExcelDataFormatter.java

@@ -0,0 +1,27 @@
+package com.aijia.kmt.common.excel.thirdparty.excel;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Excel数据导入导出格式化<br>
+ * 举例:<br>
+ * 数据导出, {lock,{0:正常,1:锁定}}<br>
+ * 数据导入,{lock,{正常:0,锁定:1}}
+ * @author Goofy <a href="http://www.xdemo.org">http://www.xdemo.org</a>
+ */
+public class ExcelDataFormatter {
+	/**
+	 * K:{V1:V2}
+	 */
+	private Map<String,Map<String,String>> formatter=new HashMap<String, Map<String,String>>();
+	
+	public void set(String key,Map<String,String> map){
+		formatter.put(key, map);
+	}
+	
+	public Map<String,String> get(String key){
+		return formatter.get(key);
+	}
+	
+}

+ 248 - 0
src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/ExcelToBean.java

@@ -0,0 +1,248 @@
+/**
+ * 
+ */
+package com.aijia.kmt.common.excel.thirdparty.excel;
+
+import com.aijia.kmt.common.excel.j2se.ReflectUtils;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * @author Goofy
+ * Excel内容转化成Bean
+ */
+public class ExcelToBean{
+
+	private final Logger logger = LoggerFactory.getLogger(this.getClass());
+	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+	private int etimes = 0;
+	
+	
+	/**
+	 * 从文件读取数据,最好是所有的单元格都是文本格式,日期格式要求yyyy-MM-dd HH:mm:ss,布尔类型0:真,1:假
+	 * 
+	 * @param edf
+	 *            数据格式化
+	 * 
+	 * @param file
+	 *            Excel文件,支持xlsx后缀,xls的没写,基本一样
+	 * @return
+	 * @throws Exception
+	 */
+	@SuppressWarnings("unchecked")
+	public <E> List<E> readFromFile(ExcelDataFormatter edf, File file, Class<?> clazz) throws Exception {
+		Field[] fields = ReflectUtils.getClassFieldsAndSuperClassFields(clazz);
+
+		Map<String, String> textToKey = new HashMap<String, String>();
+
+		Excel _excel = null;
+		for (Field field : fields) {
+			_excel = field.getAnnotation(Excel.class);
+			if (_excel == null || _excel.skip() == true) {
+				continue;
+			}
+			textToKey.put(_excel.name(), field.getName());
+		}
+
+		InputStream is = new FileInputStream(file);
+
+		Workbook wb = new XSSFWorkbook(is);
+
+		Sheet sheet = wb.getSheetAt(0);
+		Row title = sheet.getRow(0);
+		// 标题数组,后面用到,根据索引去标题名称,通过标题名称去字段名称用到 textToKey
+		String[] titles = new String[title.getPhysicalNumberOfCells()];
+		for (int i = 0; i < title.getPhysicalNumberOfCells(); i++) {
+			titles[i] = title.getCell(i).getStringCellValue();
+		}
+
+		List<E> list = new ArrayList<E>();
+
+		E e = null;
+
+		int rowIndex = 0;
+		int columnCount = titles.length;
+		Cell cell = null;
+		Row row = null;
+
+		for (Iterator<Row> it = sheet.rowIterator(); it.hasNext();) {
+
+			row = it.next();
+			if (rowIndex++ == 0) {
+				continue;
+			}
+
+			if (row == null) {
+				break;
+			}
+
+			e = (E)clazz.newInstance();
+
+			for (int i = 0; i < columnCount; i++) {
+				cell = row.getCell(i);
+				etimes = 0;
+				readCellContent(textToKey.get(titles[i]), fields, cell, e, edf);
+			}
+			list.add(e);
+		}
+		return list;
+	}
+	
+	public static void main(String[] args) throws Exception {
+	}
+
+	/**
+	 * 从单元格读取数据,根据不同的数据类型,使用不同的方式读取<br>
+	 * 有时候POI自作聪明,经常和我们期待的数据格式不一样,会报异常,<br>
+	 * 我们这里采取强硬的方式<br>
+	 * 使用各种方法,知道尝试到读到数据为止,然后根据Bean的数据类型,进行相应的转换<br>
+	 * 如果尝试完了(总共7次),还是不能得到数据,那么抛个异常出来,没办法了
+	 * 
+	 * @param key
+	 *            当前单元格对应的Bean字段
+	 * @param fields
+	 *            Bean所有的字段数组
+	 * @param cell
+	 *            单元格对象
+	 * @param obj
+	 * @throws Exception
+	 */
+	public void readCellContent(String key, Field[] fields, Cell cell, Object obj, ExcelDataFormatter edf) throws Exception {
+
+		Object o = null;
+		try {
+			switch (cell.getCellType()) {
+			case XSSFCell.CELL_TYPE_BOOLEAN:
+				o = cell.getBooleanCellValue();
+				break;
+			case XSSFCell.CELL_TYPE_NUMERIC:
+				o = cell.getNumericCellValue();
+				if (HSSFDateUtil.isCellDateFormatted(cell)) {
+					o = DateUtil.getJavaDate(cell.getNumericCellValue());
+				}
+				break;
+			case XSSFCell.CELL_TYPE_STRING:
+				o = cell.getStringCellValue();
+				break;
+			case XSSFCell.CELL_TYPE_ERROR:
+				o = cell.getErrorCellValue();
+				break;
+			case XSSFCell.CELL_TYPE_BLANK:
+				o = null;
+				break;
+			case XSSFCell.CELL_TYPE_FORMULA:
+				o = cell.getCellFormula();
+				break;
+			default:
+				o = null;
+				break;
+			}
+
+			if (o == null)
+				return;
+
+			for (Field field : fields) {
+				field.setAccessible(true);
+				if (field.getName().equals(key)) {
+					Boolean bool = true;
+					Map<String, String> map = null;
+					if (edf == null) {
+						bool = false;
+					} else {
+						map = edf.get(field.getName());
+						if (map == null) {
+							bool = false;
+						}
+					}
+
+					if (field.getType().equals(Date.class)) {
+						if (o.getClass().equals(Date.class)) {
+							field.set(obj, o);
+						} else {
+							field.set(obj, sdf.parse(o.toString()));
+						}
+					} else if (field.getType().equals(String.class)) {
+						if (o.getClass().equals(String.class)) {
+							field.set(obj, o);
+						} else {
+							field.set(obj, o.toString());
+						}
+					} else if (field.getType().equals(Long.class)) {
+						if (o.getClass().equals(Long.class)) {
+							field.set(obj, o);
+						} else {
+							field.set(obj, Long.parseLong(o.toString()));
+						}
+					} else if (field.getType().equals(Integer.class)) {
+						if (o.getClass().equals(Integer.class)) {
+							field.set(obj, o);
+						} else {
+							// 检查是否需要转换
+							if (bool) {
+								field.set(obj, map.get(o.toString()) != null ? Integer.parseInt(map.get(o.toString())) : Integer.parseInt(o.toString()));
+							} else {
+								field.set(obj, Integer.parseInt(o.toString()));
+							}
+
+						}
+					} else if (field.getType().equals(BigDecimal.class)) {
+						if (o.getClass().equals(BigDecimal.class)) {
+							field.set(obj, o);
+						} else {
+							field.set(obj, BigDecimal.valueOf(Double.parseDouble(o.toString())));
+						}
+					} else if (field.getType().equals(Boolean.class)) {
+						if (o.getClass().equals(Boolean.class)) {
+							field.set(obj, o);
+						} else {
+							// 检查是否需要转换
+							if (bool) {
+								field.set(obj, map.get(o.toString()) != null ? Boolean.parseBoolean(map.get(o.toString())) : Boolean.parseBoolean(o.toString()));
+							} else {
+								field.set(obj, Boolean.parseBoolean(o.toString()));
+							}
+						}
+					} else if (field.getType().equals(Float.class)) {
+						if (o.getClass().equals(Float.class)) {
+							field.set(obj, o);
+						} else {
+							field.set(obj, Float.parseFloat(o.toString()));
+						}
+					} else if (field.getType().equals(Double.class)) {
+						if (o.getClass().equals(Double.class)) {
+							field.set(obj, o);
+						} else {
+							field.set(obj, Double.parseDouble(o.toString()));
+						}
+
+					}
+
+				}
+			}
+
+		} catch (Exception ex) {
+			logger.error("读取单元格内容异常", ex);
+			// 如果还是读到的数据格式还是不对,只能放弃了
+			if (etimes > 7) {
+				throw ex;
+			}
+			etimes++;
+			if (o == null) {
+				readCellContent(key, fields, cell, obj, edf);
+			}
+		}
+	}
+
+}

+ 554 - 0
src/main/java/com/aijia/kmt/common/excel/thirdparty/excel/ExcelUtils.java

@@ -0,0 +1,554 @@
+package com.aijia.kmt.common.excel.thirdparty.excel;
+
+import com.aijia.kmt.common.excel.j2se.ReflectUtils;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.hssf.util.HSSFColor;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+
+/**
+ * Excel导入导出(不推荐使用,已被其他类所代替)
+ * @see org.xdemo.superutil.thirdparty.excel.BeanToExcel
+ * @see org.xdemo.superutil.thirdparty.excel.ExcelToBean
+ * @see org.xdemo.superutil.thirdparty.excel.CustomizeToExcel
+ * @author Goofy <a href="http://www.xdemo.org">http://www.xdemo.org</a>
+ */
+@Deprecated
+public class ExcelUtils<E> {
+	private E e;
+	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+	private int etimes = 0;
+
+	public ExcelUtils(E e) {
+		this.e = e;
+	}
+
+	@SuppressWarnings("unchecked")
+	public E get() throws InstantiationException, IllegalAccessException {
+		return (E) e.getClass().newInstance();
+	}
+
+	/**
+	 * 将数据写入到Excel文件
+	 * 
+	 * @param filePath
+	 *            文件路径
+	 * @param sheetName
+	 *            工作表名称
+	 * @param title
+	 *            工作表标题栏
+	 * @param data
+	 *            工作表数据
+	 * @throws FileNotFoundException
+	 *             文件不存在异常
+	 * @throws IOException
+	 *             IO异常
+	 */
+	public static void writeToFile(String filePath, String[] sheetName, List<? extends Object[]> title, List<? extends List<? extends Object[]>> data) throws FileNotFoundException, IOException {
+		// 创建并获取工作簿对象
+		Workbook wb = getWorkBook(sheetName, title, data);
+		// 写入到文件
+		FileOutputStream out = new FileOutputStream(filePath);
+		wb.write(out);
+		out.close();
+	}
+
+	/**
+	 * 创建工作簿对象<br>
+	 * <font color="red">工作表名称,工作表标题,工作表数据最好能够对应起来</font><br>
+	 * 比如三个不同或相同的工作表名称,三组不同或相同的工作表标题,三组不同或相同的工作表数据<br>
+	 * <b> 注意:<br>
+	 * 需要为每个工作表指定<font color="red">工作表名称,工作表标题,工作表数据</font><br>
+	 * 如果工作表的数目大于工作表数据的集合,那么首先会根据顺序一一创建对应的工作表名称和数据集合,然后创建的工作表里面是没有数据的<br>
+	 * 如果工作表的数目小于工作表数据的集合,那么多余的数据将不会写入工作表中 </b>
+	 * 
+	 * @param sheetName
+	 *            工作表名称的数组
+	 * @param title
+	 *            每个工作表名称的数组集合
+	 * @param data
+	 *            每个工作表数据的集合的集合
+	 * @return Workbook工作簿
+	 * @throws FileNotFoundException
+	 *             文件不存在异常
+	 * @throws IOException
+	 *             IO异常
+	 */
+	public static Workbook getWorkBook(String[] sheetName, List<? extends Object[]> title, List<? extends List<? extends Object[]>> data) throws FileNotFoundException, IOException {
+
+		// 创建工作簿
+		Workbook wb = new SXSSFWorkbook();
+		// 创建一个工作表sheet
+		Sheet sheet = null;
+		// 申明行
+		Row row = null;
+		// 申明单元格
+		Cell cell = null;
+		// 单元格样式
+		CellStyle titleStyle = wb.createCellStyle();
+		CellStyle cellStyle = wb.createCellStyle();
+		// 字体样式
+		Font font = wb.createFont();
+		// 粗体
+		font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
+		titleStyle.setFont(font);
+		// 水平居中
+		titleStyle.setAlignment(CellStyle.ALIGN_CENTER);
+		// 垂直居中
+		titleStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+
+		// 水平居中
+		cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
+		// 垂直居中
+		cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
+
+		cellStyle.setFillBackgroundColor(HSSFColor.BLUE.index);
+
+		// 标题数据
+		Object[] title_temp = null;
+
+		// 行数据
+		Object[] rowData = null;
+
+		// 工作表数据
+		List<? extends Object[]> sheetData = null;
+
+		// 遍历sheet
+		for (int sheetNumber = 0; sheetNumber < sheetName.length; sheetNumber++) {
+			// 创建工作表
+			sheet = wb.createSheet();
+			// 设置默认列宽
+			sheet.setDefaultColumnWidth(18*256);
+			// 设置工作表名称
+			wb.setSheetName(sheetNumber, sheetName[sheetNumber]);
+			// 设置标题
+			title_temp = title.get(sheetNumber);
+			row = sheet.createRow(0);
+
+			// 写入标题
+			for (int i = 0; i < title_temp.length; i++) {
+				cell = row.createCell(i);
+				cell.setCellStyle(titleStyle);
+				cell.setCellValue(title_temp[i].toString());
+			}
+
+			try {
+				sheetData = data.get(sheetNumber);
+			} catch (Exception e) {
+				continue;
+			}
+			// 写入行数据
+			for (int rowNumber = 0; rowNumber < sheetData.size(); rowNumber++) {
+				// 如果没有标题栏,起始行就是0,如果有标题栏,行号就应该为1
+				row = sheet.createRow(title_temp == null ? rowNumber : (rowNumber + 1));
+				rowData = sheetData.get(rowNumber);
+				for (int columnNumber = 0; columnNumber < rowData.length; columnNumber++) {
+					cell = row.createCell(columnNumber);
+					cell.setCellStyle(cellStyle);
+					cell.setCellValue(rowData[columnNumber] + "");
+				}
+			}
+		}
+		return wb;
+	}
+
+	/**
+	 * 将数据写入到EXCEL文档
+	 * 
+	 * @param list
+	 *            数据集合
+	 * @param edf
+	 *            数据格式化,比如有些数字代表的状态,像是0:女,1:男,或者0:正常,1:锁定,变成可读的文字
+	 *            该字段仅仅针对Boolean,Integer两种类型作处理
+	 * @param filePath
+	 *            文件路径
+	 * @throws Exception
+	 */
+	public static <T> void writeToFile(List<T> list, ExcelDataFormatter edf, String filePath) throws Exception {
+		// 创建并获取工作簿对象
+		Workbook wb = getWorkBook(list, edf);
+		// 写入到文件
+		FileOutputStream out = new FileOutputStream(filePath);
+		wb.write(out);
+		out.close();
+	}
+
+	/**
+	 * 获得Workbook对象
+	 * 
+	 * @param list
+	 *            数据集合
+	 * @return Workbook
+	 * @throws Exception
+	 */
+	public static <T> Workbook getWorkBook(List<T> list, ExcelDataFormatter edf) throws Exception {
+		// 创建工作簿
+		Workbook wb = new SXSSFWorkbook();
+
+		if (list == null || list.size() == 0)
+			return wb;
+
+		// 创建一个工作表sheet
+		Sheet sheet = wb.createSheet();
+		// 申明行
+		Row row = sheet.createRow(0);
+		// 申明单元格
+		Cell cell = null;
+
+		CreationHelper createHelper = wb.getCreationHelper();
+
+		Field[] fields = ReflectUtils.getClassFieldsAndSuperClassFields(list.get(0).getClass());
+
+		XSSFCellStyle titleStyle = (XSSFCellStyle) wb.createCellStyle();
+		titleStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
+		// 设置前景色
+		titleStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(159, 213, 183)));
+		titleStyle.setAlignment(CellStyle.ALIGN_CENTER);
+
+		Font font = wb.createFont();
+		font.setColor(HSSFColor.BROWN.index);
+		font.setBoldweight(Font.BOLDWEIGHT_BOLD);
+		// 设置字体
+		titleStyle.setFont(font);
+
+		int columnIndex = 0;
+		Excel excel = null;
+		for (Field field : fields) {
+			field.setAccessible(true);
+			excel = field.getAnnotation(Excel.class);
+			if (excel == null || excel.skip() == true) {
+				continue;
+			}
+			// 列宽注意乘256
+			sheet.setColumnWidth(columnIndex, excel.width() * 256);
+			// 写入标题
+			cell = row.createCell(columnIndex);
+			cell.setCellStyle(titleStyle);
+			cell.setCellValue(excel.name());
+
+			columnIndex++;
+		}
+
+		int rowIndex = 1;
+
+		CellStyle cs = wb.createCellStyle();
+		
+		for (T t : list) {
+			row = sheet.createRow(rowIndex);
+			columnIndex = 0;
+			Object o = null;
+			for (Field field : fields) {
+
+				field.setAccessible(true);
+
+				// 忽略标记skip的字段
+				excel = field.getAnnotation(Excel.class);
+				if (excel == null || excel.skip() == true) {
+					continue;
+				}
+				// 数据
+				cell = row.createCell(columnIndex);
+
+				o = field.get(t);
+				// 如果数据为空,跳过
+				if (o == null)
+					continue;
+
+				// 处理日期类型
+				if (o instanceof Date) {
+					//excel.dateFormat()获取注解的日期格式,默认yyyy-MM-dd HH:mm:ss
+					cs.setDataFormat(createHelper.createDataFormat().getFormat(excel.dateFormat()));
+					cell.setCellStyle(cs);
+					cell.setCellValue((Date) field.get(t));
+				} else if (o instanceof Double || o instanceof Float) {//浮点数
+					cell.setCellValue(field.get(t).toString());
+					if(excel.precision()!=-1){
+						cell.setCellValue(new BigDecimal(field.get(t).toString()).setScale(excel.precision(),excel.round()==true?BigDecimal.ROUND_HALF_UP:BigDecimal.ROUND_FLOOR).toString());
+					}
+				}else if(o instanceof BigDecimal){//BigDecimal
+					cell.setCellValue((field.get(t).toString()));
+					if(excel.precision()!=-1){
+						cell.setCellValue(new BigDecimal(field.get(t).toString()).setScale(excel.precision(),excel.round()==true?BigDecimal.ROUND_HALF_UP:BigDecimal.ROUND_FLOOR).toString());
+					}
+				} else if (o instanceof Boolean) {//布尔类型
+					Boolean bool = (Boolean) field.get(t);
+					if (edf == null) {
+						cell.setCellValue(bool);
+					} else {
+						Map<String, String> map = edf.get(field.getName());
+						if (map == null) {
+							cell.setCellValue(bool);
+						} else {
+							cell.setCellValue(map.get(bool.toString().toLowerCase()));
+						}
+					}
+
+				} else if (o instanceof Integer) {//整型
+
+					Integer intValue = (Integer) field.get(t);
+
+					if (edf == null) {
+						cell.setCellValue(intValue);
+					} else {
+						Map<String, String> map = edf.get(field.getName());
+						if (map == null) {
+							cell.setCellValue(intValue);
+						} else {
+							cell.setCellValue(map.get(intValue.toString()));
+						}
+					}
+				} else {
+					cell.setCellValue(field.get(t).toString());
+				}
+
+				columnIndex++;
+			}
+
+			rowIndex++;
+		}
+
+		return wb;
+	}
+
+
+	/**
+	 * 从文件读取数据,最好是所有的单元格都是文本格式,日期格式要求yyyy-MM-dd HH:mm:ss,布尔类型0:真,1:假
+	 * 
+	 * @param edf
+	 *            数据格式化
+	 * 
+	 * @param file
+	 *            Excel文件,支持xlsx后缀,xls的没写,基本一样
+	 * @return
+	 * @throws Exception
+	 */
+	public List<E> readFromFile(ExcelDataFormatter edf, File file) throws Exception {
+		Field[] fields = ReflectUtils.getClassFieldsAndSuperClassFields(e.getClass());
+
+		Map<String, String> textToKey = new HashMap<String, String>();
+
+		Excel _excel = null;
+		for (Field field : fields) {
+			_excel = field.getAnnotation(Excel.class);
+			if (_excel == null || _excel.skip() == true) {
+				continue;
+			}
+			textToKey.put(_excel.name(), field.getName());
+		}
+
+		InputStream is = new FileInputStream(file);
+
+		Workbook wb = new XSSFWorkbook(is);
+
+		Sheet sheet = wb.getSheetAt(0);
+		Row title = sheet.getRow(0);
+		// 标题数组,后面用到,根据索引去标题名称,通过标题名称去字段名称用到 textToKey
+		String[] titles = new String[title.getPhysicalNumberOfCells()];
+		for (int i = 0; i < title.getPhysicalNumberOfCells(); i++) {
+			titles[i] = title.getCell(i).getStringCellValue();
+		}
+
+		List<E> list = new ArrayList<E>();
+
+		E e = null;
+
+		int rowIndex = 0;
+		int columnCount = titles.length;
+		Cell cell = null;
+		Row row = null;
+
+		for (Iterator<Row> it = sheet.rowIterator(); it.hasNext();) {
+
+			row = it.next();
+			if (rowIndex++ == 0) {
+				continue;
+			}
+
+			if (row == null) {
+				break;
+			}
+
+			e = get();
+
+			for (int i = 0; i < columnCount; i++) {
+				cell = row.getCell(i);
+				etimes = 0;
+				readCellContent(textToKey.get(titles[i]), fields, cell, e, edf);
+			}
+			list.add(e);
+		}
+		return list;
+	}
+
+	/**
+	 * 从单元格读取数据,根据不同的数据类型,使用不同的方式读取<br>
+	 * 有时候POI自作聪明,经常和我们期待的数据格式不一样,会报异常,<br>
+	 * 我们这里采取强硬的方式<br>
+	 * 使用各种方法,知道尝试到读到数据为止,然后根据Bean的数据类型,进行相应的转换<br>
+	 * 如果尝试完了(总共7次),还是不能得到数据,那么抛个异常出来,没办法了
+	 * 
+	 * @param key
+	 *            当前单元格对应的Bean字段
+	 * @param fields
+	 *            Bean所有的字段数组
+	 * @param cell
+	 *            单元格对象
+	 * @param e
+	 * @throws Exception
+	 */
+	public void readCellContent(String key, Field[] fields, Cell cell, E e, ExcelDataFormatter edf) throws Exception {
+
+		Object o = null;
+		try {
+			switch (cell.getCellType()) {
+			case XSSFCell.CELL_TYPE_BOOLEAN:
+				o = cell.getBooleanCellValue();
+				break;
+			case XSSFCell.CELL_TYPE_NUMERIC:
+				o = cell.getNumericCellValue();
+				if (HSSFDateUtil.isCellDateFormatted(cell)) {
+					o = DateUtil.getJavaDate(cell.getNumericCellValue());
+				}
+				break;
+			case XSSFCell.CELL_TYPE_STRING:
+				o = cell.getStringCellValue();
+				break;
+			case XSSFCell.CELL_TYPE_ERROR:
+				o = cell.getErrorCellValue();
+				break;
+			case XSSFCell.CELL_TYPE_BLANK:
+				o = null;
+				break;
+			case XSSFCell.CELL_TYPE_FORMULA:
+				o = cell.getCellFormula();
+				break;
+			default:
+				o = null;
+				break;
+			}
+
+			if (o == null)
+				return;
+
+			for (Field field : fields) {
+				field.setAccessible(true);
+				if (field.getName().equals(key)) {
+					Boolean bool = true;
+					Map<String, String> map = null;
+					if (edf == null) {
+						bool = false;
+					} else {
+						map = edf.get(field.getName());
+						if (map == null) {
+							bool = false;
+						}
+					}
+
+					if (field.getType().equals(Date.class)) {
+						if (o.getClass().equals(Date.class)) {
+							field.set(e, o);
+						} else {
+							field.set(e, sdf.parse(o.toString()));
+						}
+					} else if (field.getType().equals(String.class)) {
+						if (o.getClass().equals(String.class)) {
+							field.set(e, o);
+						} else {
+							field.set(e, o.toString());
+						}
+					} else if (field.getType().equals(Long.class)) {
+						if (o.getClass().equals(Long.class)) {
+							field.set(e, o);
+						} else {
+							field.set(e, Long.parseLong(o.toString()));
+						}
+					} else if (field.getType().equals(Integer.class)) {
+						if (o.getClass().equals(Integer.class)) {
+							field.set(e, o);
+						} else {
+							// 检查是否需要转换
+							if (bool) {
+								field.set(e, map.get(o.toString()) != null ? Integer.parseInt(map.get(o.toString())) : Integer.parseInt(o.toString()));
+							} else {
+								field.set(e, Integer.parseInt(o.toString()));
+							}
+
+						}
+					} else if (field.getType().equals(BigDecimal.class)) {
+						if (o.getClass().equals(BigDecimal.class)) {
+							field.set(e, o);
+						} else {
+							field.set(e, BigDecimal.valueOf(Double.parseDouble(o.toString())));
+						}
+					} else if (field.getType().equals(Boolean.class)) {
+						if (o.getClass().equals(Boolean.class)) {
+							field.set(e, o);
+						} else {
+							// 检查是否需要转换
+							if (bool) {
+								field.set(e, map.get(o.toString()) != null ? Boolean.parseBoolean(map.get(o.toString())) : Boolean.parseBoolean(o.toString()));
+							} else {
+								field.set(e, Boolean.parseBoolean(o.toString()));
+							}
+						}
+					} else if (field.getType().equals(Float.class)) {
+						if (o.getClass().equals(Float.class)) {
+							field.set(e, o);
+						} else {
+							field.set(e, Float.parseFloat(o.toString()));
+						}
+					} else if (field.getType().equals(Double.class)) {
+						if (o.getClass().equals(Double.class)) {
+							field.set(e, o);
+						} else {
+							field.set(e, Double.parseDouble(o.toString()));
+						}
+
+					}
+
+				}
+			}
+
+		} catch (Exception ex) {
+			ex.printStackTrace();
+			// 如果还是读到的数据格式还是不对,只能放弃了
+			if (etimes > 7) {
+				throw ex;
+			}
+			etimes++;
+			if (o == null) {
+				readCellContent(key, fields, cell, e, edf);
+			}
+		}
+	}
+
+	/**
+	 * 将数据导入到Excel并且下载
+	 * @param response
+	 * @param list
+	 * @param edf
+	 * @param fileNameWithoutSuffix
+	 */
+	public static <T> void downloadXlsx(HttpServletResponse response, List<T> list, ExcelDataFormatter edf, String fileNameWithoutSuffix ) {
+		try {
+			Workbook workBook=getWorkBook(list, edf);
+			response.reset();
+			response.setHeader("Content-disposition", "attachment; filename=" + new String(fileNameWithoutSuffix.getBytes("gbk"), "iso8859-1") + ".xlsx");
+			response.setContentType("application/msexcel");// 定义输出类型
+			workBook.write(response.getOutputStream());
+			response.getOutputStream().flush();
+			response.getOutputStream().close();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+}

+ 39 - 0
src/main/java/com/aijia/kmt/common/excel/thirdparty/gson/GsonExclusion.java

@@ -0,0 +1,39 @@
+package com.aijia.kmt.common.excel.thirdparty.gson;
+
+import com.google.gson.ExclusionStrategy;
+import com.google.gson.FieldAttributes;
+
+import java.io.Serializable;
+
+/**
+ * Gson 字段排除
+ * @author Goofy
+ *
+ */
+public class GsonExclusion implements ExclusionStrategy , Serializable{
+	
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 6645479147142101974L;
+	public String fields[];
+	
+
+	public GsonExclusion(String[] fields) {
+		this.fields = fields;
+	}
+
+	public boolean shouldSkipField(FieldAttributes f) {
+		for(String s:fields){
+			if(s.equalsIgnoreCase(f.getName()))return true;
+		}
+		return false;
+	}
+	
+	
+
+	public boolean shouldSkipClass(Class<?> clazz) {
+		return false;
+	}
+
+}

+ 41 - 0
src/main/java/com/aijia/kmt/common/excel/thirdparty/gson/GsonKeyRename.java

@@ -0,0 +1,41 @@
+package com.aijia.kmt.common.excel.thirdparty.gson;
+
+import com.google.gson.FieldNamingStrategy;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Gson字段重命名
+ * @author Goofy
+ *
+ */
+public class GsonKeyRename implements FieldNamingStrategy , Serializable {
+	
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 2777671597798348915L;
+	public Map<String,String> map;
+
+	public GsonKeyRename(Map<String,String> map) {
+		super();
+		this.map = map;
+	}
+
+	public String translateName(Field f) {
+		
+		Iterator<Entry<String, String>> it=map.entrySet().iterator();
+		while(it.hasNext()){
+			Entry<String,String> entry=it.next();
+			if(entry.getKey().equalsIgnoreCase(f.getName()))
+				return entry.getValue();
+		}
+		
+		return f.getName();
+	}
+	
+}

+ 113 - 0
src/main/java/com/aijia/kmt/common/excel/thirdparty/gson/GsonTools.java

@@ -0,0 +1,113 @@
+/**
+ * 上海蓝鸟集团
+ * 上海蓝鸟科技股份有限公司
+ * 华东工程中心(无锡)
+ * 2015版权所有
+ */
+package com.aijia.kmt.common.excel.thirdparty.gson;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import java.io.Serializable;
+
+/**
+ * Gson工具类
+ * @author Goofy
+ * @Date 2015年7月31日 下午3:45:18
+ */
+public class GsonTools implements Serializable{
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -3879526559035952542L;
+	private boolean serializeNulls = true;
+	private String dateFormat = "yyyy-MM-dd HH:mm:ss";
+	private GsonExclusion exclusion;
+	private GsonKeyRename keyRename;
+
+	public String toJson(Object object) {
+		return getGson().toJson(object);
+	}
+
+	/**
+	 * 序列号JSON,默认日期格式yyyy-MM-dd HH:mm:ss,如果需要自定义参数,使用
+	 * @see org.xdemo.superutil.thirdparty.gson.GsonTools#GsonTools()
+	 * @see org.xdemo.superutil.thirdparty.gson.GsonTools#GsonTools(GsonExclusion, GsonKeyRename)
+	 * @see org.xdemo.superutil.thirdparty.gson.GsonTools#GsonTools(boolean, String, GsonExclusion, GsonKeyRename)
+	 * @param object
+	 * @return
+	 */
+	public static String toJson2(Object object) {
+		return new GsonBuilder().serializeNulls().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(object);
+	}
+
+	private Gson getGson() {
+		GsonBuilder builder = new GsonBuilder();
+		if (serializeNulls) {
+			builder.serializeNulls();
+		}
+		
+		if(dateFormat!=null){
+			builder.setDateFormat(dateFormat);
+		}
+		
+		if (exclusion != null) {
+			builder.setExclusionStrategies(exclusion);
+		}
+		if (keyRename != null) {
+			builder.setFieldNamingStrategy(keyRename);
+		}
+		return builder.create();
+	}
+
+	public GsonTools() {
+
+	}
+
+	public GsonTools(GsonExclusion exclusion, GsonKeyRename keyRename) {
+		this.exclusion = exclusion;
+		this.keyRename = keyRename;
+	}
+
+	public GsonTools(boolean serializeNulls, String dateFormat, GsonExclusion exclusion, GsonKeyRename keyRename) {
+		this.serializeNulls = serializeNulls;
+		this.dateFormat = dateFormat;
+		this.exclusion = exclusion;
+		this.keyRename = keyRename;
+	}
+
+	public boolean isSerializeNulls() {
+		return serializeNulls;
+	}
+
+	public void setSerializeNulls(boolean serializeNulls) {
+		this.serializeNulls = serializeNulls;
+	}
+
+	public String getDateFormat() {
+		return dateFormat;
+	}
+
+	public void setDateFormat(String dateFormat) {
+		this.dateFormat = dateFormat;
+	}
+
+	public GsonExclusion getExclusion() {
+		return exclusion;
+	}
+
+	public void setExclusion(GsonExclusion exclusion) {
+		this.exclusion = exclusion;
+	}
+
+	public GsonKeyRename getKeyRename() {
+		return keyRename;
+	}
+
+	public void setKeyRename(GsonKeyRename keyRename) {
+		this.keyRename = keyRename;
+	}
+
+}

+ 123 - 0
src/main/java/com/aijia/kmt/common/excel/thirdparty/http/CookieUtils.java

@@ -0,0 +1,123 @@
+/**
+ * 
+ */
+package com.aijia.kmt.common.excel.thirdparty.http;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Cookie操作
+ * @author Goofy
+ */
+public class CookieUtils {
+	
+	/**
+	 * 从Cookie中取出某个key的值
+	 * @param request
+	 * @param name
+	 * @return
+	 */
+	public static String getValue(HttpServletRequest request, String name){
+		Cookie[] cookies=request.getCookies();
+		if(cookies==null)return null;
+		String v=null;
+        for(Cookie cookie:cookies){
+        	if(cookie.getName().equalsIgnoreCase(name)){
+        		v=cookie.getValue();
+        		break;
+        	}
+        }
+        return v;
+	}
+	
+	/**
+	 * 设置Cookie中的某个值
+	 * @param request
+	 * @param name
+	 * @return
+	 */
+	public static void setValue(HttpServletRequest request, HttpServletResponse response, String name, String value){
+		Cookie[] cookies=request.getCookies();
+		if(cookies==null)return;
+        for(Cookie cookie:cookies){
+        	if(cookie.getName().equalsIgnoreCase(name)){
+        		cookie.setValue(value);
+        		response.addCookie(cookie);
+        		break;
+        	}
+        }
+	}
+	
+	/**
+	 * 判断Cookie中是否含有某个key
+	 * @param request
+	 * @param name
+	 * @return
+	 */
+	public static boolean hasCookie(HttpServletRequest request, String name){
+		Cookie[] cookies=request.getCookies();
+		if(cookies==null)return false;
+		boolean has=false;
+        for(Cookie cookie:cookies){
+        	if(cookie.getName().equalsIgnoreCase(name)){
+        		has=true;
+        		break;
+        	}
+        }
+        return has;
+	}
+	
+	
+	/**
+	 * 写Cookie
+	 * @param response HttpServletResponse
+	 * @param name Cookie的名字
+	 * @param value Cookie的值
+	 * @param secure 是否安全
+	 * @param expiry 过期时间,-1表示关闭浏览器即过期,请给出一个合理有效的值
+	 */
+	public static void addCookie(HttpServletRequest request, HttpServletResponse response, String name, String value, boolean secure, int expiry, String path){
+		Cookie cookie=new Cookie(name, value);
+		if(hasCookie(request, name)){
+			cookie.setValue(value);
+		}
+		cookie.setSecure(secure);
+		cookie.setMaxAge(expiry);
+		response.addCookie(cookie);
+	}
+	
+	/**
+	 * 移除Cookie中的没个Key
+	 * @param request
+	 * @param response
+	 * @param name
+	 */
+	public static void clearCookie(HttpServletRequest request, HttpServletResponse response, String name){
+		Cookie[] cookies=request.getCookies();
+		if(cookies==null)return;
+        for(Cookie cookie:cookies){
+        	if(cookie.getName().equalsIgnoreCase(name)){
+        		cookie.setMaxAge(0);
+            	cookie.setValue(null);
+            	response.addCookie(cookie);
+        	}
+        }
+	}
+	
+	/**
+	 * 清除所有Cookie
+	 * @param request
+	 * @param response
+	 */
+	public static void clearAll(HttpServletRequest request, HttpServletResponse response){
+		Cookie[] cookies=request.getCookies();
+        for(Cookie cookie:cookies){
+        	cookie.setMaxAge(0);
+        	cookie.setValue(null);
+        	response.addCookie(cookie);
+        }
+	}
+	
+}

+ 144 - 0
src/main/java/com/aijia/kmt/common/excel/thirdparty/http/HttpServletUtils.java

@@ -0,0 +1,144 @@
+/**
+ * 
+ */
+package com.aijia.kmt.common.excel.thirdparty.http;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLEncoder;
+
+/**
+ * @author Goofy 
+ * Http下载工具类
+ */
+public class HttpServletUtils {
+
+	private final Logger logger = LoggerFactory.getLogger(this.getClass());
+	
+	/**
+	 * 获取项目网络路径
+	 * @param request
+	 * @return
+	 */
+	public static String getContentpath(HttpServletRequest request){
+		return request.getContextPath();
+	}
+	
+	/**
+     * 获取项目磁盘绝对路径
+     */
+    public static String getRealPath(HttpServletRequest request){
+        return request.getSession().getServletContext().getRealPath("/");
+    }
+    
+    /**
+     * 使用了代理服务器的,无法获取正确地址的,使用这个方法获取访问者的IP地址
+     */
+    public static String getIpAddr(HttpServletRequest request) {
+        String ip = request.getHeader("x-forwarded-for");
+        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getRemoteAddr();
+        }
+        return ip;
+    }
+
+	/**
+	 * 下载多个文件
+	 * 
+	 * @param response
+	 *            HttpServletResponse
+	 * @param files
+	 *            File
+	 */
+	public void download(HttpServletResponse response, File... files) {
+
+		for (File file : files) {
+			download(response, file, file.getName());
+		}
+
+	}
+
+	/**
+	 * 下载文件
+	 * 
+	 * @param response
+	 *            HttpServletResponse
+	 * @param file
+	 *            文件
+	 * @param fileName
+	 *            下载的输出文件名
+	 */
+	public void download(HttpServletResponse response, File file, String fileName) {
+		InputStream is;
+		String _fileName;
+		try {
+			is = new FileInputStream(file);
+			_fileName = fileName == null ? file.getName() : fileName;
+			download(response, is, _fileName);
+		} catch (FileNotFoundException e) {
+			logger.error("fileName=[{}]", fileName);
+			logger.error("下载异常", e);
+		}
+	}
+
+	/**
+	 * 下载文件
+	 * 
+	 * @param is
+	 *            输入流
+	 * @param fileName
+	 *            文件名
+	 * @param response
+	 */
+	public void download(HttpServletResponse response, InputStream is, String fileName) {
+
+		OutputStream os = null;
+
+		try {
+			response.reset();
+			response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
+
+			os = response.getOutputStream();
+
+			byte buffer[] = new byte[1024];
+			int len = 0;
+
+			while ((len = is.read(buffer)) > 0) {
+				os.write(buffer, 0, len);
+			}
+
+			os.flush();
+			os.close();
+
+			is.close();
+
+		} catch (Exception e) {
+			try {
+				if (os != null) {
+					os.close();
+				}
+			} catch (IOException e1) {
+				logger.error("异常", e1);
+			}
+			try {
+				if (is != null) {
+					is.close();
+				}
+			} catch (IOException e1) {
+				logger.error("异常", e1);
+			}
+		}
+
+	}
+
+}

+ 55 - 0
src/main/java/com/aijia/kmt/common/swagger/Swagger2Config.java

@@ -0,0 +1,55 @@
+package com.aijia.kmt.common.swagger;
+
+
+//import com.aijia.parent.config.RequestApiLogInterceptor;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+/**
+ * 类名称:SpringSwaggerConfig<br>
+ * 类描述:Swagger配置<br>
+ *
+ * @version v1.0
+ */
+@EnableSwagger2
+@Configuration
+public class Swagger2Config extends WebMvcConfigurerAdapter {
+    //@Autowired
+    //private RequestApiLogInterceptor requestApiLogInterceptor;
+
+    @Bean
+    public Docket customDocket() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())
+                .select()
+                //为controller包路径
+                .apis(RequestHandlerSelectors.basePackage("com.aijia"))
+                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("爱加kmtAPP接口文档")//swagger的title
+                .description("爱加kmtRestful接口文档")//自己定义
+                .termsOfServiceUrl("https://www.sharingschool.com/")//自己定义
+                .version("2.9.2")
+                .build();
+    }
+
+    /*@Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        InterceptorRegistration addInterceptor = registry.addInterceptor(requestApiLogInterceptor);
+    }*/
+
+}

+ 57 - 0
src/main/java/com/aijia/kmt/common/taskthread/AijiaThreadPool.java

@@ -0,0 +1,57 @@
+package com.aijia.kmt.common.taskthread;
+
+import java.util.concurrent.*;
+
+public class AijiaThreadPool {
+
+    /**
+     * 核心线程数
+     */
+    private static int corePoolSize = 10;
+
+    /**
+     * 最大线程数
+     */
+    private static int maximumPoolSize = 100;
+
+    /**
+     * 空闲时间
+     */
+    private static long keepAliveTime = 10;
+
+    /**
+     * 空闲时间的单位
+     */
+    private static TimeUnit unit = TimeUnit.MINUTES;
+
+    /**
+     * 等待队列
+     */
+    private static BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(1024);
+
+    /**
+     * 线程工厂
+     */
+    //private static ThreadFactory threadFactory;
+
+    /**
+     * 拒绝策略
+     */
+    //private static RejectedExecutionHandler handler;
+
+    public static ThreadPoolExecutor _instance = null;
+
+    /* singleton */
+    public static ThreadPoolExecutor getInstance() {
+        if (_instance == null) {
+            synchronized (AijiaThreadPool.class) {
+                if (_instance == null) {
+                    _instance = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit,
+                            workQueue, Executors.defaultThreadFactory());
+                }
+            }
+        }
+        return _instance;
+    }
+
+}

+ 34 - 0
src/main/java/com/aijia/kmt/common/taskthread/Task.java

@@ -0,0 +1,34 @@
+package com.aijia.kmt.common.taskthread;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+*2017年8月17日13:43:14
+* @author wuwen
+*/
+/* 所有任务的接口 */
+ public abstract class Task implements Runnable {
+	 
+	   protected Logger logger = LoggerFactory.getLogger(this.getClass());
+       public long _taskID = 0;
+       public Task(){
+           
+       }
+       
+       public Task(long task_id){
+           _taskID = task_id;
+       }
+       
+       public void setTaskId(long task_id){
+           _taskID = task_id;
+       }
+       
+       public long getTaskId(){
+           return _taskID;
+       }
+       
+       public void run() {
+
+       }
+}

+ 166 - 0
src/main/java/com/aijia/kmt/common/taskthread/ThreadPool.java

@@ -0,0 +1,166 @@
+package com.aijia.kmt.common.taskthread;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+
+/**
+ * 线程池管理
+ * 2017年8月17日13:42:53
+ * @author wuwen
+ * 
+ */
+public class ThreadPool {
+    public static long _next_task_id = 0;
+    
+    public static final int DEFAULT_THREAD_NUM = 50;
+    
+    public static final int MAX_THREAD_NUM = 200;
+    
+    public int _cur_thread_num = 0;
+    
+    public boolean _is_closed = true;
+    
+    public List<Task> taskQueue = Collections.synchronizedList(new LinkedList<Task>());
+    
+    public WorkThread[] threads;
+    
+    public static ThreadPool _instance = null;
+    
+    
+    private ThreadPool() {
+        _cur_thread_num = DEFAULT_THREAD_NUM;
+        threads = new WorkThread[_cur_thread_num];
+        for (int i = 0; i < _cur_thread_num; ++i) {
+            threads[i] = new WorkThread(i);
+        }
+    }
+    
+    private ThreadPool(int thread_num) {
+        _cur_thread_num = thread_num;
+        threads = new WorkThread[_cur_thread_num];
+        for (int i = 0; i < _cur_thread_num; ++i) {
+            threads[i] = new WorkThread(i);
+        }
+    }
+    
+    /* singleton */
+    public static ThreadPool getInstance() {
+        if (_instance == null) {
+            synchronized (ThreadPool.class) {
+                if (_instance == null) {
+                    _instance = new ThreadPool();
+                    _instance.start();
+                }
+            }
+        }
+        return _instance;
+    }
+    
+    public static long generateTaskId() {
+        _next_task_id += (_next_task_id + 1) / 1000000;
+        if (_next_task_id == 0)
+            _next_task_id++;
+        return _next_task_id;
+    }
+    
+    public void start() {
+        _is_closed = false;
+        for (int i = 0; i < _cur_thread_num; ++i) {
+            threads[i].start();
+
+        }
+    }
+    
+    public void close() {
+        if (!_is_closed) {
+            waitforfinish();
+            _is_closed = true;
+            taskQueue.clear();
+        }
+
+    }
+    
+    public void waitforfinish() {
+        synchronized (this) {
+            _is_closed = true;
+            notifyAll();
+        }
+        for (int i = 0; i < _cur_thread_num; ++i) {
+            threads[i].stopThread();
+         
+        }
+    }
+    
+    public void addTask(Task new_task) {
+        if (_is_closed) {
+            throw new IllegalStateException();
+        }
+        synchronized (taskQueue) {
+            if (new_task != null) {
+                taskQueue.add(new_task);
+                taskQueue.notifyAll();
+                // taskQueue.notify();
+                
+            }
+        }
+    }
+    
+    public int getTaskCount() {
+        return taskQueue.size();
+    }
+    
+    public class WorkThread extends Thread {
+        private int _index;
+        
+        private boolean _is_running = true;
+        
+        public WorkThread(int index) {
+            _index = index;
+        }
+        
+        public void run() {
+            while (_is_running) {
+                Task t = getTask();
+                if (t != null) {
+                    t.run();
+                } else {
+                    // 结束线程
+                    return;
+                }
+            }
+        }
+        
+        public Task getTask() {
+            if (_is_closed)
+                return null;
+            Task r = null;
+            synchronized (taskQueue) {
+                while (taskQueue.isEmpty()) {
+                    try {
+                        /* 任务队列为空,则等待有新任务加入从而被唤醒 */
+                        taskQueue.wait();
+                    } catch (InterruptedException ie) {
+                      
+                    }
+                }
+                
+                /* 取出任务执行 */
+                r = (Task)taskQueue.remove(0);
+                return r;
+            }
+        }
+        
+        public void stopThread() {
+            _is_running = false;
+            try {
+                join();
+            } catch (InterruptedException ex) {
+               
+            }
+        }
+    }
+    
+ 
+}

+ 90 - 0
src/main/java/com/aijia/kmt/common/weixin/LoginWxUtil.java

@@ -0,0 +1,90 @@
+package com.aijia.kmt.common.weixin;
+
+
+import com.aijia.kmt.utils.SystemResourceLocator;
+import com.alibaba.fastjson.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * 公众平台通用接口工具类 
+ */  
+public class LoginWxUtil {
+
+	private  static String appId = (String) SystemResourceLocator.getValue("weixin_pc_appId");
+
+	private  static String appSecret = (String) SystemResourceLocator.getValue("weixin_pc_appSecret");
+
+
+	
+	private static Logger log = LoggerFactory.getLogger(LoginWxUtil.class);
+
+	// OAuth2.0通过code换取网页授权access_token
+	protected final static String OAUTH2_ACCESSTOKEN_URL="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
+
+
+
+	/**
+	 * 1.通过code换取网页授权access_token
+	 * @param
+	 * @param
+	 * @param code 填写第一步获取的code参数
+	 * @return WeixinOauth2Token
+	 */
+	public static WeixinOauth2Token getOauth2AccessToken(String code) {
+		WeixinOauth2Token wat=null;
+		String requestUrl=OAUTH2_ACCESSTOKEN_URL.replace("APPID", appId).replace("SECRET", appSecret).replace("CODE", code);
+		log.info("requestUrl-->"+requestUrl);
+		//获取网页授权凭证
+		JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "GET", null);
+		if (null != jsonObject) {
+			log.info("获取用户信息jsonObject---" +jsonObject.toJSONString());  
+			try {
+				wat=new WeixinOauth2Token();
+				wat.setAccessToken(jsonObject.getString("access_token"));
+				wat.setExpiresIn(jsonObject.getIntValue("expires_in"));
+				wat.setRefreshToken(jsonObject.getString("refresh_token"));
+				wat.setOpenId(jsonObject.getString("openid"));
+				wat.setScope(jsonObject.getString("scope"));
+				if(jsonObject.containsKey("unionid")){
+					wat.setUnionId(jsonObject.getString("unionid"));
+				}
+			} catch (Exception e) {
+				int errorCode=jsonObject.getIntValue("errcode");
+				String errorMsg=jsonObject.getString("errmsg");
+				log.error("获取网页授权凭证失败errcode:{"+errorCode+"} errmsg:{"+errorMsg+"}");
+				return null;
+			}
+		}
+		return wat;
+	}
+	public static WeixinOauth2Token getOauth2AccessToken(String code,String appId,String appSecret ) {
+		WeixinOauth2Token wat=null;
+		String requestUrl=OAUTH2_ACCESSTOKEN_URL.replace("APPID", appId).replace("SECRET", appSecret).replace("CODE", code);
+		log.info("requestUrl-->"+requestUrl);
+		//获取网页授权凭证
+		JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "GET", null);
+		if (null != jsonObject) {
+			log.info("获取用户信息jsonObject---" +jsonObject.toJSONString());
+			try {
+				wat=new WeixinOauth2Token();
+				wat.setAccessToken(jsonObject.getString("access_token"));
+				wat.setExpiresIn(jsonObject.getIntValue("expires_in"));
+				wat.setRefreshToken(jsonObject.getString("refresh_token"));
+				wat.setOpenId(jsonObject.getString("openid"));
+				wat.setScope(jsonObject.getString("scope"));
+				if(jsonObject.containsKey("unionid")){
+					wat.setUnionId(jsonObject.getString("unionid"));
+				}
+			} catch (Exception e) {
+				int errorCode=jsonObject.getIntValue("errcode");
+				String errorMsg=jsonObject.getString("errmsg");
+				log.error("获取网页授权凭证失败errcode:{"+errorCode+"} errmsg:{"+errorMsg+"}");
+				return null;
+			}
+		}
+		return wat;
+	}
+
+}  

+ 74 - 0
src/main/java/com/aijia/kmt/common/weixin/WeixinOauth2Token.java

@@ -0,0 +1,74 @@
+package com.aijia.kmt.common.weixin;
+
+import java.io.Serializable;
+
+/**  
+* 类描述:网页授权信息  
+*/
+public class WeixinOauth2Token implements Serializable{
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -8772941276987943393L;
+	// 网页授权接口调用凭证
+	private String accessToken;
+	// 凭证有效时长
+	private int expiresIn;
+	// 用于刷新凭证
+	private String refreshToken;
+	// 用户标识
+	private String openId;
+	// 用户授权作用域
+	private String scope;
+	
+	private String unionId;
+	
+	public String getAccessToken() {
+		return accessToken;
+	}
+	
+	public void setAccessToken(String accessToken) {
+		this.accessToken = accessToken;
+	}
+	
+	public int getExpiresIn() {
+		return expiresIn;
+	}
+	
+	public void setExpiresIn(int expiresIn) {
+		this.expiresIn = expiresIn;
+	}
+	
+	public String getRefreshToken() {
+		return refreshToken;
+	}
+	
+	public void setRefreshToken(String refreshToken) {
+		this.refreshToken = refreshToken;
+	}
+	
+	public String getOpenId() {
+		return openId;
+	}
+	
+	public void setOpenId(String openId) {
+		this.openId = openId;
+	}
+	
+	public String getScope() {
+		return scope;
+	}
+	
+	public void setScope(String scope) {
+		this.scope = scope;
+	}
+
+	public String getUnionId() {
+		return unionId;
+	}
+
+	public void setUnionId(String unionId) {
+		this.unionId = unionId;
+	}
+	
+}

+ 253 - 0
src/main/java/com/aijia/kmt/common/weixin/WeixinUtil.java

@@ -0,0 +1,253 @@
+package com.aijia.kmt.common.weixin;
+
+import com.aijia.core.utils.HttpRemote;
+import com.aijia.kmt.utils.SystemResourceLocator;
+import com.aijia.utils.MyX509TrustManager;
+import com.aijia.utils.SHA1Util;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+
+/**
+ *
+ * 公众平台通用接口工具类
+ *
+ */
+public class WeixinUtil {
+    private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);
+
+    public   static String APPID = (String) SystemResourceLocator.getValue("weixin_appId");;
+
+    public  static String APPSECRET = (String) SystemResourceLocator.getValue("weixin_appSecret");
+
+    public  static String TOKEN = (String) SystemResourceLocator.getValue("weixin_token");
+
+
+    public  static String TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token";//获取token
+
+    public  static String JSAPI_TICKET_URL="https://api.weixin.qq.com/cgi-bin/ticket/getticket";//获取jsapi_ticket
+
+    public static String API_MENU_GET="https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";
+
+    public static String API_MENU_CREATE="https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
+
+    public static String API_MATERIAL_GET="https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN";
+
+    public static  String url =(String) SystemResourceLocator.getValue("peidian_url");
+    public static String bucketName =(String) SystemResourceLocator.getValue("peidian_bucketName");
+
+    /**
+     * 发起https请求并获取结果
+     *
+     * @param requestUrl 请求地址
+     * @param requestMethod 请求方式(GET、POST)
+     * @param outputStr 提交的数据
+     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
+     */
+    public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
+        JSONObject jsonObject = null;
+        StringBuffer buffer = new StringBuffer();
+        try {
+            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
+            TrustManager[] tm = { new MyX509TrustManager() };
+            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
+            sslContext.init(null, tm, new java.security.SecureRandom());
+            // 从上述SSLContext对象中得到SSLSocketFactory对象
+            SSLSocketFactory ssf = sslContext.getSocketFactory();
+
+            URL url = new URL(requestUrl);
+            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
+            httpUrlConn.setSSLSocketFactory(ssf);
+
+            httpUrlConn.setDoOutput(true);
+            httpUrlConn.setDoInput(true);
+            httpUrlConn.setUseCaches(false);
+            // 设置请求方式(GET/POST)
+            httpUrlConn.setRequestMethod(requestMethod);
+
+            if ("GET".equalsIgnoreCase(requestMethod))
+                httpUrlConn.connect();
+
+            // 当有数据需要提交时
+            if (null != outputStr) {
+                OutputStream outputStream = httpUrlConn.getOutputStream();
+                // 注意编码格式,防止中文乱码
+                outputStream.write(outputStr.getBytes("UTF-8"));
+                outputStream.close();
+            }
+
+            // 将返回的输入流转换成字符串
+            InputStream inputStream = httpUrlConn.getInputStream();
+            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
+            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+
+            String str = null;
+            while ((str = bufferedReader.readLine()) != null) {
+                buffer.append(str);
+            }
+            bufferedReader.close();
+            inputStreamReader.close();
+            // 释放资源
+            inputStream.close();
+            inputStream = null;
+            httpUrlConn.disconnect();
+            jsonObject =  JSONObject.parseObject(buffer.toString());
+        } catch (ConnectException ce) {
+            log.error("Weixin server connection timed out.");
+            return null;
+        } catch (Exception e) {
+            log.error("https request error:{}", e);
+            return null;
+        }
+        return jsonObject;
+    }
+
+    public static String httpRequestString(String requestUrl, String requestMethod, String outputStr) {
+        StringBuffer buffer = new StringBuffer();
+        try {
+            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
+            TrustManager[] tm = { new MyX509TrustManager() };
+            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
+            sslContext.init(null, tm, new java.security.SecureRandom());
+            // 从上述SSLContext对象中得到SSLSocketFactory对象
+            SSLSocketFactory ssf = sslContext.getSocketFactory();
+
+            URL url = new URL(requestUrl);
+            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
+            httpUrlConn.setSSLSocketFactory(ssf);
+
+            httpUrlConn.setDoOutput(true);
+            httpUrlConn.setDoInput(true);
+            httpUrlConn.setUseCaches(false);
+            // 设置请求方式(GET/POST)
+            httpUrlConn.setRequestMethod(requestMethod);
+
+            if ("GET".equalsIgnoreCase(requestMethod))
+                httpUrlConn.connect();
+
+            // 当有数据需要提交时
+            if (null != outputStr) {
+                OutputStream outputStream = httpUrlConn.getOutputStream();
+                // 注意编码格式,防止中文乱码
+                outputStream.write(outputStr.getBytes("UTF-8"));
+                outputStream.close();
+            }
+
+            // 将返回的输入流转换成字符串
+            InputStream inputStream = httpUrlConn.getInputStream();
+            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
+            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+
+            String str = null;
+            while ((str = bufferedReader.readLine()) != null) {
+                buffer.append(str);
+            }
+            bufferedReader.close();
+            inputStreamReader.close();
+            // 释放资源
+            inputStream.close();
+            inputStream = null;
+            httpUrlConn.disconnect();
+        } catch (ConnectException ce) {
+            log.error("Weixin server connection timed out.");
+        } catch (Exception e) {
+            log.error("https request error:{}", e);
+        }
+        return buffer.toString();
+    }
+
+
+
+    /**
+     * 根据内容类型判断文件扩展名
+     *
+     * @param contentType 内容类型
+     * @return
+     */
+    public static String getFileEndWitsh(String contentType) {
+        String fileEndWitsh = "";
+        if ("image/jpeg".equals(contentType))
+            fileEndWitsh = ".jpg";
+        else if ("image/jpg".equals(contentType))
+            fileEndWitsh = ".jpg";
+        else if ("image/png".equals(contentType))
+            fileEndWitsh = ".png";
+        else if ("audio/mpeg".equals(contentType))
+            fileEndWitsh = ".mp3";
+        else if ("audio/amr".equals(contentType))
+            fileEndWitsh = ".amr";
+        else if ("video/mp4".equals(contentType))
+            fileEndWitsh = ".mp4";
+        else if ("video/mpeg4".equals(contentType))
+            fileEndWitsh = ".mp4";
+        return fileEndWitsh;
+    }
+
+    /**
+     * 获取access_token
+     *
+     */
+    public  JSONObject getAccessToken() throws Exception {
+        //此请求为https的get请求,返回的数据格式为{"access_token":"ACCESS_TOKEN","expires_in":7200}
+        Map<String,Object>  map = new  HashMap<String,Object>();
+        map.put("grant_type", "client_credential");
+        map.put("appid", APPID);
+        map.put("secret", APPSECRET);
+        String  result= HttpRemote.GETMethod(TOKEN_URL, map);
+        log.info("getAccessToken--返回"+result);
+        //使用FastJson将Json字符串解析成Json对象
+        JSONObject json = JSON.parseObject(result);
+        return json;
+    }
+    /**
+     * 获取jsapi_ticket
+     *
+     */
+    public JSONObject getJsApiTicket(String accessToken) throws Exception {
+        Map<String,Object>  map = new  HashMap<String,Object>();
+        map.put("type", "jsapi");
+        map.put("access_token", accessToken);
+        String  result=HttpRemote.GETMethod(JSAPI_TICKET_URL, map);
+        log.info("getjsAccessToken--返回"+result);
+        //使用FastJson将Json字符串解析成Json对象
+        JSONObject json = JSON.parseObject(result);
+        return json;
+    }
+
+    public Map<String,Object> getSignature(String url,String  jsapiToken){
+        Map<String,Object> map  =new HashMap<String, Object>();
+        if(jsapiToken!=null){
+            String timestamp = Long.toString(System.currentTimeMillis()/1000);
+            String noncestr = UUID.randomUUID().toString();
+            // 排序
+            String sortString =
+                    "jsapi_ticket=" + jsapiToken +
+                            "&noncestr=" + noncestr +
+                            "&timestamp=" + timestamp +
+                            "&url=" +url;
+            // 加密
+            String	signature =  new SHA1Util().sha1(sortString);
+            map.put("appId",APPID);
+            map.put("timestamp", timestamp);
+            map.put("noncestr", noncestr);
+            map.put("signature", signature);
+        }
+        return map;
+    }
+}

+ 265 - 0
src/main/java/com/aijia/kmt/controller/KmtExerciseController.java

@@ -0,0 +1,265 @@
+package com.aijia.kmt.controller;
+
+
+import com.aijia.core.security.exception.CommonException;
+import com.aijia.core.web.BaseController;
+import com.aijia.core.web.ResponseConstant;
+import com.aijia.core.web.ResponseEntity;
+import com.aijia.kmt.service.*;
+import com.aijia.kmt.vo.*;
+import com.aijia.kmt.vo.rollbackai.AddExerciseQuestionRequest;
+import com.aijia.kmt.vo.rollbackai.ExerciseBooksEditRequest;
+import com.aijia.kmt.vo.rollbackai.ExerciseQuestionDealRequest;
+import com.aijia.kmt.vo.rollbackai.ExerciseQuestionsEditRequest;
+import com.alibaba.fastjson.JSON;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ * kmt练习册
+ * @author chchen
+ * 2019-01-14
+ */
+@RestController
+@RequestMapping("/api/train/kmt/exercise")
+@Api(value = "kmt练习册接口", tags = "kmt练习册接口")
+public class KmtExerciseController extends BaseController {
+    private Logger logger = LoggerFactory.getLogger(this.getClass());
+    @Autowired
+    private TokenManager tokenManager;
+
+    @Autowired
+    private KmtQualityQuestionsService kmtQualityQuestionsService;
+
+    @Autowired
+    private KmtExerciseQuestionService kmtExerciseQuestionService;
+
+    @Autowired
+    private KmtExerciseMapperService kmtExerciseMapperService;
+
+    @Autowired
+    private KmtExerciseSubmitService kmtExerciseSubmitService;
+    @Autowired
+    private KmtExerciseQuestionDealService kmtExerciseQuestionDealService;
+
+    @RequestMapping(value = "/getHandlingQuestions", method = RequestMethod.POST)
+    @ApiOperation(value = "待加工/待审核题目", httpMethod = "POST",  notes = "待加工/待审核题目")
+    public ResponseEntity getHandlingQuestions(@RequestParam(name = "accessToken") String accessToken,
+                                               @RequestBody ExerciseQuestionsRequest request) {
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            String userId = tokenManager.getUserId(accessToken);
+            responseEntity = kmtExerciseQuestionService.findExerciseQuestions(userId, request);
+        } catch (Exception e) {
+            logger.error("入参={}", request);
+            logger.error("待加工/待审核题目", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        return responseEntity;
+    }
+
+    @RequestMapping(value = "/V1/submit2Auditing", method = RequestMethod.POST)
+    @ApiOperation(value = "提交审核/发布", httpMethod = "POST",  notes = "提交审核/发布")
+    public ResponseEntity submit2AuditingV1(@RequestParam(name = "accessToken") String accessToken,
+                                            @RequestBody AuditingV1Request request) {
+        long start = System.currentTimeMillis();
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            String userId = tokenManager.getUserId(accessToken);
+            responseEntity = kmtExerciseSubmitService.submit2Auditing(request, userId);
+        } catch (CommonException e) {
+            return responseEntity.failure(ResponseConstant.CODE_500, e.getMessage());
+        } catch (Exception e){
+            logger.error("入参={}", request);
+            logger.error("异常", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        logger.info(accessToken + ":" + (System.currentTimeMillis() - start));
+        return responseEntity;
+    }
+
+    @RequestMapping(value = "/findQuestionAttributeFilter", method = RequestMethod.POST)
+    @ApiOperation(value = "查询题目类型筛选项", httpMethod = "POST",  notes = "查询题目类型筛选项")
+    public ResponseEntity findQuestionAttributeFilter(@RequestParam(name = "accessToken") String accessToken) {
+        long start = System.currentTimeMillis();
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            Map<String, Object> data = new HashMap<>();
+            data.put("list", kmtExerciseQuestionService.findQuestionAttributeFilter());
+            responseEntity.success(data, "成功");
+        } catch (Exception e) {
+            logger.error("练习册筛选条件异常", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        logger.info(accessToken + ":" + (System.currentTimeMillis() - start));
+        return responseEntity;
+    }
+
+    @RequestMapping(value = "/findExerciseBooks", method = RequestMethod.POST)
+    @ApiOperation(value = "查询练习册", httpMethod = "POST",  notes = "查询练习册")
+    public ResponseEntity findExerciseBooks(@RequestParam(name = "accessToken") String accessToken, @RequestBody ExerciseConditionRequest request) {
+        long start = System.currentTimeMillis();
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            Map<String, Object> data = new HashMap<>();
+            data.put("list", kmtExerciseMapperService.findExerciseBooks(request, tokenManager.getUserId(accessToken)));
+            responseEntity.success(data, "成功");
+        } catch (Exception e) {
+            logger.error("查询练习册", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        logger.info(accessToken + ":" + (System.currentTimeMillis() - start));
+        return responseEntity;
+    }
+
+    @RequestMapping(value = "/findExerciseBookDetail", method = RequestMethod.POST)
+    @ApiOperation(value = "查询题目单元课时", httpMethod = "POST",  notes = "查询题目单元课时")
+    public ResponseEntity findExerciseBookDetail(@RequestParam(name = "accessToken") String accessToken, @RequestBody ExerciseBookIdDealTypeRequest request) {
+        long start = System.currentTimeMillis();
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            Map<String, Object> data = new HashMap<>();
+            String userId = tokenManager.getUserId(accessToken);
+            data.put("units", kmtExerciseMapperService.findExerciseBookDetail(request, userId));
+            responseEntity.success(data, "成功");
+        } catch (Exception e) {
+            logger.error("练习册筛选条件异常", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        logger.info(accessToken + ":" + (System.currentTimeMillis() - start));
+        return responseEntity;
+    }
+
+    @RequestMapping(value = "/getKmtHandlingQuestions", method = RequestMethod.POST)
+    @ApiOperation(value = "kmt题库查询待加工/待审核的题目", httpMethod = "POST",  notes = "kmt题库查询待加工/待审核的题目")
+    public ResponseEntity getKmtHandlingQuestions(@RequestParam(name = "accessToken") String accessToken, @RequestBody KmtHandlingQuestionRequest request) {
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            responseEntity.success(kmtQualityQuestionsService.getKmtHandlingQuestions(request, tokenManager.getUserId(accessToken)), "成功");
+        } catch (Exception e) {
+            logger.error("练习册筛选条件异常", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        return responseEntity;
+    }
+
+    @RequestMapping(value = "/submitKmtQuestions2Auditing", method = RequestMethod.POST)
+    @ApiOperation(value = "kmt题目提交审核", httpMethod = "POST",  notes = "kmt题目提交审核")
+    public ResponseEntity submitKmtQuestions2Auditing(@RequestParam(name = "accessToken") String accessToken, @RequestBody AuditingRequest request) {
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            logger.info(JSON.toJSONString(request));
+            String userId = tokenManager.getUserId(accessToken);
+            responseEntity = kmtQualityQuestionsService.submitKmtQuestions2Auditing(request, userId);
+        } catch (Exception e) {
+            logger.error("练习册筛选条件异常", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        return responseEntity;
+    }
+
+    @RequestMapping(value = "/findQuestionListByParentId", method = RequestMethod.POST)
+    @ApiOperation(value = "查询大小题目", httpMethod = "POST",  notes = "删除题目")
+    public ResponseEntity findQuestionListByParentId(@RequestParam(name = "accessToken") String accessToken, @RequestBody ParentIdListRequest request) {
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            responseEntity = kmtQualityQuestionsService.findQuestionListByParentId(request.getParentIdList());
+        } catch (Exception e) {
+            logger.error("练习册筛选条件异常", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        return responseEntity;
+    }
+
+
+    @RequestMapping(value = "/addOrEditExerciseQuestion", method = RequestMethod.POST)
+    @ApiOperation(value = "新增、编辑题目", httpMethod = "POST", notes = "推荐题回调接口")
+    public ResponseEntity addOrEditExerciseQuestion(@RequestParam(name = "accessToken") String accessToken,
+                                                    @RequestBody AddExerciseQuestionRequest request) {
+        long start = System.currentTimeMillis();
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            String userId = tokenManager.getUserId(accessToken);
+            return kmtExerciseQuestionDealService.addOrEditExerciseQuestion(userId, request);
+        } catch (Exception e) {
+            logger.error("异常", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        logger.info(accessToken + ":" + (System.currentTimeMillis() - start));
+        return responseEntity;
+    }
+
+
+    @RequestMapping(value = "/moveExerciseQuestion", method = RequestMethod.POST)
+    @ApiOperation(value = "移动题目", httpMethod = "POST", notes = "推荐题回调接口")
+    public ResponseEntity moveExerciseQuestion(@RequestParam(name = "accessToken") String accessToken,
+                                               @RequestBody ExerciseQuestionDealRequest request) {
+        long start = System.currentTimeMillis();
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            String userId = tokenManager.getUserId(accessToken);
+            return kmtExerciseQuestionDealService.moveExerciseQuestion(userId, request);
+        } catch (Exception e) {
+            logger.error("异常", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        logger.info(accessToken + ":" + (System.currentTimeMillis() - start));
+        return responseEntity;
+    }
+
+    @RequestMapping(value = "/findEditExerciseBooks", method = RequestMethod.POST)
+    @ApiOperation(value = "题目修改查询练习册", httpMethod = "POST", notes = "题目修改查询练习册")
+    public ResponseEntity findEditExerciseBooks(@RequestParam(name = "accessToken") String accessToken,
+                                               @RequestBody ExerciseBooksEditRequest request) {
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            responseEntity = kmtExerciseQuestionDealService.findEditExerciseBooks(request);
+        } catch (Exception e) {
+            logger.error("异常", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        return responseEntity;
+    }
+
+    @RequestMapping(value = "/findEditExerciseQuestions", method = RequestMethod.POST)
+    @ApiOperation(value = "题目修改查询练习册", httpMethod = "POST", notes = "题目修改查询练习册")
+    public ResponseEntity findEditExerciseQuestions(@RequestParam(name = "accessToken") String accessToken,
+                                               @RequestBody ExerciseQuestionsEditRequest request) {
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            responseEntity = kmtExerciseQuestionDealService.findEditExerciseQuestions(request);
+
+        } catch (Exception e) {
+            logger.error("异常", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        return responseEntity;
+    }
+
+    @RequestMapping(value = "/removeQuestionNumMark", method = RequestMethod.POST)
+    @ApiOperation(value = "抹除题目题号", httpMethod = "POST", notes = "抹除题目题号")
+    public ResponseEntity removeQuestionNumMark(@RequestParam(name = "accessToken") String accessToken,
+                                               @RequestBody QuestionNumMarkRemoveVo request) {
+        long start = System.currentTimeMillis();
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            String userId = tokenManager.getUserId(accessToken);
+            responseEntity = kmtExerciseQuestionDealService.removeQuestionNumMark(userId, request);
+        } catch (Exception e) {
+            logger.error("异常", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "暂未加载到数据,请稍后重试");
+        }
+        logger.info(accessToken + ":" + (System.currentTimeMillis() - start));
+        return responseEntity;
+    }
+
+
+}

+ 51 - 0
src/main/java/com/aijia/kmt/controller/KmtExerciseQuestionListController.java

@@ -0,0 +1,51 @@
+package com.aijia.kmt.controller;
+
+import com.aijia.core.web.BaseController;
+import com.aijia.core.web.ResponseConstant;
+import com.aijia.core.web.ResponseEntity;
+import com.aijia.kmt.service.KmtExerciseQuestionListService;
+import com.aijia.kmt.service.TokenManager;
+import com.aijia.kmt.vo.ExerciseQuestionsRequest;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ *
+ * kmt练习册
+ * @author chchen
+ * 2019-01-14
+ */
+@RestController
+@RequestMapping("/api/train/kmt/exercise")
+@Api(value = "kmt练习册题目列表接口", tags = "kmt练习册题目列表接口")
+public class KmtExerciseQuestionListController extends BaseController {
+    private Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Autowired
+    private TokenManager tokenManager;
+    @Autowired
+    private KmtExerciseQuestionListService kmtExerciseQuestionListService;
+
+    @RequestMapping(value = "/getHandlingQuestionsV1", method = RequestMethod.POST)
+    @ApiOperation(value = "待加工/待审核题目", httpMethod = "POST",  notes = "待加工/待审核题目")
+    public ResponseEntity getHandlingQuestions(@RequestParam(name = "accessToken") String accessToken,
+                                               @RequestBody ExerciseQuestionsRequest request) {
+        long start = System.currentTimeMillis();
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            String userId = tokenManager.getUserId(accessToken);
+            responseEntity = kmtExerciseQuestionListService.findQuestionList(userId, request);
+        } catch (Exception e) {
+            logger.error("入参={}", request);
+            logger.error("待加工/待审核题目", e);
+            responseEntity.failure(ResponseConstant.CODE_500, "查询失败");
+        }
+        logger.info(accessToken + ":" + (System.currentTimeMillis() - start));
+        return responseEntity;
+    }
+
+}

+ 94 - 0
src/main/java/com/aijia/kmt/controller/KmtKnowledgeController.java

@@ -0,0 +1,94 @@
+package com.aijia.kmt.controller;
+
+
+import com.aijia.core.web.BaseController;
+import com.aijia.core.web.ResponseConstant;
+import com.aijia.core.web.ResponseEntity;
+import com.aijia.kmt.dto.KnowHowDTO;
+import com.aijia.kmt.service.KmtKnowledgeService;
+import com.aijia.kmt.vo.KnowledgeRequest;
+import com.aijia.kmt.vo.TestPointRequest;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * kmt知识点功能
+ * @author chchen
+ * 2019-01-14
+ */
+@Api(value = "kmt练习册知识点相关的接口", tags = "kmt练习册知识点相关的接口")
+@RestController
+@RequestMapping("/api/train/kmt/knowledge")
+public class KmtKnowledgeController extends BaseController {
+    private Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Autowired
+    private KmtKnowledgeService kmtKnowledgeService;
+
+    @ApiOperation(value = "请求知识点筛选条件")
+    @RequestMapping(value = "getKnowledgeFilter", method = RequestMethod.POST)
+    public ResponseEntity getKnowledgeFilter(@RequestParam String accessToken) {
+        long start = System.currentTimeMillis();
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            Map<String, Object> resultMap = kmtKnowledgeService.findKnowledgeFilter();
+            responseEntity.success(resultMap, "查询成功");
+        } catch (Exception e) {
+            logger.error("请求知识点筛选条件异常:", e);
+            responseEntity.failure(ResponseConstant.CODE_500,"服务器繁忙,请稍后重试");
+        }
+        logger.info(accessToken + ":" + (System.currentTimeMillis() - start));
+        return responseEntity;
+
+    }
+
+    @ApiOperation(value = "查询知识点")
+    @RequestMapping(value = "getKnowledge", method = RequestMethod.POST)
+    public ResponseEntity getKnowledge(@RequestParam String accessToken, @RequestBody KnowledgeRequest request) {
+        long start = System.currentTimeMillis();
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            List<KnowHowDTO> knowHowDTOList = new ArrayList<>();
+            if (StringUtils.isNotBlank(request.getGrade()) && request.getVersionType() != null
+                    && request.getSemester() != null  && StringUtils.isNotBlank(request.getSubject())){
+                knowHowDTOList = kmtKnowledgeService.findSortKnowledgeByCondition(request);
+            }
+            Map<String, Object> resultMap = new HashMap<>();
+            resultMap.put("list", knowHowDTOList);
+            responseEntity.success(resultMap, "查询成功");
+        } catch (Exception e) {
+            logger.error("查询知识点异常:", e);
+            responseEntity.failure(ResponseConstant.CODE_500,"服务器繁忙,请稍后重试");
+        }
+        logger.info(accessToken + ":" + (System.currentTimeMillis() - start));
+        return responseEntity;
+    }
+
+
+    @ApiOperation(value = "查询知识点列表的考点")
+    @RequestMapping(value = "getTestingPoint", method = RequestMethod.POST)
+    public ResponseEntity getTestPoint(@RequestParam String accessToken, @RequestBody TestPointRequest request) {
+        ResponseEntity responseEntity = new ResponseEntity();
+        try {
+            Map<String, Object> resultMap = new HashMap<>();
+            resultMap.put("list", kmtKnowledgeService.findDetailsListWithKd(request.getDetailIds()));
+            responseEntity.success(resultMap, "查询成功");
+        } catch (Exception e) {
+            logger.error("查询知识点列表的考点异常:", e);
+            responseEntity.failure(ResponseConstant.CODE_500,"服务器繁忙,请稍后重试");
+        }
+        return responseEntity;
+
+    }
+}

+ 181 - 0
src/main/java/com/aijia/kmt/dto/AnswerProofreadExerciseBookDTO.java

@@ -0,0 +1,181 @@
+package com.aijia.kmt.dto;
+
+import com.aijia.kmt.common.constant.KnowledgeVersion;
+import com.aijia.kmt.enums.ExerciseBookHalfBookEnum;
+import com.aijia.kmt.utils.SystemResourceLocator;
+import com.alibaba.fastjson.annotation.JSONField;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * @author yrf
+ * @date 2020/4/26 13:26
+ */
+public class AnswerProofreadExerciseBookDTO implements Serializable {
+
+    private static final long serialVersionUID = 8352235140300284629L;
+
+    private String exerciseBookId;
+    private String bookName;
+    private String subject;
+    private String grade;
+
+    private Integer version;
+
+    private String versionName;
+    private Integer semester;
+
+    /**
+     * 答案校对状态, 0未校对, 1答案正确,2答案错误, 3管理员已修改
+     */
+    @JSONField(serialize = false)
+    private Integer proofreadStatus;
+
+    private String statusText;
+
+    /**
+     * 练习册类型,0整本,1上半本,2下半本,3完成不同的页码的新版练习册
+     */
+    @JSONField(serialize = false)
+    private Integer bookType;
+
+    private String halfBook;
+
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * 最近一次答案校对为错误的时间
+     */
+    @JSONField(format = "yyyy-MM-dd")
+    private Date proofreadDate;
+
+    public String getExerciseBookId() {
+        return exerciseBookId;
+    }
+
+    public void setExerciseBookId(String exerciseBookId) {
+        this.exerciseBookId = exerciseBookId;
+    }
+
+    public String getBookName() {
+        return bookName;
+    }
+
+    public void setBookName(String bookName) {
+        this.bookName = bookName;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getGrade() {
+        return grade;
+    }
+
+    public void setGrade(String grade) {
+        this.grade = grade;
+    }
+
+    public Integer getVersion() {
+        return version;
+    }
+
+    public void setVersion(Integer version) {
+        this.version = version;
+    }
+
+    public String getVersionName() {
+        if (StringUtils.isNotBlank(versionName)) {
+            return versionName;
+        }
+
+        KnowledgeVersion knowledgeVersion = SystemResourceLocator.getBean(KnowledgeVersion.class);
+        versionName = knowledgeVersion.getVersionNameBySubjectAndVersionNum(subject, version);
+
+        return versionName;
+    }
+
+    public void setVersionName(String versionName) {
+        this.versionName = versionName;
+    }
+
+    public Integer getSemester() {
+        return semester;
+    }
+
+    public void setSemester(Integer semester) {
+        this.semester = semester;
+    }
+
+    public Integer getProofreadStatus() {
+        return proofreadStatus;
+    }
+
+    public void setProofreadStatus(Integer proofreadStatus) {
+        this.proofreadStatus = proofreadStatus;
+    }
+
+    public String getStatusText() {
+        if (StringUtils.isNotBlank(statusText)) {
+            return statusText;
+        }
+
+        if (Objects.equals(2, proofreadStatus)) {
+            statusText = "未修改";
+        } else if (Objects.equals(3, proofreadStatus)) {
+            statusText = "完成修改";
+        }
+
+        return statusText;
+    }
+
+    public void setStatusText(String statusText) {
+        this.statusText = statusText;
+    }
+
+    public Integer getBookType() {
+        return bookType;
+    }
+
+    public void setBookType(Integer bookType) {
+        this.bookType = bookType;
+    }
+
+    public String getHalfBook() {
+        if (StringUtils.isNotBlank(halfBook)) {
+            return halfBook;
+        }
+
+        halfBook = ExerciseBookHalfBookEnum.getDescriptionByCode(bookType);
+
+        return halfBook;
+    }
+
+    public void setHalfBook(String halfBook) {
+        this.halfBook = halfBook;
+    }
+
+    public Date getProofreadDate() {
+        return proofreadDate;
+    }
+
+    public void setProofreadDate(Date proofreadDate) {
+        this.proofreadDate = proofreadDate;
+    }
+}

+ 221 - 0
src/main/java/com/aijia/kmt/dto/ApplyRegisterTeacherDto.java

@@ -0,0 +1,221 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+
+public class ApplyRegisterTeacherDto implements Serializable {
+
+    private final static long serialVersionUID = 1L;
+
+
+    private String teacherId;
+
+    private  String imgUrl;
+
+    private  String  name ;
+
+    private  String school;
+
+    private  String profession;
+
+    private  String telephone;
+
+    private  String idFace;
+
+    private  String idCon;
+
+    private  String idNumber;
+
+    private  String studentNum;
+
+    private String bankName;
+
+    private  String bankFace;
+
+    private  String bankCon;
+
+    private  String cardHolder;
+
+    private  String cardNumber;
+
+    private  String bankBranch;
+
+    private String regisTime;
+
+    private String authority;
+    private int sex;
+
+    private String bankIcon;
+    /**
+     * 科目
+     */
+    private String subject;
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+    public String getBankIcon() {
+        return bankIcon;
+    }
+
+    public void setBankIcon(String bankIcon) {
+        this.bankIcon = bankIcon;
+    }
+
+    public String getAuthority() {
+        return authority;
+    }
+
+    public void setAuthority(String authority) {
+        this.authority = authority;
+    }
+
+    public String getTeacherId() {
+        return teacherId;
+    }
+
+    public void setTeacherId(String teacherId) {
+        this.teacherId = teacherId;
+    }
+
+    public String getImgUrl() {
+        return imgUrl;
+    }
+
+    public void setImgUrl(String imgUrl) {
+        this.imgUrl = imgUrl;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getSchool() {
+        return school;
+    }
+
+    public void setSchool(String school) {
+        this.school = school;
+    }
+
+    public String getProfession() {
+        return profession;
+    }
+
+    public void setProfession(String profession) {
+        this.profession = profession;
+    }
+
+    public String getTelephone() {
+        return telephone;
+    }
+
+    public void setTelephone(String telephone) {
+        this.telephone = telephone;
+    }
+
+    public String getIdFace() {
+        return idFace;
+    }
+
+    public void setIdFace(String idFace) {
+        this.idFace = idFace;
+    }
+
+    public String getIdCon() {
+        return idCon;
+    }
+
+    public void setIdCon(String idCon) {
+        this.idCon = idCon;
+    }
+
+    public String getIdNumber() {
+        return idNumber;
+    }
+
+    public void setIdNumber(String idNumber) {
+        this.idNumber = idNumber;
+    }
+
+    public String getStudentNum() {
+        return studentNum;
+    }
+
+    public void setStudentNum(String studentNum) {
+        this.studentNum = studentNum;
+    }
+
+    public String getBankName() {
+        return bankName;
+    }
+
+    public void setBankName(String bankName) {
+        this.bankName = bankName;
+    }
+
+    public String getBankFace() {
+        return bankFace;
+    }
+
+    public void setBankFace(String bankFace) {
+        this.bankFace = bankFace;
+    }
+
+    public String getBankCon() {
+        return bankCon;
+    }
+
+    public void setBankCon(String bankCon) {
+        this.bankCon = bankCon;
+    }
+
+    public String getCardHolder() {
+        return cardHolder;
+    }
+
+    public void setCardHolder(String cardHolder) {
+        this.cardHolder = cardHolder;
+    }
+
+    public String getBankBranch() {
+        return bankBranch;
+    }
+
+    public void setBankBranch(String bankBranch) {
+        this.bankBranch = bankBranch;
+    }
+
+    public String getRegisTime() {
+        return regisTime;
+    }
+
+    public void setRegisTime(String regisTime) {
+        this.regisTime = regisTime;
+    }
+
+    public String getCardNumber() {
+        return cardNumber;
+    }
+
+    public int getSex() {
+        return sex;
+    }
+
+    public void setSex(int sex) {
+        this.sex = sex;
+    }
+
+    public void setCardNumber(String cardNumber) {
+
+
+        this.cardNumber = cardNumber;
+    }
+}

+ 58 - 0
src/main/java/com/aijia/kmt/dto/BookDTO.java

@@ -0,0 +1,58 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+
+/**
+ * @author yrf
+ * @date 2019/4/15 15:18
+ */
+public class BookDTO implements Serializable {
+
+    private static final long serialVersionUID = 4697265327369191956L;
+
+    private String bookId;
+    private String bookName;
+    private String subject;
+    private Integer version;
+    private String versionName;
+
+    public String getBookId() {
+        return bookId;
+    }
+
+    public void setBookId(String bookId) {
+        this.bookId = bookId;
+    }
+
+    public String getBookName() {
+        return bookName;
+    }
+
+    public void setBookName(String bookName) {
+        this.bookName = bookName;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public Integer getVersion() {
+        return version;
+    }
+
+    public void setVersion(Integer version) {
+        this.version = version;
+    }
+
+    public String getVersionName() {
+        return versionName;
+    }
+
+    public void setVersionName(String versionName) {
+        this.versionName = versionName;
+    }
+}

+ 116 - 0
src/main/java/com/aijia/kmt/dto/CheckTeacherDetailDto.java

@@ -0,0 +1,116 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+
+/**
+ * @author yanghuan
+ * @title: CheckTeacherDetailDto
+ * @projectName ssj
+ * @description: TODO
+ * @date 2020/5/9 10:44
+ */
+public class CheckTeacherDetailDto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    private String bookId;
+
+    private  String exerciseBookId;
+
+    private  String bookName;
+
+    private  String grade;
+
+    private  int semester;
+
+    private  String courseName;
+
+    private  String versionName;
+
+    private int bookStatus;
+
+    private  String checkTime;
+
+    private  String halfBook;
+
+    public String getBookId() {
+        return bookId;
+    }
+
+    public void setBookId(String bookId) {
+        this.bookId = bookId;
+    }
+
+    public String getExerciseBookId() {
+        return exerciseBookId;
+    }
+
+    public void setExerciseBookId(String exerciseBookId) {
+        this.exerciseBookId = exerciseBookId;
+    }
+
+    public String getBookName() {
+        return bookName;
+    }
+
+    public void setBookName(String bookName) {
+        this.bookName = bookName;
+    }
+
+    public String getGrade() {
+        return grade;
+    }
+
+    public void setGrade(String grade) {
+        this.grade = grade;
+    }
+
+    public int getSemester() {
+        return semester;
+    }
+
+    public void setSemester(int semester) {
+        this.semester = semester;
+    }
+
+    public String getCourseName() {
+        return courseName;
+    }
+
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
+    }
+
+    public String getVersionName() {
+        return versionName;
+    }
+
+    public void setVersionName(String versionName) {
+        this.versionName = versionName;
+    }
+
+    public int getBookStatus() {
+        return bookStatus;
+    }
+
+    public void setBookStatus(int bookStatus) {
+        this.bookStatus = bookStatus;
+    }
+
+    public String getCheckTime() {
+        return checkTime;
+    }
+
+    public void setCheckTime(String checkTime) {
+        this.checkTime = checkTime;
+    }
+
+    public String getHalfBook() {
+        return halfBook;
+    }
+
+    public void setHalfBook(String halfBook) {
+        this.halfBook = halfBook;
+    }
+}

+ 269 - 0
src/main/java/com/aijia/kmt/dto/DistributionExerciseBookDTO.java

@@ -0,0 +1,269 @@
+package com.aijia.kmt.dto;
+
+import com.aijia.kmt.enums.ExerciseBookHalfBookEnum;
+import com.alibaba.fastjson.annotation.JSONField;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author yrf
+ * @time 2020/5/20 16:32
+ */
+public class DistributionExerciseBookDTO implements Serializable {
+
+    private static final long serialVersionUID = 8818192568415925382L;
+
+    private String exerciseBookId;
+
+    @JSONField(format = "yyyy.MM.dd")
+    private Date importDate;
+
+    private String subject;
+    private String grade;
+    private String versionName;
+    private Integer semester;
+    private String bookName;
+
+    @JSONField(serialize = false)
+    private Integer bookType;
+
+    private String halfBook;
+    private Integer unitNum;
+    private Integer courseNum;
+    private Integer questionNum;
+
+    @JSONField(serialize = false)
+    private Integer intHandleAccuracy;
+    private String handleAccuracy;
+
+    @JSONField(serialize = false)
+    private Integer intHandleAuditAccuracy;
+    private String handleAuditAccuracy;
+
+    @JSONField(serialize = false)
+    private Integer intAnalysisAccuracy;
+    private String analysisAccuracy;
+
+    private String assignedBatch;
+
+    private List<DistributionTeacherDTO> handleUserList;
+    private List<DistributionTeacherDTO> auditingUserList;
+    private List<DistributionTeacherDTO> analysisUserList;
+    private List<DistributionTeacherDTO> analysisAuditerList;
+
+    public String getExerciseBookId() {
+        return exerciseBookId;
+    }
+
+    public void setExerciseBookId(String exerciseBookId) {
+        this.exerciseBookId = exerciseBookId;
+    }
+
+    public Date getImportDate() {
+        return importDate;
+    }
+
+    public void setImportDate(Date importDate) {
+        this.importDate = importDate;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getGrade() {
+        return grade;
+    }
+
+    public void setGrade(String grade) {
+        this.grade = grade;
+    }
+
+    public String getVersionName() {
+        return versionName;
+    }
+
+    public void setVersionName(String versionName) {
+        this.versionName = versionName;
+    }
+
+    public Integer getSemester() {
+        return semester;
+    }
+
+    public void setSemester(Integer semester) {
+        this.semester = semester;
+    }
+
+    public String getBookName() {
+        return bookName;
+    }
+
+    public void setBookName(String bookName) {
+        this.bookName = bookName;
+    }
+
+    public Integer getBookType() {
+        return bookType;
+    }
+
+    public void setBookType(Integer bookType) {
+        this.bookType = bookType;
+    }
+
+    public String getHalfBook() {
+        if (StringUtils.isNotBlank(halfBook)) {
+            return halfBook;
+        }
+
+        halfBook = ExerciseBookHalfBookEnum.getDescriptionByCode(bookType);
+
+        return halfBook;
+    }
+
+    public void setHalfBook(String halfBook) {
+        this.halfBook = halfBook;
+    }
+
+    public Integer getUnitNum() {
+        return unitNum;
+    }
+
+    public void setUnitNum(Integer unitNum) {
+        this.unitNum = unitNum;
+    }
+
+    public Integer getCourseNum() {
+        return courseNum;
+    }
+
+    public void setCourseNum(Integer courseNum) {
+        this.courseNum = courseNum;
+    }
+
+    public Integer getIntHandleAccuracy() {
+        return intHandleAccuracy;
+    }
+
+    public void setIntHandleAccuracy(Integer intHandleAccuracy) {
+        this.intHandleAccuracy = intHandleAccuracy;
+    }
+
+    public String getHandleAccuracy() {
+        if (StringUtils.isBlank(handleAccuracy) && intHandleAccuracy != null) {
+            handleAccuracy = BigDecimal.valueOf(intHandleAccuracy * 0.01).setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
+        }
+        return handleAccuracy;
+    }
+
+    public void setHandleAccuracy(String handleAccuracy) {
+        this.handleAccuracy = handleAccuracy;
+    }
+
+    public Integer getIntHandleAuditAccuracy() {
+        return intHandleAuditAccuracy;
+    }
+
+    public void setIntHandleAuditAccuracy(Integer intHandleAuditAccuracy) {
+        this.intHandleAuditAccuracy = intHandleAuditAccuracy;
+    }
+
+    public String getHandleAuditAccuracy() {
+        if (StringUtils.isBlank(handleAuditAccuracy) && intHandleAuditAccuracy != null) {
+            handleAuditAccuracy = BigDecimal.valueOf(intHandleAuditAccuracy * 0.01).setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
+        }
+        return handleAuditAccuracy;
+    }
+
+    public void setHandleAuditAccuracy(String handleAuditAccuracy) {
+        this.handleAuditAccuracy = handleAuditAccuracy;
+    }
+
+    public Integer getIntAnalysisAccuracy() {
+        return intAnalysisAccuracy;
+    }
+
+    public void setIntAnalysisAccuracy(Integer intAnalysisAccuracy) {
+        this.intAnalysisAccuracy = intAnalysisAccuracy;
+    }
+
+    public String getAnalysisAccuracy() {
+        if (StringUtils.isBlank(analysisAccuracy) && intAnalysisAccuracy != null) {
+            analysisAccuracy = BigDecimal.valueOf(intAnalysisAccuracy * 0.01).setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
+        }
+        return analysisAccuracy;
+    }
+
+    public void setAnalysisAccuracy(String analysisAccuracy) {
+        this.analysisAccuracy = analysisAccuracy;
+    }
+
+    public List<DistributionTeacherDTO> getHandleUserList() {
+        if (handleUserList != null) {
+            Collections.sort(handleUserList);
+        }
+        return handleUserList;
+    }
+
+    public void setHandleUserList(List<DistributionTeacherDTO> handleUserList) {
+        this.handleUserList = handleUserList;
+    }
+
+    public List<DistributionTeacherDTO> getAuditingUserList() {
+        if (auditingUserList != null) {
+            Collections.sort(auditingUserList);
+        }
+        return auditingUserList;
+    }
+
+    public void setAuditingUserList(List<DistributionTeacherDTO> auditingUserList) {
+        this.auditingUserList = auditingUserList;
+    }
+
+    public List<DistributionTeacherDTO> getAnalysisUserList() {
+        if (analysisUserList != null) {
+            Collections.sort(analysisUserList);
+        }
+        return analysisUserList;
+    }
+
+    public void setAnalysisUserList(List<DistributionTeacherDTO> analysisUserList) {
+        this.analysisUserList = analysisUserList;
+    }
+
+    public List<DistributionTeacherDTO> getAnalysisAuditerList() {
+        if (analysisAuditerList != null) {
+            Collections.sort(analysisAuditerList);
+        }
+        return analysisAuditerList;
+    }
+
+    public void setAnalysisAuditerList(List<DistributionTeacherDTO> analysisAuditerList) {
+        this.analysisAuditerList = analysisAuditerList;
+    }
+
+    public String getAssignedBatch() {
+        return assignedBatch;
+    }
+
+    public void setAssignedBatch(String assignedBatch) {
+        this.assignedBatch = assignedBatch;
+    }
+
+    public Integer getQuestionNum() {
+        return questionNum;
+    }
+
+    public void setQuestionNum(Integer questionNum) {
+        this.questionNum = questionNum;
+    }
+}

+ 98 - 0
src/main/java/com/aijia/kmt/dto/DistributionTeacherDTO.java

@@ -0,0 +1,98 @@
+package com.aijia.kmt.dto;
+
+import com.alibaba.fastjson.annotation.JSONField;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author yrf
+ * @time 2020/5/20 16:57
+ */
+public class DistributionTeacherDTO implements Serializable, Comparable<DistributionTeacherDTO> {
+
+    private static final long serialVersionUID = -2974341943777847448L;
+
+    private String teacherId;
+    private String teacherName;
+    private Integer salaryGiven;
+
+    @JSONField(format = "yyyy.MM.dd")
+    private Date salaryGivenTime;
+
+    private Date lastSubmitTime;
+
+    @JSONField(serialize = false)
+    private Date createTime;
+
+    public String getTeacherId() {
+        return teacherId;
+    }
+
+    public void setTeacherId(String teacherId) {
+        this.teacherId = teacherId;
+    }
+
+    public String getTeacherName() {
+        return teacherName;
+    }
+
+    public void setTeacherName(String teacherName) {
+        this.teacherName = teacherName;
+    }
+
+    public Integer getSalaryGiven() {
+        return salaryGiven;
+    }
+
+    public void setSalaryGiven(Integer salaryGiven) {
+        this.salaryGiven = salaryGiven;
+    }
+
+    public Date getSalaryGivenTime() {
+        return salaryGivenTime;
+    }
+
+    public void setSalaryGivenTime(Date salaryGivenTime) {
+        this.salaryGivenTime = salaryGivenTime;
+    }
+
+    public Date getLastSubmitTime() {
+        return lastSubmitTime;
+    }
+
+    public void setLastSubmitTime(Date lastSubmitTime) {
+        this.lastSubmitTime = lastSubmitTime;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    @Override
+    public int compareTo(DistributionTeacherDTO o) {
+        if (this.createTime == null) {
+            return -1;
+        }
+        if (o == null) {
+            return -1;
+        }
+        if (this == o) {
+            return 0;
+        }
+        if (o.getCreateTime() == null) {
+            return 1;
+        }
+        if (o.getCreateTime().getTime() > this.getCreateTime().getTime()){
+            return 1;
+        } else if (o.getCreateTime().getTime() < this.getCreateTime().getTime()){
+            return -1;
+        } else{
+            return 0;
+        }
+    }
+}

+ 119 - 0
src/main/java/com/aijia/kmt/dto/Exercise1Dto.java

@@ -0,0 +1,119 @@
+package com.aijia.kmt.dto;
+
+
+import com.aijia.kmt.po.KmtExerciseBook;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+
+/**
+ * @author Mount Liu
+ * @date 2020/4/14
+ */
+public class Exercise1Dto extends KmtExerciseBook {
+
+    private static final long serialVersionUID = 1L;
+    /**
+     * 练习册id
+     */
+    private String exerciseBookId;
+    /**
+     * 科目
+     */
+    private String subject;
+    /**
+     * 老师名字
+     */
+    private String teacherName;
+    /**
+     * 使用年份,同bookYear
+     */
+    private int useYear;
+
+    private String publishDate;
+
+    private String bookQuestionPdf;
+
+    private String bookAnswerPdf;
+
+    private int uploadType;
+
+    /**
+     * 分配校对时间
+     * @return
+     */
+    private String allotCheckTime;
+
+    public String getAllotCheckTime() {
+        return allotCheckTime;
+    }
+
+    public void setAllotCheckTime(String allotCheckTime) {
+        this.allotCheckTime = allotCheckTime;
+    }
+
+    public int getUseYear() {
+        return useYear;
+    }
+
+    public void setUseYear(int useYear) {
+        this.useYear = useYear;
+    }
+
+    public String getTeacherName() {
+        return teacherName;
+    }
+
+    public void setTeacherName(String teacherName) {
+        this.teacherName = teacherName;
+    }
+
+    public String getExerciseBookId() {
+        return exerciseBookId;
+    }
+
+    public void setExerciseBookId(String exerciseBookId) {
+        this.exerciseBookId = exerciseBookId;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getPublishDate() {
+        return publishDate;
+    }
+
+    public void setPublishDate(String publishDate) {
+        this.publishDate = publishDate;
+    }
+
+    public String getBookQuestionPdf() {
+        return bookQuestionPdf;
+    }
+
+    public void setBookQuestionPdf(String bookQuestionPdf) {
+        this.bookQuestionPdf = bookQuestionPdf;
+    }
+
+    public String getBookAnswerPdf() {
+        return bookAnswerPdf;
+    }
+
+    public void setBookAnswerPdf(String bookAnswerPdf) {
+        this.bookAnswerPdf = bookAnswerPdf;
+    }
+
+    public int getUploadType() {
+        if (StringUtils.isBlank(this.getBookQuestionPdf()) && StringUtils.isBlank(this.getBookAnswerPdf())){
+            return 2;
+        }
+        return 1;
+    }
+
+    public void setUploadType(int uploadType) {
+        this.uploadType = uploadType;
+    }
+}

+ 295 - 0
src/main/java/com/aijia/kmt/dto/Exercise2Dto.java

@@ -0,0 +1,295 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author Mount Liu
+ * @date 2020/4/14
+ */
+public class Exercise2Dto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 练习册完整封面页
+     */
+    private String url1;
+    /**
+     * 含印刷版次页
+     */
+    private String url2;
+    /**
+     * 练习册名
+     */
+    private String bookName;
+    /**
+     * 出版社
+     */
+    private String press;
+    /**
+     * 科目
+     */
+    private String subject;
+    /**
+     * 年级
+     */
+    private String grade;
+    /**
+     * 版本
+     */
+    private Integer version;
+    /**
+     * 版本名称
+     */
+    private String versionName;
+    /**
+     * 上下册(1:上,2:下)
+     */
+    private Integer semester;
+    /**
+     * 印刷年份
+     */
+    private String printYear;
+    /**
+     * 使用年份
+     */
+    private String useYear;
+    /**
+     * 状态
+     */
+    private String status;
+    /**
+     * 关联机构数
+     */
+    private int orgNums;
+    /**
+     * 对接进度
+     */
+    private String progress;
+    /**
+     * 优先级
+     */
+    private String priority;
+    /**
+     * 被识别次数
+     */
+    private int identifiedNums;
+    /**
+     * 最近编辑人
+     */
+    private String editName;
+    /**
+     * 最近编辑时间
+     */
+    private String updateTime;
+    /**
+     * 关联机构
+     */
+    private List<Library> libList;
+    /**
+     * 练习册类型(0整本,1上半本,2下半本,3完成不同的页码的新版练习册)
+     */
+    private int bookType;
+
+    /**
+     * 归属批次
+     */
+    private String assignedBatch;
+
+    public int getBookType() {
+        return bookType;
+    }
+
+    public void setBookType(int bookType) {
+        this.bookType = bookType;
+    }
+
+    public class Library implements Serializable {
+        private static final long serialVersionUID = 1L;
+        /**
+         * 机构id
+         */
+        private String libId;
+        /**
+         * 机构名称
+         */
+        private String libName;
+
+        public String getLibId() {
+            return libId;
+        }
+
+        public void setLibId(String libId) {
+            this.libId = libId;
+        }
+
+        public String getLibName() {
+            return libName;
+        }
+
+        public void setLibName(String libName) {
+            this.libName = libName;
+        }
+    }
+
+    public String getUrl1() {
+        return url1;
+    }
+
+    public void setUrl1(String url1) {
+        this.url1 = url1;
+    }
+
+    public String getUrl2() {
+        return url2;
+    }
+
+    public void setUrl2(String url2) {
+        this.url2 = url2;
+    }
+
+    public String getBookName() {
+        return bookName;
+    }
+
+    public void setBookName(String bookName) {
+        this.bookName = bookName;
+    }
+
+    public String getPress() {
+        return press;
+    }
+
+    public void setPress(String press) {
+        this.press = press;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getGrade() {
+        return grade;
+    }
+
+    public void setGrade(String grade) {
+        this.grade = grade;
+    }
+
+    public Integer getVersion() {
+        return version;
+    }
+
+    public void setVersion(Integer version) {
+        this.version = version;
+    }
+
+    public String getVersionName() {
+        return versionName;
+    }
+
+    public void setVersionName(String versionName) {
+        this.versionName = versionName;
+    }
+
+    public Integer getSemester() {
+        return semester;
+    }
+
+    public void setSemester(Integer semester) {
+        this.semester = semester;
+    }
+
+    public String getPrintYear() {
+        return printYear;
+    }
+
+    public void setPrintYear(String printYear) {
+        this.printYear = printYear;
+    }
+
+    public String getUseYear() {
+        return useYear;
+    }
+
+    public void setUseYear(String useYear) {
+        this.useYear = useYear;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public int getOrgNums() {
+        return orgNums;
+    }
+
+    public void setOrgNums(int orgNums) {
+        this.orgNums = orgNums;
+    }
+
+    public String getProgress() {
+        return progress;
+    }
+
+    public void setProgress(String progress) {
+        this.progress = progress;
+    }
+
+    public String getPriority() {
+        return priority;
+    }
+
+    public void setPriority(String priority) {
+        this.priority = priority;
+    }
+
+    public int getIdentifiedNums() {
+        return identifiedNums;
+    }
+
+    public void setIdentifiedNums(int identifiedNums) {
+        this.identifiedNums = identifiedNums;
+    }
+
+    public String getEditName() {
+        return editName;
+    }
+
+    public void setEditName(String editName) {
+        this.editName = editName;
+    }
+
+    public String getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(String updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public List<Library> getLibList() {
+        return libList;
+    }
+
+    public void setLibList(List<Library> libList) {
+        this.libList = libList;
+    }
+
+    public String getAssignedBatch() {
+        return assignedBatch;
+    }
+
+    public void setAssignedBatch(String assignedBatch) {
+        this.assignedBatch = assignedBatch;
+    }
+}

+ 136 - 0
src/main/java/com/aijia/kmt/dto/Exercise3Dto.java

@@ -0,0 +1,136 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+
+/**
+ * @author Mount Liu
+ * @date 2020/4/26
+ */
+public class Exercise3Dto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+    /**
+     * 练习册id
+     */
+    private String exerciseBookId;
+    /**
+     * 科目
+     */
+    private String subject;
+    /**
+     * 0整本,1:上半,2下半
+     */
+    private int bookType;
+    /**
+     * 练习册名称
+     */
+    private String bookName;
+    /**
+     * 年级
+     */
+    private String grade;
+    /**
+     * 版本
+     */
+    private String versionName;
+    /**
+     * 上下册,1上2下
+     */
+    private int semester;
+
+    /**
+     * 题目数量
+     */
+    private int questionNum;
+
+    /**
+     * 练习册发布时间
+     * @return
+     */
+    private String publishDate;
+    /**
+     * 分配校对时间
+     * @return
+     */
+    private String allotCheckTime;
+
+    public String getAllotCheckTime() {
+        return allotCheckTime;
+    }
+
+    public void setAllotCheckTime(String allotCheckTime) {
+        this.allotCheckTime = allotCheckTime;
+    }
+
+    public String getPublishDate() {
+        return publishDate;
+    }
+
+    public void setPublishDate(String publishDate) {
+        this.publishDate = publishDate;
+    }
+
+    public String getExerciseBookId() {
+        return exerciseBookId;
+    }
+
+    public void setExerciseBookId(String exerciseBookId) {
+        this.exerciseBookId = exerciseBookId;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public int getBookType() {
+        return bookType;
+    }
+
+    public void setBookType(int bookType) {
+        this.bookType = bookType;
+    }
+
+    public String getBookName() {
+        return bookName;
+    }
+
+    public void setBookName(String bookName) {
+        this.bookName = bookName;
+    }
+
+    public String getGrade() {
+        return grade;
+    }
+
+    public void setGrade(String grade) {
+        this.grade = grade;
+    }
+
+    public String getVersionName() {
+        return versionName;
+    }
+
+    public void setVersionName(String versionName) {
+        this.versionName = versionName;
+    }
+
+    public int getSemester() {
+        return semester;
+    }
+
+    public void setSemester(int semester) {
+        this.semester = semester;
+    }
+
+    public int getQuestionNum() {
+        return questionNum;
+    }
+
+    public void setQuestionNum(int questionNum) {
+        this.questionNum = questionNum;
+    }
+}

+ 36 - 0
src/main/java/com/aijia/kmt/dto/Exercise4Dto.java

@@ -0,0 +1,36 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author yanghuan
+ * @title: Exercise4Dto
+ * @projectName ssj
+ * @description: TODO
+ * @date 2020/4/28 15:38
+ */
+public class Exercise4Dto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private String teacherName;
+
+    private List<Exercise3Dto> exercise3DtoList;
+
+    public String getTeacherName() {
+        return teacherName;
+    }
+
+    public void setTeacherName(String teacherName) {
+        this.teacherName = teacherName;
+    }
+
+    public List<Exercise3Dto> getExercise3DtoList() {
+        return exercise3DtoList;
+    }
+
+    public void setExercise3DtoList(List<Exercise3Dto> exercise3DtoList) {
+        this.exercise3DtoList = exercise3DtoList;
+    }
+}

+ 59 - 0
src/main/java/com/aijia/kmt/dto/Exercise5Dto.java

@@ -0,0 +1,59 @@
+package com.aijia.kmt.dto;
+
+/**
+ * @author Mount Liu
+ * @date 2020/5/11
+ */
+public class Exercise5Dto extends Exercise3Dto {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 完成时间
+     */
+    private String checkedTime;
+    /**
+     * 校对老师
+     */
+    private String teacherName;
+    /**
+     * 使用年份
+     */
+    private int useYear;
+    /**
+     * ai打回重导标记,0无重导,1有重导
+     */
+    private int aiRollbackImport;
+
+    public int getAiRollbackImport() {
+        return aiRollbackImport;
+    }
+
+    public void setAiRollbackImport(int aiRollbackImport) {
+        this.aiRollbackImport = aiRollbackImport;
+    }
+
+    public int getUseYear() {
+        return useYear;
+    }
+
+    public void setUseYear(int useYear) {
+        this.useYear = useYear;
+    }
+
+    public String getCheckedTime() {
+        return checkedTime;
+    }
+
+    public void setCheckedTime(String checkedTime) {
+        this.checkedTime = checkedTime;
+    }
+
+    public String getTeacherName() {
+        return teacherName;
+    }
+
+    public void setTeacherName(String teacherName) {
+        this.teacherName = teacherName;
+    }
+}

+ 34 - 0
src/main/java/com/aijia/kmt/dto/ExerciseBaseDto.java

@@ -0,0 +1,34 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+
+/**
+ * @Author: chchen
+ * @Description
+ * @Date Create in 20:40 2019/12/9
+ * @Modified By
+ */
+public class ExerciseBaseDto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private String type;
+
+    private String name;
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

+ 40 - 0
src/main/java/com/aijia/kmt/dto/ExerciseBookBaseDto.java

@@ -0,0 +1,40 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+
+public class ExerciseBookBaseDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    protected String id;
+
+    protected String name;
+
+    public ExerciseBookBaseDto () {
+
+    }
+
+    public ExerciseBookBaseDto (String name) {
+        this.name = name;
+    }
+
+    public ExerciseBookBaseDto (String id, String name) {
+        this.id = id;
+        this.name = name;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

+ 84 - 0
src/main/java/com/aijia/kmt/dto/ExerciseBookCountDTO.java

@@ -0,0 +1,84 @@
+package com.aijia.kmt.dto;
+
+import com.aijia.kmt.enums.ExerciseBookStatusEnum;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.Serializable;
+
+/**
+ * @author yrf
+ * @description
+ * @time 2020/4/15 11:15
+ */
+public class ExerciseBookCountDTO implements Serializable {
+
+    private static final long serialVersionUID = -7835795022709907714L;
+
+
+    /**
+     * status : 0
+     * statusText : 0打回AI
+     * totalCount : 20
+     * chineseCount : 8
+     * mathCount : 8
+     * englishCount : 4
+     */
+
+    private Integer status;
+    private String statusText;
+    private Integer totalCount;
+    private Integer chineseCount;
+    private Integer mathCount;
+    private Integer englishCount;
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    public String getStatusText() {
+        if (StringUtils.isBlank(statusText)) {
+            this.statusText = ExerciseBookStatusEnum.getDescriptionByCode(this.status);
+        }
+        return statusText;
+    }
+
+    public void setStatusText(String statusText) {
+        this.statusText = statusText;
+    }
+
+    public Integer getTotalCount() {
+        return totalCount;
+    }
+
+    public void setTotalCount(Integer totalCount) {
+        this.totalCount = totalCount;
+    }
+
+    public Integer getChineseCount() {
+        return chineseCount;
+    }
+
+    public void setChineseCount(Integer chineseCount) {
+        this.chineseCount = chineseCount;
+    }
+
+    public Integer getMathCount() {
+        return mathCount;
+    }
+
+    public void setMathCount(Integer mathCount) {
+        this.mathCount = mathCount;
+    }
+
+    public Integer getEnglishCount() {
+        return englishCount;
+    }
+
+    public void setEnglishCount(Integer englishCount) {
+        this.englishCount = englishCount;
+    }
+}

+ 78 - 0
src/main/java/com/aijia/kmt/dto/ExerciseBookCountSubjectDetailDTO.java

@@ -0,0 +1,78 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+
+/**
+ * @description
+ * @author yrf
+ * @time 2020/3/23 17:36
+ */
+public class ExerciseBookCountSubjectDetailDTO implements Serializable {
+
+    private static final long serialVersionUID = -2910322613090385380L;
+
+    private String bookId;
+    private String bookName;
+    private Integer bookYear;
+    private String subject;
+    private String grade;
+    private int semester;
+
+    private int bookType;
+
+    public String getBookId() {
+        return bookId;
+    }
+
+    public void setBookId(String bookId) {
+        this.bookId = bookId;
+    }
+
+    public String getBookName() {
+        return bookName;
+    }
+
+    public void setBookName(String bookName) {
+        this.bookName = bookName;
+    }
+
+    public Integer getBookYear() {
+        return bookYear;
+    }
+
+    public void setBookYear(Integer bookYear) {
+        this.bookYear = bookYear;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getGrade() {
+        return grade;
+    }
+
+    public void setGrade(String grade) {
+        this.grade = grade;
+    }
+
+    public int getSemester() {
+        return semester;
+    }
+
+    public void setSemester(int semester) {
+        this.semester = semester;
+    }
+
+    public int getBookType() {
+        return bookType;
+    }
+
+    public void setBookType(int bookType) {
+        this.bookType = bookType;
+    }
+}

+ 62 - 0
src/main/java/com/aijia/kmt/dto/ExerciseBookCourseClassDto.java

@@ -0,0 +1,62 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ExerciseBookCourseClassDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String courseId = "";
+
+    private String name = "";
+
+    private String parentId = "";
+
+    private List<ExerciseQuetionDto> list = new ArrayList<>();
+
+    public ExerciseBookCourseClassDto () {
+
+    }
+
+    public ExerciseBookCourseClassDto (String courseId, String name){
+        this.courseId = courseId;
+        this.name = name;
+    }
+
+    public String getCourseId() {
+        return courseId;
+    }
+
+    public void setCourseId(String courseId) {
+        this.courseId = courseId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public List<ExerciseQuetionDto> getList() {
+        return list;
+    }
+
+    public void setList(List<ExerciseQuetionDto> list) {
+        this.list = list;
+    }
+
+    public void addExerciseQuestion (ExerciseQuetionDto question){
+        this.list.add(question);
+    }
+
+    public String getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(String parentId) {
+        this.parentId = parentId;
+    }
+}

+ 111 - 0
src/main/java/com/aijia/kmt/dto/ExerciseBookCourseDTO.java

@@ -0,0 +1,111 @@
+package com.aijia.kmt.dto;
+
+import com.aijia.kmt.common.constant.KnowledgeVersion;
+import com.alibaba.fastjson.annotation.JSONField;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+public class ExerciseBookCourseDTO implements Serializable {
+
+    private static final long serialVersionUID = -3341421097866292443L;
+
+    private String id;
+    private String name;
+    @JSONField(serialize=false)
+    private Integer version;
+    @JSONField(serialize=false)
+    private String courseName;
+    @JSONField(serialize=false)
+    private String grade;
+    @JSONField(serialize=false)
+    private Integer semester;
+    @JSONField(serialize=false)
+    private String unit;
+    @JSONField(serialize=false)
+    private String period;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        if (StringUtils.isBlank(name)) {
+            StringBuilder nameSb = new StringBuilder();
+
+            nameSb.append(courseName);
+
+            KnowledgeVersion knowledgeVersion = new KnowledgeVersion();
+            knowledgeVersion.init();
+            nameSb.append(knowledgeVersion.getVersionNameBySubjectAndVersionNum(courseName, version));
+
+            nameSb.append(grade);
+
+            if (Objects.equals(1, semester)) {
+                nameSb.append("上册");
+            } else {
+                nameSb.append("下册");
+            }
+
+            nameSb.append(unit);
+            nameSb.append(period);
+
+            name = nameSb.toString();
+        }
+
+        return name;
+    }
+
+    public String getCourseName() {
+        return courseName;
+    }
+
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
+    }
+
+    public Integer getVersion() {
+        return version;
+    }
+
+    public void setVersion(Integer version) {
+        this.version = version;
+    }
+
+    public String getGrade() {
+        return grade;
+    }
+
+    public void setGrade(String grade) {
+        this.grade = grade;
+    }
+
+    public Integer getSemester() {
+        return semester;
+    }
+
+    public void setSemester(Integer semester) {
+        this.semester = semester;
+    }
+
+    public String getUnit() {
+        return unit;
+    }
+
+    public void setUnit(String unit) {
+        this.unit = unit;
+    }
+
+    public String getPeriod() {
+        return period;
+    }
+
+    public void setPeriod(String period) {
+        this.period = period;
+    }
+}

+ 191 - 0
src/main/java/com/aijia/kmt/dto/ExerciseBookDto.java

@@ -0,0 +1,191 @@
+package com.aijia.kmt.dto;
+
+import com.aijia.kmt.dto.exercise.ExerciseBookYearDto;
+import com.alibaba.fastjson.annotation.JSONField;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ExerciseBookDto extends ExerciseBookBaseDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private String exerciseBookId;
+
+    private String grade;
+
+    private String subject;
+
+    private int semester;
+
+    private ExerciseBookBaseDto version;
+
+    private int versionType;
+
+    private int index;
+
+    private int bookType;
+
+    private int bookYear;
+
+    private int aiRollbackImport;
+
+    public int getAiRollbackImport() {
+        return aiRollbackImport;
+    }
+
+    public void setAiRollbackImport(int aiRollbackImport) {
+        this.aiRollbackImport = aiRollbackImport;
+    }
+
+    private List<ExerciseBookYearDto> bookYearList = new ArrayList<>();
+
+    private List<ExerciseBookUnitDto> units = new ArrayList<>();
+
+    public String getExerciseBookId() {
+        return exerciseBookId;
+    }
+
+    public void setExerciseBookId(String exerciseBookId) {
+        this.exerciseBookId = exerciseBookId;
+    }
+
+    public ExerciseBookDto (){
+
+    }
+
+    public ExerciseBookDto(String id, String name) {
+        this.id = id;
+        this.name = name;
+    }
+
+    public List<ExerciseBookUnitDto> getUnits() {
+        Collections.reverse(this.units);
+        return this.units;
+    }
+
+    public void setUnits(List<ExerciseBookUnitDto> units) {
+        this.units = units;
+    }
+
+    public String getGrade() {
+        return grade;
+    }
+
+    public void setGrade(String grade) {
+        this.grade = grade;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public int getSemester() {
+        return semester;
+    }
+
+    public void setSemester(int semester) {
+        this.semester = semester;
+    }
+
+    public ExerciseBookBaseDto getVersion() {
+        return version;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+
+    public void setVersion(ExerciseBookBaseDto version) {
+        this.version = version;
+    }
+
+    @JSONField(serialize=false)
+    public int getVersionType() {
+        return versionType;
+    }
+
+    public void setVersionType(int versionType) {
+        this.versionType = versionType;
+    }
+
+    @JSONField(serialize=false)
+    public int getBookType() {
+        return bookType;
+    }
+
+    public void setBookType(int bookType) {
+        this.bookType = bookType;
+    }
+
+    @JSONField(serialize=false)
+    public int getBookYear() {
+        return bookYear;
+    }
+
+    public void setBookYear(int bookYear) {
+        this.bookYear = bookYear;
+    }
+
+    public boolean isContainBookYear (int bookYear){
+        boolean result = false;
+        for (ExerciseBookYearDto bookYearDto : this.bookYearList){
+            if (bookYearDto.getBookYear() == bookYear){
+                result = true;
+                break;
+            }
+        }
+        return result;
+    }
+
+    public void setBookYearList(List<ExerciseBookYearDto> bookYearList) {
+        this.bookYearList = bookYearList;
+    }
+    public List<ExerciseBookYearDto> getBookYearList (){
+        return bookYearList;
+    }
+
+    public void addBookYear (int bookYear, int bookType, String exerciseBookId, int type){
+        ExerciseBookYearDto dto = new ExerciseBookYearDto(bookYear);
+        dto.addBookType(bookType, exerciseBookId);
+        if (type == 3){
+            dto.addBookPartType(bookType);
+        }
+        this.bookYearList.add(dto);
+    }
+
+
+    public void addUnit(String unitId, String unitName, String courseId, String courseName){
+        boolean isExist = false;
+
+        //新建课时对象
+        ExerciseBookBaseDto course = new ExerciseBookBaseDto();
+        course.setId(courseId);
+        course.setName(courseName);
+
+        for (ExerciseBookUnitDto unit : this.units){
+            if (unit.getId().equals(unitId)){
+                isExist = true;
+                unit.addPeriod(course);
+            }
+        }
+
+        //如果单元不存在,需要新增单元
+        if (!isExist){
+            ExerciseBookUnitDto unit = new ExerciseBookUnitDto();
+            unit.setId(unitId);
+            unit.setName(unitName);
+            unit.addPeriod(course);
+            this.units.add(0, unit);
+        }
+    }
+}

+ 34 - 0
src/main/java/com/aijia/kmt/dto/ExerciseBookUnitDto.java

@@ -0,0 +1,34 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ExerciseBookUnitDto extends ExerciseBookBaseDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private List<ExerciseBookBaseDto> periods = new ArrayList<>();
+
+    private int index;
+
+    public List<ExerciseBookBaseDto> getPeriods() {
+        return periods;
+    }
+
+    public void setPeriod(List<ExerciseBookBaseDto> periods) {
+        this.periods = periods;
+    }
+
+    public void addPeriod (ExerciseBookBaseDto period){
+        this.periods.add(period);
+    }
+
+
+    public int getIndex() {
+        return index;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+}

+ 56 - 0
src/main/java/com/aijia/kmt/dto/ExerciseDistributionCountDTO.java

@@ -0,0 +1,56 @@
+package com.aijia.kmt.dto;
+
+import com.alibaba.fastjson.annotation.JSONField;
+
+import java.io.Serializable;
+
+/**
+ * @author yrf
+ * @time 2020/5/20 14:26
+ */
+public class ExerciseDistributionCountDTO implements Serializable {
+
+    private static final long serialVersionUID = -3774170751213051880L;
+
+    private Integer notDistributedExerciseBookCount;
+    private Integer distributedExerciseBookCount;
+
+    @JSONField(serialize = false)
+    private Integer totalExerciseBookCount;
+
+    public Integer getNotDistributedExerciseBookCount() {
+        return notDistributedExerciseBookCount;
+    }
+
+    public void setNotDistributedExerciseBookCount(Integer notDistributedExerciseBookCount) {
+        this.notDistributedExerciseBookCount = notDistributedExerciseBookCount;
+    }
+
+    public Integer getDistributedExerciseBookCount() {
+        if (distributedExerciseBookCount != null) {
+            return distributedExerciseBookCount;
+        }
+
+        if (totalExerciseBookCount == null || totalExerciseBookCount < 1) {
+            distributedExerciseBookCount = 0;
+        } else if (notDistributedExerciseBookCount == null) {
+            distributedExerciseBookCount = totalExerciseBookCount;
+        } else {
+            distributedExerciseBookCount = totalExerciseBookCount - notDistributedExerciseBookCount;
+        }
+
+        return distributedExerciseBookCount;
+    }
+
+    public void setDistributedExerciseBookCount(Integer distributedExerciseBookCount) {
+        this.distributedExerciseBookCount = distributedExerciseBookCount;
+    }
+
+    public Integer getTotalExerciseBookCount() {
+        return totalExerciseBookCount;
+    }
+
+    public void setTotalExerciseBookCount(Integer totalExerciseBookCount) {
+        this.totalExerciseBookCount = totalExerciseBookCount;
+    }
+}

+ 55 - 0
src/main/java/com/aijia/kmt/dto/ExercisePriorityDto.java

@@ -0,0 +1,55 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+
+/**
+ * @author yanghuan
+ * @title: ExercisePriorityDto
+ * @projectName ssj
+ * @description: TODO
+ * @date 2020/4/22 17:32
+ */
+public class ExercisePriorityDto implements Serializable {
+
+    private static final long serialVersionUID = -2910322613090385380L;
+
+    private String id;
+
+    private String exerciseBookId;
+
+    private String lib;
+
+    private int signService;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getExerciseBookId() {
+        return exerciseBookId;
+    }
+
+    public void setExerciseBookId(String exerciseBookId) {
+        this.exerciseBookId = exerciseBookId;
+    }
+
+    public String getLib() {
+        return lib;
+    }
+
+    public void setLib(String lib) {
+        this.lib = lib;
+    }
+
+    public int getSignService() {
+        return signService;
+    }
+
+    public void setSignService(int signService) {
+        this.signService = signService;
+    }
+}

+ 32 - 0
src/main/java/com/aijia/kmt/dto/ExerciseQuestionAnswer4CorrectDTO.java

@@ -0,0 +1,32 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author yrf
+ * @date 2019/4/10 17:37
+ */
+public class ExerciseQuestionAnswer4CorrectDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private String bigQuestionIndex;
+    private List<ExerciseQuestionDto> questionList;
+
+    public String getBigQuestionIndex() {
+        return bigQuestionIndex;
+    }
+
+    public void setBigQuestionIndex(String bigQuestionIndex) {
+        this.bigQuestionIndex = bigQuestionIndex;
+    }
+
+    public List<ExerciseQuestionDto> getQuestionList() {
+        return questionList;
+    }
+
+    public void setQuestionList(List<ExerciseQuestionDto> questionList) {
+        this.questionList = questionList;
+    }
+}

+ 25 - 0
src/main/java/com/aijia/kmt/dto/ExerciseQuestionAnswerDto.java

@@ -0,0 +1,25 @@
+package com.aijia.kmt.dto;
+
+import java.io.Serializable;
+
+public class ExerciseQuestionAnswerDto extends ExerciseBookBaseDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private int selectedType;
+
+    public ExerciseQuestionAnswerDto () {
+
+    }
+
+    public ExerciseQuestionAnswerDto(String name) {
+        super(name);
+    }
+
+    public int getSelectedType() {
+        return selectedType;
+    }
+
+    public void setSelectedType(int selectedType) {
+        this.selectedType = selectedType;
+    }
+}

+ 174 - 0
src/main/java/com/aijia/kmt/dto/ExerciseQuestionDto.java

@@ -0,0 +1,174 @@
+package com.aijia.kmt.dto;
+
+import com.aijia.kmt.dto.exercise.ExerciseQuestionAnswerSpace;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.annotation.JSONField;
+import org.apache.commons.collections4.CollectionUtils;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ExerciseQuestionDto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private String questionId;
+    private String bigQuestionIndex = "";
+    private String smallQuestionIndex;
+    private String optionAnswer;
+    private String bookCourseId = "";
+    private String answerJson;
+    private Integer dealStatus;
+    private List<ExerciseQuestionAnswerDto> answers = new ArrayList<>();
+    private List<List<ExerciseQuestionAnswerSpace>> json = new ArrayList<List<ExerciseQuestionAnswerSpace>>();
+    private List<ExerciseQuestionAnswerSpace> answerJsonV1 = new ArrayList<>();
+
+    public Integer getDealStatus() {
+		return dealStatus;
+	}
+	public void setDealStatus(Integer dealStatus) {
+		this.dealStatus = dealStatus;
+	}
+	public String getQuestionId() {
+        return questionId;
+    }
+    public void setQuestionId(String questionId) {
+        this.questionId = questionId;
+    }
+    @JSONField(serialize=false)
+    public String getBigQuestionIndex() {
+        return bigQuestionIndex;
+    }
+
+    public void setBigQuestionIndex(String bigQuestionIndex) {
+        this.bigQuestionIndex = bigQuestionIndex;
+    }
+
+    public String getSmallQuestionIndex() {
+        return smallQuestionIndex;
+    }
+
+    public void setSmallQuestionIndex(String smallQuestionIndex) {
+        //如果小题号为0或者(0)则设置为空字符串
+        if("0".equals(smallQuestionIndex) || "(0)".equals(smallQuestionIndex)) {
+            this.smallQuestionIndex = "";
+        }else {
+            this.smallQuestionIndex = smallQuestionIndex;
+        }
+    }
+
+    @JSONField(serialize=false)
+    public String getBookCourseId() {
+        return bookCourseId;
+    }
+
+    public void setBookCourseId(String bookCourseId) {
+        this.bookCourseId = bookCourseId;
+    }
+
+    @JSONField(serialize=false)
+    public String getOptionAnswer() {
+        return optionAnswer;
+    }
+
+    public void setOptionAnswer(String optionAnswer) {
+        this.optionAnswer = optionAnswer;
+//        if (StringUtil.isNotBlank(optionAnswer)){
+//            String[] answer = optionAnswer.split("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|#&");
+//            this.addAnswers((Arrays.asList(answer)));
+//        }
+    }
+
+    public List<ExerciseQuestionAnswerDto> getAnswers() {
+        return answers;
+    }
+    public void addAnswers (List<String> answers) {
+        if (answers != null){
+            for (String an : answers){
+                ExerciseQuestionAnswerDto base = new ExerciseQuestionAnswerDto(an);
+                this.answers.add(base);
+            }
+        }
+    }
+
+    @JSONField(serialize=false)
+    public String getAnswerJson() {
+        return this.answerJson;
+    }
+
+    public void setAnswerJson(String answerJson) {
+        this.answerJson = answerJson;
+        List<ExerciseQuestionAnswerSpace> questionAnswers = JSON.parseArray(answerJson, ExerciseQuestionAnswerSpace.class);
+        int index = 1;
+        if (questionAnswers != null && questionAnswers.size() > 0) {
+            for (ExerciseQuestionAnswerSpace questionAnswer : questionAnswers) {
+                questionAnswer.setIndex(index);
+                index++;
+            }
+            this.answerJsonV1 = questionAnswers;
+            this.json.add(questionAnswers);
+        }
+    }
+
+    /**
+     * 设置空的选择类型
+     * @param index
+     * @param type
+     */
+    public void setAnswerSelectedType (int index, int type){
+        if (this.json != null && this.json.size() >0){
+            for (List<ExerciseQuestionAnswerSpace> spaces : this.json){
+                for (ExerciseQuestionAnswerSpace space : spaces){
+                    if (index == space.getIndex()){
+                        space.setSelectedType(type);
+                    }
+                }
+            }
+        }
+
+        //answerjsonv1
+        if (CollectionUtils.isNotEmpty(this.answerJsonV1)){
+            for (ExerciseQuestionAnswerSpace space : this.answerJsonV1){
+                if (index == space.getIndex()){
+                    space.setSelectedType(type);
+                }
+            }
+        }
+    }
+    /**
+     * 设置所有的空都为选择类型
+     * @param type
+     */
+    public void setAllAnswerSelectedType (int type){
+        if (this.json != null && this.json.size() >0){
+            for (List<ExerciseQuestionAnswerSpace> spaces : this.json){
+                for (ExerciseQuestionAnswerSpace space : spaces){
+                    space.setSelectedType(type);
+                }
+            }
+        }
+        //answerjsonv1
+        if (CollectionUtils.isNotEmpty(this.answerJsonV1)){
+            for (ExerciseQuestionAnswerSpace space : this.answerJsonV1){
+                space.setSelectedType(type);
+            }
+        }
+    }
+
+    public List<List<ExerciseQuestionAnswerSpace>> getJson() {
+        return json;
+    }
+
+    public void setJson(List<List<ExerciseQuestionAnswerSpace>> json) {
+        this.json = json;
+    }
+
+    public List<ExerciseQuestionAnswerSpace> getAnswerJsonV1() {
+        return answerJsonV1;
+    }
+
+    public void setAnswerJsonV1(List<ExerciseQuestionAnswerSpace> answerJsonV1) {
+        this.answerJsonV1 = answerJsonV1;
+    }
+}

+ 0 - 0
src/main/java/com/aijia/kmt/dto/ExerciseQuestionNumberDto.java


Some files were not shown because too many files changed in this diff