Commit 6c6376411cccdd1dd1fdc0f5861661bda4e1f332

Authored by wxy
1 parent b7c29a22

no message

Showing 1744 changed files with 570595 additions and 0 deletions

Too many changes.

To preserve performance only 100 of 1744 files are displayed.

juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/IPUtils.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import javax.servlet.http.HttpServletRequest;
  4 +
  5 +import org.apache.commons.lang3.StringUtils;
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
  8 +
  9 +/**
  10 + * IP地址
  11 + *
  12 + * @Author scott
  13 + * @email jeecgos@163.com
  14 + * @Date 2019年01月14日
  15 + */
  16 +public class IPUtils {
  17 + private static Logger logger = LoggerFactory.getLogger(IPUtils.class);
  18 +
  19 + /**
  20 + * 获取IP地址
  21 + *
  22 + * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
  23 + * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
  24 + */
  25 + public static String getIpAddr(HttpServletRequest request) {
  26 + String ip = null;
  27 + try {
  28 + ip = request.getHeader("x-forwarded-for");
  29 + if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
  30 + ip = request.getHeader("Proxy-Client-IP");
  31 + }
  32 + if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  33 + ip = request.getHeader("WL-Proxy-Client-IP");
  34 + }
  35 + if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
  36 + ip = request.getHeader("HTTP_CLIENT_IP");
  37 + }
  38 + if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
  39 + ip = request.getHeader("HTTP_X_FORWARDED_FOR");
  40 + }
  41 + if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
  42 + ip = request.getRemoteAddr();
  43 + }
  44 + } catch (Exception e) {
  45 + logger.error("IPUtils ERROR ", e);
  46 + }
  47 +
  48 +// //使用代理,则获取第一个IP地址
  49 +// if(StringUtils.isEmpty(ip) && ip.length() > 15) {
  50 +// if(ip.indexOf(",") > 0) {
  51 +// ip = ip.substring(0, ip.indexOf(","));
  52 +// }
  53 +// }
  54 +
  55 + return ip;
  56 + }
  57 +
  58 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/ImportExcelUtil.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.baomidou.mybatisplus.extension.service.IService;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.jeecg.common.api.vo.Result;
  7 +import org.jeecg.common.constant.CommonConstant;
  8 +
  9 +import java.io.File;
  10 +import java.io.IOException;
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * 导出返回信息
  15 + */
  16 +@Slf4j
  17 +public class ImportExcelUtil {
  18 +
  19 + public static Result<?> imporReturnRes(int errorLines,int successLines,List<String> errorMessage) throws IOException {
  20 + if (errorLines == 0) {
  21 + return Result.ok("共" + successLines + "行数据全部导入成功!");
  22 + } else {
  23 + JSONObject result = new JSONObject(5);
  24 + int totalCount = successLines + errorLines;
  25 + result.put("totalCount", totalCount);
  26 + result.put("errorCount", errorLines);
  27 + result.put("successCount", successLines);
  28 + result.put("msg", "总上传行数:" + totalCount + ",已导入行数:" + successLines + ",错误行数:" + errorLines);
  29 + String fileUrl = PmsUtil.saveErrorTxtByList(errorMessage, "userImportExcelErrorLog");
  30 + int lastIndex = fileUrl.lastIndexOf(File.separator);
  31 + String fileName = fileUrl.substring(lastIndex + 1);
  32 + result.put("fileUrl", "/sys/common/static/" + fileUrl);
  33 + result.put("fileName", fileName);
  34 + Result res = Result.ok(result);
  35 + res.setCode(201);
  36 + res.setMessage("文件导入成功,但有错误。");
  37 + return res;
  38 + }
  39 + }
  40 +
  41 + public static List<String> importDateSave(List<Object> list, Class serviceClass,List<String> errorMessage,String errorFlag) {
  42 + IService bean =(IService) SpringContextUtils.getBean(serviceClass);
  43 + for (int i = 0; i < list.size(); i++) {
  44 + try {
  45 + boolean save = bean.save(list.get(i));
  46 + if(!save){
  47 + throw new Exception(errorFlag);
  48 + }
  49 + } catch (Exception e) {
  50 + String message = e.getMessage().toLowerCase();
  51 + int lineNumber = i + 1;
  52 + // 通过索引名判断出错信息
  53 + if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_ROLE_CODE)) {
  54 + errorMessage.add("第 " + lineNumber + " 行:角色编码已经存在,忽略导入。");
  55 + } else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_JOB_CLASS_NAME)) {
  56 + errorMessage.add("第 " + lineNumber + " 行:任务类名已经存在,忽略导入。");
  57 + }else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_CODE)) {
  58 + errorMessage.add("第 " + lineNumber + " 行:职务编码已经存在,忽略导入。");
  59 + }else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_DEPART_ORG_CODE)) {
  60 + errorMessage.add("第 " + lineNumber + " 行:部门编码已经存在,忽略导入。");
  61 + }else {
  62 + errorMessage.add("第 " + lineNumber + " 行:未知错误,忽略导入");
  63 + log.error(e.getMessage(), e);
  64 + }
  65 + }
  66 + }
  67 + return errorMessage;
  68 + }
  69 +
  70 + public static List<String> importDateSaveOne(Object obj, Class serviceClass,List<String> errorMessage,int i,String errorFlag) {
  71 + IService bean =(IService) SpringContextUtils.getBean(serviceClass);
  72 + try {
  73 + boolean save = bean.save(obj);
  74 + if(!save){
  75 + throw new Exception(errorFlag);
  76 + }
  77 + } catch (Exception e) {
  78 + String message = e.getMessage().toLowerCase();
  79 + int lineNumber = i + 1;
  80 + // 通过索引名判断出错信息
  81 + if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_ROLE_CODE)) {
  82 + errorMessage.add("第 " + lineNumber + " 行:角色编码已经存在,忽略导入。");
  83 + } else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_JOB_CLASS_NAME)) {
  84 + errorMessage.add("第 " + lineNumber + " 行:任务类名已经存在,忽略导入。");
  85 + }else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_CODE)) {
  86 + errorMessage.add("第 " + lineNumber + " 行:职务编码已经存在,忽略导入。");
  87 + }else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_DEPART_ORG_CODE)) {
  88 + errorMessage.add("第 " + lineNumber + " 行:部门编码已经存在,忽略导入。");
  89 + }else {
  90 + errorMessage.add("第 " + lineNumber + " 行:未知错误,忽略导入");
  91 + log.error(e.getMessage(), e);
  92 + }
  93 + }
  94 + return errorMessage;
  95 + }
  96 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/MD5Util.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import java.security.MessageDigest;
  4 +
  5 +public class MD5Util {
  6 +
  7 + public static String byteArrayToHexString(byte b[]) {
  8 + StringBuffer resultSb = new StringBuffer();
  9 + for (int i = 0; i < b.length; i++){
  10 + resultSb.append(byteToHexString(b[i]));
  11 + }
  12 + return resultSb.toString();
  13 + }
  14 +
  15 + private static String byteToHexString(byte b) {
  16 + int n = b;
  17 + if (n < 0) {
  18 + n += 256;
  19 + }
  20 + int d1 = n / 16;
  21 + int d2 = n % 16;
  22 + return hexDigits[d1] + hexDigits[d2];
  23 + }
  24 +
  25 + public static String MD5Encode(String origin, String charsetname) {
  26 + String resultString = null;
  27 + try {
  28 + resultString = new String(origin);
  29 + MessageDigest md = MessageDigest.getInstance("MD5");
  30 + if (charsetname == null || "".equals(charsetname)) {
  31 + resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
  32 + } else {
  33 + resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
  34 + }
  35 + } catch (Exception exception) {
  36 + }
  37 + return resultString;
  38 + }
  39 +
  40 + private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
  41 + "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
  42 +
  43 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/MinioUtil.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import io.minio.*;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.jeecg.common.util.filter.StrAttackFilter;
  6 +import org.springframework.web.multipart.MultipartFile;
  7 +
  8 +import java.io.InputStream;
  9 +import java.net.URLDecoder;
  10 +
  11 +/**
  12 + * minio文件上传工具类
  13 + */
  14 +@Slf4j
  15 +public class MinioUtil {
  16 + private static String minioUrl;
  17 + private static String minioName;
  18 + private static String minioPass;
  19 + private static String bucketName;
  20 +
  21 + public static void setMinioUrl(String minioUrl) {
  22 + MinioUtil.minioUrl = minioUrl;
  23 + }
  24 +
  25 + public static void setMinioName(String minioName) {
  26 + MinioUtil.minioName = minioName;
  27 + }
  28 +
  29 + public static void setMinioPass(String minioPass) {
  30 + MinioUtil.minioPass = minioPass;
  31 + }
  32 +
  33 + public static void setBucketName(String bucketName) {
  34 + MinioUtil.bucketName = bucketName;
  35 + }
  36 +
  37 + public static String getMinioUrl() {
  38 + return minioUrl;
  39 + }
  40 +
  41 + public static String getBucketName() {
  42 + return bucketName;
  43 + }
  44 +
  45 + private static MinioClient minioClient = null;
  46 +
  47 + /**
  48 + * 上传文件
  49 + * @param file
  50 + * @return
  51 + */
  52 + public static String upload(MultipartFile file, String bizPath, String customBucket) {
  53 + String file_url = "";
  54 + //update-begin-author:wangshuai date:20201012 for: 过滤上传文件夹名特殊字符,防止攻击
  55 + bizPath=StrAttackFilter.filter(bizPath);
  56 + //update-end-author:wangshuai date:20201012 for: 过滤上传文件夹名特殊字符,防止攻击
  57 + String newBucket = bucketName;
  58 + if(oConvertUtils.isNotEmpty(customBucket)){
  59 + newBucket = customBucket;
  60 + }
  61 + try {
  62 + initMinio(minioUrl, minioName,minioPass);
  63 + // 检查存储桶是否已经存在
  64 + if(minioClient.bucketExists(BucketExistsArgs.builder().bucket(newBucket).build())) {
  65 + log.info("Bucket already exists.");
  66 + } else {
  67 + // 创建一个名为ota的存储桶
  68 + minioClient.makeBucket(MakeBucketArgs.builder().bucket(newBucket).build());
  69 + log.info("create a new bucket.");
  70 + }
  71 + InputStream stream = file.getInputStream();
  72 + // 获取文件名
  73 + String orgName = file.getOriginalFilename();
  74 + if("".equals(orgName)){
  75 + orgName=file.getName();
  76 + }
  77 + orgName = CommonUtils.getFileName(orgName);
  78 + String objectName = bizPath+"/"
  79 + +( orgName.indexOf(".")==-1
  80 + ?orgName + "_" + System.currentTimeMillis()
  81 + :orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."))
  82 + );
  83 +
  84 + // 使用putObject上传一个本地文件到存储桶中。
  85 + if(objectName.startsWith("/")){
  86 + objectName = objectName.substring(1);
  87 + }
  88 + PutObjectArgs objectArgs = PutObjectArgs.builder().object(objectName)
  89 + .bucket(newBucket)
  90 + .contentType("application/octet-stream")
  91 + .stream(stream,stream.available(),-1).build();
  92 + minioClient.putObject(objectArgs);
  93 + stream.close();
  94 + file_url = minioUrl+newBucket+"/"+objectName;
  95 + }catch (Exception e){
  96 + log.error(e.getMessage(), e);
  97 + }
  98 + return file_url;
  99 + }
  100 +
  101 + /**
  102 + * 文件上传
  103 + * @param file
  104 + * @param bizPath
  105 + * @return
  106 + */
  107 + public static String upload(MultipartFile file, String bizPath) {
  108 + return upload(file,bizPath,null);
  109 + }
  110 +
  111 + /**
  112 + * 获取文件流
  113 + * @param bucketName
  114 + * @param objectName
  115 + * @return
  116 + */
  117 + public static InputStream getMinioFile(String bucketName,String objectName){
  118 + InputStream inputStream = null;
  119 + try {
  120 + initMinio(minioUrl, minioName, minioPass);
  121 + GetObjectArgs objectArgs = GetObjectArgs.builder().object(objectName)
  122 + .bucket(bucketName).build();
  123 + inputStream = minioClient.getObject(objectArgs);
  124 + } catch (Exception e) {
  125 + log.info("文件获取失败" + e.getMessage());
  126 + }
  127 + return inputStream;
  128 + }
  129 +
  130 + /**
  131 + * 删除文件
  132 + * @param bucketName
  133 + * @param objectName
  134 + * @throws Exception
  135 + */
  136 + public static void removeObject(String bucketName, String objectName) {
  137 + try {
  138 + initMinio(minioUrl, minioName,minioPass);
  139 + RemoveObjectArgs objectArgs = RemoveObjectArgs.builder().object(objectName)
  140 + .bucket(bucketName).build();
  141 + minioClient.removeObject(objectArgs);
  142 + }catch (Exception e){
  143 + log.info("文件删除失败" + e.getMessage());
  144 + }
  145 + }
  146 +
  147 + /**
  148 + * 获取文件外链
  149 + * @param bucketName
  150 + * @param objectName
  151 + * @param expires
  152 + * @return
  153 + */
  154 + public static String getObjectURL(String bucketName, String objectName, Integer expires) {
  155 + initMinio(minioUrl, minioName,minioPass);
  156 + try{
  157 + GetPresignedObjectUrlArgs objectArgs = GetPresignedObjectUrlArgs.builder().object(objectName)
  158 + .bucket(bucketName)
  159 + .expiry(expires).build();
  160 + String url = minioClient.getPresignedObjectUrl(objectArgs);
  161 + return URLDecoder.decode(url,"UTF-8");
  162 + }catch (Exception e){
  163 + log.info("文件路径获取失败" + e.getMessage());
  164 + }
  165 + return null;
  166 + }
  167 +
  168 + /**
  169 + * 初始化客户端
  170 + * @param minioUrl
  171 + * @param minioName
  172 + * @param minioPass
  173 + * @return
  174 + */
  175 + private static MinioClient initMinio(String minioUrl, String minioName,String minioPass) {
  176 + if (minioClient == null) {
  177 + try {
  178 + minioClient = MinioClient.builder()
  179 + .endpoint(minioUrl)
  180 + .credentials(minioName, minioPass)
  181 + .build();
  182 + } catch (Exception e) {
  183 + e.printStackTrace();
  184 + }
  185 + }
  186 + return minioClient;
  187 + }
  188 +
  189 + /**
  190 + * 上传文件到minio
  191 + * @param stream
  192 + * @param relativePath
  193 + * @return
  194 + */
  195 + public static String upload(InputStream stream,String relativePath) throws Exception {
  196 + initMinio(minioUrl, minioName,minioPass);
  197 + if(minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
  198 + log.info("Bucket already exists.");
  199 + } else {
  200 + // 创建一个名为ota的存储桶
  201 + minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
  202 + log.info("create a new bucket.");
  203 + }
  204 + PutObjectArgs objectArgs = PutObjectArgs.builder().object(relativePath)
  205 + .bucket(bucketName)
  206 + .contentType("application/octet-stream")
  207 + .stream(stream,stream.available(),-1).build();
  208 + minioClient.putObject(objectArgs);
  209 + stream.close();
  210 + return minioUrl+bucketName+"/"+relativePath;
  211 + }
  212 +
  213 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/MyClassLoader.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +/**
  4 + * @Author 张代浩
  5 + */
  6 +public class MyClassLoader extends ClassLoader {
  7 + public static Class getClassByScn(String className) {
  8 + Class myclass = null;
  9 + try {
  10 + myclass = Class.forName(className);
  11 + } catch (ClassNotFoundException e) {
  12 + e.printStackTrace();
  13 + throw new RuntimeException(className+" not found!");
  14 + }
  15 + return myclass;
  16 + }
  17 +
  18 + // 获得类的全名,包括包名
  19 + public static String getPackPath(Object object) {
  20 + // 检查用户传入的参数是否为空
  21 + if (object == null) {
  22 + throw new java.lang.IllegalArgumentException("参数不能为空!");
  23 + }
  24 + // 获得类的全名,包括包名
  25 + String clsName = object.getClass().getName();
  26 + return clsName;
  27 + }
  28 +
  29 + public static String getAppPath(Class cls) {
  30 + // 检查用户传入的参数是否为空
  31 + if (cls == null) {
  32 + throw new java.lang.IllegalArgumentException("参数不能为空!");
  33 + }
  34 + ClassLoader loader = cls.getClassLoader();
  35 + // 获得类的全名,包括包名
  36 + String clsName = cls.getName() + ".class";
  37 + // 获得传入参数所在的包
  38 + Package pack = cls.getPackage();
  39 + String path = "";
  40 + // 如果不是匿名包,将包名转化为路径
  41 + if (pack != null) {
  42 + String packName = pack.getName();
  43 + // 此处简单判定是否是Java基础类库,防止用户传入JDK内置的类库
  44 + if (packName.startsWith("java.") || packName.startsWith("javax.")) {
  45 + throw new java.lang.IllegalArgumentException("不要传送系统类!");
  46 + }
  47 + // 在类的名称中,去掉包名的部分,获得类的文件名
  48 + clsName = clsName.substring(packName.length() + 1);
  49 + // 判定包名是否是简单包名,如果是,则直接将包名转换为路径,
  50 + if (packName.indexOf(".") < 0) {
  51 + path = packName + "/";
  52 + } else {// 否则按照包名的组成部分,将包名转换为路径
  53 + int start = 0, end = 0;
  54 + end = packName.indexOf(".");
  55 + while (end != -1) {
  56 + path = path + packName.substring(start, end) + "/";
  57 + start = end + 1;
  58 + end = packName.indexOf(".", start);
  59 + }
  60 + path = path + packName.substring(start) + "/";
  61 + }
  62 + }
  63 + // 调用ClassLoader的getResource方法,传入包含路径信息的类文件名
  64 + java.net.URL url = loader.getResource(path + clsName);
  65 + // 从URL对象中获取路径信息
  66 + String realPath = url.getPath();
  67 + // 去掉路径信息中的协议名"file:"
  68 + int pos = realPath.indexOf("file:");
  69 + if (pos > -1) {
  70 + realPath = realPath.substring(pos + 5);
  71 + }
  72 + // 去掉路径信息最后包含类文件信息的部分,得到类所在的路径
  73 + pos = realPath.indexOf(path + clsName);
  74 + realPath = realPath.substring(0, pos - 1);
  75 + // 如果类文件被打包到JAR等文件中时,去掉对应的JAR等打包文件名
  76 + if (realPath.endsWith("!")) {
  77 + realPath = realPath.substring(0, realPath.lastIndexOf("/"));
  78 + }
  79 + /*------------------------------------------------------------
  80 + ClassLoader的getResource方法使用了utf-8对路径信息进行了编码,当路径
  81 + 中存在中文和空格时,他会对这些字符进行转换,这样,得到的往往不是我们想要
  82 + 的真实路径,在此,调用了URLDecoder的decode方法进行解码,以便得到原始的
  83 + 中文及空格路径
  84 + -------------------------------------------------------------*/
  85 + try {
  86 + realPath = java.net.URLDecoder.decode(realPath, "utf-8");
  87 + } catch (Exception e) {
  88 + throw new RuntimeException(e);
  89 + }
  90 + return realPath;
  91 + }// getAppPath定义结束
  92 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/PasswordUtil.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import java.security.Key;
  4 +import java.security.SecureRandom;
  5 +import javax.crypto.Cipher;
  6 +import javax.crypto.SecretKey;
  7 +import javax.crypto.SecretKeyFactory;
  8 +import javax.crypto.spec.PBEKeySpec;
  9 +import javax.crypto.spec.PBEParameterSpec;
  10 +public class PasswordUtil {
  11 +
  12 + /**
  13 + * JAVA6支持以下任意一种算法 PBEWITHMD5ANDDES PBEWITHMD5ANDTRIPLEDES
  14 + * PBEWITHSHAANDDESEDE PBEWITHSHA1ANDRC2_40 PBKDF2WITHHMACSHA1
  15 + * */
  16 +
  17 + /**
  18 + * 定义使用的算法为:PBEWITHMD5andDES算法
  19 + */
  20 + public static final String ALGORITHM = "PBEWithMD5AndDES";//加密算法
  21 + public static final String Salt = "63293188";//密钥
  22 +
  23 + /**
  24 + * 定义迭代次数为1000次
  25 + */
  26 + private static final int ITERATIONCOUNT = 1000;
  27 +
  28 + /**
  29 + * 获取加密算法中使用的盐值,解密中使用的盐值必须与加密中使用的相同才能完成操作. 盐长度必须为8字节
  30 + *
  31 + * @return byte[] 盐值
  32 + * */
  33 + public static byte[] getSalt() throws Exception {
  34 + // 实例化安全随机数
  35 + SecureRandom random = new SecureRandom();
  36 + // 产出盐
  37 + return random.generateSeed(8);
  38 + }
  39 +
  40 + public static byte[] getStaticSalt() {
  41 + // 产出盐
  42 + return Salt.getBytes();
  43 + }
  44 +
  45 + /**
  46 + * 根据PBE密码生成一把密钥
  47 + *
  48 + * @param password
  49 + * 生成密钥时所使用的密码
  50 + * @return Key PBE算法密钥
  51 + * */
  52 + private static Key getPBEKey(String password) {
  53 + // 实例化使用的算法
  54 + SecretKeyFactory keyFactory;
  55 + SecretKey secretKey = null;
  56 + try {
  57 + keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
  58 + // 设置PBE密钥参数
  59 + PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
  60 + // 生成密钥
  61 + secretKey = keyFactory.generateSecret(keySpec);
  62 + } catch (Exception e) {
  63 + // TODO Auto-generated catch block
  64 + e.printStackTrace();
  65 + }
  66 +
  67 + return secretKey;
  68 + }
  69 +
  70 + /**
  71 + * 加密明文字符串
  72 + *
  73 + * @param plaintext
  74 + * 待加密的明文字符串
  75 + * @param password
  76 + * 生成密钥时所使用的密码
  77 + * @param salt
  78 + * 盐值
  79 + * @return 加密后的密文字符串
  80 + * @throws Exception
  81 + */
  82 + public static String encrypt(String plaintext, String password, String salt) {
  83 +
  84 + Key key = getPBEKey(password);
  85 + byte[] encipheredData = null;
  86 + PBEParameterSpec parameterSpec = new PBEParameterSpec(salt.getBytes(), ITERATIONCOUNT);
  87 + try {
  88 + Cipher cipher = Cipher.getInstance(ALGORITHM);
  89 +
  90 + cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);
  91 + //update-begin-author:sccott date:20180815 for:中文作为用户名时,加密的密码windows和linux会得到不同的结果 gitee/issues/IZUD7
  92 + encipheredData = cipher.doFinal(plaintext.getBytes("utf-8"));
  93 + //update-end-author:sccott date:20180815 for:中文作为用户名时,加密的密码windows和linux会得到不同的结果 gitee/issues/IZUD7
  94 + } catch (Exception e) {
  95 + }
  96 + return bytesToHexString(encipheredData);
  97 + }
  98 +
  99 + /**
  100 + * 解密密文字符串
  101 + *
  102 + * @param ciphertext
  103 + * 待解密的密文字符串
  104 + * @param password
  105 + * 生成密钥时所使用的密码(如需解密,该参数需要与加密时使用的一致)
  106 + * @param salt
  107 + * 盐值(如需解密,该参数需要与加密时使用的一致)
  108 + * @return 解密后的明文字符串
  109 + * @throws Exception
  110 + */
  111 + public static String decrypt(String ciphertext, String password, String salt) {
  112 +
  113 + Key key = getPBEKey(password);
  114 + byte[] passDec = null;
  115 + PBEParameterSpec parameterSpec = new PBEParameterSpec(salt.getBytes(), ITERATIONCOUNT);
  116 + try {
  117 + Cipher cipher = Cipher.getInstance(ALGORITHM);
  118 +
  119 + cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
  120 +
  121 + passDec = cipher.doFinal(hexStringToBytes(ciphertext));
  122 + }
  123 +
  124 + catch (Exception e) {
  125 + // TODO: handle exception
  126 + }
  127 + return new String(passDec);
  128 + }
  129 +
  130 + /**
  131 + * 将字节数组转换为十六进制字符串
  132 + *
  133 + * @param src
  134 + * 字节数组
  135 + * @return
  136 + */
  137 + public static String bytesToHexString(byte[] src) {
  138 + StringBuilder stringBuilder = new StringBuilder("");
  139 + if (src == null || src.length <= 0) {
  140 + return null;
  141 + }
  142 + for (int i = 0; i < src.length; i++) {
  143 + int v = src[i] & 0xFF;
  144 + String hv = Integer.toHexString(v);
  145 + if (hv.length() < 2) {
  146 + stringBuilder.append(0);
  147 + }
  148 + stringBuilder.append(hv);
  149 + }
  150 + return stringBuilder.toString();
  151 + }
  152 +
  153 + /**
  154 + * 将十六进制字符串转换为字节数组
  155 + *
  156 + * @param hexString
  157 + * 十六进制字符串
  158 + * @return
  159 + */
  160 + public static byte[] hexStringToBytes(String hexString) {
  161 + if (hexString == null || hexString.equals("")) {
  162 + return null;
  163 + }
  164 + hexString = hexString.toUpperCase();
  165 + int length = hexString.length() / 2;
  166 + char[] hexChars = hexString.toCharArray();
  167 + byte[] d = new byte[length];
  168 + for (int i = 0; i < length; i++) {
  169 + int pos = i * 2;
  170 + d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
  171 + }
  172 + return d;
  173 + }
  174 +
  175 + private static byte charToByte(char c) {
  176 + return (byte) "0123456789ABCDEF".indexOf(c);
  177 + }
  178 +
  179 +
  180 +}
0 \ No newline at end of file 181 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/PmsUtil.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.springframework.beans.factory.annotation.Value;
  5 +import org.springframework.stereotype.Component;
  6 +
  7 +import java.io.BufferedWriter;
  8 +import java.io.File;
  9 +import java.io.FileWriter;
  10 +import java.util.Date;
  11 +import java.util.List;
  12 +
  13 +@Slf4j
  14 +@Component
  15 +public class PmsUtil {
  16 +
  17 +
  18 + private static String uploadPath;
  19 +
  20 + @Value("${jeecg.path.upload}")
  21 + public void setUploadPath(String uploadPath) {
  22 + PmsUtil.uploadPath = uploadPath;
  23 + }
  24 +
  25 + public static String saveErrorTxtByList(List<String> msg, String name) {
  26 + Date d = new Date();
  27 + String saveDir = "logs" + File.separator + DateUtils.yyyyMMdd.get().format(d) + File.separator;
  28 + String saveFullDir = uploadPath + File.separator + saveDir;
  29 +
  30 + File saveFile = new File(saveFullDir);
  31 + if (!saveFile.exists()) {
  32 + saveFile.mkdirs();
  33 + }
  34 + name += DateUtils.yyyymmddhhmmss.get().format(d) + Math.round(Math.random() * 10000);
  35 + String saveFilePath = saveFullDir + name + ".txt";
  36 +
  37 + try {
  38 + //封装目的地
  39 + BufferedWriter bw = new BufferedWriter(new FileWriter(saveFilePath));
  40 + //遍历集合
  41 + for (String s : msg) {
  42 + //写数据
  43 + if (s.indexOf("_") > 0) {
  44 + String arr[] = s.split("_");
  45 + bw.write("第" + arr[0] + "行:" + arr[1]);
  46 + } else {
  47 + bw.write(s);
  48 + }
  49 + //bw.newLine();
  50 + bw.write("\r\n");
  51 + }
  52 + //释放资源
  53 + bw.flush();
  54 + bw.close();
  55 + } catch (Exception e) {
  56 + log.info("excel导入生成错误日志文件异常:" + e.getMessage());
  57 + }
  58 + return saveDir + name + ".txt";
  59 + }
  60 +
  61 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/ReflectHelper.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +
  5 +import java.lang.reflect.Field;
  6 +import java.lang.reflect.Method;
  7 +import java.util.*;
  8 +import java.util.Map.Entry;
  9 +import java.util.regex.Pattern;
  10 +
  11 +/**
  12 + * @author 张代浩
  13 + * @desc 通过反射来动态调用get 和 set 方法
  14 + */
  15 +@Slf4j
  16 +public class ReflectHelper {
  17 +
  18 + private Class cls;
  19 +
  20 + /**
  21 + * 传过来的对象
  22 + */
  23 + private Object obj;
  24 +
  25 + /**
  26 + * 存放get方法
  27 + */
  28 + private Hashtable<String, Method> getMethods = null;
  29 + /**
  30 + * 存放set方法
  31 + */
  32 + private Hashtable<String, Method> setMethods = null;
  33 +
  34 + /**
  35 + * 定义构造方法 -- 一般来说是个pojo
  36 + *
  37 + * @param o 目标对象
  38 + */
  39 + public ReflectHelper(Object o) {
  40 + obj = o;
  41 + initMethods();
  42 + }
  43 +
  44 + /**
  45 + * @desc 初始化
  46 + */
  47 + public void initMethods() {
  48 + getMethods = new Hashtable<String, Method>();
  49 + setMethods = new Hashtable<String, Method>();
  50 + cls = obj.getClass();
  51 + Method[] methods = cls.getMethods();
  52 + // 定义正则表达式,从方法中过滤出getter / setter 函数.
  53 + String gs = "get(\\w+)";
  54 + Pattern getM = Pattern.compile(gs);
  55 + String ss = "set(\\w+)";
  56 + Pattern setM = Pattern.compile(ss);
  57 + // 把方法中的"set" 或者 "get" 去掉
  58 + String rapl = "$1";
  59 + String param;
  60 + for (int i = 0; i < methods.length; ++i) {
  61 + Method m = methods[i];
  62 + String methodName = m.getName();
  63 + if (Pattern.matches(gs, methodName)) {
  64 + param = getM.matcher(methodName).replaceAll(rapl).toLowerCase();
  65 + getMethods.put(param, m);
  66 + } else if (Pattern.matches(ss, methodName)) {
  67 + param = setM.matcher(methodName).replaceAll(rapl).toLowerCase();
  68 + setMethods.put(param, m);
  69 + } else {
  70 + // logger.info(methodName + " 不是getter,setter方法!");
  71 + }
  72 + }
  73 + }
  74 +
  75 + /**
  76 + * @desc 调用set方法
  77 + */
  78 + public boolean setMethodValue(String property, Object object) {
  79 + Method m = setMethods.get(property.toLowerCase());
  80 + if (m != null) {
  81 + try {
  82 + // 调用目标类的setter函数
  83 + m.invoke(obj, object);
  84 + return true;
  85 + } catch (Exception ex) {
  86 + log.info("invoke getter on " + property + " error: " + ex.toString());
  87 + return false;
  88 + }
  89 + }
  90 + return false;
  91 + }
  92 +
  93 + /**
  94 + * @desc 调用set方法
  95 + */
  96 + public Object getMethodValue(String property) {
  97 + Object value = null;
  98 + Method m = getMethods.get(property.toLowerCase());
  99 + if (m != null) {
  100 + try {
  101 + /*
  102 + * 调用obj类的setter函数
  103 + */
  104 + value = m.invoke(obj, new Object[]{});
  105 +
  106 + } catch (Exception ex) {
  107 + log.info("invoke getter on " + property + " error: " + ex.toString());
  108 + }
  109 + }
  110 + return value;
  111 + }
  112 +
  113 + /**
  114 + * 把map中的内容全部注入到obj中
  115 + *
  116 + * @param data
  117 + * @return
  118 + */
  119 + public Object setAll(Map<String, Object> data) {
  120 + if (data == null || data.keySet().size() <= 0) {
  121 + return null;
  122 + }
  123 + for (Entry<String, Object> entry : data.entrySet()) {
  124 + this.setMethodValue(entry.getKey(), entry.getValue());
  125 + }
  126 + return obj;
  127 + }
  128 +
  129 + /**
  130 + * 把map中的内容全部注入到obj中
  131 + *
  132 + * @param o
  133 + * @param data
  134 + * @return
  135 + */
  136 + public static Object setAll(Object o, Map<String, Object> data) {
  137 + ReflectHelper reflectHelper = new ReflectHelper(o);
  138 + reflectHelper.setAll(data);
  139 + return o;
  140 + }
  141 +
  142 + /**
  143 + * 把map中的内容全部注入到新实例中
  144 + *
  145 + * @param clazz
  146 + * @param data
  147 + * @return
  148 + */
  149 + @SuppressWarnings("unchecked")
  150 + public static <T> T setAll(Class<T> clazz, Map<String, Object> data) {
  151 + T o = null;
  152 + try {
  153 + o = clazz.newInstance();
  154 + } catch (Exception e) {
  155 + e.printStackTrace();
  156 + o = null;
  157 + return o;
  158 + }
  159 + return (T) setAll(o, data);
  160 + }
  161 +
  162 + /**
  163 + * 根据传入的class将mapList转换为实体类list
  164 + *
  165 + * @param mapist
  166 + * @param clazz
  167 + * @return
  168 + */
  169 + public static <T> List<T> transList2Entrys(List<Map<String, Object>> mapist, Class<T> clazz) {
  170 + List<T> list = new ArrayList<T>();
  171 + if (mapist != null && mapist.size() > 0) {
  172 + for (Map<String, Object> data : mapist) {
  173 + list.add(ReflectHelper.setAll(clazz, data));
  174 + }
  175 + }
  176 + return list;
  177 + }
  178 +
  179 + /**
  180 + * 根据属性名获取属性值
  181 + */
  182 + public static Object getFieldValueByName(String fieldName, Object o) {
  183 + try {
  184 + String firstLetter = fieldName.substring(0, 1).toUpperCase();
  185 + String getter = "get" + firstLetter + fieldName.substring(1);
  186 + Method method = o.getClass().getMethod(getter, new Class[]{});
  187 + Object value = method.invoke(o, new Object[]{});
  188 + return value;
  189 + } catch (Exception e) {
  190 + e.printStackTrace();
  191 + return null;
  192 + }
  193 + }
  194 +
  195 + /**
  196 + * 获取属性名数组
  197 + */
  198 + public static String[] getFiledName(Object o) {
  199 + Field[] fields = o.getClass().getDeclaredFields();
  200 + String[] fieldNames = new String[fields.length];
  201 + for (int i = 0; i < fields.length; i++) {
  202 + //log.info(fields[i].getType());
  203 + fieldNames[i] = fields[i].getName();
  204 + }
  205 + return fieldNames;
  206 + }
  207 +
  208 + /**
  209 + * 获取属性类型(type),属性名(name),属性值(value)的map组成的list
  210 + */
  211 + public static List<Map> getFiledsInfo(Object o) {
  212 + Field[] fields = o.getClass().getDeclaredFields();
  213 + String[] fieldNames = new String[fields.length];
  214 + List<Map> list = new ArrayList<Map>();
  215 + Map<String, Object> infoMap = null;
  216 + for (int i = 0; i < fields.length; i++) {
  217 + infoMap = new HashMap<String, Object>();
  218 + infoMap.put("type", fields[i].getType().toString());
  219 + infoMap.put("name", fields[i].getName());
  220 + infoMap.put("value", getFieldValueByName(fields[i].getName(), o));
  221 + list.add(infoMap);
  222 + }
  223 + return list;
  224 + }
  225 +
  226 + /**
  227 + * 获取对象的所有属性值,返回一个对象数组
  228 + */
  229 + public static Object[] getFiledValues(Object o) {
  230 + String[] fieldNames = getFiledName(o);
  231 + Object[] value = new Object[fieldNames.length];
  232 + for (int i = 0; i < fieldNames.length; i++) {
  233 + value[i] = getFieldValueByName(fieldNames[i], o);
  234 + }
  235 + return value;
  236 + }
  237 +
  238 +}
0 \ No newline at end of file 239 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/RestDesformUtil.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import org.jeecg.common.api.vo.Result;
  5 +import org.springframework.http.HttpHeaders;
  6 +import org.springframework.http.HttpMethod;
  7 +import org.springframework.http.MediaType;
  8 +import org.springframework.http.ResponseEntity;
  9 +
  10 +/**
  11 + * 通过 RESTful 风格的接口操纵 desform 里的数据
  12 + *
  13 + * @author sunjianlei
  14 + */
  15 +public class RestDesformUtil {
  16 +
  17 + private static String domain = null;
  18 + private static String path = null;
  19 +
  20 + static {
  21 + domain = SpringContextUtils.getDomain();
  22 + path = oConvertUtils.getString(SpringContextUtils.getApplicationContext().getEnvironment().getProperty("server.servlet.context-path"));
  23 + }
  24 +
  25 + /**
  26 + * 查询数据
  27 + *
  28 + * @param desformCode
  29 + * @param dataId
  30 + * @param token
  31 + * @return
  32 + */
  33 + public static Result queryOne(String desformCode, String dataId, String token) {
  34 + String url = getBaseUrl(desformCode, dataId).toString();
  35 + HttpHeaders headers = getHeaders(token);
  36 + ResponseEntity<JSONObject> result = RestUtil.request(url, HttpMethod.GET, headers, null, null, JSONObject.class);
  37 + return packageReturn(result);
  38 + }
  39 +
  40 + /**
  41 + * 新增数据
  42 + *
  43 + * @param desformCode
  44 + * @param formData
  45 + * @param token
  46 + * @return
  47 + */
  48 + public static Result addOne(String desformCode, JSONObject formData, String token) {
  49 + return addOrEditOne(desformCode, formData, token, HttpMethod.POST);
  50 + }
  51 +
  52 + /**
  53 + * 修改数据
  54 + *
  55 + * @param desformCode
  56 + * @param formData
  57 + * @param token
  58 + * @return
  59 + */
  60 + public static Result editOne(String desformCode, JSONObject formData, String token) {
  61 + return addOrEditOne(desformCode, formData, token, HttpMethod.PUT);
  62 + }
  63 +
  64 + private static Result addOrEditOne(String desformCode, JSONObject formData, String token, HttpMethod method) {
  65 + String url = getBaseUrl(desformCode).toString();
  66 + HttpHeaders headers = getHeaders(token);
  67 + ResponseEntity<JSONObject> result = RestUtil.request(url, method, headers, null, formData, JSONObject.class);
  68 + return packageReturn(result);
  69 + }
  70 +
  71 + /**
  72 + * 删除数据
  73 + *
  74 + * @param desformCode
  75 + * @param dataId
  76 + * @param token
  77 + * @return
  78 + */
  79 + public static Result removeOne(String desformCode, String dataId, String token) {
  80 + String url = getBaseUrl(desformCode, dataId).toString();
  81 + HttpHeaders headers = getHeaders(token);
  82 + ResponseEntity<JSONObject> result = RestUtil.request(url, HttpMethod.DELETE, headers, null, null, JSONObject.class);
  83 + return packageReturn(result);
  84 + }
  85 +
  86 + private static Result packageReturn(ResponseEntity<JSONObject> result) {
  87 + if (result.getBody() != null) {
  88 + return result.getBody().toJavaObject(Result.class);
  89 + }
  90 + return Result.error("操作失败");
  91 + }
  92 +
  93 + private static StringBuilder getBaseUrl() {
  94 + StringBuilder builder = new StringBuilder(domain).append(path);
  95 + builder.append("/desform/api");
  96 + return builder;
  97 + }
  98 +
  99 + private static StringBuilder getBaseUrl(String desformCode, String dataId) {
  100 + StringBuilder builder = getBaseUrl();
  101 + builder.append("/").append(desformCode);
  102 + if (dataId != null) {
  103 + builder.append("/").append(dataId);
  104 + }
  105 + return builder;
  106 + }
  107 +
  108 + private static StringBuilder getBaseUrl(String desformCode) {
  109 + return getBaseUrl(desformCode, null);
  110 + }
  111 +
  112 + private static HttpHeaders getHeaders(String token) {
  113 + HttpHeaders headers = new HttpHeaders();
  114 + String mediaType = MediaType.APPLICATION_JSON_UTF8_VALUE;
  115 + headers.setContentType(MediaType.parseMediaType(mediaType));
  116 + headers.set("Accept", mediaType);
  117 + headers.set("X-Access-Token", token);
  118 + return headers;
  119 + }
  120 +
  121 +}
0 \ No newline at end of file 122 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/RestUtil.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.apache.commons.lang3.StringUtils;
  6 +import org.springframework.http.*;
  7 +import org.springframework.http.client.SimpleClientHttpRequestFactory;
  8 +import org.springframework.http.converter.StringHttpMessageConverter;
  9 +import org.springframework.web.client.RestTemplate;
  10 +
  11 +import java.nio.charset.StandardCharsets;
  12 +import java.util.Iterator;
  13 +import java.util.Map;
  14 +
  15 +/**
  16 + * 调用 Restful 接口 Util
  17 + *
  18 + * @author sunjianlei
  19 + */
  20 +@Slf4j
  21 +public class RestUtil {
  22 +
  23 + private static String domain = null;
  24 +
  25 + public static String getDomain() {
  26 + if (domain == null) {
  27 + domain = SpringContextUtils.getDomain();
  28 + }
  29 + return domain;
  30 + }
  31 +
  32 + public static String path = null;
  33 +
  34 + public static String getPath() {
  35 + if (path == null) {
  36 + path = SpringContextUtils.getApplicationContext().getEnvironment().getProperty("server.servlet.context-path");
  37 + }
  38 + return oConvertUtils.getString(path);
  39 + }
  40 +
  41 + public static String getBaseUrl() {
  42 + String basepath = getDomain() + getPath();
  43 + log.info(" RestUtil.getBaseUrl: " + basepath);
  44 + return basepath;
  45 + }
  46 +
  47 + /**
  48 + * RestAPI 调用器
  49 + */
  50 + private final static RestTemplate RT;
  51 +
  52 + static {
  53 + SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
  54 + requestFactory.setConnectTimeout(3000);
  55 + requestFactory.setReadTimeout(3000);
  56 + RT = new RestTemplate(requestFactory);
  57 + // 解决乱码问题
  58 + RT.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
  59 + }
  60 +
  61 + public static RestTemplate getRestTemplate() {
  62 + return RT;
  63 + }
  64 +
  65 + /**
  66 + * 发送 get 请求
  67 + */
  68 + public static JSONObject get(String url) {
  69 + return getNative(url, null, null).getBody();
  70 + }
  71 +
  72 + /**
  73 + * 发送 get 请求
  74 + */
  75 + public static JSONObject get(String url, JSONObject variables) {
  76 + return getNative(url, variables, null).getBody();
  77 + }
  78 +
  79 + /**
  80 + * 发送 get 请求
  81 + */
  82 + public static JSONObject get(String url, JSONObject variables, JSONObject params) {
  83 + return getNative(url, variables, params).getBody();
  84 + }
  85 +
  86 + /**
  87 + * 发送 get 请求,返回原生 ResponseEntity 对象
  88 + */
  89 + public static ResponseEntity<JSONObject> getNative(String url, JSONObject variables, JSONObject params) {
  90 + return request(url, HttpMethod.GET, variables, params);
  91 + }
  92 +
  93 + /**
  94 + * 发送 Post 请求
  95 + */
  96 + public static JSONObject post(String url) {
  97 + return postNative(url, null, null).getBody();
  98 + }
  99 +
  100 + /**
  101 + * 发送 Post 请求
  102 + */
  103 + public static JSONObject post(String url, JSONObject params) {
  104 + return postNative(url, null, params).getBody();
  105 + }
  106 +
  107 + /**
  108 + * 发送 Post 请求
  109 + */
  110 + public static JSONObject post(String url, JSONObject variables, JSONObject params) {
  111 + return postNative(url, variables, params).getBody();
  112 + }
  113 +
  114 + /**
  115 + * 发送 POST 请求,返回原生 ResponseEntity 对象
  116 + */
  117 + public static ResponseEntity<JSONObject> postNative(String url, JSONObject variables, JSONObject params) {
  118 + return request(url, HttpMethod.POST, variables, params);
  119 + }
  120 +
  121 + /**
  122 + * 发送 put 请求
  123 + */
  124 + public static JSONObject put(String url) {
  125 + return putNative(url, null, null).getBody();
  126 + }
  127 +
  128 + /**
  129 + * 发送 put 请求
  130 + */
  131 + public static JSONObject put(String url, JSONObject params) {
  132 + return putNative(url, null, params).getBody();
  133 + }
  134 +
  135 + /**
  136 + * 发送 put 请求
  137 + */
  138 + public static JSONObject put(String url, JSONObject variables, JSONObject params) {
  139 + return putNative(url, variables, params).getBody();
  140 + }
  141 +
  142 + /**
  143 + * 发送 put 请求,返回原生 ResponseEntity 对象
  144 + */
  145 + public static ResponseEntity<JSONObject> putNative(String url, JSONObject variables, JSONObject params) {
  146 + return request(url, HttpMethod.PUT, variables, params);
  147 + }
  148 +
  149 + /**
  150 + * 发送 delete 请求
  151 + */
  152 + public static JSONObject delete(String url) {
  153 + return deleteNative(url, null, null).getBody();
  154 + }
  155 +
  156 + /**
  157 + * 发送 delete 请求
  158 + */
  159 + public static JSONObject delete(String url, JSONObject variables, JSONObject params) {
  160 + return deleteNative(url, variables, params).getBody();
  161 + }
  162 +
  163 + /**
  164 + * 发送 delete 请求,返回原生 ResponseEntity 对象
  165 + */
  166 + public static ResponseEntity<JSONObject> deleteNative(String url, JSONObject variables, JSONObject params) {
  167 + return request(url, HttpMethod.DELETE, null, variables, params, JSONObject.class);
  168 + }
  169 +
  170 + /**
  171 + * 发送请求
  172 + */
  173 + public static ResponseEntity<JSONObject> request(String url, HttpMethod method, JSONObject variables, JSONObject params) {
  174 + return request(url, method, getHeaderApplicationJson(), variables, params, JSONObject.class);
  175 + }
  176 +
  177 + /**
  178 + * 发送请求
  179 + *
  180 + * @param url 请求地址
  181 + * @param method 请求方式
  182 + * @param headers 请求头 可空
  183 + * @param variables 请求url参数 可空
  184 + * @param params 请求body参数 可空
  185 + * @param responseType 返回类型
  186 + * @return ResponseEntity<responseType>
  187 + */
  188 + public static <T> ResponseEntity<T> request(String url, HttpMethod method, HttpHeaders headers, JSONObject variables, Object params, Class<T> responseType) {
  189 + log.info(" RestUtil --- request --- url = "+ url);
  190 + if (StringUtils.isEmpty(url)) {
  191 + throw new RuntimeException("url 不能为空");
  192 + }
  193 + if (method == null) {
  194 + throw new RuntimeException("method 不能为空");
  195 + }
  196 + if (headers == null) {
  197 + headers = new HttpHeaders();
  198 + }
  199 + // 请求体
  200 + String body = "";
  201 + if (params != null) {
  202 + if (params instanceof JSONObject) {
  203 + body = ((JSONObject) params).toJSONString();
  204 +
  205 + } else {
  206 + body = params.toString();
  207 + }
  208 + }
  209 + // 拼接 url 参数
  210 + if (variables != null) {
  211 + url += ("?" + asUrlVariables(variables));
  212 + }
  213 + // 发送请求
  214 + HttpEntity<String> request = new HttpEntity<>(body, headers);
  215 + return RT.exchange(url, method, request, responseType);
  216 + }
  217 +
  218 + /**
  219 + * 获取JSON请求头
  220 + */
  221 + public static HttpHeaders getHeaderApplicationJson() {
  222 + return getHeader(MediaType.APPLICATION_JSON_UTF8_VALUE);
  223 + }
  224 +
  225 + /**
  226 + * 获取请求头
  227 + */
  228 + public static HttpHeaders getHeader(String mediaType) {
  229 + HttpHeaders headers = new HttpHeaders();
  230 + headers.setContentType(MediaType.parseMediaType(mediaType));
  231 + headers.add("Accept", mediaType);
  232 + return headers;
  233 + }
  234 +
  235 + /**
  236 + * 将 JSONObject 转为 a=1&b=2&c=3...&n=n 的形式
  237 + */
  238 + public static String asUrlVariables(JSONObject variables) {
  239 + Map<String, Object> source = variables.getInnerMap();
  240 + Iterator<String> it = source.keySet().iterator();
  241 + StringBuilder urlVariables = new StringBuilder();
  242 + while (it.hasNext()) {
  243 + String key = it.next();
  244 + String value = "";
  245 + Object object = source.get(key);
  246 + if (object != null) {
  247 + if (!StringUtils.isEmpty(object.toString())) {
  248 + value = object.toString();
  249 + }
  250 + }
  251 + urlVariables.append("&").append(key).append("=").append(value);
  252 + }
  253 + // 去掉第一个&
  254 + return urlVariables.substring(1);
  255 + }
  256 +
  257 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/SpringContextUtils.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import javax.servlet.http.HttpServletRequest;
  4 +
  5 +import org.jeecg.common.constant.ServiceNameConstants;
  6 +import org.springframework.beans.BeansException;
  7 +import org.springframework.context.ApplicationContext;
  8 +import org.springframework.context.ApplicationContextAware;
  9 +import org.springframework.stereotype.Component;
  10 +import org.springframework.web.context.request.RequestContextHolder;
  11 +import org.springframework.web.context.request.ServletRequestAttributes;
  12 +
  13 +@Component
  14 +public class SpringContextUtils implements ApplicationContextAware {
  15 +
  16 + /**
  17 + * 上下文对象实例
  18 + */
  19 + private static ApplicationContext applicationContext;
  20 +
  21 + @Override
  22 + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  23 + SpringContextUtils.applicationContext = applicationContext;
  24 + }
  25 +
  26 + /**
  27 + * 获取applicationContext
  28 + *
  29 + * @return
  30 + */
  31 + public static ApplicationContext getApplicationContext() {
  32 + return applicationContext;
  33 + }
  34 +
  35 + /**
  36 + * 获取HttpServletRequest
  37 + */
  38 + public static HttpServletRequest getHttpServletRequest() {
  39 + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
  40 + }
  41 +
  42 + /**
  43 + * 获取项目根路径 basePath
  44 + */
  45 + public static String getDomain(){
  46 + HttpServletRequest request = getHttpServletRequest();
  47 + StringBuffer url = request.getRequestURL();
  48 + //微服务情况下,获取gateway的basePath
  49 + String basePath = request.getHeader(ServiceNameConstants.X_GATEWAY_BASE_PATH);
  50 + if(oConvertUtils.isNotEmpty(basePath)){
  51 + return basePath;
  52 + }else{
  53 + return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
  54 + }
  55 + }
  56 +
  57 + public static String getOrigin(){
  58 + HttpServletRequest request = getHttpServletRequest();
  59 + return request.getHeader("Origin");
  60 + }
  61 +
  62 + /**
  63 + * 通过name获取 Bean.
  64 + *
  65 + * @param name
  66 + * @return
  67 + */
  68 + public static Object getBean(String name) {
  69 + return getApplicationContext().getBean(name);
  70 + }
  71 +
  72 + /**
  73 + * 通过class获取Bean.
  74 + *
  75 + * @param clazz
  76 + * @param <T>
  77 + * @return
  78 + */
  79 + public static <T> T getBean(Class<T> clazz) {
  80 + return getApplicationContext().getBean(clazz);
  81 + }
  82 +
  83 + /**
  84 + * 通过name,以及Clazz返回指定的Bean
  85 + *
  86 + * @param name
  87 + * @param clazz
  88 + * @param <T>
  89 + * @return
  90 + */
  91 + public static <T> T getBean(String name, Class<T> clazz) {
  92 + return getApplicationContext().getBean(name, clazz);
  93 + }
  94 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/SqlInjectionUtil.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import cn.hutool.crypto.SecureUtil;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.jeecg.common.exception.JeecgBootException;
  6 +import javax.servlet.http.HttpServletRequest;
  7 +
  8 +/**
  9 + * sql注入处理工具类
  10 + *
  11 + * @author zhoujf
  12 + */
  13 +@Slf4j
  14 +public class SqlInjectionUtil {
  15 + /**
  16 + * sign 用于表字典加签的盐值【SQL漏洞】
  17 + * (上线修改值 20200501,同步修改前端的盐值)
  18 + */
  19 + private final static String TABLE_DICT_SIGN_SALT = "20200501";
  20 + private final static String xssStr = "'|and |exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|or |+";
  21 +
  22 + /*
  23 + * 针对表字典进行额外的sign签名校验(增加安全机制)
  24 + * @param dictCode:
  25 + * @param sign:
  26 + * @param request:
  27 + * @Return: void
  28 + */
  29 + public static void checkDictTableSign(String dictCode, String sign, HttpServletRequest request) {
  30 + //表字典SQL注入漏洞,签名校验
  31 + String accessToken = request.getHeader("X-Access-Token");
  32 + String signStr = dictCode + SqlInjectionUtil.TABLE_DICT_SIGN_SALT + accessToken;
  33 + String javaSign = SecureUtil.md5(signStr);
  34 + if (!javaSign.equals(sign)) {
  35 + log.error("表字典,SQL注入漏洞签名校验失败 :" + sign + "!=" + javaSign+ ",dictCode=" + dictCode);
  36 + throw new JeecgBootException("无权限访问!");
  37 + }
  38 + log.info(" 表字典,SQL注入漏洞签名校验成功!sign=" + sign + ",dictCode=" + dictCode);
  39 + }
  40 +
  41 +
  42 + /**
  43 + * sql注入过滤处理,遇到注入关键字抛异常
  44 + *
  45 + * @param value
  46 + * @return
  47 + */
  48 + public static void filterContent(String value) {
  49 + if (value == null || "".equals(value)) {
  50 + return;
  51 + }
  52 + // 统一转为小写
  53 + value = value.toLowerCase();
  54 + String[] xssArr = xssStr.split("\\|");
  55 + for (int i = 0; i < xssArr.length; i++) {
  56 + if (value.indexOf(xssArr[i]) > -1) {
  57 + log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
  58 + log.error("请注意,值可能存在SQL注入风险!---> {}", value);
  59 + throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
  60 + }
  61 + }
  62 + return;
  63 + }
  64 +
  65 + /**
  66 + * sql注入过滤处理,遇到注入关键字抛异常
  67 + *
  68 + * @param values
  69 + * @return
  70 + */
  71 + public static void filterContent(String[] values) {
  72 + String[] xssArr = xssStr.split("\\|");
  73 + for (String value : values) {
  74 + if (value == null || "".equals(value)) {
  75 + return;
  76 + }
  77 + // 统一转为小写
  78 + value = value.toLowerCase();
  79 + for (int i = 0; i < xssArr.length; i++) {
  80 + if (value.indexOf(xssArr[i]) > -1) {
  81 + log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
  82 + log.error("请注意,值可能存在SQL注入风险!---> {}", value);
  83 + throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
  84 + }
  85 + }
  86 + }
  87 + return;
  88 + }
  89 +
  90 + /**
  91 + * @特殊方法(不通用) 仅用于字典条件SQL参数,注入过滤
  92 + * @param value
  93 + * @return
  94 + */
  95 + @Deprecated
  96 + public static void specialFilterContent(String value) {
  97 + String specialXssStr = " exec | insert | select | delete | update | drop | count | chr | mid | master | truncate | char | declare |;|+|";
  98 + String[] xssArr = specialXssStr.split("\\|");
  99 + if (value == null || "".equals(value)) {
  100 + return;
  101 + }
  102 + // 统一转为小写
  103 + value = value.toLowerCase();
  104 + for (int i = 0; i < xssArr.length; i++) {
  105 + if (value.indexOf(xssArr[i]) > -1 || value.startsWith(xssArr[i].trim())) {
  106 + log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
  107 + log.error("请注意,值可能存在SQL注入风险!---> {}", value);
  108 + throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
  109 + }
  110 + }
  111 + return;
  112 + }
  113 +
  114 +
  115 + /**
  116 + * @特殊方法(不通用) 仅用于Online报表SQL解析,注入过滤
  117 + * @param value
  118 + * @return
  119 + */
  120 + @Deprecated
  121 + public static void specialFilterContentForOnlineReport(String value) {
  122 + String specialXssStr = " exec | insert | delete | update | drop | chr | mid | master | truncate | char | declare |";
  123 + String[] xssArr = specialXssStr.split("\\|");
  124 + if (value == null || "".equals(value)) {
  125 + return;
  126 + }
  127 + // 统一转为小写
  128 + value = value.toLowerCase();
  129 + for (int i = 0; i < xssArr.length; i++) {
  130 + if (value.indexOf(xssArr[i]) > -1 || value.startsWith(xssArr[i].trim())) {
  131 + log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
  132 + log.error("请注意,值可能存在SQL注入风险!---> {}", value);
  133 + throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
  134 + }
  135 + }
  136 + return;
  137 + }
  138 +
  139 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/SysAnnmentTypeEnum.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +/**
  4 + * 系统公告自定义跳转方式
  5 + */
  6 +public enum SysAnnmentTypeEnum {
  7 + /**
  8 + * 邮件跳转组件
  9 + */
  10 + EMAIL("email", "component", "modules/eoa/email/modals/EoaEmailInForm"),
  11 + /**
  12 + * 工作流跳转链接我的办公
  13 + */
  14 + BPM("bpm", "url", "/bpm/task/MyTaskList");
  15 +
  16 + /**
  17 + * 业务类型(email:邮件 bpm:流程)
  18 + */
  19 + private String type;
  20 + /**
  21 + * 打开方式 组件:component 路由:url
  22 + */
  23 + private String openType;
  24 + /**
  25 + * 组件/路由 地址
  26 + */
  27 + private String openPage;
  28 +
  29 + SysAnnmentTypeEnum(String type, String openType, String openPage) {
  30 + this.type = type;
  31 + this.openType = openType;
  32 + this.openPage = openPage;
  33 + }
  34 +
  35 + public String getType() {
  36 + return type;
  37 + }
  38 +
  39 + public void setType(String type) {
  40 + this.type = type;
  41 + }
  42 +
  43 + public String getOpenType() {
  44 + return openType;
  45 + }
  46 +
  47 + public void setOpenType(String openType) {
  48 + this.openType = openType;
  49 + }
  50 +
  51 + public String getOpenPage() {
  52 + return openPage;
  53 + }
  54 +
  55 + public void setOpenPage(String openPage) {
  56 + this.openPage = openPage;
  57 + }
  58 +
  59 + public static SysAnnmentTypeEnum getByType(String type) {
  60 + if (oConvertUtils.isEmpty(type)) {
  61 + return null;
  62 + }
  63 + for (SysAnnmentTypeEnum val : values()) {
  64 + if (val.getType().equals(type)) {
  65 + return val;
  66 + }
  67 + }
  68 + return null;
  69 + }
  70 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/TokenUtils.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.apache.commons.lang3.StringUtils;
  5 +import org.apache.shiro.authc.AuthenticationException;
  6 +import org.jeecg.common.api.CommonAPI;
  7 +import org.jeecg.common.constant.CommonConstant;
  8 +import org.jeecg.common.system.util.JwtUtil;
  9 +import org.jeecg.common.system.vo.LoginUser;
  10 +
  11 +import javax.servlet.http.HttpServletRequest;
  12 +
  13 +/**
  14 + * @Author scott
  15 + * @Date 2019/9/23 14:12
  16 + * @Description: 编程校验token有效性
  17 + */
  18 +@Slf4j
  19 +public class TokenUtils {
  20 +
  21 + /**
  22 + * 获取 request 里传递的 token
  23 + *
  24 + * @param request
  25 + * @return
  26 + */
  27 + public static String getTokenByRequest(HttpServletRequest request) {
  28 + String token = request.getParameter("token");
  29 + if (token == null) {
  30 + token = request.getHeader("X-Access-Token");
  31 + }
  32 + return token;
  33 + }
  34 +
  35 + /**
  36 + * 验证Token
  37 + */
  38 + public static boolean verifyToken(HttpServletRequest request, CommonAPI commonAPI, RedisUtil redisUtil) {
  39 + log.debug(" -- url --" + request.getRequestURL());
  40 + String token = getTokenByRequest(request);
  41 +
  42 + if (StringUtils.isBlank(token)) {
  43 + throw new AuthenticationException("Token不能为空!");
  44 + }
  45 +
  46 + // 解密获得username,用于和数据库进行对比
  47 + String username = JwtUtil.getUsername(token);
  48 + if (username == null) {
  49 + throw new AuthenticationException("Token非法无效!");
  50 + }
  51 +
  52 + // 查询用户信息
  53 + LoginUser user = commonAPI.getUserByName(username);
  54 + if (user == null) {
  55 + throw new AuthenticationException("用户不存在!");
  56 + }
  57 + // 判断用户状态
  58 + if (user.getStatus() != 1) {
  59 + throw new AuthenticationException("账号已锁定,请联系管理员!");
  60 + }
  61 + // 校验token是否超时失效 & 或者账号密码是否错误
  62 + if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
  63 + throw new AuthenticationException("Token失效,请重新登录");
  64 + }
  65 + return true;
  66 + }
  67 +
  68 + /**
  69 + * 刷新token(保证用户在线操作不掉线)
  70 + * @param token
  71 + * @param userName
  72 + * @param passWord
  73 + * @param redisUtil
  74 + * @return
  75 + */
  76 + private static boolean jwtTokenRefresh(String token, String userName, String passWord, RedisUtil redisUtil) {
  77 + String cacheToken = String.valueOf(redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token));
  78 + if (oConvertUtils.isNotEmpty(cacheToken)) {
  79 + // 校验token有效性
  80 + if (!JwtUtil.verify(cacheToken, userName, passWord)) {
  81 + String newAuthorization = JwtUtil.sign(userName, passWord);
  82 + // 设置Toekn缓存有效时间
  83 + redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, newAuthorization);
  84 + redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000);
  85 + }
  86 + //update-begin--Author:scott Date:20191005 for:解决每次请求,都重写redis中 token缓存问题
  87 +// else {
  88 +// redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, cacheToken);
  89 +// // 设置超时时间
  90 +// redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
  91 +// }
  92 + //update-end--Author:scott Date:20191005 for:解决每次请求,都重写redis中 token缓存问题
  93 + return true;
  94 + }
  95 + return false;
  96 + }
  97 +
  98 + /**
  99 + * 验证Token
  100 + */
  101 + public static boolean verifyToken(String token, CommonAPI commonAPI, RedisUtil redisUtil) {
  102 + if (StringUtils.isBlank(token)) {
  103 + throw new AuthenticationException("token不能为空!");
  104 + }
  105 +
  106 + // 解密获得username,用于和数据库进行对比
  107 + String username = JwtUtil.getUsername(token);
  108 + if (username == null) {
  109 + throw new AuthenticationException("token非法无效!");
  110 + }
  111 +
  112 + // 查询用户信息
  113 + LoginUser user = commonAPI.getUserByName(username);
  114 + if (user == null) {
  115 + throw new AuthenticationException("用户不存在!");
  116 + }
  117 + // 判断用户状态
  118 + if (user.getStatus() != 1) {
  119 + throw new AuthenticationException("账号已被锁定,请联系管理员!");
  120 + }
  121 + // 校验token是否超时失效 & 或者账号密码是否错误
  122 + if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
  123 + throw new AuthenticationException("Token失效,请重新登录!");
  124 + }
  125 + return true;
  126 + }
  127 +
  128 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/UUIDGenerator.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +
  4 +import java.net.InetAddress;
  5 +
  6 +/**
  7 + *
  8 + * @Author 张代浩
  9 + *
  10 + */
  11 +public class UUIDGenerator {
  12 +
  13 +
  14 + /**
  15 + * 产生一个32位的UUID
  16 + *
  17 + * @return
  18 + */
  19 +
  20 + public static String generate() {
  21 + return new StringBuilder(32).append(format(getIP())).append(
  22 + format(getJVM())).append(format(getHiTime())).append(
  23 + format(getLoTime())).append(format(getCount())).toString();
  24 +
  25 + }
  26 +
  27 + private static final int IP;
  28 + static {
  29 + int ipadd;
  30 + try {
  31 + ipadd = toInt(InetAddress.getLocalHost().getAddress());
  32 + } catch (Exception e) {
  33 + ipadd = 0;
  34 + }
  35 + IP = ipadd;
  36 + }
  37 +
  38 + private static short counter = (short) 0;
  39 +
  40 + private static final int JVM = (int) (System.currentTimeMillis() >>> 8);
  41 +
  42 + private final static String format(int intval) {
  43 + String formatted = Integer.toHexString(intval);
  44 + StringBuilder buf = new StringBuilder("00000000");
  45 + buf.replace(8 - formatted.length(), 8, formatted);
  46 + return buf.toString();
  47 + }
  48 +
  49 + private final static String format(short shortval) {
  50 + String formatted = Integer.toHexString(shortval);
  51 + StringBuilder buf = new StringBuilder("0000");
  52 + buf.replace(4 - formatted.length(), 4, formatted);
  53 + return buf.toString();
  54 + }
  55 +
  56 + private final static int getJVM() {
  57 + return JVM;
  58 + }
  59 +
  60 + private final static short getCount() {
  61 + synchronized (UUIDGenerator.class) {
  62 + if (counter < 0) {
  63 + counter = 0;
  64 + }
  65 + return counter++;
  66 + }
  67 + }
  68 +
  69 + /**
  70 + * Unique in a local network
  71 + */
  72 + private final static int getIP() {
  73 + return IP;
  74 + }
  75 +
  76 + /**
  77 + * Unique down to millisecond
  78 + */
  79 + private final static short getHiTime() {
  80 + return (short) (System.currentTimeMillis() >>> 32);
  81 + }
  82 +
  83 + private final static int getLoTime() {
  84 + return (int) System.currentTimeMillis();
  85 + }
  86 +
  87 + private final static int toInt(byte[] bytes) {
  88 + int result = 0;
  89 + for (int i = 0; i < 4; i++) {
  90 + result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i];
  91 + }
  92 + return result;
  93 + }
  94 +
  95 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/YouBianCodeUtil.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import io.netty.util.internal.StringUtil;
  4 +
  5 +/**
  6 + * 流水号生成规则(按默认规则递增,数字从1-99开始递增,数字到99,递增字母;位数不够增加位数)
  7 + * A001
  8 + * A001A002
  9 + * @Author zhangdaihao
  10 + *
  11 + */
  12 +public class YouBianCodeUtil {
  13 +
  14 + // 数字位数(默认生成3位的数字)
  15 +
  16 + private static final int numLength = 2;//代表数字位数
  17 +
  18 + public static final int zhanweiLength = 1+numLength;
  19 +
  20 + /**
  21 + * 根据前一个code,获取同级下一个code
  22 + * 例如:当前最大code为D01A04,下一个code为:D01A05
  23 + *
  24 + * @param code
  25 + * @return
  26 + */
  27 + public static synchronized String getNextYouBianCode(String code) {
  28 + String newcode = "";
  29 + if (code == null || code =="") {
  30 + String zimu = "A";
  31 + String num = getStrNum(1);
  32 + newcode = zimu + num;
  33 + } else {
  34 + String before_code = code.substring(0, code.length() - 1- numLength);
  35 + String after_code = code.substring(code.length() - 1 - numLength,code.length());
  36 + char after_code_zimu = after_code.substring(0, 1).charAt(0);
  37 + Integer after_code_num = Integer.parseInt(after_code.substring(1));
  38 +// org.jeecgframework.core.util.LogUtil.info(after_code);
  39 +// org.jeecgframework.core.util.LogUtil.info(after_code_zimu);
  40 +// org.jeecgframework.core.util.LogUtil.info(after_code_num);
  41 +
  42 + String nextNum = "";
  43 + char nextZimu = 'A';
  44 + // 先判断数字等于999*,则计数从1重新开始,递增
  45 + if (after_code_num == getMaxNumByLength(numLength)) {
  46 + nextNum = getNextStrNum(0);
  47 + } else {
  48 + nextNum = getNextStrNum(after_code_num);
  49 + }
  50 + // 先判断数字等于999*,则字母从A重新开始,递增
  51 + if(after_code_num == getMaxNumByLength(numLength)) {
  52 + nextZimu = getNextZiMu(after_code_zimu);
  53 + }else{
  54 + nextZimu = after_code_zimu;
  55 + }
  56 +
  57 + // 例如Z99,下一个code就是Z99A01
  58 + if ('Z' == after_code_zimu && getMaxNumByLength(numLength) == after_code_num) {
  59 + newcode = code + (nextZimu + nextNum);
  60 + } else {
  61 + newcode = before_code + (nextZimu + nextNum);
  62 + }
  63 + }
  64 + return newcode;
  65 +
  66 + }
  67 +
  68 + /**
  69 + * 根据父亲code,获取下级的下一个code
  70 + *
  71 + * 例如:父亲CODE:A01
  72 + * 当前CODE:A01B03
  73 + * 获取的code:A01B04
  74 + *
  75 + * @param parentCode 上级code
  76 + * @param localCode 同级code
  77 + * @return
  78 + */
  79 + public static synchronized String getSubYouBianCode(String parentCode,String localCode) {
  80 + if(localCode!=null && localCode!=""){
  81 +
  82 +// return parentCode + getNextYouBianCode(localCode);
  83 + return getNextYouBianCode(localCode);
  84 +
  85 + }else{
  86 + parentCode = parentCode + "A"+ getNextStrNum(0);
  87 + }
  88 + return parentCode;
  89 + }
  90 +
  91 +
  92 +
  93 + /**
  94 + * 将数字前面位数补零
  95 + *
  96 + * @param num
  97 + * @return
  98 + */
  99 + private static String getNextStrNum(int num) {
  100 + return getStrNum(getNextNum(num));
  101 + }
  102 +
  103 + /**
  104 + * 将数字前面位数补零
  105 + *
  106 + * @param num
  107 + * @return
  108 + */
  109 + private static String getStrNum(int num) {
  110 + String s = String.format("%0" + numLength + "d", num);
  111 + return s;
  112 + }
  113 +
  114 + /**
  115 + * 递增获取下个数字
  116 + *
  117 + * @param num
  118 + * @return
  119 + */
  120 + private static int getNextNum(int num) {
  121 + num++;
  122 + return num;
  123 + }
  124 +
  125 + /**
  126 + * 递增获取下个字母
  127 + *
  128 + * @param num
  129 + * @return
  130 + */
  131 + private static char getNextZiMu(char zimu) {
  132 + if (zimu == 'Z') {
  133 + return 'A';
  134 + }
  135 + zimu++;
  136 + return zimu;
  137 + }
  138 +
  139 + /**
  140 + * 根据数字位数获取最大值
  141 + * @param length
  142 + * @return
  143 + */
  144 + private static int getMaxNumByLength(int length){
  145 + if(length==0){
  146 + return 0;
  147 + }
  148 + String max_num = "";
  149 + for (int i=0;i<length;i++){
  150 + max_num = max_num + "9";
  151 + }
  152 + return Integer.parseInt(max_num);
  153 + }
  154 + public static String[] cutYouBianCode(String code){
  155 + if(code==null || StringUtil.isNullOrEmpty(code)){
  156 + return null;
  157 + }else{
  158 + //获取标准长度为numLength+1,截取的数量为code.length/numLength+1
  159 + int c = code.length()/(numLength+1);
  160 + String[] cutcode = new String[c];
  161 + for(int i =0 ; i <c;i++){
  162 + cutcode[i] = code.substring(0,(i+1)*(numLength+1));
  163 + }
  164 + return cutcode;
  165 + }
  166 +
  167 + }
  168 +// public static void main(String[] args) {
  169 +// // org.jeecgframework.core.util.LogUtil.info(getNextZiMu('C'));
  170 +// // org.jeecgframework.core.util.LogUtil.info(getNextNum(8));
  171 +// // org.jeecgframework.core.util.LogUtil.info(cutYouBianCode("C99A01B01")[2]);
  172 +// }
  173 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/dynamic/db/DataSourceCachePool.java 0 → 100644
  1 +package org.jeecg.common.util.dynamic.db;
  2 +
  3 +import com.alibaba.druid.pool.DruidDataSource;
  4 +import org.jeecg.common.api.CommonAPI;
  5 +import org.jeecg.common.constant.CacheConstant;
  6 +import org.jeecg.common.system.vo.DynamicDataSourceModel;
  7 +import org.jeecg.common.util.RedisUtil;
  8 +import org.jeecg.common.util.SpringContextUtils;
  9 +import org.springframework.data.redis.core.RedisTemplate;
  10 +import java.util.HashMap;
  11 +import java.util.Map;
  12 +
  13 +
  14 +/**
  15 + * 数据源缓存池
  16 + */
  17 +public class DataSourceCachePool {
  18 + /** 数据源连接池缓存【本地 class缓存 - 不支持分布式】 */
  19 + private static Map<String, DruidDataSource> dbSources = new HashMap<>();
  20 + private static RedisTemplate<String, Object> redisTemplate;
  21 +
  22 + private static RedisTemplate<String, Object> getRedisTemplate() {
  23 + if (redisTemplate == null) {
  24 + redisTemplate = (RedisTemplate<String, Object>) SpringContextUtils.getBean("redisTemplate");
  25 + }
  26 + return redisTemplate;
  27 + }
  28 +
  29 + /**
  30 + * 获取多数据源缓存
  31 + *
  32 + * @param dbKey
  33 + * @return
  34 + */
  35 + public static DynamicDataSourceModel getCacheDynamicDataSourceModel(String dbKey) {
  36 + String redisCacheKey = CacheConstant.SYS_DYNAMICDB_CACHE + dbKey;
  37 + if (getRedisTemplate().hasKey(redisCacheKey)) {
  38 + return (DynamicDataSourceModel) getRedisTemplate().opsForValue().get(redisCacheKey);
  39 + }
  40 + CommonAPI commonAPI = SpringContextUtils.getBean(CommonAPI.class);
  41 + DynamicDataSourceModel dbSource = commonAPI.getDynamicDbSourceByCode(dbKey);
  42 + if (dbSource != null) {
  43 + getRedisTemplate().opsForValue().set(redisCacheKey, dbSource);
  44 + }
  45 + return dbSource;
  46 + }
  47 +
  48 + public static DruidDataSource getCacheBasicDataSource(String dbKey) {
  49 + return dbSources.get(dbKey);
  50 + }
  51 +
  52 + /**
  53 + * put 数据源缓存
  54 + *
  55 + * @param dbKey
  56 + * @param db
  57 + */
  58 + public static void putCacheBasicDataSource(String dbKey, DruidDataSource db) {
  59 + dbSources.put(dbKey, db);
  60 + }
  61 +
  62 + /**
  63 + * 清空数据源缓存
  64 + */
  65 + public static void cleanAllCache() {
  66 + //关闭数据源连接
  67 + for(Map.Entry<String, DruidDataSource> entry : dbSources.entrySet()){
  68 + String dbkey = entry.getKey();
  69 + DruidDataSource druidDataSource = entry.getValue();
  70 + if(druidDataSource!=null && druidDataSource.isEnable()){
  71 + druidDataSource.close();
  72 + }
  73 + //清空redis缓存
  74 + getRedisTemplate().delete(CacheConstant.SYS_DYNAMICDB_CACHE + dbkey);
  75 + }
  76 + //清空缓存
  77 + dbSources.clear();
  78 + }
  79 +
  80 + public static void removeCache(String dbKey) {
  81 + //关闭数据源连接
  82 + DruidDataSource druidDataSource = dbSources.get(dbKey);
  83 + if(druidDataSource!=null && druidDataSource.isEnable()){
  84 + druidDataSource.close();
  85 + }
  86 + //清空redis缓存
  87 + getRedisTemplate().delete(CacheConstant.SYS_DYNAMICDB_CACHE + dbKey);
  88 + //清空缓存
  89 + dbSources.remove(dbKey);
  90 + }
  91 +
  92 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/dynamic/db/DynamicDBUtil.java 0 → 100644
  1 +package org.jeecg.common.util.dynamic.db;
  2 +
  3 +import com.alibaba.druid.pool.DruidDataSource;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.apache.commons.lang3.ArrayUtils;
  6 +import org.jeecg.common.exception.JeecgBootException;
  7 +import org.jeecg.common.exception.JeecgBootException;
  8 +import org.jeecg.common.system.vo.DynamicDataSourceModel;
  9 +import org.jeecg.common.util.ReflectHelper;
  10 +import org.jeecg.common.util.oConvertUtils;
  11 +import org.springframework.jdbc.core.JdbcTemplate;
  12 +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
  13 +
  14 +import javax.sql.DataSource;
  15 +import java.sql.SQLException;
  16 +import java.util.HashMap;
  17 +import java.util.List;
  18 +import java.util.Map;
  19 +
  20 +/**
  21 + * Spring JDBC 实时数据库访问
  22 + *
  23 + * @author chenguobin
  24 + * @version 1.0
  25 + * @date 2014-09-05
  26 + */
  27 +@Slf4j
  28 +public class DynamicDBUtil {
  29 +
  30 + /**
  31 + * 获取数据源【最底层方法,不要随便调用】
  32 + *
  33 + * @param dbSource
  34 + * @return
  35 + */
  36 + private static DruidDataSource getJdbcDataSource(final DynamicDataSourceModel dbSource) {
  37 + DruidDataSource dataSource = new DruidDataSource();
  38 +
  39 + String driverClassName = dbSource.getDbDriver();
  40 + String url = dbSource.getDbUrl();
  41 + String dbUser = dbSource.getDbUsername();
  42 + String dbPassword = dbSource.getDbPassword();
  43 + dataSource.setDriverClassName(driverClassName);
  44 + dataSource.setUrl(url);
  45 + //dataSource.setValidationQuery("SELECT 1 FROM DUAL");
  46 + dataSource.setTestWhileIdle(true);
  47 + dataSource.setTestOnBorrow(false);
  48 + dataSource.setTestOnReturn(false);
  49 + dataSource.setBreakAfterAcquireFailure(true);
  50 + dataSource.setConnectionErrorRetryAttempts(0);
  51 + dataSource.setUsername(dbUser);
  52 + dataSource.setMaxWait(60000);
  53 + dataSource.setPassword(dbPassword);
  54 +
  55 + log.info("******************************************");
  56 + log.info("* *");
  57 + log.info("*====【"+dbSource.getCode()+"】=====Druid连接池已启用 ====*");
  58 + log.info("* *");
  59 + log.info("******************************************");
  60 + return dataSource;
  61 + }
  62 +
  63 + /**
  64 + * 通过 dbKey ,获取数据源
  65 + *
  66 + * @param dbKey
  67 + * @return
  68 + */
  69 + public static DruidDataSource getDbSourceByDbKey(final String dbKey) {
  70 + //获取多数据源配置
  71 + DynamicDataSourceModel dbSource = DataSourceCachePool.getCacheDynamicDataSourceModel(dbKey);
  72 + //先判断缓存中是否存在数据库链接
  73 + DruidDataSource cacheDbSource = DataSourceCachePool.getCacheBasicDataSource(dbKey);
  74 + if (cacheDbSource != null && !cacheDbSource.isClosed()) {
  75 + log.debug("--------getDbSourceBydbKey------------------从缓存中获取DB连接-------------------");
  76 + return cacheDbSource;
  77 + } else {
  78 + DruidDataSource dataSource = getJdbcDataSource(dbSource);
  79 + if(dataSource!=null && dataSource.isEnable()){
  80 + DataSourceCachePool.putCacheBasicDataSource(dbKey, dataSource);
  81 + }else{
  82 + throw new JeecgBootException("动态数据源连接失败,dbKey:"+dbKey);
  83 + }
  84 + log.info("--------getDbSourceBydbKey------------------创建DB数据库连接-------------------");
  85 + return dataSource;
  86 + }
  87 + }
  88 +
  89 + /**
  90 + * 关闭数据库连接池
  91 + *
  92 + * @param dbKey
  93 + * @return
  94 + */
  95 + public static void closeDbKey(final String dbKey) {
  96 + DruidDataSource dataSource = getDbSourceByDbKey(dbKey);
  97 + try {
  98 + if (dataSource != null && !dataSource.isClosed()) {
  99 + dataSource.getConnection().commit();
  100 + dataSource.getConnection().close();
  101 + dataSource.close();
  102 + }
  103 + } catch (SQLException e) {
  104 + e.printStackTrace();
  105 + }
  106 + }
  107 +
  108 +
  109 + private static JdbcTemplate getJdbcTemplate(String dbKey) {
  110 + DruidDataSource dataSource = getDbSourceByDbKey(dbKey);
  111 + return new JdbcTemplate(dataSource);
  112 + }
  113 +
  114 + /**
  115 + * Executes the SQL statement in this <code>PreparedStatement</code> object,
  116 + * which must be an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
  117 + * <code>DELETE</code>; or an SQL statement that returns nothing,
  118 + * such as a DDL statement.
  119 + */
  120 + public static int update(final String dbKey, String sql, Object... param) {
  121 + int effectCount;
  122 + JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
  123 + if (ArrayUtils.isEmpty(param)) {
  124 + effectCount = jdbcTemplate.update(sql);
  125 + } else {
  126 + effectCount = jdbcTemplate.update(sql, param);
  127 + }
  128 + return effectCount;
  129 + }
  130 +
  131 + /**
  132 + * 支持miniDao语法操作的Update
  133 + *
  134 + * @param dbKey 数据源标识
  135 + * @param sql 执行sql语句,sql支持minidao语法逻辑
  136 + * @param data sql语法中需要判断的数据及sql拼接注入中需要的数据
  137 + * @return
  138 + */
  139 + public static int updateByHash(final String dbKey, String sql, HashMap<String, Object> data) {
  140 + int effectCount;
  141 + JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
  142 + //根据模板获取sql
  143 + sql = FreemarkerParseFactory.parseTemplateContent(sql, data);
  144 + NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate.getDataSource());
  145 + effectCount = namedParameterJdbcTemplate.update(sql, data);
  146 + return effectCount;
  147 + }
  148 +
  149 + public static Object findOne(final String dbKey, String sql, Object... param) {
  150 + List<Map<String, Object>> list;
  151 + list = findList(dbKey, sql, param);
  152 + if (oConvertUtils.listIsEmpty(list)) {
  153 + log.error("Except one, but not find actually");
  154 + }
  155 + if (list.size() > 1) {
  156 + log.error("Except one, but more than one actually");
  157 + }
  158 + return list.get(0);
  159 + }
  160 +
  161 + /**
  162 + * 支持miniDao语法操作的查询 返回HashMap
  163 + *
  164 + * @param dbKey 数据源标识
  165 + * @param sql 执行sql语句,sql支持minidao语法逻辑
  166 + * @param data sql语法中需要判断的数据及sql拼接注入中需要的数据
  167 + * @return
  168 + */
  169 + public static Object findOneByHash(final String dbKey, String sql, HashMap<String, Object> data) {
  170 + List<Map<String, Object>> list;
  171 + list = findListByHash(dbKey, sql, data);
  172 + if (oConvertUtils.listIsEmpty(list)) {
  173 + log.error("Except one, but not find actually");
  174 + }
  175 + if (list.size() > 1) {
  176 + log.error("Except one, but more than one actually");
  177 + }
  178 + return list.get(0);
  179 + }
  180 +
  181 + /**
  182 + * 直接sql查询 根据clazz返回单个实例
  183 + *
  184 + * @param dbKey 数据源标识
  185 + * @param sql 执行sql语句
  186 + * @param clazz 返回实例的Class
  187 + * @param param
  188 + * @return
  189 + */
  190 + @SuppressWarnings("unchecked")
  191 + public static <T> Object findOne(final String dbKey, String sql, Class<T> clazz, Object... param) {
  192 + Map<String, Object> map = (Map<String, Object>) findOne(dbKey, sql, param);
  193 + return ReflectHelper.setAll(clazz, map);
  194 + }
  195 +
  196 + /**
  197 + * 支持miniDao语法操作的查询 返回单个实例
  198 + *
  199 + * @param dbKey 数据源标识
  200 + * @param sql 执行sql语句,sql支持minidao语法逻辑
  201 + * @param clazz 返回实例的Class
  202 + * @param data sql语法中需要判断的数据及sql拼接注入中需要的数据
  203 + * @return
  204 + */
  205 + @SuppressWarnings("unchecked")
  206 + public static <T> Object findOneByHash(final String dbKey, String sql, Class<T> clazz, HashMap<String, Object> data) {
  207 + Map<String, Object> map = (Map<String, Object>) findOneByHash(dbKey, sql, data);
  208 + return ReflectHelper.setAll(clazz, map);
  209 + }
  210 +
  211 + public static List<Map<String, Object>> findList(final String dbKey, String sql, Object... param) {
  212 + List<Map<String, Object>> list;
  213 + JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
  214 +
  215 + if (ArrayUtils.isEmpty(param)) {
  216 + list = jdbcTemplate.queryForList(sql);
  217 + } else {
  218 + list = jdbcTemplate.queryForList(sql, param);
  219 + }
  220 + return list;
  221 + }
  222 +
  223 + /**
  224 + * 支持miniDao语法操作的查询
  225 + *
  226 + * @param dbKey 数据源标识
  227 + * @param sql 执行sql语句,sql支持minidao语法逻辑
  228 + * @param data sql语法中需要判断的数据及sql拼接注入中需要的数据
  229 + * @return
  230 + */
  231 + public static List<Map<String, Object>> findListByHash(final String dbKey, String sql, HashMap<String, Object> data) {
  232 + List<Map<String, Object>> list;
  233 + JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
  234 + //根据模板获取sql
  235 + sql = FreemarkerParseFactory.parseTemplateContent(sql, data);
  236 + NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate.getDataSource());
  237 + list = namedParameterJdbcTemplate.queryForList(sql, data);
  238 + return list;
  239 + }
  240 +
  241 + //此方法只能返回单列,不能返回实体类
  242 + public static <T> List<T> findList(final String dbKey, String sql, Class<T> clazz, Object... param) {
  243 + List<T> list;
  244 + JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
  245 +
  246 + if (ArrayUtils.isEmpty(param)) {
  247 + list = jdbcTemplate.queryForList(sql, clazz);
  248 + } else {
  249 + list = jdbcTemplate.queryForList(sql, clazz, param);
  250 + }
  251 + return list;
  252 + }
  253 +
  254 + /**
  255 + * 支持miniDao语法操作的查询 返回单列数据list
  256 + *
  257 + * @param dbKey 数据源标识
  258 + * @param sql 执行sql语句,sql支持minidao语法逻辑
  259 + * @param clazz 类型Long、String等
  260 + * @param data sql语法中需要判断的数据及sql拼接注入中需要的数据
  261 + * @return
  262 + */
  263 + public static <T> List<T> findListByHash(final String dbKey, String sql, Class<T> clazz, HashMap<String, Object> data) {
  264 + List<T> list;
  265 + JdbcTemplate jdbcTemplate = getJdbcTemplate(dbKey);
  266 + //根据模板获取sql
  267 + sql = FreemarkerParseFactory.parseTemplateContent(sql, data);
  268 + NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate.getDataSource());
  269 + list = namedParameterJdbcTemplate.queryForList(sql, data, clazz);
  270 + return list;
  271 + }
  272 +
  273 + /**
  274 + * 直接sql查询 返回实体类列表
  275 + *
  276 + * @param dbKey 数据源标识
  277 + * @param sql 执行sql语句,sql支持 minidao 语法逻辑
  278 + * @param clazz 返回实体类列表的class
  279 + * @param param sql拼接注入中需要的数据
  280 + * @return
  281 + */
  282 + public static <T> List<T> findListEntities(final String dbKey, String sql, Class<T> clazz, Object... param) {
  283 + List<Map<String, Object>> queryList = findList(dbKey, sql, param);
  284 + return ReflectHelper.transList2Entrys(queryList, clazz);
  285 + }
  286 +
  287 + /**
  288 + * 支持miniDao语法操作的查询 返回实体类列表
  289 + *
  290 + * @param dbKey 数据源标识
  291 + * @param sql 执行sql语句,sql支持minidao语法逻辑
  292 + * @param clazz 返回实体类列表的class
  293 + * @param data sql语法中需要判断的数据及sql拼接注入中需要的数据
  294 + * @return
  295 + */
  296 + public static <T> List<T> findListEntitiesByHash(final String dbKey, String sql, Class<T> clazz, HashMap<String, Object> data) {
  297 + List<Map<String, Object>> queryList = findListByHash(dbKey, sql, data);
  298 + return ReflectHelper.transList2Entrys(queryList, clazz);
  299 + }
  300 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/dynamic/db/FreemarkerParseFactory.java 0 → 100644
  1 +package org.jeecg.common.util.dynamic.db;
  2 +
  3 +import freemarker.cache.StringTemplateLoader;
  4 +import freemarker.core.ParseException;
  5 +import freemarker.template.Configuration;
  6 +import freemarker.template.Template;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.apache.commons.lang3.StringUtils;
  9 +import org.jeecgframework.codegenerate.generate.util.SimpleFormat;
  10 +
  11 +import java.io.StringWriter;
  12 +import java.util.Map;
  13 +import java.util.regex.Pattern;
  14 +
  15 +/**
  16 + * @author 赵俊夫
  17 + * @version V1.0
  18 + * @Title:FreemarkerHelper
  19 + * @description:Freemarker引擎协助类
  20 + * @date Jul 5, 2013 2:58:29 PM
  21 + */
  22 +@Slf4j
  23 +public class FreemarkerParseFactory {
  24 +
  25 + private static final String ENCODE = "utf-8";
  26 + /**
  27 + * 参数格式化工具类
  28 + */
  29 + private static final String MINI_DAO_FORMAT = "DaoFormat";
  30 +
  31 + /**
  32 + * 文件缓存
  33 + */
  34 + private static final Configuration _tplConfig = new Configuration();
  35 + /**
  36 + * SQL 缓存
  37 + */
  38 + private static final Configuration _sqlConfig = new Configuration();
  39 +
  40 + private static StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
  41 +
  42 + // 使用内嵌的(?ms)打开单行和多行模式
  43 + private final static Pattern p = Pattern
  44 + .compile("(?ms)/\\*.*?\\*/|^\\s*//.*?$");
  45 +
  46 + static {
  47 + _tplConfig.setClassForTemplateLoading(
  48 + new FreemarkerParseFactory().getClass(), "/");
  49 + _tplConfig.setNumberFormat("0.#####################");
  50 + _sqlConfig.setTemplateLoader(stringTemplateLoader);
  51 + _sqlConfig.setNumberFormat("0.#####################");
  52 + //classic_compatible设置,解决报空指针错误
  53 + _sqlConfig.setClassicCompatible(true);
  54 + }
  55 +
  56 + /**
  57 + * 判断模板是否存在
  58 + *
  59 + * @throws Exception
  60 + */
  61 + public static boolean isExistTemplate(String tplName) throws Exception {
  62 + try {
  63 + Template mytpl = _tplConfig.getTemplate(tplName, "UTF-8");
  64 + if (mytpl == null) {
  65 + return false;
  66 + }
  67 + } catch (Exception e) {
  68 + //update-begin--Author:scott Date:20180320 for:解决问题 - 错误提示sql文件不存在,实际问题是sql freemarker用法错误-----
  69 + if (e instanceof ParseException) {
  70 + log.error(e.getMessage(), e.fillInStackTrace());
  71 + throw new Exception(e);
  72 + }
  73 + log.debug("----isExistTemplate----" + e.toString());
  74 + //update-end--Author:scott Date:20180320 for:解决问题 - 错误提示sql文件不存在,实际问题是sql freemarker用法错误------
  75 + return false;
  76 + }
  77 + return true;
  78 + }
  79 +
  80 + /**
  81 + * 解析ftl模板
  82 + *
  83 + * @param tplName 模板名
  84 + * @param paras 参数
  85 + * @return
  86 + */
  87 + public static String parseTemplate(String tplName, Map<String, Object> paras) {
  88 + try {
  89 + log.debug(" minidao sql templdate : " + tplName);
  90 + StringWriter swriter = new StringWriter();
  91 + Template mytpl = _tplConfig.getTemplate(tplName, ENCODE);
  92 + if (paras.containsKey(MINI_DAO_FORMAT)) {
  93 + throw new RuntimeException("DaoFormat 是 minidao 保留关键字,不允许使用 ,请更改参数定义!");
  94 + }
  95 + paras.put(MINI_DAO_FORMAT, new SimpleFormat());
  96 + mytpl.process(paras, swriter);
  97 + String sql = getSqlText(swriter.toString());
  98 + paras.remove(MINI_DAO_FORMAT);
  99 + return sql;
  100 + } catch (Exception e) {
  101 + log.error(e.getMessage(), e.fillInStackTrace());
  102 + log.error("发送一次的模板key:{ " + tplName + " }");
  103 + //System.err.println(e.getMessage());
  104 + //System.err.println("模板名:{ "+ tplName +" }");
  105 + throw new RuntimeException("解析SQL模板异常");
  106 + }
  107 + }
  108 +
  109 + /**
  110 + * 解析ftl
  111 + *
  112 + * @param tplContent 模板内容
  113 + * @param paras 参数
  114 + * @return String 模板解析后内容
  115 + */
  116 + public static String parseTemplateContent(String tplContent,
  117 + Map<String, Object> paras) {
  118 + try {
  119 + StringWriter swriter = new StringWriter();
  120 + if (stringTemplateLoader.findTemplateSource("sql_" + tplContent.hashCode()) == null) {
  121 + stringTemplateLoader.putTemplate("sql_" + tplContent.hashCode(), tplContent);
  122 + }
  123 + Template mytpl = _sqlConfig.getTemplate("sql_" + tplContent.hashCode(), ENCODE);
  124 + if (paras.containsKey(MINI_DAO_FORMAT)) {
  125 + throw new RuntimeException("DaoFormat 是 minidao 保留关键字,不允许使用 ,请更改参数定义!");
  126 + }
  127 + paras.put(MINI_DAO_FORMAT, new SimpleFormat());
  128 + mytpl.process(paras, swriter);
  129 + String sql = getSqlText(swriter.toString());
  130 + paras.remove(MINI_DAO_FORMAT);
  131 + return sql;
  132 + } catch (Exception e) {
  133 + log.error(e.getMessage(), e.fillInStackTrace());
  134 + log.error("发送一次的模板key:{ " + tplContent + " }");
  135 + //System.err.println(e.getMessage());
  136 + //System.err.println("模板内容:{ "+ tplContent +" }");
  137 + throw new RuntimeException("解析SQL模板异常");
  138 + }
  139 + }
  140 +
  141 + /**
  142 + * 除去无效字段,去掉注释 不然批量处理可能报错 去除无效的等于
  143 + */
  144 + private static String getSqlText(String sql) {
  145 + // 将注释替换成""
  146 + sql = p.matcher(sql).replaceAll("");
  147 + sql = sql.replaceAll("\\n", " ").replaceAll("\\t", " ")
  148 + .replaceAll("\\s{1,}", " ").trim();
  149 + // 去掉 最后是 where这样的问题
  150 + if (sql.endsWith("where") || sql.endsWith("where ")) {
  151 + sql = sql.substring(0, sql.lastIndexOf("where"));
  152 + }
  153 + // 去掉where and 这样的问题
  154 + int index = 0;
  155 + while ((index = StringUtils.indexOfIgnoreCase(sql, "where and", index)) != -1) {
  156 + sql = sql.substring(0, index + 5)
  157 + + sql.substring(index + 9, sql.length());
  158 + }
  159 + // 去掉 , where 这样的问题
  160 + index = 0;
  161 + while ((index = StringUtils.indexOfIgnoreCase(sql, ", where", index)) != -1) {
  162 + sql = sql.substring(0, index)
  163 + + sql.substring(index + 1, sql.length());
  164 + }
  165 + // 去掉 最后是 ,这样的问题
  166 + if (sql.endsWith(",") || sql.endsWith(", ")) {
  167 + sql = sql.substring(0, sql.lastIndexOf(","));
  168 + }
  169 + return sql;
  170 + }
  171 +}
0 \ No newline at end of file 172 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/dynamic/db/SqlUtils.java 0 → 100644
  1 +package org.jeecg.common.util.dynamic.db;
  2 +
  3 +import org.apache.commons.lang3.StringUtils;
  4 +import org.jeecg.common.constant.DataBaseConstant;
  5 +import org.jeecg.common.system.vo.DynamicDataSourceModel;
  6 +
  7 +import java.text.MessageFormat;
  8 +import java.util.Map;
  9 +
  10 +/**
  11 + * 根据不同的数据库,动态生成SQL,例如分页
  12 + */
  13 +public class SqlUtils {
  14 +
  15 + public static final String DATABSE_TYPE_MYSQL = "mysql";
  16 + public static final String DATABSE_TYPE_MARIADB = "mariadb";
  17 + public static final String DATABSE_TYPE_POSTGRE = "postgresql";
  18 + public static final String DATABSE_TYPE_ORACLE = "oracle";
  19 + public static final String DATABSE_TYPE_SQLSERVER = "sqlserver";
  20 +
  21 +
  22 + /**
  23 + * 分页SQL
  24 + */
  25 + public static final String MYSQL_SQL = "select * from ( {0}) sel_tab00 limit {1},{2}";
  26 + public static final String POSTGRE_SQL = "select * from ( {0}) sel_tab00 limit {2} offset {1}";
  27 + public static final String ORACLE_SQL = "select * from (select row_.*,rownum rownum_ from ({0}) row_ where rownum <= {1}) where rownum_>{2}";
  28 + public static final String SQLSERVER_SQL = "select * from ( select row_number() over(order by tempColumn) tempRowNumber, * from (select top {1} tempColumn = 0, {0}) t ) tt where tempRowNumber > {2}";
  29 +
  30 + /**
  31 + * 获取所有表的SQL
  32 + */
  33 + public static final String MYSQL_ALLTABLES_SQL = "select distinct table_name from information_schema.columns where table_schema = {0}";
  34 + public static final String POSTGRE__ALLTABLES_SQL = "SELECT distinct c.relname AS table_name FROM pg_class c";
  35 + public static final String ORACLE__ALLTABLES_SQL = "select distinct colstable.table_name as table_name from user_tab_cols colstable";
  36 + public static final String SQLSERVER__ALLTABLES_SQL = "select distinct c.name as table_name from sys.objects c";
  37 +
  38 + /**
  39 + * 获取指定表的所有列名
  40 + */
  41 + public static final String MYSQL_ALLCOLUMNS_SQL = "select column_name from information_schema.columns where table_name = {0} and table_schema = {1}";
  42 + public static final String POSTGRE_ALLCOLUMNS_SQL = "select table_name from information_schema.columns where table_name = {0}";
  43 + public static final String ORACLE_ALLCOLUMNS_SQL = "select column_name from all_tab_columns where table_name ={0}";
  44 + public static final String SQLSERVER_ALLCOLUMNS_SQL = "select name from syscolumns where id={0}";
  45 +
  46 + /*
  47 + * 判断数据库类型
  48 + */
  49 +
  50 + public static boolean dbTypeIsMySQL(String dbType) {
  51 + return dbTypeIf(dbType, DATABSE_TYPE_MYSQL, DataBaseConstant.DB_TYPE_MYSQL_NUM) || dbTypeIf(dbType, DATABSE_TYPE_MARIADB, DataBaseConstant.DB_TYPE_MARIADB_NUM);
  52 + }
  53 +
  54 + public static boolean dbTypeIsOracle(String dbType) {
  55 + return dbTypeIf(dbType, DATABSE_TYPE_ORACLE, DataBaseConstant.DB_TYPE_ORACLE_NUM);
  56 + }
  57 +
  58 + public static boolean dbTypeIsSQLServer(String dbType) {
  59 + return dbTypeIf(dbType, DATABSE_TYPE_SQLSERVER, DataBaseConstant.DB_TYPE_SQLSERVER_NUM);
  60 + }
  61 +
  62 + public static boolean dbTypeIsPostgre(String dbType) {
  63 + return dbTypeIf(dbType, DATABSE_TYPE_POSTGRE, DataBaseConstant.DB_TYPE_POSTGRESQL_NUM);
  64 + }
  65 +
  66 + /**
  67 + * 判断数据库类型
  68 + */
  69 + public static boolean dbTypeIf(String dbType, String... correctTypes) {
  70 + for (String type : correctTypes) {
  71 + if (type.equalsIgnoreCase(dbType)) {
  72 + return true;
  73 + }
  74 + }
  75 + return false;
  76 + }
  77 +
  78 + /**
  79 + * 获取全 SQL
  80 + * 拼接 where 条件
  81 + *
  82 + * @param sql
  83 + * @param params
  84 + * @return
  85 + */
  86 + public static String getFullSql(String sql, Map params) {
  87 + return getFullSql(sql, params, null, null);
  88 + }
  89 +
  90 + /**
  91 + * 获取全 SQL
  92 + * 拼接 where 条件
  93 + * 拼接 order 排序
  94 + *
  95 + * @param sql
  96 + * @param params
  97 + * @param orderColumn 排序字段
  98 + * @param orderBy 排序方式,只能是 DESC 或 ASC
  99 + * @return
  100 + */
  101 + public static String getFullSql(String sql, Map params, String orderColumn, String orderBy) {
  102 + StringBuilder sqlBuilder = new StringBuilder();
  103 + sqlBuilder.append("SELECT t.* FROM ( ").append(sql).append(" ) t ");
  104 + if (params != null && params.size() >= 1) {
  105 + sqlBuilder.append("WHERE 1=1 ");
  106 + for (Object key : params.keySet()) {
  107 + String value = String.valueOf(params.get(key));
  108 + if (StringUtils.isNotBlank(value)) {
  109 + sqlBuilder.append(" AND (").append(key).append(" = N'").append(value).append("')");
  110 + }
  111 + }
  112 + if (StringUtils.isNotBlank(orderColumn) && StringUtils.isNotBlank(orderBy)) {
  113 + sqlBuilder.append("ORDER BY ").append(orderColumn).append(" ").append("DESC".equalsIgnoreCase(orderBy) ? "DESC" : "ASC");
  114 + }
  115 + }
  116 + return sqlBuilder.toString();
  117 + }
  118 +
  119 + /**
  120 + * 获取求数量 SQL
  121 + *
  122 + * @param sql
  123 + * @return
  124 + */
  125 + public static String getCountSql(String sql) {
  126 + return String.format("SELECT COUNT(1) \"total\" FROM ( %s ) temp_count", sql);
  127 + }
  128 +
  129 + /**
  130 + * 生成分页查询 SQL
  131 + *
  132 + * @param dbType 数据库类型
  133 + * @param sql
  134 + * @param page
  135 + * @param rows
  136 + * @return
  137 + */
  138 + public static String createPageSqlByDBType(String dbType, String sql, int page, int rows) {
  139 + int beginNum = (page - 1) * rows;
  140 + Object[] sqlParam = new Object[3];
  141 + sqlParam[0] = sql;
  142 + sqlParam[1] = String.valueOf(beginNum);
  143 + sqlParam[2] = String.valueOf(rows);
  144 + if (dbTypeIsMySQL(dbType)) {
  145 + sql = MessageFormat.format(MYSQL_SQL, sqlParam);
  146 + } else if (dbTypeIsPostgre(dbType)) {
  147 + sql = MessageFormat.format(POSTGRE_SQL, sqlParam);
  148 + } else {
  149 + int beginIndex = (page - 1) * rows;
  150 + int endIndex = beginIndex + rows;
  151 + sqlParam[2] = Integer.toString(beginIndex);
  152 + sqlParam[1] = Integer.toString(endIndex);
  153 + if (dbTypeIsOracle(dbType)) {
  154 + sql = MessageFormat.format(ORACLE_SQL, sqlParam);
  155 + } else if (dbTypeIsSQLServer(dbType)) {
  156 + sqlParam[0] = sql.substring(getAfterSelectInsertPoint(sql));
  157 + sql = MessageFormat.format(SQLSERVER_SQL, sqlParam);
  158 + }
  159 + }
  160 + return sql;
  161 + }
  162 +
  163 + /**
  164 + * 生成分页查询 SQL
  165 + *
  166 + * @param sql
  167 + * @param page
  168 + * @param rows
  169 + * @return
  170 + */
  171 + public static String createPageSqlByDBKey(String dbKey, String sql, int page, int rows) {
  172 + DynamicDataSourceModel dynamicSourceEntity = DataSourceCachePool.getCacheDynamicDataSourceModel(dbKey);
  173 + String dbType = dynamicSourceEntity.getDbType();
  174 + return createPageSqlByDBType(dbType, sql, page, rows);
  175 + }
  176 +
  177 + private static int getAfterSelectInsertPoint(String sql) {
  178 + int selectIndex = sql.toLowerCase().indexOf("select");
  179 + int selectDistinctIndex = sql.toLowerCase().indexOf("select distinct");
  180 + return selectIndex + (selectDistinctIndex == selectIndex ? 15 : 6);
  181 + }
  182 +
  183 + public static String getAllTableSql(String dbType, Object... params) {
  184 + if (StringUtils.isNotEmpty(dbType)) {
  185 + if (dbTypeIsMySQL(dbType)) {
  186 + return MessageFormat.format(MYSQL_ALLTABLES_SQL, params);
  187 + } else if (dbTypeIsOracle(dbType)) {
  188 + return ORACLE__ALLTABLES_SQL;
  189 + } else if (dbTypeIsPostgre(dbType)) {
  190 + return POSTGRE__ALLTABLES_SQL;
  191 + } else if (dbTypeIsSQLServer(dbType)) {
  192 + return SQLSERVER__ALLTABLES_SQL;
  193 + }
  194 + }
  195 + return null;
  196 + }
  197 +
  198 + public static String getAllColumnSQL(String dbType, Object... params) {
  199 + if (StringUtils.isNotEmpty(dbType)) {
  200 + if (dbTypeIsMySQL(dbType)) {
  201 + return MessageFormat.format(MYSQL_ALLCOLUMNS_SQL, params);
  202 + } else if (dbTypeIsOracle(dbType)) {
  203 + return MessageFormat.format(ORACLE_ALLCOLUMNS_SQL, params);
  204 + } else if (dbTypeIsPostgre(dbType)) {
  205 + return MessageFormat.format(POSTGRE_ALLCOLUMNS_SQL, params);
  206 + } else if (dbTypeIsSQLServer(dbType)) {
  207 + return MessageFormat.format(SQLSERVER_ALLCOLUMNS_SQL, params);
  208 + }
  209 + }
  210 + return null;
  211 + }
  212 +
  213 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/encryption/AesEncryptUtil.java 0 → 100644
  1 +package org.jeecg.common.util.encryption;
  2 +
  3 +import org.apache.shiro.codec.Base64;
  4 +
  5 +import javax.crypto.Cipher;
  6 +import javax.crypto.spec.IvParameterSpec;
  7 +import javax.crypto.spec.SecretKeySpec;
  8 +
  9 +/**
  10 + * AES 加密
  11 + */
  12 +public class AesEncryptUtil {
  13 +
  14 + //使用AES-128-CBC加密模式,key需要为16位,key和iv可以相同!
  15 + private static String KEY = EncryptedString.key;
  16 + private static String IV = EncryptedString.iv;
  17 +
  18 + /**
  19 + * 加密方法
  20 + * @param data 要加密的数据
  21 + * @param key 加密key
  22 + * @param iv 加密iv
  23 + * @return 加密的结果
  24 + * @throws Exception
  25 + */
  26 + public static String encrypt(String data, String key, String iv) throws Exception {
  27 + try {
  28 +
  29 + Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");//"算法/模式/补码方式"NoPadding PkcsPadding
  30 + int blockSize = cipher.getBlockSize();
  31 +
  32 + byte[] dataBytes = data.getBytes();
  33 + int plaintextLength = dataBytes.length;
  34 + if (plaintextLength % blockSize != 0) {
  35 + plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
  36 + }
  37 +
  38 + byte[] plaintext = new byte[plaintextLength];
  39 + System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
  40 +
  41 + SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
  42 + IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
  43 +
  44 + cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
  45 + byte[] encrypted = cipher.doFinal(plaintext);
  46 +
  47 + return Base64.encodeToString(encrypted);
  48 +
  49 + } catch (Exception e) {
  50 + e.printStackTrace();
  51 + return null;
  52 + }
  53 + }
  54 +
  55 + /**
  56 + * 解密方法
  57 + * @param data 要解密的数据
  58 + * @param key 解密key
  59 + * @param iv 解密iv
  60 + * @return 解密的结果
  61 + * @throws Exception
  62 + */
  63 + public static String desEncrypt(String data, String key, String iv) throws Exception {
  64 + try {
  65 + byte[] encrypted1 = Base64.decode(data);
  66 +
  67 + Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
  68 + SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
  69 + IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
  70 +
  71 + cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
  72 +
  73 + byte[] original = cipher.doFinal(encrypted1);
  74 + String originalString = new String(original);
  75 + return originalString;
  76 + } catch (Exception e) {
  77 + e.printStackTrace();
  78 + return null;
  79 + }
  80 + }
  81 +
  82 + /**
  83 + * 使用默认的key和iv加密
  84 + * @param data
  85 + * @return
  86 + * @throws Exception
  87 + */
  88 + public static String encrypt(String data) throws Exception {
  89 + return encrypt(data, KEY, IV);
  90 + }
  91 +
  92 + /**
  93 + * 使用默认的key和iv解密
  94 + * @param data
  95 + * @return
  96 + * @throws Exception
  97 + */
  98 + public static String desEncrypt(String data) throws Exception {
  99 + return desEncrypt(data, KEY, IV);
  100 + }
  101 +
  102 +
  103 +
  104 +// /**
  105 +// * 测试
  106 +// */
  107 +// public static void main(String args[]) throws Exception {
  108 +// String test1 = "sa";
  109 +// String test =new String(test1.getBytes(),"UTF-8");
  110 +// String data = null;
  111 +// String key = KEY;
  112 +// String iv = IV;
  113 +// // /g2wzfqvMOeazgtsUVbq1kmJawROa6mcRAzwG1/GeJ4=
  114 +// data = encrypt(test, key, iv);
  115 +// System.out.println("数据:"+test);
  116 +// System.out.println("加密:"+data);
  117 +// String jiemi =desEncrypt(data, key, iv).trim();
  118 +// System.out.println("解密:"+jiemi);
  119 +// }
  120 +
  121 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/encryption/EncryptedString.java 0 → 100644
  1 +package org.jeecg.common.util.encryption;
  2 +
  3 +
  4 +import lombok.Data;
  5 +
  6 +@Data
  7 +public class EncryptedString {
  8 +
  9 + public static String key = "1234567890adbcde";//长度为16个字符
  10 +
  11 + public static String iv = "1234567890hjlkew";//长度为16个字符
  12 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/filter/StrAttackFilter.java 0 → 100644
  1 +package org.jeecg.common.util.filter;
  2 +
  3 +import java.util.regex.Matcher;
  4 +import java.util.regex.Pattern;
  5 +import java.util.regex.PatternSyntaxException;
  6 +
  7 +/**
  8 + * 文件上传字符串过滤特殊字符
  9 + */
  10 +public class StrAttackFilter {
  11 +
  12 + public static String filter(String str) throws PatternSyntaxException {
  13 + // 清除掉所有特殊字符
  14 + String regEx = "[`_《》~!@#$%^&*()+=|{}':;',\\[\\].<>?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]";
  15 + Pattern p = Pattern.compile(regEx);
  16 + Matcher m = p.matcher(str);
  17 + return m.replaceAll("").trim();
  18 + }
  19 +
  20 +// public static void main(String[] args) {
  21 +// String filter = filter("@#jeecg/《》【bo】¥%……&*(o))))!@t<>,.,/?'\'~~`");
  22 +// System.out.println(filter);
  23 +// }
  24 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/oConvertUtils.java 0 → 100644
  1 +package org.jeecg.common.util;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.apache.commons.io.IOUtils;
  5 +import org.springframework.beans.BeanUtils;
  6 +
  7 +import javax.servlet.http.HttpServletRequest;
  8 +import java.io.IOException;
  9 +import java.io.InputStream;
  10 +import java.io.UnsupportedEncodingException;
  11 +import java.lang.reflect.Field;
  12 +import java.math.BigDecimal;
  13 +import java.math.BigInteger;
  14 +import java.net.InetAddress;
  15 +import java.net.NetworkInterface;
  16 +import java.net.SocketException;
  17 +import java.net.UnknownHostException;
  18 +import java.sql.Date;
  19 +import java.util.*;
  20 +import java.util.regex.Matcher;
  21 +import java.util.regex.Pattern;
  22 +
  23 +/**
  24 + *
  25 + * @Author 张代浩
  26 + *
  27 + */
  28 +@Slf4j
  29 +public class oConvertUtils {
  30 + public static boolean isEmpty(Object object) {
  31 + if (object == null) {
  32 + return (true);
  33 + }
  34 + if ("".equals(object)) {
  35 + return (true);
  36 + }
  37 + if ("null".equals(object)) {
  38 + return (true);
  39 + }
  40 + return (false);
  41 + }
  42 +
  43 + public static boolean isNotEmpty(Object object) {
  44 + if (object != null && !object.equals("") && !object.equals("null")) {
  45 + return (true);
  46 + }
  47 + return (false);
  48 + }
  49 +
  50 + public static String decode(String strIn, String sourceCode, String targetCode) {
  51 + String temp = code2code(strIn, sourceCode, targetCode);
  52 + return temp;
  53 + }
  54 +
  55 + public static String StrToUTF(String strIn, String sourceCode, String targetCode) {
  56 + strIn = "";
  57 + try {
  58 + strIn = new String(strIn.getBytes("ISO-8859-1"), "GBK");
  59 + } catch (UnsupportedEncodingException e) {
  60 + // TODO Auto-generated catch block
  61 + e.printStackTrace();
  62 + }
  63 + return strIn;
  64 +
  65 + }
  66 +
  67 + private static String code2code(String strIn, String sourceCode, String targetCode) {
  68 + String strOut = null;
  69 + if (strIn == null || (strIn.trim()).equals("")) {
  70 + return strIn;
  71 + }
  72 + try {
  73 + byte[] b = strIn.getBytes(sourceCode);
  74 + for (int i = 0; i < b.length; i++) {
  75 + System.out.print(b[i] + " ");
  76 + }
  77 + strOut = new String(b, targetCode);
  78 + } catch (Exception e) {
  79 + e.printStackTrace();
  80 + return null;
  81 + }
  82 + return strOut;
  83 + }
  84 +
  85 + public static int getInt(String s, int defval) {
  86 + if (s == null || s == "") {
  87 + return (defval);
  88 + }
  89 + try {
  90 + return (Integer.parseInt(s));
  91 + } catch (NumberFormatException e) {
  92 + return (defval);
  93 + }
  94 + }
  95 +
  96 + public static int getInt(String s) {
  97 + if (s == null || s == "") {
  98 + return 0;
  99 + }
  100 + try {
  101 + return (Integer.parseInt(s));
  102 + } catch (NumberFormatException e) {
  103 + return 0;
  104 + }
  105 + }
  106 +
  107 + public static int getInt(String s, Integer df) {
  108 + if (s == null || s == "") {
  109 + return df;
  110 + }
  111 + try {
  112 + return (Integer.parseInt(s));
  113 + } catch (NumberFormatException e) {
  114 + return 0;
  115 + }
  116 + }
  117 +
  118 + public static Integer[] getInts(String[] s) {
  119 + Integer[] integer = new Integer[s.length];
  120 + if (s == null) {
  121 + return null;
  122 + }
  123 + for (int i = 0; i < s.length; i++) {
  124 + integer[i] = Integer.parseInt(s[i]);
  125 + }
  126 + return integer;
  127 +
  128 + }
  129 +
  130 + public static double getDouble(String s, double defval) {
  131 + if (s == null || s == "") {
  132 + return (defval);
  133 + }
  134 + try {
  135 + return (Double.parseDouble(s));
  136 + } catch (NumberFormatException e) {
  137 + return (defval);
  138 + }
  139 + }
  140 +
  141 + public static double getDou(Double s, double defval) {
  142 + if (s == null) {
  143 + return (defval);
  144 + }
  145 + return s;
  146 + }
  147 +
  148 + /*public static Short getShort(String s) {
  149 + if (StringUtil.isNotEmpty(s)) {
  150 + return (Short.parseShort(s));
  151 + } else {
  152 + return null;
  153 + }
  154 + }*/
  155 +
  156 + public static int getInt(Object object, int defval) {
  157 + if (isEmpty(object)) {
  158 + return (defval);
  159 + }
  160 + try {
  161 + return (Integer.parseInt(object.toString()));
  162 + } catch (NumberFormatException e) {
  163 + return (defval);
  164 + }
  165 + }
  166 +
  167 + public static Integer getInt(Object object) {
  168 + if (isEmpty(object)) {
  169 + return null;
  170 + }
  171 + try {
  172 + return (Integer.parseInt(object.toString()));
  173 + } catch (NumberFormatException e) {
  174 + return null;
  175 + }
  176 + }
  177 +
  178 + public static int getInt(BigDecimal s, int defval) {
  179 + if (s == null) {
  180 + return (defval);
  181 + }
  182 + return s.intValue();
  183 + }
  184 +
  185 + public static Integer[] getIntegerArry(String[] object) {
  186 + int len = object.length;
  187 + Integer[] result = new Integer[len];
  188 + try {
  189 + for (int i = 0; i < len; i++) {
  190 + result[i] = new Integer(object[i].trim());
  191 + }
  192 + return result;
  193 + } catch (NumberFormatException e) {
  194 + return null;
  195 + }
  196 + }
  197 +
  198 + public static String getString(String s) {
  199 + return (getString(s, ""));
  200 + }
  201 +
  202 + /**
  203 + * 转义成Unicode编码
  204 + * @param s
  205 + * @return
  206 + */
  207 + /*public static String escapeJava(Object s) {
  208 + return StringEscapeUtils.escapeJava(getString(s));
  209 + }*/
  210 +
  211 + public static String getString(Object object) {
  212 + if (isEmpty(object)) {
  213 + return "";
  214 + }
  215 + return (object.toString().trim());
  216 + }
  217 +
  218 + public static String getString(int i) {
  219 + return (String.valueOf(i));
  220 + }
  221 +
  222 + public static String getString(float i) {
  223 + return (String.valueOf(i));
  224 + }
  225 +
  226 + public static String getString(String s, String defval) {
  227 + if (isEmpty(s)) {
  228 + return (defval);
  229 + }
  230 + return (s.trim());
  231 + }
  232 +
  233 + public static String getString(Object s, String defval) {
  234 + if (isEmpty(s)) {
  235 + return (defval);
  236 + }
  237 + return (s.toString().trim());
  238 + }
  239 +
  240 + public static long stringToLong(String str) {
  241 + Long test = new Long(0);
  242 + try {
  243 + test = Long.valueOf(str);
  244 + } catch (Exception e) {
  245 + }
  246 + return test.longValue();
  247 + }
  248 +
  249 + /**
  250 + * 获取本机IP
  251 + */
  252 + public static String getIp() {
  253 + String ip = null;
  254 + try {
  255 + InetAddress address = InetAddress.getLocalHost();
  256 + ip = address.getHostAddress();
  257 +
  258 + } catch (UnknownHostException e) {
  259 + e.printStackTrace();
  260 + }
  261 + return ip;
  262 + }
  263 +
  264 + /**
  265 + * 判断一个类是否为基本数据类型。
  266 + *
  267 + * @param clazz
  268 + * 要判断的类。
  269 + * @return true 表示为基本数据类型。
  270 + */
  271 + private static boolean isBaseDataType(Class clazz) throws Exception {
  272 + return (clazz.equals(String.class) || clazz.equals(Integer.class) || clazz.equals(Byte.class) || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Character.class) || clazz.equals(Short.class) || clazz.equals(BigDecimal.class) || clazz.equals(BigInteger.class) || clazz.equals(Boolean.class) || clazz.equals(Date.class) || clazz.isPrimitive());
  273 + }
  274 +
  275 + /**
  276 + * @param request
  277 + * IP
  278 + * @return IP Address
  279 + */
  280 + public static String getIpAddrByRequest(HttpServletRequest request) {
  281 + String ip = request.getHeader("x-forwarded-for");
  282 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  283 + ip = request.getHeader("Proxy-Client-IP");
  284 + }
  285 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  286 + ip = request.getHeader("WL-Proxy-Client-IP");
  287 + }
  288 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  289 + ip = request.getRemoteAddr();
  290 + }
  291 + return ip;
  292 + }
  293 +
  294 + /**
  295 + * @return 本机IP
  296 + * @throws SocketException
  297 + */
  298 + public static String getRealIp() throws SocketException {
  299 + String localip = null;// 本地IP,如果没有配置外网IP则返回它
  300 + String netip = null;// 外网IP
  301 +
  302 + Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
  303 + InetAddress ip = null;
  304 + boolean finded = false;// 是否找到外网IP
  305 + while (netInterfaces.hasMoreElements() && !finded) {
  306 + NetworkInterface ni = netInterfaces.nextElement();
  307 + Enumeration<InetAddress> address = ni.getInetAddresses();
  308 + while (address.hasMoreElements()) {
  309 + ip = address.nextElement();
  310 + if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 外网IP
  311 + netip = ip.getHostAddress();
  312 + finded = true;
  313 + break;
  314 + } else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 内网IP
  315 + localip = ip.getHostAddress();
  316 + }
  317 + }
  318 + }
  319 +
  320 + if (netip != null && !"".equals(netip)) {
  321 + return netip;
  322 + } else {
  323 + return localip;
  324 + }
  325 + }
  326 +
  327 + /**
  328 + * java去除字符串中的空格、回车、换行符、制表符
  329 + *
  330 + * @param str
  331 + * @return
  332 + */
  333 + public static String replaceBlank(String str) {
  334 + String dest = "";
  335 + if (str != null) {
  336 + Pattern p = Pattern.compile("\\s*|\t|\r|\n");
  337 + Matcher m = p.matcher(str);
  338 + dest = m.replaceAll("");
  339 + }
  340 + return dest;
  341 +
  342 + }
  343 +
  344 + /**
  345 + * 判断元素是否在数组内
  346 + *
  347 + * @param substring
  348 + * @param source
  349 + * @return
  350 + */
  351 + public static boolean isIn(String substring, String[] source) {
  352 + if (source == null || source.length == 0) {
  353 + return false;
  354 + }
  355 + for (int i = 0; i < source.length; i++) {
  356 + String aSource = source[i];
  357 + if (aSource.equals(substring)) {
  358 + return true;
  359 + }
  360 + }
  361 + return false;
  362 + }
  363 +
  364 + /**
  365 + * 获取Map对象
  366 + */
  367 + public static Map<Object, Object> getHashMap() {
  368 + return new HashMap<Object, Object>();
  369 + }
  370 +
  371 + /**
  372 + * SET转换MAP
  373 + *
  374 + * @param str
  375 + * @return
  376 + */
  377 + public static Map<Object, Object> SetToMap(Set<Object> setobj) {
  378 + Map<Object, Object> map = getHashMap();
  379 + for (Iterator iterator = setobj.iterator(); iterator.hasNext();) {
  380 + Map.Entry<Object, Object> entry = (Map.Entry<Object, Object>) iterator.next();
  381 + map.put(entry.getKey().toString(), entry.getValue() == null ? "" : entry.getValue().toString().trim());
  382 + }
  383 + return map;
  384 +
  385 + }
  386 +
  387 + public static boolean isInnerIP(String ipAddress) {
  388 + boolean isInnerIp = false;
  389 + long ipNum = getIpNum(ipAddress);
  390 + /**
  391 + * 私有IP:A类 10.0.0.0-10.255.255.255 B类 172.16.0.0-172.31.255.255 C类 192.168.0.0-192.168.255.255 当然,还有127这个网段是环回地址
  392 + **/
  393 + long aBegin = getIpNum("10.0.0.0");
  394 + long aEnd = getIpNum("10.255.255.255");
  395 + long bBegin = getIpNum("172.16.0.0");
  396 + long bEnd = getIpNum("172.31.255.255");
  397 + long cBegin = getIpNum("192.168.0.0");
  398 + long cEnd = getIpNum("192.168.255.255");
  399 + isInnerIp = isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd) || ipAddress.equals("127.0.0.1");
  400 + return isInnerIp;
  401 + }
  402 +
  403 + private static long getIpNum(String ipAddress) {
  404 + String[] ip = ipAddress.split("\\.");
  405 + long a = Integer.parseInt(ip[0]);
  406 + long b = Integer.parseInt(ip[1]);
  407 + long c = Integer.parseInt(ip[2]);
  408 + long d = Integer.parseInt(ip[3]);
  409 +
  410 + long ipNum = a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;
  411 + return ipNum;
  412 + }
  413 +
  414 + private static boolean isInner(long userIp, long begin, long end) {
  415 + return (userIp >= begin) && (userIp <= end);
  416 + }
  417 +
  418 + /**
  419 + * 将下划线大写方式命名的字符串转换为驼峰式。
  420 + * 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
  421 + * 例如:hello_world->helloWorld
  422 + *
  423 + * @param name
  424 + * 转换前的下划线大写方式命名的字符串
  425 + * @return 转换后的驼峰式命名的字符串
  426 + */
  427 + public static String camelName(String name) {
  428 + StringBuilder result = new StringBuilder();
  429 + // 快速检查
  430 + if (name == null || name.isEmpty()) {
  431 + // 没必要转换
  432 + return "";
  433 + } else if (!name.contains("_")) {
  434 + // 不含下划线,仅将首字母小写
  435 + //update-begin--Author:zhoujf Date:20180503 for:TASK #2500 【代码生成器】代码生成器开发一通用模板生成功能
  436 + //update-begin--Author:zhoujf Date:20180503 for:TASK #2500 【代码生成器】代码生成器开发一通用模板生成功能
  437 + return name.substring(0, 1).toLowerCase() + name.substring(1).toLowerCase();
  438 + //update-end--Author:zhoujf Date:20180503 for:TASK #2500 【代码生成器】代码生成器开发一通用模板生成功能
  439 + }
  440 + // 用下划线将原始字符串分割
  441 + String camels[] = name.split("_");
  442 + for (String camel : camels) {
  443 + // 跳过原始字符串中开头、结尾的下换线或双重下划线
  444 + if (camel.isEmpty()) {
  445 + continue;
  446 + }
  447 + // 处理真正的驼峰片段
  448 + if (result.length() == 0) {
  449 + // 第一个驼峰片段,全部字母都小写
  450 + result.append(camel.toLowerCase());
  451 + } else {
  452 + // 其他的驼峰片段,首字母大写
  453 + result.append(camel.substring(0, 1).toUpperCase());
  454 + result.append(camel.substring(1).toLowerCase());
  455 + }
  456 + }
  457 + return result.toString();
  458 + }
  459 +
  460 + /**
  461 + * 将下划线大写方式命名的字符串转换为驼峰式。
  462 + * 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
  463 + * 例如:hello_world,test_id->helloWorld,testId
  464 + *
  465 + * @param name
  466 + * 转换前的下划线大写方式命名的字符串
  467 + * @return 转换后的驼峰式命名的字符串
  468 + */
  469 + public static String camelNames(String names) {
  470 + if(names==null||names.equals("")){
  471 + return null;
  472 + }
  473 + StringBuffer sf = new StringBuffer();
  474 + String[] fs = names.split(",");
  475 + for (String field : fs) {
  476 + field = camelName(field);
  477 + sf.append(field + ",");
  478 + }
  479 + String result = sf.toString();
  480 + return result.substring(0, result.length() - 1);
  481 + }
  482 +
  483 + //update-begin--Author:zhoujf Date:20180503 for:TASK #2500 【代码生成器】代码生成器开发一通用模板生成功能
  484 + /**
  485 + * 将下划线大写方式命名的字符串转换为驼峰式。(首字母写)
  486 + * 如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
  487 + * 例如:hello_world->HelloWorld
  488 + *
  489 + * @param name
  490 + * 转换前的下划线大写方式命名的字符串
  491 + * @return 转换后的驼峰式命名的字符串
  492 + */
  493 + public static String camelNameCapFirst(String name) {
  494 + StringBuilder result = new StringBuilder();
  495 + // 快速检查
  496 + if (name == null || name.isEmpty()) {
  497 + // 没必要转换
  498 + return "";
  499 + } else if (!name.contains("_")) {
  500 + // 不含下划线,仅将首字母小写
  501 + return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
  502 + }
  503 + // 用下划线将原始字符串分割
  504 + String camels[] = name.split("_");
  505 + for (String camel : camels) {
  506 + // 跳过原始字符串中开头、结尾的下换线或双重下划线
  507 + if (camel.isEmpty()) {
  508 + continue;
  509 + }
  510 + // 其他的驼峰片段,首字母大写
  511 + result.append(camel.substring(0, 1).toUpperCase());
  512 + result.append(camel.substring(1).toLowerCase());
  513 + }
  514 + return result.toString();
  515 + }
  516 + //update-end--Author:zhoujf Date:20180503 for:TASK #2500 【代码生成器】代码生成器开发一通用模板生成功能
  517 +
  518 + /**
  519 + * 将驼峰命名转化成下划线
  520 + * @param para
  521 + * @return
  522 + */
  523 + public static String camelToUnderline(String para){
  524 + if(para.length()<3){
  525 + return para.toLowerCase();
  526 + }
  527 + StringBuilder sb=new StringBuilder(para);
  528 + int temp=0;//定位
  529 + //从第三个字符开始 避免命名不规范
  530 + for(int i=2;i<para.length();i++){
  531 + if(Character.isUpperCase(para.charAt(i))){
  532 + sb.insert(i+temp, "_");
  533 + temp+=1;
  534 + }
  535 + }
  536 + return sb.toString().toLowerCase();
  537 + }
  538 +
  539 + /**
  540 + * 随机数
  541 + * @param place 定义随机数的位数
  542 + */
  543 + public static String randomGen(int place) {
  544 + String base = "qwertyuioplkjhgfdsazxcvbnmQAZWSXEDCRFVTGBYHNUJMIKLOP0123456789";
  545 + StringBuffer sb = new StringBuffer();
  546 + Random rd = new Random();
  547 + for(int i=0;i<place;i++) {
  548 + sb.append(base.charAt(rd.nextInt(base.length())));
  549 + }
  550 + return sb.toString();
  551 + }
  552 +
  553 + /**
  554 + * 获取类的所有属性,包括父类
  555 + *
  556 + * @param object
  557 + * @return
  558 + */
  559 + public static Field[] getAllFields(Object object) {
  560 + Class<?> clazz = object.getClass();
  561 + List<Field> fieldList = new ArrayList<>();
  562 + while (clazz != null) {
  563 + fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
  564 + clazz = clazz.getSuperclass();
  565 + }
  566 + Field[] fields = new Field[fieldList.size()];
  567 + fieldList.toArray(fields);
  568 + return fields;
  569 + }
  570 +
  571 + /**
  572 + * 将map的key全部转成小写
  573 + * @param list
  574 + * @return
  575 + */
  576 + public static List<Map<String, Object>> toLowerCasePageList(List<Map<String, Object>> list){
  577 + List<Map<String, Object>> select = new ArrayList<>();
  578 + for (Map<String, Object> row : list) {
  579 + Map<String, Object> resultMap = new HashMap<>();
  580 + Set<String> keySet = row.keySet();
  581 + for (String key : keySet) {
  582 + String newKey = key.toLowerCase();
  583 + resultMap.put(newKey, row.get(key));
  584 + }
  585 + select.add(resultMap);
  586 + }
  587 + return select;
  588 + }
  589 +
  590 + /**
  591 + * 将entityList转换成modelList
  592 + * @param fromList
  593 + * @param tClass
  594 + * @param <F>
  595 + * @param <T>
  596 + * @return
  597 + */
  598 + public static<F,T> List<T> entityListToModelList(List<F> fromList, Class<T> tClass){
  599 + if(fromList == null || fromList.isEmpty()){
  600 + return null;
  601 + }
  602 + List<T> tList = new ArrayList<>();
  603 + for(F f : fromList){
  604 + T t = entityToModel(f, tClass);
  605 + tList.add(t);
  606 + }
  607 + return tList;
  608 + }
  609 +
  610 + public static<F,T> T entityToModel(F entity, Class<T> modelClass) {
  611 + log.debug("entityToModel : Entity属性的值赋值到Model");
  612 + Object model = null;
  613 + if (entity == null || modelClass ==null) {
  614 + return null;
  615 + }
  616 +
  617 + try {
  618 + model = modelClass.newInstance();
  619 + } catch (InstantiationException e) {
  620 + log.error("entityToModel : 实例化异常", e);
  621 + } catch (IllegalAccessException e) {
  622 + log.error("entityToModel : 安全权限异常", e);
  623 + }
  624 + BeanUtils.copyProperties(entity, model);
  625 + return (T)model;
  626 + }
  627 +
  628 + /**
  629 + * 判断 list 是否为空
  630 + *
  631 + * @param list
  632 + * @return true or false
  633 + * list == null : true
  634 + * list.size() == 0 : true
  635 + */
  636 + public static boolean listIsEmpty(Collection list) {
  637 + return (list == null || list.size() == 0);
  638 + }
  639 +
  640 + /**
  641 + * 判断 list 是否不为空
  642 + *
  643 + * @param list
  644 + * @return true or false
  645 + * list == null : false
  646 + * list.size() == 0 : false
  647 + */
  648 + public static boolean listIsNotEmpty(Collection list) {
  649 + return !listIsEmpty(list);
  650 + }
  651 +
  652 + /**
  653 + * 读取静态文本内容
  654 + * @param url
  655 + * @return
  656 + */
  657 + public static String readStatic(String url) {
  658 + String json = "";
  659 + try {
  660 + //换个写法,解决springboot读取jar包中文件的问题
  661 + InputStream stream = oConvertUtils.class.getClassLoader().getResourceAsStream(url.replace("classpath:", ""));
  662 + json = IOUtils.toString(stream,"UTF-8");
  663 + } catch (IOException e) {
  664 + log.error(e.getMessage(),e);
  665 + }
  666 + return json;
  667 + }
  668 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/oss/OssBootUtil.java 0 → 100644
  1 +package org.jeecg.common.util.oss;
  2 +
  3 +import com.aliyun.oss.ClientConfiguration;
  4 +import com.aliyun.oss.OSSClient;
  5 +import com.aliyun.oss.common.auth.DefaultCredentialProvider;
  6 +import com.aliyun.oss.model.CannedAccessControlList;
  7 +import com.aliyun.oss.model.OSSObject;
  8 +import com.aliyun.oss.model.PutObjectResult;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.apache.tomcat.util.http.fileupload.FileItemStream;
  11 +import org.jeecg.common.util.CommonUtils;
  12 +import org.jeecg.common.util.filter.StrAttackFilter;
  13 +import org.jeecg.common.util.oConvertUtils;
  14 +import org.springframework.web.multipart.MultipartFile;
  15 +
  16 +import java.io.BufferedInputStream;
  17 +import java.io.IOException;
  18 +import java.io.InputStream;
  19 +import java.net.URL;
  20 +import java.net.URLDecoder;
  21 +import java.util.Date;
  22 +import java.util.UUID;
  23 +
  24 +/**
  25 + * @Description: 阿里云 oss 上传工具类(高依赖版)
  26 + * @Date: 2019/5/10
  27 + */
  28 +@Slf4j
  29 +public class OssBootUtil {
  30 +
  31 + private static String endPoint;
  32 + private static String accessKeyId;
  33 + private static String accessKeySecret;
  34 + private static String bucketName;
  35 + private static String staticDomain;
  36 +
  37 + public static void setEndPoint(String endPoint) {
  38 + OssBootUtil.endPoint = endPoint;
  39 + }
  40 +
  41 + public static void setAccessKeyId(String accessKeyId) {
  42 + OssBootUtil.accessKeyId = accessKeyId;
  43 + }
  44 +
  45 + public static void setAccessKeySecret(String accessKeySecret) {
  46 + OssBootUtil.accessKeySecret = accessKeySecret;
  47 + }
  48 +
  49 + public static void setBucketName(String bucketName) {
  50 + OssBootUtil.bucketName = bucketName;
  51 + }
  52 +
  53 + public static void setStaticDomain(String staticDomain) {
  54 + OssBootUtil.staticDomain = staticDomain;
  55 + }
  56 +
  57 + public static String getStaticDomain() {
  58 + return staticDomain;
  59 + }
  60 +
  61 + public static String getEndPoint() {
  62 + return endPoint;
  63 + }
  64 +
  65 + public static String getAccessKeyId() {
  66 + return accessKeyId;
  67 + }
  68 +
  69 + public static String getAccessKeySecret() {
  70 + return accessKeySecret;
  71 + }
  72 +
  73 + public static String getBucketName() {
  74 + return bucketName;
  75 + }
  76 +
  77 + public static OSSClient getOssClient() {
  78 + return ossClient;
  79 + }
  80 +
  81 + /**
  82 + * oss 工具客户端
  83 + */
  84 + private static OSSClient ossClient = null;
  85 +
  86 + /**
  87 + * 上传文件至阿里云 OSS
  88 + * 文件上传成功,返回文件完整访问路径
  89 + * 文件上传失败,返回 null
  90 + *
  91 + * @param file 待上传文件
  92 + * @param fileDir 文件保存目录
  93 + * @return oss 中的相对文件路径
  94 + */
  95 + public static String upload(MultipartFile file, String fileDir,String customBucket) {
  96 + String FILE_URL = null;
  97 + initOSS(endPoint, accessKeyId, accessKeySecret);
  98 + StringBuilder fileUrl = new StringBuilder();
  99 + String newBucket = bucketName;
  100 + if(oConvertUtils.isNotEmpty(customBucket)){
  101 + newBucket = customBucket;
  102 + }
  103 + try {
  104 + //判断桶是否存在,不存在则创建桶
  105 + if(!ossClient.doesBucketExist(newBucket)){
  106 + ossClient.createBucket(newBucket);
  107 + }
  108 + // 获取文件名
  109 + String orgName = file.getOriginalFilename();
  110 + if("" == orgName){
  111 + orgName=file.getName();
  112 + }
  113 + orgName = CommonUtils.getFileName(orgName);
  114 + String fileName = orgName.indexOf(".")==-1
  115 + ?orgName + "_" + System.currentTimeMillis()
  116 + :orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
  117 + if (!fileDir.endsWith("/")) {
  118 + fileDir = fileDir.concat("/");
  119 + }
  120 + //update-begin-author:wangshuai date:20201012 for: 过滤上传文件夹名特殊字符,防止攻击
  121 + fileDir=StrAttackFilter.filter(fileDir);
  122 + //update-end-author:wangshuai date:20201012 for: 过滤上传文件夹名特殊字符,防止攻击
  123 + fileUrl = fileUrl.append(fileDir + fileName);
  124 +
  125 + if (oConvertUtils.isNotEmpty(staticDomain) && staticDomain.toLowerCase().startsWith("http")) {
  126 + FILE_URL = staticDomain + "/" + fileUrl;
  127 + } else {
  128 + FILE_URL = "https://" + newBucket + "." + endPoint + "/" + fileUrl;
  129 + }
  130 + PutObjectResult result = ossClient.putObject(newBucket, fileUrl.toString(), file.getInputStream());
  131 + // 设置权限(公开读)
  132 +// ossClient.setBucketAcl(newBucket, CannedAccessControlList.PublicRead);
  133 + if (result != null) {
  134 + log.info("------OSS文件上传成功------" + fileUrl);
  135 + }
  136 + } catch (IOException e) {
  137 + e.printStackTrace();
  138 + return null;
  139 + }
  140 + return FILE_URL;
  141 + }
  142 +
  143 + /**
  144 + * 获取原始URL
  145 + * @param url: 原始URL
  146 + * @Return: java.lang.String
  147 + */
  148 + public static String getOriginalUrl(String url) {
  149 + String originalDomain = "https://" + bucketName + "." + endPoint;
  150 + if(url.indexOf(staticDomain)!=-1){
  151 + url = url.replace(staticDomain,originalDomain);
  152 + }
  153 + return url;
  154 + }
  155 +
  156 + /**
  157 + * 文件上传
  158 + * @param file
  159 + * @param fileDir
  160 + * @return
  161 + */
  162 + public static String upload(MultipartFile file, String fileDir) {
  163 + return upload(file, fileDir,null);
  164 + }
  165 +
  166 + /**
  167 + * 上传文件至阿里云 OSS
  168 + * 文件上传成功,返回文件完整访问路径
  169 + * 文件上传失败,返回 null
  170 + *
  171 + * @param file 待上传文件
  172 + * @param fileDir 文件保存目录
  173 + * @return oss 中的相对文件路径
  174 + */
  175 + public static String upload(FileItemStream file, String fileDir) {
  176 + String FILE_URL = null;
  177 + initOSS(endPoint, accessKeyId, accessKeySecret);
  178 + StringBuilder fileUrl = new StringBuilder();
  179 + try {
  180 + String suffix = file.getName().substring(file.getName().lastIndexOf('.'));
  181 + String fileName = UUID.randomUUID().toString().replace("-", "") + suffix;
  182 + if (!fileDir.endsWith("/")) {
  183 + fileDir = fileDir.concat("/");
  184 + }
  185 + fileDir = StrAttackFilter.filter(fileDir);
  186 + fileUrl = fileUrl.append(fileDir + fileName);
  187 + if (oConvertUtils.isNotEmpty(staticDomain) && staticDomain.toLowerCase().startsWith("http")) {
  188 + FILE_URL = staticDomain + "/" + fileUrl;
  189 + } else {
  190 + FILE_URL = "https://" + bucketName + "." + endPoint + "/" + fileUrl;
  191 + }
  192 + PutObjectResult result = ossClient.putObject(bucketName, fileUrl.toString(), file.openStream());
  193 + // 设置权限(公开读)
  194 + ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
  195 + if (result != null) {
  196 + log.info("------OSS文件上传成功------" + fileUrl);
  197 + }
  198 + } catch (IOException e) {
  199 + e.printStackTrace();
  200 + return null;
  201 + }
  202 + return FILE_URL;
  203 + }
  204 +
  205 + /**
  206 + * 删除文件
  207 + * @param url
  208 + */
  209 + public static void deleteUrl(String url) {
  210 + deleteUrl(url,null);
  211 + }
  212 +
  213 + /**
  214 + * 删除文件
  215 + * @param url
  216 + */
  217 + public static void deleteUrl(String url,String bucket) {
  218 + String newBucket = bucketName;
  219 + if(oConvertUtils.isNotEmpty(bucket)){
  220 + newBucket = bucket;
  221 + }
  222 + String bucketUrl = "";
  223 + if (oConvertUtils.isNotEmpty(staticDomain) && staticDomain.toLowerCase().startsWith("http")) {
  224 + bucketUrl = staticDomain + "/" ;
  225 + } else {
  226 + bucketUrl = "https://" + newBucket + "." + endPoint + "/";
  227 + }
  228 + url = url.replace(bucketUrl,"");
  229 + ossClient.deleteObject(newBucket, url);
  230 + }
  231 +
  232 + /**
  233 + * 删除文件
  234 + * @param fileName
  235 + */
  236 + public static void delete(String fileName) {
  237 + ossClient.deleteObject(bucketName, fileName);
  238 + }
  239 +
  240 + /**
  241 + * 获取文件流
  242 + * @param objectName
  243 + * @param bucket
  244 + * @return
  245 + */
  246 + public static InputStream getOssFile(String objectName,String bucket){
  247 + InputStream inputStream = null;
  248 + try{
  249 + String newBucket = bucketName;
  250 + if(oConvertUtils.isNotEmpty(bucket)){
  251 + newBucket = bucket;
  252 + }
  253 + initOSS(endPoint, accessKeyId, accessKeySecret);
  254 + OSSObject ossObject = ossClient.getObject(newBucket,objectName);
  255 + inputStream = new BufferedInputStream(ossObject.getObjectContent());
  256 + }catch (Exception e){
  257 + log.info("文件获取失败" + e.getMessage());
  258 + }
  259 + return inputStream;
  260 + }
  261 +
  262 + /**
  263 + * 获取文件流
  264 + * @param objectName
  265 + * @return
  266 + */
  267 + public static InputStream getOssFile(String objectName){
  268 + return getOssFile(objectName,null);
  269 + }
  270 +
  271 + /**
  272 + * 获取文件外链
  273 + * @param bucketName
  274 + * @param objectName
  275 + * @param expires
  276 + * @return
  277 + */
  278 + public static String getObjectURL(String bucketName, String objectName, Date expires) {
  279 + initOSS(endPoint, accessKeyId, accessKeySecret);
  280 + try{
  281 + if(ossClient.doesObjectExist(bucketName,objectName)){
  282 + URL url = ossClient.generatePresignedUrl(bucketName,objectName,expires);
  283 + return URLDecoder.decode(url.toString(),"UTF-8");
  284 + }
  285 + }catch (Exception e){
  286 + log.info("文件路径获取失败" + e.getMessage());
  287 + }
  288 + return null;
  289 + }
  290 +
  291 + /**
  292 + * 初始化 oss 客户端
  293 + *
  294 + * @return
  295 + */
  296 + private static OSSClient initOSS(String endpoint, String accessKeyId, String accessKeySecret) {
  297 + if (ossClient == null) {
  298 + ossClient = new OSSClient(endpoint,
  299 + new DefaultCredentialProvider(accessKeyId, accessKeySecret),
  300 + new ClientConfiguration());
  301 + }
  302 + return ossClient;
  303 + }
  304 +
  305 +
  306 + /**
  307 + * 上传文件到oss
  308 + * @param stream
  309 + * @param relativePath
  310 + * @return
  311 + */
  312 + public static String upload(InputStream stream, String relativePath) {
  313 + String FILE_URL = null;
  314 + String fileUrl = relativePath;
  315 + initOSS(endPoint, accessKeyId, accessKeySecret);
  316 + if (oConvertUtils.isNotEmpty(staticDomain) && staticDomain.toLowerCase().startsWith("http")) {
  317 + FILE_URL = staticDomain + "/" + relativePath;
  318 + } else {
  319 + FILE_URL = "https://" + bucketName + "." + endPoint + "/" + fileUrl;
  320 + }
  321 + PutObjectResult result = ossClient.putObject(bucketName, fileUrl.toString(),stream);
  322 + // 设置权限(公开读)
  323 + ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
  324 + if (result != null) {
  325 + log.info("------OSS文件上传成功------" + fileUrl);
  326 + }
  327 + return FILE_URL;
  328 + }
  329 +
  330 +
  331 +}
0 \ No newline at end of file 332 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/security/SecurityTools.java 0 → 100644
  1 +package org.jeecg.common.util.security;
  2 +
  3 +import cn.hutool.core.codec.Base64Decoder;
  4 +import cn.hutool.core.codec.Base64Encoder;
  5 +import cn.hutool.crypto.SecureUtil;
  6 +import cn.hutool.crypto.asymmetric.KeyType;
  7 +import cn.hutool.crypto.asymmetric.RSA;
  8 +import cn.hutool.crypto.asymmetric.Sign;
  9 +import cn.hutool.crypto.asymmetric.SignAlgorithm;
  10 +import cn.hutool.crypto.symmetric.AES;
  11 +import cn.hutool.json.JSONObject;
  12 +import org.jeecg.common.util.security.entity.*;
  13 +
  14 +import javax.crypto.SecretKey;
  15 +import java.security.KeyPair;
  16 +
  17 +public class SecurityTools {
  18 + public static final String ALGORITHM = "AES/ECB/PKCS5Padding";
  19 +
  20 + public static SecurityResp valid(SecurityReq req) {
  21 + SecurityResp resp=new SecurityResp();
  22 + String pubKey=req.getPubKey();
  23 + String aesKey=req.getAesKey();
  24 + String data=req.getData();
  25 + String signData=req.getSignData();
  26 + RSA rsa=new RSA(null, Base64Decoder.decode(pubKey));
  27 + Sign sign= new Sign(SignAlgorithm.SHA1withRSA,null,pubKey);
  28 +
  29 +
  30 +
  31 + byte[] decryptAes = rsa.decrypt(aesKey, KeyType.PublicKey);
  32 + //log.info("rsa解密后的秘钥"+ Base64Encoder.encode(decryptAes));
  33 + AES aes = SecureUtil.aes(decryptAes);
  34 +
  35 + String dencrptValue =aes.decryptStr(data);
  36 + //log.info("解密后报文"+dencrptValue);
  37 + resp.setData(new JSONObject(dencrptValue));
  38 +
  39 + boolean verify = sign.verify(dencrptValue.getBytes(), Base64Decoder.decode(signData));
  40 + resp.setSuccess(verify);
  41 + return resp;
  42 + }
  43 +
  44 + public static SecuritySignResp sign(SecuritySignReq req) {
  45 + SecretKey secretKey = SecureUtil.generateKey(ALGORITHM);
  46 + byte[] key= secretKey.getEncoded();
  47 + String prikey=req.getPrikey();
  48 + String data=req.getData();
  49 +
  50 + AES aes = SecureUtil.aes(key);
  51 + aes.getSecretKey().getEncoded();
  52 + String encrptData =aes.encryptBase64(data);
  53 + RSA rsa=new RSA(prikey,null);
  54 + byte[] encryptAesKey = rsa.encrypt(secretKey.getEncoded(), KeyType.PrivateKey);
  55 + //log.info(("rsa加密过的秘钥=="+Base64Encoder.encode(encryptAesKey));
  56 +
  57 + Sign sign= new Sign(SignAlgorithm.SHA1withRSA,prikey,null);
  58 + byte[] signed = sign.sign(data.getBytes());
  59 +
  60 + //log.info(("签名数据===》》"+Base64Encoder.encode(signed));
  61 +
  62 + SecuritySignResp resp=new SecuritySignResp();
  63 + resp.setAesKey(Base64Encoder.encode(encryptAesKey));
  64 + resp.setData(encrptData);
  65 + resp.setSignData(Base64Encoder.encode(signed));
  66 + return resp;
  67 + }
  68 + public static MyKeyPair generateKeyPair(){
  69 + KeyPair keyPair= SecureUtil.generateKeyPair(SignAlgorithm.SHA1withRSA.getValue(),2048);
  70 + String priKey= Base64Encoder.encode(keyPair.getPrivate().getEncoded());
  71 + String pubkey= Base64Encoder.encode(keyPair.getPublic().getEncoded());
  72 + MyKeyPair resp=new MyKeyPair();
  73 + resp.setPriKey(priKey);
  74 + resp.setPubKey(pubkey);
  75 + return resp;
  76 + }
  77 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/security/entity/MyKeyPair.java 0 → 100644
  1 +package org.jeecg.common.util.security.entity;
  2 +
  3 +import lombok.Data;
  4 +
  5 +@Data
  6 +public class MyKeyPair {
  7 + private String priKey;
  8 + private String pubKey;
  9 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/security/entity/SecurityReq.java 0 → 100644
  1 +package org.jeecg.common.util.security.entity;
  2 +
  3 +import lombok.Data;
  4 +
  5 +@Data
  6 +public class SecurityReq {
  7 + private String data;
  8 + private String pubKey;
  9 + private String signData;
  10 + private String aesKey;
  11 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/security/entity/SecurityResp.java 0 → 100644
  1 +package org.jeecg.common.util.security.entity;
  2 +
  3 +import cn.hutool.json.JSONObject;
  4 +import lombok.Data;
  5 +
  6 +@Data
  7 +public class SecurityResp {
  8 + private Boolean success;
  9 + private JSONObject data;
  10 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/security/entity/SecuritySignReq.java 0 → 100644
  1 +package org.jeecg.common.util.security.entity;
  2 +
  3 +import lombok.Data;
  4 +
  5 +@Data
  6 +public class SecuritySignReq {
  7 + private String data;
  8 + private String prikey;
  9 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/security/entity/SecuritySignResp.java 0 → 100644
  1 +package org.jeecg.common.util.security.entity;
  2 +
  3 +import lombok.Data;
  4 +
  5 +@Data
  6 +public class SecuritySignResp {
  7 + private String data;
  8 + private String signData;
  9 + private String aesKey;
  10 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/superSearch/ObjectParseUtil.java 0 → 100644
  1 +package org.jeecg.common.util.superSearch;
  2 +
  3 +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  4 +
  5 +/**
  6 + * 判断类型,追加查询规则
  7 + *
  8 + * @Author Scott
  9 + * @Date 2019年02月14日
  10 + */
  11 +public class ObjectParseUtil {
  12 +
  13 + /**
  14 + *
  15 + * @param queryWrapper QueryWrapper
  16 + * @param name 字段名字
  17 + * @param rule 查询规则
  18 + * @param value 查询条件值
  19 + */
  20 + public static void addCriteria(QueryWrapper<?> queryWrapper, String name, QueryRuleEnum rule, Object value) {
  21 + if (value == null || rule == null) {
  22 + return;
  23 + }
  24 + switch (rule) {
  25 + case GT:
  26 + queryWrapper.gt(name, value);
  27 + break;
  28 + case GE:
  29 + queryWrapper.ge(name, value);
  30 + break;
  31 + case LT:
  32 + queryWrapper.lt(name, value);
  33 + break;
  34 + case LE:
  35 + queryWrapper.le(name, value);
  36 + break;
  37 + case EQ:
  38 + queryWrapper.eq(name, value);
  39 + break;
  40 + case NE:
  41 + queryWrapper.ne(name, value);
  42 + break;
  43 + case IN:
  44 + queryWrapper.in(name, (Object[]) value);
  45 + break;
  46 + case LIKE:
  47 + queryWrapper.like(name, value);
  48 + break;
  49 + case LEFT_LIKE:
  50 + queryWrapper.likeLeft(name, value);
  51 + break;
  52 + case RIGHT_LIKE:
  53 + queryWrapper.likeRight(name, value);
  54 + break;
  55 + default:
  56 + break;
  57 + }
  58 + }
  59 +
  60 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/superSearch/QueryRuleEnum.java 0 → 100644
  1 +package org.jeecg.common.util.superSearch;
  2 +
  3 +import org.jeecg.common.util.oConvertUtils;
  4 +
  5 +/**
  6 + * Query 规则 常量
  7 + * @Author Scott
  8 + * @Date 2019年02月14日
  9 + */
  10 +public enum QueryRuleEnum {
  11 +
  12 + GT(">","大于"),
  13 + GE(">=","大于等于"),
  14 + LT("<","小于"),
  15 + LE("<=","小于等于"),
  16 + EQ("=","等于"),
  17 + NE("!=","不等于"),
  18 + IN("IN","包含"),
  19 + LIKE("LIKE","全模糊"),
  20 + LEFT_LIKE("LEFT_LIKE","左模糊"),
  21 + RIGHT_LIKE("RIGHT_LIKE","右模糊"),
  22 + SQL_RULES("EXTEND_SQL","自定义SQL片段");
  23 +
  24 + private String value;
  25 +
  26 + private String msg;
  27 +
  28 + QueryRuleEnum(String value, String msg){
  29 + this.value = value;
  30 + this.msg = msg;
  31 + }
  32 +
  33 + public String getValue() {
  34 + return value;
  35 + }
  36 +
  37 + public void setValue(String value) {
  38 + this.value = value;
  39 + }
  40 +
  41 + public String getMsg() {
  42 + return msg;
  43 + }
  44 +
  45 + public void setMsg(String msg) {
  46 + this.msg = msg;
  47 + }
  48 +
  49 + public static QueryRuleEnum getByValue(String value){
  50 + if(oConvertUtils.isEmpty(value)) {
  51 + return null;
  52 + }
  53 + for(QueryRuleEnum val :values()){
  54 + if (val.getValue().equals(value)){
  55 + return val;
  56 + }
  57 + }
  58 + return null;
  59 + }
  60 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/superSearch/QueryRuleVo.java 0 → 100644
  1 +package org.jeecg.common.util.superSearch;
  2 +
  3 +import lombok.Data;
  4 +
  5 +@Data
  6 +public class QueryRuleVo {
  7 +
  8 + private String field;
  9 + private String rule;
  10 + private String val;
  11 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/AutoPoiConfig.java 0 → 100644
  1 +package org.jeecg.config;
  2 +
  3 +import org.jeecgframework.core.util.ApplicationContextUtil;
  4 +import org.springframework.context.annotation.Bean;
  5 +import org.springframework.context.annotation.Configuration;
  6 +
  7 +/**
  8 + * @Author: Scott
  9 + * @Date: 2018/2/7
  10 + * @description: autopoi 配置类
  11 + */
  12 +
  13 +@Configuration
  14 +public class AutoPoiConfig {
  15 +
  16 + /**
  17 + * excel注解字典参数支持(导入导出字典值,自动翻译)
  18 + * 举例: @Excel(name = "性别", width = 15, dicCode = "sex")
  19 + * 1、导出的时候会根据字典配置,把值1,2翻译成:男、女;
  20 + * 2、导入的时候,会把男、女翻译成1,2存进数据库;
  21 + * @return
  22 + */
  23 + @Bean
  24 + public ApplicationContextUtil applicationContextUtil() {
  25 + return new org.jeecgframework.core.util.ApplicationContextUtil();
  26 + }
  27 +
  28 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/AutoPoiDictConfig.java 0 → 100644
  1 +package org.jeecg.config;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.jeecg.common.api.CommonAPI;
  5 +import org.jeecg.common.system.vo.DictModel;
  6 +import org.jeecg.common.util.oConvertUtils;
  7 +import org.jeecgframework.dict.service.AutoPoiDictServiceI;
  8 +import org.springframework.context.annotation.Lazy;
  9 +import org.springframework.stereotype.Service;
  10 +
  11 +import javax.annotation.Resource;
  12 +import java.util.ArrayList;
  13 +import java.util.List;
  14 +
  15 +/**
  16 + * 描述:AutoPoi Excel注解支持字典参数设置
  17 + * 举例: @Excel(name = "性别", width = 15, dicCode = "sex")
  18 + * 1、导出的时候会根据字典配置,把值1,2翻译成:男、女;
  19 + * 2、导入的时候,会把男、女翻译成1,2存进数据库;
  20 + *
  21 + * @Author:scott
  22 + * @since:2019-04-09
  23 + * @Version:1.0
  24 + */
  25 +@Slf4j
  26 +@Service
  27 +public class AutoPoiDictConfig implements AutoPoiDictServiceI {
  28 + @Lazy
  29 + @Resource
  30 + private CommonAPI commonAPI;
  31 +
  32 + /**
  33 + * 通过字典查询easypoi,所需字典文本
  34 + *
  35 + * @Author:scott
  36 + * @since:2019-04-09
  37 + * @return
  38 + */
  39 + @Override
  40 + public String[] queryDict(String dicTable, String dicCode, String dicText) {
  41 + List<String> dictReplaces = new ArrayList<String>();
  42 + List<DictModel> dictList = null;
  43 + // step.1 如果没有字典表则使用系统字典表
  44 + if (oConvertUtils.isEmpty(dicTable)) {
  45 + dictList = commonAPI.queryDictItemsByCode(dicCode);
  46 + } else {
  47 + try {
  48 + dicText = oConvertUtils.getString(dicText, dicCode);
  49 + dictList = commonAPI.queryTableDictItemsByCode(dicTable, dicText, dicCode);
  50 + } catch (Exception e) {
  51 + log.error(e.getMessage(),e);
  52 + }
  53 + }
  54 + for (DictModel t : dictList) {
  55 + if(t!=null){
  56 + dictReplaces.add(t.getText() + "_" + t.getValue());
  57 + }
  58 + }
  59 + if (dictReplaces != null && dictReplaces.size() != 0) {
  60 + log.info("---AutoPoi--Get_DB_Dict------"+ dictReplaces.toString());
  61 + return dictReplaces.toArray(new String[dictReplaces.size()]);
  62 + }
  63 + return null;
  64 + }
  65 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/CorsFilterCondition.java 0 → 100644
  1 +package org.jeecg.config;
  2 +
  3 +import org.jeecg.common.constant.CommonConstant;
  4 +import org.springframework.context.annotation.Condition;
  5 +import org.springframework.context.annotation.ConditionContext;
  6 +import org.springframework.core.type.AnnotatedTypeMetadata;
  7 +
  8 +/**
  9 + * 跨域配置加载条件
  10 + */
  11 +public class CorsFilterCondition implements Condition {
  12 +
  13 + @Override
  14 + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
  15 + Object object = context.getEnvironment().getProperty(CommonConstant.CLOUD_SERVER_KEY);
  16 + //如果没有服务注册发现的配置 说明是单体应用 则加载跨域配置 返回true
  17 + if(object==null){
  18 + return true;
  19 + }
  20 + return false;
  21 + }
  22 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/DruidConfig.java 0 → 100644
  1 +package org.jeecg.config;
  2 +
  3 +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
  4 +import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
  5 +import com.alibaba.druid.util.Utils;
  6 +import org.springframework.boot.autoconfigure.AutoConfigureAfter;
  7 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  8 +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
  9 +import org.springframework.boot.web.servlet.FilterRegistrationBean;
  10 +import org.springframework.context.annotation.Bean;
  11 +import org.springframework.context.annotation.Configuration;
  12 +
  13 +import javax.servlet.*;
  14 +import java.io.IOException;
  15 +
  16 +@Configuration
  17 +@AutoConfigureAfter(DruidDataSourceAutoConfigure.class)
  18 +public class DruidConfig {
  19 +
  20 + /**
  21 + * 带有广告的common.js全路径,druid-1.1.14
  22 + */
  23 + private static final String FILE_PATH = "support/http/resources/js/common.js";
  24 + /**
  25 + * 原始脚本,触发构建广告的语句
  26 + */
  27 + private static final String ORIGIN_JS = "this.buildFooter();";
  28 + /**
  29 + * 替换后的脚本
  30 + */
  31 + private static final String NEW_JS = "//this.buildFooter();";
  32 +
  33 + /**
  34 + * 去除Druid监控页面的广告
  35 + *
  36 + * @param properties DruidStatProperties属性集合
  37 + * @return {@link org.springframework.boot.web.servlet.FilterRegistrationBean}
  38 + */
  39 + @Bean
  40 + @ConditionalOnWebApplication
  41 + @ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true")
  42 + public FilterRegistrationBean<RemoveAdFilter> removeDruidAdFilter(
  43 + DruidStatProperties properties) throws IOException {
  44 + // 获取web监控页面的参数
  45 + DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
  46 + // 提取common.js的配置路径
  47 + String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
  48 + String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
  49 + // 获取common.js
  50 + String text = Utils.readFromResource(FILE_PATH);
  51 + // 屏蔽 this.buildFooter(); 不构建广告
  52 + final String newJs = text.replace(ORIGIN_JS, NEW_JS);
  53 + FilterRegistrationBean<RemoveAdFilter> registration = new FilterRegistrationBean<>();
  54 + registration.setFilter(new RemoveAdFilter(newJs));
  55 + registration.addUrlPatterns(commonJsPattern);
  56 + return registration;
  57 + }
  58 +
  59 + /**
  60 + * 删除druid的广告过滤器
  61 + *
  62 + * @author BBF
  63 + */
  64 + private class RemoveAdFilter implements Filter {
  65 +
  66 + private final String newJs;
  67 +
  68 + public RemoveAdFilter(String newJS) {
  69 + this.newJs = newJS;
  70 + }
  71 +
  72 + @Override
  73 + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  74 + throws IOException, ServletException {
  75 + chain.doFilter(request, response);
  76 + // 重置缓冲区,响应头不会被重置
  77 + response.resetBuffer();
  78 + response.getWriter().write(newJs);
  79 + }
  80 + }
  81 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/JeecgCloudCondition.java 0 → 100644
  1 +package org.jeecg.config;
  2 +
  3 +import org.jeecg.common.constant.CommonConstant;
  4 +import org.springframework.context.annotation.Condition;
  5 +import org.springframework.context.annotation.ConditionContext;
  6 +import org.springframework.core.type.AnnotatedTypeMetadata;
  7 +
  8 +/**
  9 + * 微服务环境加载条件
  10 + */
  11 +public class JeecgCloudCondition implements Condition {
  12 +
  13 + @Override
  14 + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
  15 + Object object = context.getEnvironment().getProperty(CommonConstant.CLOUD_SERVER_KEY);
  16 + //如果没有服务注册发现的配置 说明是单体应用
  17 + if(object==null){
  18 + return false;
  19 + }
  20 + return true;
  21 + }
  22 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/RestTemplateConfig.java 0 → 100644
  1 +package org.jeecg.config;
  2 +
  3 +import org.springframework.context.annotation.Bean;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.http.client.ClientHttpRequestFactory;
  6 +import org.springframework.http.client.SimpleClientHttpRequestFactory;
  7 +import org.springframework.web.client.RestTemplate;
  8 +
  9 +/**
  10 +* 优雅的http请求方式RestTemplate
  11 +* @Return:
  12 +*/
  13 +@Configuration
  14 +public class RestTemplateConfig {
  15 +
  16 + @Bean
  17 + public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
  18 + return new RestTemplate(factory);
  19 + }
  20 +
  21 + @Bean
  22 + public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
  23 + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
  24 + factory.setReadTimeout(5000);//ms
  25 + factory.setConnectTimeout(15000);//ms
  26 + return factory;
  27 + }
  28 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/StaticConfig.java 0 → 100644
  1 +package org.jeecg.config;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.beans.factory.annotation.Value;
  5 +import org.springframework.stereotype.Component;
  6 +
  7 +/**
  8 + * 设置静态参数初始化
  9 + */
  10 +@Component
  11 +@Data
  12 +public class StaticConfig {
  13 +
  14 + @Value("${jeecg.oss.accessKey}")
  15 + private String accessKeyId;
  16 +
  17 + @Value("${jeecg.oss.secretKey}")
  18 + private String accessKeySecret;
  19 +
  20 + @Value(value = "${spring.mail.username}")
  21 + private String emailFrom;
  22 +
  23 +
  24 + /*@Bean
  25 + public void initStatic() {
  26 + DySmsHelper.setAccessKeyId(accessKeyId);
  27 + DySmsHelper.setAccessKeySecret(accessKeySecret);
  28 + EmailSendMsgHandle.setEmailFrom(emailFrom);
  29 + }*/
  30 +
  31 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java 0 → 100644
  1 +package org.jeecg.config;
  2 +
  3 +
  4 +import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
  5 +import io.swagger.annotations.ApiOperation;
  6 +import lombok.extern.slf4j.Slf4j;
  7 +import org.jeecg.common.constant.CommonConstant;
  8 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  9 +import org.springframework.context.annotation.Bean;
  10 +import org.springframework.context.annotation.Configuration;
  11 +
  12 +import org.springframework.context.annotation.Import;
  13 +import org.springframework.web.bind.annotation.RestController;
  14 +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
  15 +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  16 +import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
  17 +import springfox.documentation.builders.ApiInfoBuilder;
  18 +import springfox.documentation.builders.ParameterBuilder;
  19 +import springfox.documentation.builders.PathSelectors;
  20 +import springfox.documentation.builders.RequestHandlerSelectors;
  21 +import springfox.documentation.schema.ModelRef;
  22 +import springfox.documentation.service.*;
  23 +import springfox.documentation.spi.DocumentationType;
  24 +import springfox.documentation.spi.service.contexts.SecurityContext;
  25 +import springfox.documentation.spring.web.plugins.Docket;
  26 +import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
  27 +
  28 +import java.util.ArrayList;
  29 +import java.util.Collections;
  30 +import java.util.List;
  31 +
  32 +/**
  33 + * @Author scott
  34 + */
  35 +@Configuration
  36 +@EnableSwagger2WebMvc
  37 +@EnableKnife4j
  38 +@Import(BeanValidatorPluginsConfiguration.class)
  39 +public class Swagger2Config implements WebMvcConfigurer {
  40 +
  41 + /**
  42 + *
  43 + * 显示swagger-ui.html文档展示页,还必须注入swagger资源:
  44 + *
  45 + * @param registry
  46 + */
  47 + @Override
  48 + public void addResourceHandlers(ResourceHandlerRegistry registry) {
  49 + registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
  50 + registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
  51 + registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
  52 + }
  53 +
  54 + /**
  55 + * swagger2的配置文件,这里可以配置swagger2的一些基本的内容,比如扫描的包等等
  56 + *
  57 + * @return Docket
  58 + */
  59 + @Bean(value = "defaultApi2")
  60 + public Docket defaultApi2() {
  61 + return new Docket(DocumentationType.SWAGGER_2)
  62 + .apiInfo(apiInfo())
  63 + .select()
  64 + //此包路径下的类,才生成接口文档
  65 + .apis(RequestHandlerSelectors.basePackage("org.jeecg"))
  66 + //加了ApiOperation注解的类,才生成接口文档
  67 + .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
  68 + .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
  69 + .paths(PathSelectors.any())
  70 + .build()
  71 + .securitySchemes(Collections.singletonList(securityScheme()))
  72 + .securityContexts(securityContexts());
  73 + //.globalOperationParameters(setHeaderToken());
  74 + }
  75 +
  76 + /***
  77 + * oauth2配置
  78 + * 需要增加swagger授权回调地址
  79 + * http://localhost:8888/webjars/springfox-swagger-ui/o2c.html
  80 + * @return
  81 + */
  82 + @Bean
  83 + SecurityScheme securityScheme() {
  84 + return new ApiKey(CommonConstant.X_ACCESS_TOKEN, CommonConstant.X_ACCESS_TOKEN, "header");
  85 + }
  86 + /**
  87 + * JWT token
  88 + * @return
  89 + */
  90 + private List<Parameter> setHeaderToken() {
  91 + ParameterBuilder tokenPar = new ParameterBuilder();
  92 + List<Parameter> pars = new ArrayList<>();
  93 + tokenPar.name(CommonConstant.X_ACCESS_TOKEN).description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
  94 + pars.add(tokenPar.build());
  95 + return pars;
  96 + }
  97 +
  98 + /**
  99 + * api文档的详细信息函数,注意这里的注解引用的是哪个
  100 + *
  101 + * @return
  102 + */
  103 + private ApiInfo apiInfo() {
  104 + return new ApiInfoBuilder()
  105 + // //大标题
  106 + .title("Jeecg-Boot 后台服务API接口文档")
  107 + // 版本号
  108 + .version("1.0")
  109 +// .termsOfServiceUrl("NO terms of service")
  110 + // 描述
  111 + .description("后台API接口")
  112 + // 作者
  113 + .contact("JEECG团队")
  114 + .license("The Apache License, Version 2.0")
  115 + .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
  116 + .build();
  117 + }
  118 +
  119 + /**
  120 + * 新增 securityContexts 保持登录状态
  121 + */
  122 + private List<SecurityContext> securityContexts() {
  123 + return new ArrayList(
  124 + Collections.singleton(SecurityContext.builder()
  125 + .securityReferences(defaultAuth())
  126 + .forPaths(PathSelectors.regex("^(?!auth).*$"))
  127 + .build())
  128 + );
  129 + }
  130 +
  131 + private List<SecurityReference> defaultAuth() {
  132 + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
  133 + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
  134 + authorizationScopes[0] = authorizationScope;
  135 + return new ArrayList(
  136 + Collections.singleton(new SecurityReference(CommonConstant.X_ACCESS_TOKEN, authorizationScopes)));
  137 + }
  138 +
  139 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/WebMvcConfiguration.java 0 → 100644
  1 +package org.jeecg.config;
  2 +
  3 +import com.fasterxml.jackson.databind.ObjectMapper;
  4 +import com.fasterxml.jackson.databind.module.SimpleModule;
  5 +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
  6 +import org.springframework.beans.factory.annotation.Value;
  7 +import org.springframework.boot.actuate.trace.http.InMemoryHttpTraceRepository;
  8 +import org.springframework.context.annotation.Bean;
  9 +import org.springframework.context.annotation.Conditional;
  10 +import org.springframework.context.annotation.Configuration;
  11 +import org.springframework.http.converter.HttpMessageConverter;
  12 +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
  13 +import org.springframework.web.cors.CorsConfiguration;
  14 +import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
  15 +import org.springframework.web.filter.CorsFilter;
  16 +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
  17 +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
  18 +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  19 +
  20 +import java.util.List;
  21 +
  22 +/**
  23 + * Spring Boot 2.0 解决跨域问题
  24 + *
  25 + * @Author qinfeng
  26 + *
  27 + */
  28 +@Configuration
  29 +public class WebMvcConfiguration implements WebMvcConfigurer {
  30 +
  31 + @Value("${jeecg.path.upload}")
  32 + private String upLoadPath;
  33 + @Value("${jeecg.path.webapp}")
  34 + private String webAppPath;
  35 + @Value("${spring.resource.static-locations}")
  36 + private String staticLocations;
  37 +
  38 + /**
  39 + * 静态资源的配置 - 使得可以从磁盘中读取 Html、图片、视频、音频等
  40 + */
  41 + @Override
  42 + public void addResourceHandlers(ResourceHandlerRegistry registry) {
  43 + registry.addResourceHandler("/**")
  44 + .addResourceLocations("file:" + upLoadPath + "//", "file:" + webAppPath + "//")
  45 + .addResourceLocations(staticLocations.split(","));
  46 + }
  47 +
  48 + /**
  49 + * 方案一: 默认访问根路径跳转 doc.html页面 (swagger文档页面)
  50 + * 方案二: 访问根路径改成跳转 index.html页面 (简化部署方案: 可以把前端打包直接放到项目的 webapp,上面的配置)
  51 + */
  52 + @Override
  53 + public void addViewControllers(ViewControllerRegistry registry) {
  54 + registry.addViewController("/").setViewName("doc.html");
  55 + }
  56 +
  57 + @Bean
  58 + @Conditional(CorsFilterCondition.class)
  59 + public CorsFilter corsFilter() {
  60 + final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
  61 + final CorsConfiguration corsConfiguration = new CorsConfiguration();
  62 + //是否允许请求带有验证信息
  63 + corsConfiguration.setAllowCredentials(true);
  64 + // 允许访问的客户端域名
  65 + corsConfiguration.addAllowedOrigin("*");
  66 + // 允许服务端访问的客户端请求头
  67 + corsConfiguration.addAllowedHeader("*");
  68 + // 允许访问的方法名,GET POST等
  69 + corsConfiguration.addAllowedMethod("*");
  70 + urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
  71 + return new CorsFilter(urlBasedCorsConfigurationSource);
  72 + }
  73 +
  74 + /**
  75 + * 添加Long转json精度丢失的配置
  76 + * @Return: void
  77 + */
  78 + @Override
  79 + public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  80 + MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
  81 + ObjectMapper objectMapper = new ObjectMapper();
  82 + SimpleModule simpleModule = new SimpleModule();
  83 + simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
  84 + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
  85 + objectMapper.registerModule(simpleModule);
  86 + jackson2HttpMessageConverter.setObjectMapper(objectMapper);
  87 + converters.add(jackson2HttpMessageConverter);
  88 + }
  89 +
  90 + /**
  91 + * SpringBootAdmin的Httptrace不见了
  92 + * https://blog.csdn.net/u013810234/article/details/110097201
  93 + */
  94 + @Bean
  95 + public InMemoryHttpTraceRepository getInMemoryHttpTrace(){
  96 + return new InMemoryHttpTraceRepository();
  97 + }
  98 +
  99 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/WebSocketConfig.java 0 → 100644
  1 +package org.jeecg.config;
  2 +
  3 +import org.springframework.context.annotation.Bean;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.web.socket.server.standard.ServerEndpointExporter;
  6 +
  7 +@Configuration
  8 +public class WebSocketConfig {
  9 + /**
  10 + * 注入ServerEndpointExporter,
  11 + * 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
  12 + */
  13 + @Bean
  14 + public ServerEndpointExporter serverEndpointExporter() {
  15 + return new ServerEndpointExporter();
  16 + }
  17 +
  18 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/mybatis/JeecgTenantParser.java 0 → 100644
  1 +package org.jeecg.config.mybatis;
  2 +
  3 +import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
  4 +import net.sf.jsqlparser.expression.BinaryExpression;
  5 +import net.sf.jsqlparser.expression.Expression;
  6 +import net.sf.jsqlparser.expression.Parenthesis;
  7 +import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
  8 +import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
  9 +import net.sf.jsqlparser.expression.operators.relational.*;
  10 +import net.sf.jsqlparser.schema.Column;
  11 +import net.sf.jsqlparser.schema.Table;
  12 +import net.sf.jsqlparser.statement.select.*;
  13 +
  14 +import java.util.List;
  15 +
  16 +/**
  17 + * 复写租户条件
  18 + */
  19 +public class JeecgTenantParser extends TenantSqlParser {
  20 +
  21 + /**
  22 + * @param expression
  23 + * @param table
  24 + * @return
  25 + */
  26 + protected Expression processTableAlias(Expression expression, Table table) {
  27 + String tableAliasName;
  28 + if (table.getAlias() == null) {
  29 + tableAliasName = table.getName();
  30 + } else {
  31 + tableAliasName = table.getAlias().getName();
  32 + }
  33 +
  34 + // in
  35 + if (expression instanceof InExpression) {
  36 + InExpression in = (InExpression) expression;
  37 + if (in.getLeftExpression() instanceof Column) {
  38 + setTableAliasNameForColumn((Column) in.getLeftExpression(), tableAliasName);
  39 + }
  40 +
  41 + // 比较操作
  42 + } else if (expression instanceof BinaryExpression) {
  43 + BinaryExpression compare = (BinaryExpression) expression;
  44 + if (compare.getLeftExpression() instanceof Column) {
  45 + setTableAliasNameForColumn((Column) compare.getLeftExpression(), tableAliasName);
  46 + } else if (compare.getRightExpression() instanceof Column) {
  47 + setTableAliasNameForColumn((Column) compare.getRightExpression(), tableAliasName);
  48 + }
  49 +
  50 + // between
  51 + } else if (expression instanceof Between) {
  52 + Between between = (Between) expression;
  53 + if (between.getLeftExpression() instanceof Column) {
  54 + setTableAliasNameForColumn((Column) between.getLeftExpression(), tableAliasName);
  55 + }
  56 + }
  57 + return expression;
  58 + }
  59 +
  60 + private void setTableAliasNameForColumn(Column column, String tableAliasName) {
  61 + column.setColumnName(tableAliasName + "." + column.getColumnName());
  62 + }
  63 +
  64 + /**
  65 + * 默认是按 tenant_id=1 按等于条件追加
  66 + *
  67 + * @param currentExpression 现有的条件:比如你原来的sql查询条件
  68 + * @param table
  69 + * @return
  70 + */
  71 + @Override
  72 + protected Expression builderExpression(Expression currentExpression, Table table) {
  73 + final Expression tenantExpression = this.getTenantHandler().getTenantId(true);
  74 + Expression appendExpression;
  75 + if (!(tenantExpression instanceof SupportsOldOracleJoinSyntax)) {
  76 + appendExpression = new EqualsTo();
  77 + ((EqualsTo) appendExpression).setLeftExpression(this.getAliasColumn(table));
  78 + ((EqualsTo) appendExpression).setRightExpression(tenantExpression);
  79 + } else {
  80 + appendExpression = processTableAlias(tenantExpression, table);
  81 + }
  82 + if (currentExpression == null) {
  83 + return appendExpression;
  84 + }
  85 + if (currentExpression instanceof BinaryExpression) {
  86 + BinaryExpression binaryExpression = (BinaryExpression) currentExpression;
  87 + if (binaryExpression.getLeftExpression() instanceof FromItem) {
  88 + processFromItem((FromItem) binaryExpression.getLeftExpression());
  89 + }
  90 + if (binaryExpression.getRightExpression() instanceof FromItem) {
  91 + processFromItem((FromItem) binaryExpression.getRightExpression());
  92 + }
  93 + } else if (currentExpression instanceof InExpression) {
  94 + InExpression inExp = (InExpression) currentExpression;
  95 + ItemsList rightItems = inExp.getRightItemsList();
  96 + if (rightItems instanceof SubSelect) {
  97 + processSelectBody(((SubSelect) rightItems).getSelectBody());
  98 + }
  99 + }
  100 + if (currentExpression instanceof OrExpression) {
  101 + return new AndExpression(new Parenthesis(currentExpression), appendExpression);
  102 + } else {
  103 + return new AndExpression(currentExpression, appendExpression);
  104 + }
  105 + }
  106 +
  107 + @Override
  108 + protected void processPlainSelect(PlainSelect plainSelect, boolean addColumn) {
  109 + FromItem fromItem = plainSelect.getFromItem();
  110 + if (fromItem instanceof Table) {
  111 + Table fromTable = (Table) fromItem;
  112 + if (!this.getTenantHandler().doTableFilter(fromTable.getName())) {
  113 + plainSelect.setWhere(builderExpression(plainSelect.getWhere(), fromTable));
  114 + if (addColumn) {
  115 + plainSelect.getSelectItems().add(new SelectExpressionItem(new Column(this.getTenantHandler().getTenantIdColumn())));
  116 + }
  117 + }
  118 + } else {
  119 + processFromItem(fromItem);
  120 + }
  121 + List<Join> joins = plainSelect.getJoins();
  122 + if (joins != null && joins.size() > 0) {
  123 + joins.forEach(j -> {
  124 + processJoin(j);
  125 + processFromItem(j.getRightItem());
  126 + });
  127 + }
  128 + }
  129 +
  130 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/mybatis/MybatisInterceptor.java 0 → 100644
  1 +package org.jeecg.config.mybatis;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.apache.ibatis.binding.MapperMethod.ParamMap;
  5 +import org.apache.ibatis.executor.Executor;
  6 +import org.apache.ibatis.mapping.MappedStatement;
  7 +import org.apache.ibatis.mapping.SqlCommandType;
  8 +import org.apache.ibatis.plugin.*;
  9 +import org.apache.shiro.SecurityUtils;
  10 +import org.jeecg.common.system.vo.LoginUser;
  11 +import org.jeecg.common.util.oConvertUtils;
  12 +import org.springframework.stereotype.Component;
  13 +
  14 +import java.lang.reflect.Field;
  15 +import java.util.Date;
  16 +import java.util.Properties;
  17 +
  18 +/**
  19 + * mybatis拦截器,自动注入创建人、创建时间、修改人、修改时间
  20 + * @Author scott
  21 + * @Date 2019-01-19
  22 + *
  23 + */
  24 +@Slf4j
  25 +@Component
  26 +@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
  27 +public class MybatisInterceptor implements Interceptor {
  28 +
  29 + @Override
  30 + public Object intercept(Invocation invocation) throws Throwable {
  31 + MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
  32 + String sqlId = mappedStatement.getId();
  33 + log.debug("------sqlId------" + sqlId);
  34 + SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
  35 + Object parameter = invocation.getArgs()[1];
  36 + log.debug("------sqlCommandType------" + sqlCommandType);
  37 +
  38 + if (parameter == null) {
  39 + return invocation.proceed();
  40 + }
  41 + if (SqlCommandType.INSERT == sqlCommandType) {
  42 + LoginUser sysUser = this.getLoginUser();
  43 + Field[] fields = oConvertUtils.getAllFields(parameter);
  44 + for (Field field : fields) {
  45 + log.debug("------field.name------" + field.getName());
  46 + try {
  47 + if ("createBy".equals(field.getName())) {
  48 + field.setAccessible(true);
  49 + Object local_createBy = field.get(parameter);
  50 + field.setAccessible(false);
  51 + if (local_createBy == null || local_createBy.equals("")) {
  52 + if (sysUser != null) {
  53 + // 登录人账号
  54 + field.setAccessible(true);
  55 + field.set(parameter, sysUser.getUsername());
  56 + field.setAccessible(false);
  57 + }
  58 + }
  59 + }
  60 + // 注入创建时间
  61 + if ("createTime".equals(field.getName())) {
  62 + field.setAccessible(true);
  63 + Object local_createDate = field.get(parameter);
  64 + field.setAccessible(false);
  65 + if (local_createDate == null || local_createDate.equals("")) {
  66 + field.setAccessible(true);
  67 + field.set(parameter, new Date());
  68 + field.setAccessible(false);
  69 + }
  70 + }
  71 + //注入部门编码
  72 + if ("sysOrgCode".equals(field.getName())) {
  73 + field.setAccessible(true);
  74 + Object local_sysOrgCode = field.get(parameter);
  75 + field.setAccessible(false);
  76 + if (local_sysOrgCode == null || local_sysOrgCode.equals("")) {
  77 + // 获取登录用户信息
  78 + if (sysUser != null) {
  79 + field.setAccessible(true);
  80 + field.set(parameter, sysUser.getOrgCode());
  81 + field.setAccessible(false);
  82 + }
  83 + }
  84 + }
  85 + } catch (Exception e) {
  86 + }
  87 + }
  88 + }
  89 + if (SqlCommandType.UPDATE == sqlCommandType) {
  90 + LoginUser sysUser = this.getLoginUser();
  91 + Field[] fields = null;
  92 + if (parameter instanceof ParamMap) {
  93 + ParamMap<?> p = (ParamMap<?>) parameter;
  94 + //update-begin-author:scott date:20190729 for:批量更新报错issues/IZA3Q--
  95 + if (p.containsKey("et")) {
  96 + parameter = p.get("et");
  97 + } else {
  98 + parameter = p.get("param1");
  99 + }
  100 + //update-end-author:scott date:20190729 for:批量更新报错issues/IZA3Q-
  101 +
  102 + //update-begin-author:scott date:20190729 for:更新指定字段时报错 issues/#516-
  103 + if (parameter == null) {
  104 + return invocation.proceed();
  105 + }
  106 + //update-end-author:scott date:20190729 for:更新指定字段时报错 issues/#516-
  107 +
  108 + fields = oConvertUtils.getAllFields(parameter);
  109 + } else {
  110 + fields = oConvertUtils.getAllFields(parameter);
  111 + }
  112 +
  113 + for (Field field : fields) {
  114 + log.debug("------field.name------" + field.getName());
  115 + try {
  116 + if ("updateBy".equals(field.getName())) {
  117 + //获取登录用户信息
  118 + if (sysUser != null) {
  119 + // 登录账号
  120 + field.setAccessible(true);
  121 + field.set(parameter, sysUser.getUsername());
  122 + field.setAccessible(false);
  123 + }
  124 + }
  125 + if ("updateTime".equals(field.getName())) {
  126 + field.setAccessible(true);
  127 + field.set(parameter, new Date());
  128 + field.setAccessible(false);
  129 + }
  130 + } catch (Exception e) {
  131 + e.printStackTrace();
  132 + }
  133 + }
  134 + }
  135 + return invocation.proceed();
  136 + }
  137 +
  138 + @Override
  139 + public Object plugin(Object target) {
  140 + return Plugin.wrap(target, this);
  141 + }
  142 +
  143 + @Override
  144 + public void setProperties(Properties properties) {
  145 + // TODO Auto-generated method stub
  146 + }
  147 +
  148 + //update-begin--Author:scott Date:20191213 for:关于使用Quzrtz 开启线程任务, #465
  149 + private LoginUser getLoginUser() {
  150 + LoginUser sysUser = null;
  151 + try {
  152 + sysUser = SecurityUtils.getSubject().getPrincipal() != null ? (LoginUser) SecurityUtils.getSubject().getPrincipal() : null;
  153 + } catch (Exception e) {
  154 + //e.printStackTrace();
  155 + sysUser = null;
  156 + }
  157 + return sysUser;
  158 + }
  159 + //update-end--Author:scott Date:20191213 for:关于使用Quzrtz 开启线程任务, #465
  160 +
  161 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/mybatis/MybatisPlusConfig.java 0 → 100644
  1 +package org.jeecg.config.mybatis;
  2 +
  3 +import com.baomidou.mybatisplus.core.parser.ISqlParser;
  4 +import com.baomidou.mybatisplus.core.parser.ISqlParserFilter;
  5 +import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
  6 +import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
  7 +import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler;
  8 +import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
  9 +import net.sf.jsqlparser.expression.Expression;
  10 +import net.sf.jsqlparser.expression.LongValue;
  11 +import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
  12 +import net.sf.jsqlparser.expression.operators.relational.InExpression;
  13 +import net.sf.jsqlparser.schema.Column;
  14 +import org.apache.ibatis.reflection.MetaObject;
  15 +import org.jeecg.common.util.oConvertUtils;
  16 +import org.mybatis.spring.annotation.MapperScan;
  17 +import org.springframework.context.annotation.Bean;
  18 +import org.springframework.context.annotation.Configuration;
  19 +
  20 +import java.util.ArrayList;
  21 +import java.util.List;
  22 +
  23 +/**
  24 + * 单数据源配置(jeecg.datasource.open = false时生效)
  25 + * @Author zhoujf
  26 + *
  27 + */
  28 +@Configuration
  29 +@MapperScan(value={"org.jeecg.modules.**.mapper*"})
  30 +public class MybatisPlusConfig {
  31 +
  32 + /**
  33 + * tenant_id 字段名
  34 + */
  35 + public static final String tenant_field = "tenant_id";
  36 +
  37 + /**
  38 + * 有哪些表需要做多租户 这些表需要添加一个字段 ,字段名和tenant_field对应的值一样
  39 + */
  40 + private static final List<String> tenantTable = new ArrayList<String>();
  41 + /**
  42 + * ddl 关键字 判断不走多租户的sql过滤
  43 + */
  44 + private static final List<String> DDL_KEYWORD = new ArrayList<String>();
  45 + static {
  46 + tenantTable.add("jee_bug_danbiao");
  47 + DDL_KEYWORD.add("alter");
  48 + }
  49 +
  50 + /**
  51 + * 多租户属于 SQL 解析部分,依赖 MP 分页插件
  52 + */
  53 + @Bean
  54 + public PaginationInterceptor paginationInterceptor() {
  55 + PaginationInterceptor paginationInterceptor = new PaginationInterceptor().setLimit(-1);
  56 + //多租户配置 配置后每次执行sql会走一遍他的转化器 如果不需要多租户功能 可以将其注释
  57 + tenantConfig(paginationInterceptor);
  58 + return paginationInterceptor;
  59 + }
  60 +
  61 + /**
  62 + * 多租户的配置
  63 + * @param paginationInterceptor
  64 + */
  65 + private void tenantConfig(PaginationInterceptor paginationInterceptor){
  66 + /*
  67 + * 【测试多租户】 SQL 解析处理拦截器<br>
  68 + * 这里固定写成住户 1 实际情况你可以从cookie读取,因此数据看不到 【 麻花藤 】 这条记录( 注意观察 SQL )<br>
  69 + */
  70 + List<ISqlParser> sqlParserList = new ArrayList<>();
  71 + TenantSqlParser tenantSqlParser = new JeecgTenantParser();
  72 + tenantSqlParser.setTenantHandler(new TenantHandler() {
  73 +
  74 + @Override
  75 + public Expression getTenantId(boolean select) {
  76 + String tenant_id = oConvertUtils.getString(TenantContext.getTenant(),"0");
  77 + return new LongValue(tenant_id);
  78 + }
  79 + @Override
  80 + public String getTenantIdColumn() {
  81 + return tenant_field;
  82 + }
  83 +
  84 + @Override
  85 + public boolean doTableFilter(String tableName) {
  86 + //true则不加租户条件查询 false则加
  87 + // return excludeTable.contains(tableName);
  88 + if(tenantTable.contains(tableName)){
  89 + return false;
  90 + }
  91 + return true;
  92 + }
  93 +
  94 + private Expression in(String ids){
  95 + final InExpression inExpression = new InExpression();
  96 + inExpression.setLeftExpression(new Column(getTenantIdColumn()));
  97 + final ExpressionList itemsList = new ExpressionList();
  98 + final List<Expression> inValues = new ArrayList<>(2);
  99 + for(String id:ids.split(",")){
  100 + inValues.add(new LongValue(id));
  101 + }
  102 + itemsList.setExpressions(inValues);
  103 + inExpression.setRightItemsList(itemsList);
  104 + return inExpression;
  105 + }
  106 +
  107 + });
  108 +
  109 + sqlParserList.add(tenantSqlParser);
  110 + paginationInterceptor.setSqlParserList(sqlParserList);
  111 + paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() {
  112 + @Override
  113 + public boolean doFilter(MetaObject metaObject) {
  114 + String sql = (String) metaObject.getValue(PluginUtils.DELEGATE_BOUNDSQL_SQL);
  115 + for(String tableName: tenantTable){
  116 + String sql_lowercase = sql.toLowerCase();
  117 + if(sql_lowercase.indexOf(tableName.toLowerCase())>=0){
  118 + for(String key: DDL_KEYWORD){
  119 + if(sql_lowercase.indexOf(key)>=0){
  120 + return true;
  121 + }
  122 + }
  123 + return false;
  124 + }
  125 + }
  126 + /*if ("mapper路径.方法名".equals(ms.getId())) {
  127 + //使用这种判断也可以避免走此过滤器
  128 + return true;
  129 + }*/
  130 + return true;
  131 + }
  132 + });
  133 + }
  134 +// /**
  135 +// * mybatis-plus SQL执行效率插件【生产环境可以关闭】
  136 +// */
  137 +// @Bean
  138 +// public PerformanceInterceptor performanceInterceptor() {
  139 +// return new PerformanceInterceptor();
  140 +// }
  141 +
  142 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/mybatis/TenantContext.java 0 → 100644
  1 +package org.jeecg.config.mybatis;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +
  5 +/**
  6 + * 多租户 tenant_id存储器
  7 + */
  8 +@Slf4j
  9 +public class TenantContext {
  10 +
  11 + private static ThreadLocal<String> currentTenant = new ThreadLocal<>();
  12 +
  13 + public static void setTenant(String tenant) {
  14 + log.debug(" setting tenant to " + tenant);
  15 + currentTenant.set(tenant);
  16 + }
  17 +
  18 + public static String getTenant() {
  19 + return currentTenant.get();
  20 + }
  21 +
  22 + public static void clear(){
  23 + currentTenant.remove();
  24 + }
  25 +}
0 \ No newline at end of file 26 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/oss/MinioConfig.java 0 → 100644
  1 +package org.jeecg.config.oss;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.jeecg.common.util.MinioUtil;
  5 +import org.springframework.beans.factory.annotation.Value;
  6 +import org.springframework.context.annotation.Bean;
  7 +import org.springframework.context.annotation.Configuration;
  8 +
  9 +/**
  10 + * Minio文件上传配置文件
  11 + */
  12 +@Slf4j
  13 +@Configuration
  14 +public class MinioConfig {
  15 + @Value(value = "${jeecg.minio.minio_url}")
  16 + private String minioUrl;
  17 + @Value(value = "${jeecg.minio.minio_name}")
  18 + private String minioName;
  19 + @Value(value = "${jeecg.minio.minio_pass}")
  20 + private String minioPass;
  21 + @Value(value = "${jeecg.minio.bucketName}")
  22 + private String bucketName;
  23 +
  24 + @Bean
  25 + public void initMinio(){
  26 + if(!minioUrl.startsWith("http")){
  27 + minioUrl = "http://" + minioUrl;
  28 + }
  29 + if(!minioUrl.endsWith("/")){
  30 + minioUrl = minioUrl.concat("/");
  31 + }
  32 + MinioUtil.setMinioUrl(minioUrl);
  33 + MinioUtil.setMinioName(minioName);
  34 + MinioUtil.setMinioPass(minioPass);
  35 + MinioUtil.setBucketName(bucketName);
  36 + }
  37 +
  38 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/oss/OssConfiguration.java 0 → 100644
  1 +package org.jeecg.config.oss;
  2 +
  3 +import org.jeecg.common.util.oss.OssBootUtil;
  4 +import org.springframework.beans.factory.annotation.Value;
  5 +import org.springframework.context.annotation.Bean;
  6 +import org.springframework.context.annotation.Configuration;
  7 +
  8 +/**
  9 + * 云存储 配置
  10 + */
  11 +@Configuration
  12 +public class OssConfiguration {
  13 +
  14 + @Value("${jeecg.oss.endpoint}")
  15 + private String endpoint;
  16 + @Value("${jeecg.oss.accessKey}")
  17 + private String accessKeyId;
  18 + @Value("${jeecg.oss.secretKey}")
  19 + private String accessKeySecret;
  20 + @Value("${jeecg.oss.bucketName}")
  21 + private String bucketName;
  22 + @Value("${jeecg.oss.staticDomain:}")
  23 + private String staticDomain;
  24 +
  25 +
  26 + @Bean
  27 + public void initOssBootConfiguration() {
  28 + OssBootUtil.setEndPoint(endpoint);
  29 + OssBootUtil.setAccessKeyId(accessKeyId);
  30 + OssBootUtil.setAccessKeySecret(accessKeySecret);
  31 + OssBootUtil.setBucketName(bucketName);
  32 + OssBootUtil.setStaticDomain(staticDomain);
  33 + }
  34 +}
0 \ No newline at end of file 35 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/JwtToken.java 0 → 100644
  1 +package org.jeecg.config.shiro;
  2 +
  3 +import org.apache.shiro.authc.AuthenticationToken;
  4 +
  5 +/**
  6 + * @Author Scott
  7 + * @create 2018-07-12 15:19
  8 + * @desc
  9 + **/
  10 +public class JwtToken implements AuthenticationToken {
  11 +
  12 + private static final long serialVersionUID = 1L;
  13 + private String token;
  14 +
  15 + public JwtToken(String token) {
  16 + this.token = token;
  17 + }
  18 +
  19 + @Override
  20 + public Object getPrincipal() {
  21 + return token;
  22 + }
  23 +
  24 + @Override
  25 + public Object getCredentials() {
  26 + return token;
  27 + }
  28 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java 0 → 100644
  1 +package org.jeecg.config.shiro;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
  5 +import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
  6 +import org.apache.shiro.mgt.DefaultSubjectDAO;
  7 +import org.apache.shiro.mgt.SecurityManager;
  8 +import org.apache.shiro.spring.LifecycleBeanPostProcessor;
  9 +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
  10 +import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
  11 +import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
  12 +import org.crazycake.shiro.IRedisManager;
  13 +import org.crazycake.shiro.RedisCacheManager;
  14 +import org.crazycake.shiro.RedisClusterManager;
  15 +import org.crazycake.shiro.RedisManager;
  16 +import org.jeecg.common.constant.CommonConstant;
  17 +import org.jeecg.common.util.oConvertUtils;
  18 +import org.jeecg.config.shiro.filters.CustomShiroFilterFactoryBean;
  19 +import org.jeecg.config.shiro.filters.JwtFilter;
  20 +import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
  21 +import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.beans.factory.annotation.Value;
  23 +import org.springframework.context.annotation.Bean;
  24 +import org.springframework.context.annotation.Configuration;
  25 +import org.springframework.context.annotation.DependsOn;
  26 +import org.springframework.core.env.Environment;
  27 +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
  28 +import org.springframework.util.StringUtils;
  29 +import redis.clients.jedis.HostAndPort;
  30 +import redis.clients.jedis.JedisCluster;
  31 +
  32 +import javax.annotation.Resource;
  33 +import javax.servlet.Filter;
  34 +import java.util.*;
  35 +
  36 +/**
  37 + * @author: Scott
  38 + * @date: 2018/2/7
  39 + * @description: shiro 配置类
  40 + */
  41 +
  42 +@Slf4j
  43 +@Configuration
  44 +public class ShiroConfig {
  45 +
  46 + @Value("${jeecg.shiro.excludeUrls}")
  47 + private String excludeUrls;
  48 + @Resource
  49 + LettuceConnectionFactory lettuceConnectionFactory;
  50 + @Autowired
  51 + private Environment env;
  52 +
  53 +
  54 + /**
  55 + * Filter Chain定义说明
  56 + *
  57 + * 1、一个URL可以配置多个Filter,使用逗号分隔
  58 + * 2、当设置多个过滤器时,全部验证通过,才视为通过
  59 + * 3、部分过滤器可指定参数,如perms,roles
  60 + */
  61 + @Bean("shiroFilter")
  62 + public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
  63 + CustomShiroFilterFactoryBean shiroFilterFactoryBean = new CustomShiroFilterFactoryBean();
  64 + shiroFilterFactoryBean.setSecurityManager(securityManager);
  65 + // 拦截器
  66 + Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
  67 + if(oConvertUtils.isNotEmpty(excludeUrls)){
  68 + String[] permissionUrl = excludeUrls.split(",");
  69 + for(String url : permissionUrl){
  70 + filterChainDefinitionMap.put(url,"anon");
  71 + }
  72 + }
  73 + // 配置不会被拦截的链接 顺序判断
  74 + filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //cas验证登录
  75 + filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //登录验证码接口排除
  76 + filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //登录验证码接口排除
  77 + filterChainDefinitionMap.put("/sys/login", "anon"); //登录接口排除
  78 + filterChainDefinitionMap.put("/sys/mLogin", "anon"); //登录接口排除
  79 + filterChainDefinitionMap.put("/sys/logout", "anon"); //登出接口排除
  80 + filterChainDefinitionMap.put("/sys/thirdLogin/**", "anon"); //第三方登录
  81 + filterChainDefinitionMap.put("/sys/getEncryptedString", "anon"); //获取加密串
  82 + filterChainDefinitionMap.put("/sys/sms", "anon");//短信验证码
  83 + filterChainDefinitionMap.put("/sys/phoneLogin", "anon");//手机登录
  84 + filterChainDefinitionMap.put("/sys/user/checkOnlyUser", "anon");//校验用户是否存在
  85 + filterChainDefinitionMap.put("/sys/user/register", "anon");//用户注册
  86 + filterChainDefinitionMap.put("/sys/user/querySysUser", "anon");//根据手机号获取用户信息
  87 + filterChainDefinitionMap.put("/sys/user/phoneVerification", "anon");//用户忘记密码验证手机号
  88 + filterChainDefinitionMap.put("/sys/user/passwordChange", "anon");//用户更改密码
  89 + filterChainDefinitionMap.put("/auth/2step-code", "anon");//登录验证码
  90 + filterChainDefinitionMap.put("/sys/common/static/**", "anon");//图片预览 &下载文件不限制token
  91 + filterChainDefinitionMap.put("/sys/common/pdf/**", "anon");//pdf预览
  92 + filterChainDefinitionMap.put("/generic/**", "anon");//pdf预览需要文件
  93 + filterChainDefinitionMap.put("/", "anon");
  94 + filterChainDefinitionMap.put("/doc.html", "anon");
  95 + filterChainDefinitionMap.put("/**/*.js", "anon");
  96 + filterChainDefinitionMap.put("/**/*.css", "anon");
  97 + filterChainDefinitionMap.put("/**/*.html", "anon");
  98 + filterChainDefinitionMap.put("/**/*.svg", "anon");
  99 + filterChainDefinitionMap.put("/**/*.pdf", "anon");
  100 + filterChainDefinitionMap.put("/**/*.jpg", "anon");
  101 + filterChainDefinitionMap.put("/**/*.png", "anon");
  102 + filterChainDefinitionMap.put("/**/*.ico", "anon");
  103 +
  104 + filterChainDefinitionMap.put("/**/*.ttf", "anon");
  105 + filterChainDefinitionMap.put("/**/*.woff", "anon");
  106 + filterChainDefinitionMap.put("/**/*.woff2", "anon");
  107 +
  108 + filterChainDefinitionMap.put("/druid/**", "anon");
  109 + filterChainDefinitionMap.put("/swagger-ui.html", "anon");
  110 + filterChainDefinitionMap.put("/swagger**/**", "anon");
  111 + filterChainDefinitionMap.put("/webjars/**", "anon");
  112 + filterChainDefinitionMap.put("/v2/**", "anon");
  113 +
  114 +
  115 + // update-begin--Author:sunjianlei Date:20210510 for:排除消息通告查看详情页面(用于第三方APP)
  116 + filterChainDefinitionMap.put("/sys/annountCement/show/**", "anon");
  117 + // update-end--Author:sunjianlei Date:20210510 for:排除消息通告查看详情页面(用于第三方APP)
  118 +
  119 + //积木报表排除
  120 +// filterChainDefinitionMap.put("/jmreport/**", "anon");
  121 + filterChainDefinitionMap.put("/**/*.js.map", "anon");
  122 + filterChainDefinitionMap.put("/**/*.css.map", "anon");
  123 + //大屏设计器排除
  124 + filterChainDefinitionMap.put("/bigscreen/**", "anon");
  125 +
  126 + //测试示例
  127 + filterChainDefinitionMap.put("/test/bigScreen/**", "anon"); //大屏模板例子
  128 + //filterChainDefinitionMap.put("/test/jeecgDemo/rabbitMqClientTest/**", "anon"); //MQ测试
  129 + //filterChainDefinitionMap.put("/test/jeecgDemo/html", "anon"); //模板页面
  130 + //filterChainDefinitionMap.put("/test/jeecgDemo/redis/**", "anon"); //redis测试
  131 +
  132 + //websocket排除
  133 + filterChainDefinitionMap.put("/websocket/**", "anon");//系统通知和公告
  134 + filterChainDefinitionMap.put("/newsWebsocket/**", "anon");//CMS模块
  135 + filterChainDefinitionMap.put("/vxeSocket/**", "anon");//JVxeTable无痕刷新示例
  136 +
  137 +
  138 + //性能监控 TODO 存在安全漏洞泄露TOEKN(durid连接池也有)
  139 + filterChainDefinitionMap.put("/actuator/**", "anon");
  140 +
  141 + // 添加自己的过滤器并且取名为jwt
  142 + Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
  143 + //如果cloudServer为空 则说明是单体 需要加载跨域配置
  144 + Object cloudServer = env.getProperty(CommonConstant.CLOUD_SERVER_KEY);
  145 + filterMap.put("jwt", new JwtFilter(cloudServer==null));
  146 + shiroFilterFactoryBean.setFilters(filterMap);
  147 + // <!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边
  148 + filterChainDefinitionMap.put("/**", "jwt");
  149 +
  150 + // 未授权界面返回JSON
  151 + shiroFilterFactoryBean.setUnauthorizedUrl("/sys/common/403");
  152 + shiroFilterFactoryBean.setLoginUrl("/sys/common/403");
  153 + shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
  154 + return shiroFilterFactoryBean;
  155 + }
  156 +
  157 + @Bean("securityManager")
  158 + public DefaultWebSecurityManager securityManager(ShiroRealm myRealm) {
  159 + DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
  160 + securityManager.setRealm(myRealm);
  161 +
  162 + /*
  163 + * 关闭shiro自带的session,详情见文档
  164 + * http://shiro.apache.org/session-management.html#SessionManagement-
  165 + * StatelessApplications%28Sessionless%29
  166 + */
  167 + DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
  168 + DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
  169 + defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
  170 + subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
  171 + securityManager.setSubjectDAO(subjectDAO);
  172 + //自定义缓存实现,使用redis
  173 + securityManager.setCacheManager(redisCacheManager());
  174 + return securityManager;
  175 + }
  176 +
  177 + /**
  178 + * 下面的代码是添加注解支持
  179 + * @return
  180 + */
  181 + @Bean
  182 + @DependsOn("lifecycleBeanPostProcessor")
  183 + public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
  184 + DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
  185 + defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
  186 + /**
  187 + * 解决重复代理问题 github#994
  188 + * 添加前缀判断 不匹配 任何Advisor
  189 + */
  190 + defaultAdvisorAutoProxyCreator.setUsePrefix(true);
  191 + defaultAdvisorAutoProxyCreator.setAdvisorBeanNamePrefix("_no_advisor");
  192 + return defaultAdvisorAutoProxyCreator;
  193 + }
  194 +
  195 + @Bean
  196 + public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
  197 + return new LifecycleBeanPostProcessor();
  198 + }
  199 +
  200 + @Bean
  201 + public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
  202 + AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
  203 + advisor.setSecurityManager(securityManager);
  204 + return advisor;
  205 + }
  206 +
  207 + /**
  208 + * cacheManager 缓存 redis实现
  209 + * 使用的是shiro-redis开源插件
  210 + *
  211 + * @return
  212 + */
  213 + public RedisCacheManager redisCacheManager() {
  214 + log.info("===============(1)创建缓存管理器RedisCacheManager");
  215 + RedisCacheManager redisCacheManager = new RedisCacheManager();
  216 + redisCacheManager.setRedisManager(redisManager());
  217 + //redis中针对不同用户缓存(此处的id需要对应user实体中的id字段,用于唯一标识)
  218 + redisCacheManager.setPrincipalIdFieldName("id");
  219 + //用户权限信息缓存时间
  220 + redisCacheManager.setExpire(200000);
  221 + return redisCacheManager;
  222 + }
  223 +
  224 + /**
  225 + * 配置shiro redisManager
  226 + * 使用的是shiro-redis开源插件
  227 + *
  228 + * @return
  229 + */
  230 + @Bean
  231 + public IRedisManager redisManager() {
  232 + log.info("===============(2)创建RedisManager,连接Redis..");
  233 + IRedisManager manager;
  234 + // redis 单机支持,在集群为空,或者集群无机器时候使用 add by jzyadmin@163.com
  235 + if (lettuceConnectionFactory.getClusterConfiguration() == null || lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().isEmpty()) {
  236 + RedisManager redisManager = new RedisManager();
  237 + redisManager.setHost(lettuceConnectionFactory.getHostName());
  238 + redisManager.setPort(lettuceConnectionFactory.getPort());
  239 + redisManager.setDatabase(lettuceConnectionFactory.getDatabase());
  240 + redisManager.setTimeout(0);
  241 + if (!StringUtils.isEmpty(lettuceConnectionFactory.getPassword())) {
  242 + redisManager.setPassword(lettuceConnectionFactory.getPassword());
  243 + }
  244 + manager = redisManager;
  245 + }else{
  246 + // redis集群支持,优先使用集群配置
  247 + RedisClusterManager redisManager = new RedisClusterManager();
  248 + Set<HostAndPort> portSet = new HashSet<>();
  249 + lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().forEach(node -> portSet.add(new HostAndPort(node.getHost() , node.getPort())));
  250 + //update-begin--Author:scott Date:20210531 for:修改集群模式下未设置redis密码的bug issues/I3QNIC
  251 + if (oConvertUtils.isNotEmpty(lettuceConnectionFactory.getPassword())) {
  252 + JedisCluster jedisCluster = new JedisCluster(portSet, 2000, 2000, 5,
  253 + lettuceConnectionFactory.getPassword(), new GenericObjectPoolConfig());
  254 + redisManager.setPassword(lettuceConnectionFactory.getPassword());
  255 + redisManager.setJedisCluster(jedisCluster);
  256 + } else {
  257 + JedisCluster jedisCluster = new JedisCluster(portSet);
  258 + redisManager.setJedisCluster(jedisCluster);
  259 + }
  260 + //update-end--Author:scott Date:20210531 for:修改集群模式下未设置redis密码的bug issues/I3QNIC
  261 + manager = redisManager;
  262 + }
  263 + return manager;
  264 + }
  265 +
  266 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroRealm.java 0 → 100644
  1 +package org.jeecg.config.shiro;
  2 +
  3 +import cn.hutool.crypto.SecureUtil;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.apache.shiro.authc.AuthenticationException;
  6 +import org.apache.shiro.authc.AuthenticationInfo;
  7 +import org.apache.shiro.authc.AuthenticationToken;
  8 +import org.apache.shiro.authc.SimpleAuthenticationInfo;
  9 +import org.apache.shiro.authz.AuthorizationInfo;
  10 +import org.apache.shiro.authz.SimpleAuthorizationInfo;
  11 +import org.apache.shiro.realm.AuthorizingRealm;
  12 +import org.apache.shiro.subject.PrincipalCollection;
  13 +import org.jeecg.common.api.CommonAPI;
  14 +import org.jeecg.common.constant.CacheConstant;
  15 +import org.jeecg.common.constant.CommonConstant;
  16 +import org.jeecg.common.system.util.JwtUtil;
  17 +import org.jeecg.common.system.vo.LoginUser;
  18 +import org.jeecg.common.util.RedisUtil;
  19 +import org.jeecg.common.util.SpringContextUtils;
  20 +import org.jeecg.common.util.oConvertUtils;
  21 +import org.springframework.context.annotation.Lazy;
  22 +import org.springframework.stereotype.Component;
  23 +
  24 +import javax.annotation.Resource;
  25 +import java.util.Set;
  26 +
  27 +/**
  28 + * @Description: 用户登录鉴权和获取用户授权
  29 + * @Author: Scott
  30 + * @Date: 2019-4-23 8:13
  31 + * @Version: 1.1
  32 + */
  33 +@Component
  34 +@Slf4j
  35 +public class ShiroRealm extends AuthorizingRealm {
  36 + @Lazy
  37 + @Resource
  38 + private CommonAPI commonAPI;
  39 +
  40 + @Lazy
  41 + @Resource
  42 + private RedisUtil redisUtil;
  43 +
  44 + /**
  45 + * 必须重写此方法,不然Shiro会报错
  46 + */
  47 + @Override
  48 + public boolean supports(AuthenticationToken token) {
  49 + return token instanceof JwtToken;
  50 + }
  51 +
  52 + /**
  53 + * 权限信息认证(包括角色以及权限)是用户访问controller的时候才进行验证(redis存储的此处权限信息)
  54 + * 触发检测用户权限时才会调用此方法,例如checkRole,checkPermission
  55 + *
  56 + * @param principals 身份信息
  57 + * @return AuthorizationInfo 权限信息
  58 + */
  59 + @Override
  60 + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  61 + log.info("===============Shiro权限认证开始============ [ roles、permissions]==========");
  62 + String username = null;
  63 + if (principals != null) {
  64 + LoginUser sysUser = (LoginUser) principals.getPrimaryPrincipal();
  65 + username = sysUser.getUsername();
  66 + }
  67 + SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
  68 +
  69 + // 设置用户拥有的角色集合,比如“admin,test”
  70 + Set<String> roleSet = commonAPI.queryUserRoles(username);
  71 + System.out.println(roleSet.toString());
  72 + info.setRoles(roleSet);
  73 +
  74 + // 设置用户拥有的权限集合,比如“sys:role:add,sys:user:add”
  75 + Set<String> permissionSet = commonAPI.queryUserAuths(username);
  76 + info.addStringPermissions(permissionSet);
  77 + System.out.println(permissionSet);
  78 + log.info("===============Shiro权限认证成功==============");
  79 + return info;
  80 + }
  81 +
  82 + /**
  83 + * 用户信息认证是在用户进行登录的时候进行验证(不存redis)
  84 + * 也就是说验证用户输入的账号和密码是否正确,错误抛出异常
  85 + *
  86 + * @param auth 用户登录的账号密码信息
  87 + * @return 返回封装了用户信息的 AuthenticationInfo 实例
  88 + * @throws AuthenticationException
  89 + */
  90 + @Override
  91 + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
  92 + log.debug("===============Shiro身份认证开始============doGetAuthenticationInfo==========");
  93 + String token = (String) auth.getCredentials();
  94 + if (token == null) {
  95 + log.info("————————身份认证失败——————————IP地址: "+ oConvertUtils.getIpAddrByRequest(SpringContextUtils.getHttpServletRequest()));
  96 + throw new AuthenticationException("token为空!");
  97 + }
  98 + // 校验token有效性
  99 + LoginUser loginUser = this.checkUserTokenIsEffect(token);
  100 + return new SimpleAuthenticationInfo(loginUser, token, getName());
  101 + }
  102 +
  103 + /**
  104 + * 校验token的有效性
  105 + *
  106 + * @param token
  107 + */
  108 + public LoginUser checkUserTokenIsEffect(String token) throws AuthenticationException {
  109 + // 解密获得username,用于和数据库进行对比
  110 + String username = JwtUtil.getUsername(token);
  111 + if (username == null) {
  112 + throw new AuthenticationException("token非法无效!");
  113 + }
  114 +
  115 + // 查询用户信息
  116 + log.debug("———校验token是否有效————checkUserTokenIsEffect——————— "+ token);
  117 + LoginUser loginUser = commonAPI.getUserByName(username);
  118 + if (loginUser == null) {
  119 + throw new AuthenticationException("用户不存在!");
  120 + }
  121 + // 判断用户状态
  122 + if (loginUser.getStatus() != 1) {
  123 + throw new AuthenticationException("账号已被锁定,请联系管理员!");
  124 + }
  125 + // 校验token是否超时失效 & 或者账号密码是否错误
  126 + if (!jwtTokenRefresh(token, username, loginUser.getPassword())) {
  127 + throw new AuthenticationException("Token失效,请重新登录!");
  128 + }
  129 +
  130 + return loginUser;
  131 + }
  132 +
  133 + /**
  134 + * JWTToken刷新生命周期 (实现: 用户在线操作不掉线功能)
  135 + * 1、登录成功后将用户的JWT生成的Token作为k、v存储到cache缓存里面(这时候k、v值一样),缓存有效期设置为Jwt有效时间的2倍
  136 + * 2、当该用户再次请求时,通过JWTFilter层层校验之后会进入到doGetAuthenticationInfo进行身份验证
  137 + * 3、当该用户这次请求jwt生成的token值已经超时,但该token对应cache中的k还是存在,则表示该用户一直在操作只是JWT的token失效了,程序会给token对应的k映射的v值重新生成JWTToken并覆盖v值,该缓存生命周期重新计算
  138 + * 4、当该用户这次请求jwt在生成的token值已经超时,并在cache中不存在对应的k,则表示该用户账户空闲超时,返回用户信息已失效,请重新登录。
  139 + * 注意: 前端请求Header中设置Authorization保持不变,校验有效性以缓存中的token为准。
  140 + * 用户过期时间 = Jwt有效时间 * 2。
  141 + *
  142 + * @param userName
  143 + * @param passWord
  144 + * @return
  145 + */
  146 + public boolean jwtTokenRefresh(String token, String userName, String passWord) {
  147 + String cacheToken = String.valueOf(redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token));
  148 + if (oConvertUtils.isNotEmpty(cacheToken)) {
  149 + // 校验token有效性
  150 + if (!JwtUtil.verify(cacheToken, userName, passWord)) {
  151 + String newAuthorization = JwtUtil.sign(userName, passWord);
  152 + // 设置超时时间
  153 + redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, newAuthorization);
  154 + redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME *2 / 1000);
  155 + log.debug("——————————用户在线操作,更新token保证不掉线—————————jwtTokenRefresh——————— "+ token);
  156 + }
  157 + //update-begin--Author:scott Date:20191005 for:解决每次请求,都重写redis中 token缓存问题
  158 +// else {
  159 +// // 设置超时时间
  160 +// redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, cacheToken);
  161 +// redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
  162 +// }
  163 + //update-end--Author:scott Date:20191005 for:解决每次请求,都重写redis中 token缓存问题
  164 + return true;
  165 + }
  166 + return false;
  167 + }
  168 +
  169 + /**
  170 + * 清除当前用户的权限认证缓存
  171 + *
  172 + * @param principals 权限信息
  173 + */
  174 + @Override
  175 + public void clearCache(PrincipalCollection principals) {
  176 + super.clearCache(principals);
  177 + }
  178 +
  179 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/filters/CustomShiroFilterFactoryBean.java 0 → 100644
  1 +package org.jeecg.config.shiro.filters;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
  5 +import org.apache.shiro.web.filter.InvalidRequestFilter;
  6 +import org.apache.shiro.web.filter.mgt.DefaultFilter;
  7 +import org.apache.shiro.web.filter.mgt.FilterChainManager;
  8 +import org.apache.shiro.web.filter.mgt.FilterChainResolver;
  9 +import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
  10 +import org.apache.shiro.web.mgt.WebSecurityManager;
  11 +import org.apache.shiro.web.servlet.AbstractShiroFilter;
  12 +import org.apache.shiro.mgt.SecurityManager;
  13 +import org.springframework.beans.factory.BeanInitializationException;
  14 +
  15 +import javax.servlet.Filter;
  16 +import java.util.Map;
  17 +
  18 +/**
  19 + * 自定义ShiroFilterFactoryBean解决资源中文路径问题
  20 + */
  21 +@Slf4j
  22 +public class CustomShiroFilterFactoryBean extends ShiroFilterFactoryBean {
  23 + @Override
  24 + public Class getObjectType() {
  25 + return MySpringShiroFilter.class;
  26 + }
  27 +
  28 + @Override
  29 + protected AbstractShiroFilter createInstance() throws Exception {
  30 +
  31 + SecurityManager securityManager = getSecurityManager();
  32 + if (securityManager == null) {
  33 + String msg = "SecurityManager property must be set.";
  34 + throw new BeanInitializationException(msg);
  35 + }
  36 +
  37 + if (!(securityManager instanceof WebSecurityManager)) {
  38 + String msg = "The security manager does not implement the WebSecurityManager interface.";
  39 + throw new BeanInitializationException(msg);
  40 + }
  41 +
  42 + FilterChainManager manager = createFilterChainManager();
  43 + //Expose the constructed FilterChainManager by first wrapping it in a
  44 + // FilterChainResolver implementation. The AbstractShiroFilter implementations
  45 + // do not know about FilterChainManagers - only resolvers:
  46 + PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
  47 + chainResolver.setFilterChainManager(manager);
  48 +
  49 + Map<String, Filter> filterMap = manager.getFilters();
  50 + Filter invalidRequestFilter = filterMap.get(DefaultFilter.invalidRequest.name());
  51 + if (invalidRequestFilter instanceof InvalidRequestFilter) {
  52 + //此处是关键,设置false跳过URL携带中文400,servletPath中文校验bug
  53 + ((InvalidRequestFilter) invalidRequestFilter).setBlockNonAscii(false);
  54 + }
  55 + //Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
  56 + //FilterChainResolver. It doesn't matter that the instance is an anonymous inner class
  57 + //here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
  58 + //injection of the SecurityManager and FilterChainResolver:
  59 + return new MySpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
  60 + }
  61 +
  62 + private static final class MySpringShiroFilter extends AbstractShiroFilter {
  63 + protected MySpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
  64 + if (webSecurityManager == null) {
  65 + throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
  66 + } else {
  67 + this.setSecurityManager(webSecurityManager);
  68 + if (resolver != null) {
  69 + this.setFilterChainResolver(resolver);
  70 + }
  71 +
  72 + }
  73 + }
  74 + }
  75 +
  76 +}
0 \ No newline at end of file 77 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/filters/JwtFilter.java 0 → 100644
  1 +package org.jeecg.config.shiro.filters;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.apache.shiro.authc.AuthenticationException;
  5 +import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
  6 +import org.jeecg.common.constant.CommonConstant;
  7 +import org.jeecg.config.mybatis.TenantContext;
  8 +import org.jeecg.config.shiro.JwtToken;
  9 +import org.springframework.http.HttpStatus;
  10 +import org.springframework.web.bind.annotation.RequestMethod;
  11 +
  12 +import javax.servlet.ServletRequest;
  13 +import javax.servlet.ServletResponse;
  14 +import javax.servlet.http.HttpServletRequest;
  15 +import javax.servlet.http.HttpServletResponse;
  16 +
  17 +/**
  18 + * @Description: 鉴权登录拦截器
  19 + * @Author: Scott
  20 + * @Date: 2018/10/7
  21 + **/
  22 +@Slf4j
  23 +public class JwtFilter extends BasicHttpAuthenticationFilter {
  24 +
  25 + private boolean allowOrigin = true;
  26 +
  27 + public JwtFilter(){}
  28 + public JwtFilter(boolean allowOrigin){
  29 + this.allowOrigin = allowOrigin;
  30 + }
  31 +
  32 + /**
  33 + * 执行登录认证
  34 + *
  35 + * @param request
  36 + * @param response
  37 + * @param mappedValue
  38 + * @return
  39 + */
  40 + @Override
  41 + protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
  42 + try {
  43 + executeLogin(request, response);
  44 + return true;
  45 + } catch (Exception e) {
  46 + throw new AuthenticationException("Token失效,请重新登录", e);
  47 + }
  48 + }
  49 +
  50 + /**
  51 + *
  52 + */
  53 + @Override
  54 + protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
  55 + HttpServletRequest httpServletRequest = (HttpServletRequest) request;
  56 + String token = httpServletRequest.getHeader(CommonConstant.X_ACCESS_TOKEN);
  57 + // update-begin--Author:lvdandan Date:20210105 for:JT-355 OA聊天添加token验证,获取token参数
  58 + if(token == null){
  59 + token = httpServletRequest.getParameter("token");
  60 + }
  61 + // update-end--Author:lvdandan Date:20210105 for:JT-355 OA聊天添加token验证,获取token参数
  62 +
  63 + JwtToken jwtToken = new JwtToken(token);
  64 + // 提交给realm进行登入,如果错误他会抛出异常并被捕获
  65 + getSubject(request, response).login(jwtToken);
  66 + // 如果没有抛出异常则代表登入成功,返回true
  67 + return true;
  68 + }
  69 +
  70 + /**
  71 + * 对跨域提供支持
  72 + */
  73 + @Override
  74 + protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
  75 + HttpServletRequest httpServletRequest = (HttpServletRequest) request;
  76 + HttpServletResponse httpServletResponse = (HttpServletResponse) response;
  77 + if(allowOrigin){
  78 + httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
  79 + httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
  80 + httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
  81 + //update-begin-author:scott date:20200907 for:issues/I1TAAP 前后端分离,shiro过滤器配置引起的跨域问题
  82 + // 是否允许发送Cookie,默认Cookie不包括在CORS请求之中。设为true时,表示服务器允许Cookie包含在请求中。
  83 + httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
  84 + //update-end-author:scott date:20200907 for:issues/I1TAAP 前后端分离,shiro过滤器配置引起的跨域问题
  85 + }
  86 + // 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态
  87 + if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
  88 + httpServletResponse.setStatus(HttpStatus.OK.value());
  89 + return false;
  90 + }
  91 + //update-begin-author:taoyan date:20200708 for:多租户用到
  92 + String tenant_id = httpServletRequest.getHeader(CommonConstant.TENANT_ID);
  93 + TenantContext.setTenant(tenant_id);
  94 + //update-end-author:taoyan date:20200708 for:多租户用到
  95 + return super.preHandle(request, response);
  96 + }
  97 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/filters/ResourceCheckFilter.java 0 → 100644
  1 +package org.jeecg.config.shiro.filters;
  2 +
  3 +import javax.servlet.ServletRequest;
  4 +import javax.servlet.ServletResponse;
  5 +import javax.servlet.http.HttpServletRequest;
  6 +import javax.servlet.http.HttpServletResponse;
  7 +import org.apache.shiro.subject.Subject;
  8 +import org.apache.shiro.web.filter.AccessControlFilter;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +
  11 +/**
  12 + * @Author Scott
  13 + * @create 2019-02-01 15:56
  14 + * @desc 鉴权请求URL访问权限拦截器
  15 + */
  16 +@Slf4j
  17 +public class ResourceCheckFilter extends AccessControlFilter {
  18 +
  19 + private String errorUrl;
  20 +
  21 + public String getErrorUrl() {
  22 + return errorUrl;
  23 + }
  24 +
  25 + public void setErrorUrl(String errorUrl) {
  26 + this.errorUrl = errorUrl;
  27 + }
  28 +
  29 + /**
  30 + * 表示是否允许访问 ,如果允许访问返回true,否则false;
  31 + *
  32 + * @param servletRequest
  33 + * @param servletResponse
  34 + * @param o 表示写在拦截器中括号里面的字符串 mappedValue 就是 [urls] 配置中拦截器参数部分
  35 + * @return
  36 + * @throws Exception
  37 + */
  38 + @Override
  39 + protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
  40 + Subject subject = getSubject(servletRequest, servletResponse);
  41 + String url = getPathWithinApplication(servletRequest);
  42 + log.info("当前用户正在访问的 url => " + url);
  43 + return subject.isPermitted(url);
  44 + }
  45 +
  46 + /**
  47 + * onAccessDenied:表示当访问拒绝时是否已经处理了; 如果返回 true 表示需要继续处理; 如果返回 false
  48 + * 表示该拦截器实例已经处理了,将直接返回即可。
  49 + *
  50 + * @param servletRequest
  51 + * @param servletResponse
  52 + * @return
  53 + * @throws Exception
  54 + */
  55 + @Override
  56 + protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
  57 + log.info("当 isAccessAllowed 返回 false 的时候,才会执行 method onAccessDenied ");
  58 +
  59 + HttpServletRequest request = (HttpServletRequest) servletRequest;
  60 + HttpServletResponse response = (HttpServletResponse) servletResponse;
  61 + response.sendRedirect(request.getContextPath() + this.errorUrl);
  62 +
  63 + // 返回 false 表示已经处理,例如页面跳转啥的,表示不在走以下的拦截器了(如果还有配置的话)
  64 + return false;
  65 + }
  66 +
  67 +}
0 \ No newline at end of file 68 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/interceptor/SignAuthConfiguration.java 0 → 100644
  1 +package org.jeecg.config.sign.interceptor;
  2 +
  3 +import org.springframework.context.annotation.Bean;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  6 +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  7 +
  8 +/**
  9 + * online 拦截器配置
  10 + */
  11 +@Configuration
  12 +public class SignAuthConfiguration implements WebMvcConfigurer {
  13 +
  14 + @Bean
  15 + public SignAuthInterceptor signAuthInterceptor() {
  16 + return new SignAuthInterceptor();
  17 + }
  18 +
  19 + @Override
  20 + public void addInterceptors(InterceptorRegistry registry) {
  21 + String[] inculudes = new String[] {"/sys/dict/getDictItems/*", "/sys/dict/loadDict/*",
  22 + "/sys/dict/loadDictOrderByValue/*", "/sys/dict/loadDictItem/*", "/sys/dict/loadTreeData",
  23 + "/sys/api/queryTableDictItemsByCode", "/sys/api/queryFilterTableDictInfo", "/sys/api/queryTableDictByKeys",
  24 + "/sys/api/translateDictFromTable", "/sys/api/translateDictFromTableByKeys"};
  25 + registry.addInterceptor(signAuthInterceptor()).addPathPatterns(inculudes);
  26 + }
  27 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/interceptor/SignAuthInterceptor.java 0 → 100644
  1 +package org.jeecg.config.sign.interceptor;
  2 +
  3 +
  4 +import java.io.PrintWriter;
  5 +import java.util.SortedMap;
  6 +
  7 +import javax.servlet.http.HttpServletRequest;
  8 +import javax.servlet.http.HttpServletResponse;
  9 +
  10 +import org.jeecg.common.api.vo.Result;
  11 +import org.jeecg.common.util.DateUtils;
  12 +import org.jeecg.config.sign.util.BodyReaderHttpServletRequestWrapper;
  13 +import org.jeecg.config.sign.util.HttpUtils;
  14 +import org.jeecg.config.sign.util.SignUtil;
  15 +import org.springframework.web.servlet.HandlerInterceptor;
  16 +
  17 +import com.alibaba.fastjson.JSON;
  18 +
  19 +import lombok.extern.slf4j.Slf4j;
  20 +
  21 +/**
  22 + * 签名拦截器
  23 + * @author qinfeng
  24 + */
  25 +@Slf4j
  26 +public class SignAuthInterceptor implements HandlerInterceptor {
  27 + /**
  28 + * 5分钟有效期
  29 + */
  30 + private final static long MAX_EXPIRE = 5 * 60;
  31 +
  32 + @Override
  33 + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  34 + log.debug("request URI = " + request.getRequestURI());
  35 + HttpServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
  36 + //获取全部参数(包括URL和body上的)
  37 + SortedMap<String, String> allParams = HttpUtils.getAllParams(requestWrapper);
  38 + //对参数进行签名验证
  39 + String headerSign = request.getHeader("X-Sign");
  40 + String timesTamp = request.getHeader("X-TIMESTAMP");
  41 +
  42 + //1.校验时间有消息
  43 + try {
  44 + DateUtils.parseDate(timesTamp, "yyyyMMddHHmmss");
  45 + } catch (Exception e) {
  46 + throw new IllegalArgumentException("签名验证失败:X-TIMESTAMP格式必须为:yyyyMMddHHmmss");
  47 + }
  48 + Long clientTimestamp = Long.parseLong(timesTamp);
  49 + //判断时间戳 timestamp=201808091113
  50 + if ((DateUtils.getCurrentTimestamp() - clientTimestamp) > MAX_EXPIRE) {
  51 + throw new IllegalArgumentException("签名验证失败:X-TIMESTAMP已过期");
  52 + }
  53 +
  54 + //2.校验签名
  55 + boolean isSigned = SignUtil.verifySign(allParams,headerSign);
  56 +
  57 + if (isSigned) {
  58 + log.debug("Sign 签名通过!Header Sign : {}",headerSign);
  59 + return true;
  60 + } else {
  61 + log.error("request URI = " + request.getRequestURI());
  62 + log.error("Sign 签名校验失败!Header Sign : {}",headerSign);
  63 +// //打印日志参数
  64 +// Set<String> keySet = allParams.keySet();
  65 +// Iterator<String> paramIt = keySet.iterator();
  66 +// while(paramIt.hasNext()){
  67 +// String pkey = paramIt.next();
  68 +// String pval = allParams.get(pkey);
  69 +// log.error(" ["+pkey+":"+pval+"] ");
  70 +// }
  71 +
  72 + //校验失败返回前端
  73 + response.setCharacterEncoding("UTF-8");
  74 + response.setContentType("application/json; charset=utf-8");
  75 + PrintWriter out = response.getWriter();
  76 + Result<?> result = Result.error("Sign签名校验失败!");
  77 + out.print(JSON.toJSON(result));
  78 + return false;
  79 + }
  80 + }
  81 +
  82 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/util/BodyReaderHttpServletRequestWrapper.java 0 → 100644
  1 +package org.jeecg.config.sign.util;
  2 +
  3 +import javax.servlet.ReadListener;
  4 +import javax.servlet.ServletInputStream;
  5 +import javax.servlet.ServletRequest;
  6 +import javax.servlet.http.HttpServletRequest;
  7 +import javax.servlet.http.HttpServletRequestWrapper;
  8 +import java.io.*;
  9 +import java.nio.charset.Charset;
  10 +
  11 +/**
  12 + * 保存过滤器里面的流
  13 + *
  14 + * @author show
  15 + * @date 10:03 2019/5/30
  16 + */
  17 +public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
  18 +
  19 + private final byte[] body;
  20 +
  21 + public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) {
  22 +
  23 + super(request);
  24 + String sessionStream = getBodyString(request);
  25 + body = sessionStream.getBytes(Charset.forName("UTF-8"));
  26 + }
  27 +
  28 + /**
  29 + * 获取请求Body
  30 + *
  31 + * @param request
  32 + * @return
  33 + */
  34 + public String getBodyString(final ServletRequest request) {
  35 +
  36 + StringBuilder sb = new StringBuilder();
  37 + try (InputStream inputStream = cloneInputStream(request.getInputStream());
  38 + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")))) {
  39 + String line;
  40 + while ((line = reader.readLine()) != null) {
  41 + sb.append(line);
  42 + }
  43 + } catch (IOException e) {
  44 + e.printStackTrace();
  45 + }
  46 + return sb.toString();
  47 + }
  48 +
  49 + /**
  50 + * Description: 复制输入流</br>
  51 + *
  52 + * @param inputStream
  53 + * @return</br>
  54 + */
  55 + public InputStream cloneInputStream(ServletInputStream inputStream) {
  56 +
  57 + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  58 + byte[] buffer = new byte[1024];
  59 + int len;
  60 + try {
  61 + while ((len = inputStream.read(buffer)) > -1) {
  62 + byteArrayOutputStream.write(buffer, 0, len);
  63 + }
  64 + byteArrayOutputStream.flush();
  65 + } catch (IOException e) {
  66 + e.printStackTrace();
  67 + }
  68 + return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
  69 + }
  70 +
  71 + @Override
  72 + public BufferedReader getReader() {
  73 +
  74 + return new BufferedReader(new InputStreamReader(getInputStream()));
  75 + }
  76 +
  77 + @Override
  78 + public ServletInputStream getInputStream() {
  79 +
  80 + final ByteArrayInputStream bais = new ByteArrayInputStream(body);
  81 + return new ServletInputStream() {
  82 +
  83 + @Override
  84 + public int read() {
  85 +
  86 + return bais.read();
  87 + }
  88 +
  89 + @Override
  90 + public boolean isFinished() {
  91 +
  92 + return false;
  93 + }
  94 +
  95 + @Override
  96 + public boolean isReady() {
  97 +
  98 + return false;
  99 + }
  100 +
  101 + @Override
  102 + public void setReadListener(ReadListener readListener) {
  103 +
  104 + }
  105 + };
  106 + }
  107 +}
0 \ No newline at end of file 108 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/util/HttpUtils.java 0 → 100644
  1 +package org.jeecg.config.sign.util;
  2 +
  3 +import java.io.BufferedReader;
  4 +import java.io.IOException;
  5 +import java.io.InputStreamReader;
  6 +import java.io.UnsupportedEncodingException;
  7 +import java.net.URLDecoder;
  8 +import java.util.HashMap;
  9 +import java.util.Map;
  10 +import java.util.SortedMap;
  11 +import java.util.TreeMap;
  12 +
  13 +import javax.servlet.http.HttpServletRequest;
  14 +
  15 +import org.jeecg.common.util.oConvertUtils;
  16 +import org.springframework.http.HttpMethod;
  17 +
  18 +import com.alibaba.fastjson.JSONObject;
  19 +
  20 +/**
  21 + * http 工具类 获取请求中的参数
  22 + *
  23 + * @author show
  24 + * @date 14:23 2019/5/29
  25 + */
  26 +public class HttpUtils {
  27 +
  28 + /**
  29 + * 将URL的参数和body参数合并
  30 + *
  31 + * @author show
  32 + * @date 14:24 2019/5/29
  33 + * @param request
  34 + */
  35 + public static SortedMap<String, String> getAllParams(HttpServletRequest request) throws IOException {
  36 +
  37 + SortedMap<String, String> result = new TreeMap<>();
  38 + // 获取URL上最后带逗号的参数变量 sys/dict/getDictItems/sys_user,realname,username
  39 + String pathVariable = request.getRequestURI().substring(request.getRequestURI().lastIndexOf("/")+1);
  40 + if(pathVariable.contains(",")){
  41 + result.put(SignUtil.xPathVariable,pathVariable);
  42 + }
  43 + // 获取URL上的参数
  44 + Map<String, String> urlParams = getUrlParams(request);
  45 + for (Map.Entry entry : urlParams.entrySet()) {
  46 + result.put((String)entry.getKey(), (String)entry.getValue());
  47 + }
  48 + Map<String, String> allRequestParam = new HashMap<>(16);
  49 + // get请求不需要拿body参数
  50 + if (!HttpMethod.GET.name().equals(request.getMethod())) {
  51 + allRequestParam = getAllRequestParam(request);
  52 + }
  53 + // 将URL的参数和body参数进行合并
  54 + if (allRequestParam != null) {
  55 + for (Map.Entry entry : allRequestParam.entrySet()) {
  56 + result.put((String)entry.getKey(), (String)entry.getValue());
  57 + }
  58 + }
  59 + return result;
  60 + }
  61 +
  62 + /**
  63 + * 获取 Body 参数
  64 + *
  65 + * @author show
  66 + * @date 15:04 2019/5/30
  67 + * @param request
  68 + */
  69 + public static Map<String, String> getAllRequestParam(final HttpServletRequest request) throws IOException {
  70 +
  71 + BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
  72 + String str = "";
  73 + StringBuilder wholeStr = new StringBuilder();
  74 + // 一行一行的读取body体里面的内容;
  75 + while ((str = reader.readLine()) != null) {
  76 + wholeStr.append(str);
  77 + }
  78 + // 转化成json对象
  79 + return JSONObject.parseObject(wholeStr.toString(), Map.class);
  80 + }
  81 +
  82 + /**
  83 + * 将URL请求参数转换成Map
  84 + *
  85 + * @author show
  86 + * @param request
  87 + */
  88 + public static Map<String, String> getUrlParams(HttpServletRequest request) {
  89 + Map<String, String> result = new HashMap<>(16);
  90 + if(oConvertUtils.isEmpty(request.getQueryString())){
  91 + return result;
  92 + }
  93 + String param = "";
  94 + try {
  95 + param = URLDecoder.decode(request.getQueryString(), "utf-8");
  96 + } catch (UnsupportedEncodingException e) {
  97 + e.printStackTrace();
  98 + }
  99 + String[] params = param.split("&");
  100 + for (String s : params) {
  101 + int index = s.indexOf("=");
  102 + result.put(s.substring(0, index), s.substring(index + 1));
  103 + }
  104 + return result;
  105 + }
  106 +}
0 \ No newline at end of file 107 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/util/SignUtil.java 0 → 100644
  1 +package org.jeecg.config.sign.util;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.util.DigestUtils;
  6 +import org.springframework.util.StringUtils;
  7 +
  8 +import java.util.SortedMap;
  9 +
  10 +/**
  11 + * 签名工具类
  12 + *
  13 + * @author show
  14 + * @date 10:01 2019/5/30
  15 + */
  16 +@Slf4j
  17 +public class SignUtil {
  18 + //签名密钥串(前后端要一致,正式发布请自行修改)
  19 + private static final String signatureSecret = "dd05f1c54d63749eda95f9fa6d49v442a";
  20 + public static final String xPathVariable = "x-path-variable";
  21 +
  22 + /**
  23 + * @param params
  24 + * 所有的请求参数都会在这里进行排序加密
  25 + * @return 验证签名结果
  26 + */
  27 + public static boolean verifySign(SortedMap<String, String> params,String headerSign) {
  28 + if (params == null || StringUtils.isEmpty(headerSign)) {
  29 + return false;
  30 + }
  31 + // 把参数加密
  32 + String paramsSign = getParamsSign(params);
  33 + log.info("Param Sign : {}", paramsSign);
  34 + return !StringUtils.isEmpty(paramsSign) && headerSign.equals(paramsSign);
  35 + }
  36 +
  37 + /**
  38 + * @param params
  39 + * 所有的请求参数都会在这里进行排序加密
  40 + * @return 得到签名
  41 + */
  42 + public static String getParamsSign(SortedMap<String, String> params) {
  43 + //去掉 Url 里的时间戳
  44 + params.remove("_t");
  45 + String paramsJsonStr = JSONObject.toJSONString(params);
  46 + log.info("Param paramsJsonStr : {}", paramsJsonStr);
  47 + return DigestUtils.md5DigestAsHex((paramsJsonStr+signatureSecret).getBytes()).toUpperCase();
  48 + }
  49 +}
0 \ No newline at end of file 50 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/thirdapp/ThirdAppConfig.java 0 → 100644
  1 +package org.jeecg.config.thirdapp;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.beans.factory.annotation.Value;
  5 +import org.springframework.context.annotation.Configuration;
  6 +
  7 +/**
  8 + * 第三方App对接配置
  9 + */
  10 +@Configuration
  11 +public class ThirdAppConfig {
  12 +
  13 + /**
  14 + * 钉钉
  15 + */
  16 + public final static String DINGTALK = "DINGTALK";
  17 + /**
  18 + * 企业微信
  19 + */
  20 + public final static String WECHAT_ENTERPRISE = "WECHAT_ENTERPRISE";
  21 +
  22 + /**
  23 + * 是否启用 第三方App对接
  24 + */
  25 + @Value("${third-app.enabled:false}")
  26 + private boolean enabled;
  27 +
  28 + /**
  29 + * 系统类型,目前支持:WECHAT_ENTERPRISE(企业微信);DINGTALK (钉钉)
  30 + */
  31 + @Autowired
  32 + private ThirdAppTypeConfig type;
  33 +
  34 + public boolean isEnabled() {
  35 + return enabled;
  36 + }
  37 +
  38 + public ThirdAppConfig setEnabled(boolean enabled) {
  39 + this.enabled = enabled;
  40 + return this;
  41 + }
  42 +
  43 + /**
  44 + * 获取企业微信配置
  45 + */
  46 + public ThirdAppTypeItemVo getWechatEnterprise() {
  47 + return this.type.getWECHAT_ENTERPRISE();
  48 + }
  49 +
  50 + /**
  51 + * 获取钉钉配置
  52 + */
  53 + public ThirdAppTypeItemVo getDingtalk() {
  54 + return this.type.getDINGTALK();
  55 + }
  56 +
  57 + /**
  58 + * 获取企业微信是否启用
  59 + */
  60 + public boolean isWechatEnterpriseEnabled() {
  61 + try {
  62 + return this.enabled && this.getWechatEnterprise().isEnabled();
  63 + } catch (Exception e) {
  64 + return false;
  65 + }
  66 + }
  67 +
  68 + /**
  69 + * 获取钉钉是否启用
  70 + */
  71 + public boolean isDingtalkEnabled() {
  72 + try {
  73 + return this.enabled && this.getDingtalk().isEnabled();
  74 + } catch (Exception e) {
  75 + return false;
  76 + }
  77 + }
  78 +
  79 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/thirdapp/ThirdAppTypeConfig.java 0 → 100644
  1 +package org.jeecg.config.thirdapp;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.boot.context.properties.ConfigurationProperties;
  5 +import org.springframework.context.annotation.Configuration;
  6 +
  7 +/**
  8 + * 第三方APP配置
  9 + *
  10 + * @author sunjianlei
  11 + */
  12 +@Data
  13 +@Configuration
  14 +@ConfigurationProperties(prefix = "third-app.type")
  15 +public class ThirdAppTypeConfig {
  16 +
  17 + /**
  18 + * 对应企业微信配置
  19 + */
  20 + private ThirdAppTypeItemVo WECHAT_ENTERPRISE;
  21 + /**
  22 + * 对应钉钉配置
  23 + */
  24 + private ThirdAppTypeItemVo DINGTALK;
  25 +
  26 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/thirdapp/ThirdAppTypeItemVo.java 0 → 100644
  1 +package org.jeecg.config.thirdapp;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * 第三方App对接
  7 + */
  8 +@Data
  9 +public class ThirdAppTypeItemVo {
  10 +
  11 + /**
  12 + * 是否启用
  13 + */
  14 + private boolean enabled;
  15 + /**
  16 + * 应用Key
  17 + */
  18 + private String clientId;
  19 + /**
  20 + * 应用Secret
  21 + */
  22 + private String clientSecret;
  23 + /**
  24 + * 应用ID
  25 + */
  26 + private String agentId;
  27 + /**
  28 + * 目前仅企业微信用到:自建应用Secret
  29 + */
  30 + private String agentAppSecret;
  31 +
  32 + public int getAgentIdInt() {
  33 + return Integer.parseInt(agentId);
  34 + }
  35 +
  36 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/mapper/BaseCommonMapper.java 0 → 100644
  1 +package org.jeecg.modules.base.mapper;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.SqlParser;
  4 +import org.apache.ibatis.annotations.Param;
  5 +import org.jeecg.common.api.dto.LogDTO;
  6 +
  7 +public interface BaseCommonMapper {
  8 +
  9 + /**
  10 + * 保存日志
  11 + * @param dto
  12 + */
  13 + @SqlParser(filter=true)
  14 + void saveLog(@Param("dto")LogDTO dto);
  15 +
  16 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/mapper/xml/BaseCommonMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="org.jeecg.modules.base.mapper.BaseCommonMapper">
  4 +
  5 + <!-- 保存日志11 -->
  6 + <insert id="saveLog" parameterType="Object">
  7 + insert into sys_log (id, log_type, log_content, method, operate_type, request_param, ip, userid, username, cost_time, create_time)
  8 + values(
  9 + #{dto.id,jdbcType=VARCHAR},
  10 + #{dto.logType,jdbcType=INTEGER},
  11 + #{dto.logContent,jdbcType=VARCHAR},
  12 + #{dto.method,jdbcType=VARCHAR},
  13 + #{dto.operateType,jdbcType=INTEGER},
  14 + #{dto.requestParam,jdbcType=VARCHAR},
  15 + #{dto.ip,jdbcType=VARCHAR},
  16 + #{dto.userid,jdbcType=VARCHAR},
  17 + #{dto.username,jdbcType=VARCHAR},
  18 + #{dto.costTime,jdbcType=BIGINT},
  19 + #{dto.createTime,jdbcType=TIMESTAMP}
  20 + )
  21 + </insert>
  22 +
  23 +</mapper>
0 \ No newline at end of file 24 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/BaseCommonService.java 0 → 100644
  1 +package org.jeecg.modules.base.service;
  2 +
  3 +import org.jeecg.common.api.dto.LogDTO;
  4 +import org.jeecg.common.system.vo.LoginUser;
  5 +
  6 +/**
  7 + * common接口
  8 + */
  9 +public interface BaseCommonService {
  10 +
  11 + /**
  12 + * 保存日志
  13 + * @param logDTO
  14 + */
  15 + void addLog(LogDTO logDTO);
  16 +
  17 + /**
  18 + * 保存日志
  19 + * @param LogContent
  20 + * @param logType
  21 + * @param operateType
  22 + * @param user
  23 + */
  24 + void addLog(String LogContent, Integer logType, Integer operateType, LoginUser user);
  25 +
  26 + /**
  27 + * 保存日志
  28 + * @param LogContent
  29 + * @param logType
  30 + * @param operateType
  31 + */
  32 + void addLog(String LogContent, Integer logType, Integer operateType);
  33 +
  34 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/impl/BaseCommonServiceImpl.java 0 → 100644
  1 +package org.jeecg.modules.base.service.impl;
  2 +
  3 +import com.baomidou.mybatisplus.core.toolkit.IdWorker;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.apache.shiro.SecurityUtils;
  6 +import org.jeecg.common.api.dto.LogDTO;
  7 +import org.jeecg.common.constant.CacheConstant;
  8 +import org.jeecg.modules.base.mapper.BaseCommonMapper;
  9 +import org.jeecg.modules.base.service.BaseCommonService;
  10 +import org.jeecg.common.system.vo.LoginUser;
  11 +import org.jeecg.common.system.vo.SysPermissionDataRuleModel;
  12 +import org.jeecg.common.system.vo.SysUserCacheInfo;
  13 +import org.jeecg.common.util.IPUtils;
  14 +import org.jeecg.common.util.SpringContextUtils;
  15 +import org.jeecg.common.util.oConvertUtils;
  16 +import org.springframework.cache.annotation.Cacheable;
  17 +import org.springframework.stereotype.Service;
  18 +import org.springframework.util.AntPathMatcher;
  19 +import org.springframework.util.PathMatcher;
  20 +
  21 +import javax.annotation.Resource;
  22 +import javax.servlet.http.HttpServletRequest;
  23 +import java.util.*;
  24 +
  25 +@Service
  26 +@Slf4j
  27 +public class BaseCommonServiceImpl implements BaseCommonService {
  28 +
  29 + @Resource
  30 + private BaseCommonMapper baseCommonMapper;
  31 +
  32 + @Override
  33 + public void addLog(LogDTO logDTO) {
  34 + if(oConvertUtils.isEmpty(logDTO.getId())){
  35 + logDTO.setId(String.valueOf(IdWorker.getId()));
  36 + }
  37 + //保存日志(异常捕获处理,防止数据太大存储失败,导致业务失败)JT-238
  38 + try {
  39 + baseCommonMapper.saveLog(logDTO);
  40 + } catch (Exception e) {
  41 + log.warn(" LogContent length : "+logDTO.getLogContent().length());
  42 + log.warn(e.getMessage());
  43 + }
  44 + }
  45 +
  46 + @Override
  47 + public void addLog(String logContent, Integer logType, Integer operatetype, LoginUser user) {
  48 + LogDTO sysLog = new LogDTO();
  49 + sysLog.setId(String.valueOf(IdWorker.getId()));
  50 + //注解上的描述,操作日志内容
  51 + sysLog.setLogContent(logContent);
  52 + sysLog.setLogType(logType);
  53 + sysLog.setOperateType(operatetype);
  54 + try {
  55 + //获取request
  56 + HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
  57 + //设置IP地址
  58 + sysLog.setIp(IPUtils.getIpAddr(request));
  59 + } catch (Exception e) {
  60 + sysLog.setIp("127.0.0.1");
  61 + }
  62 + //获取登录用户信息
  63 + if(user==null){
  64 + try {
  65 + user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
  66 + } catch (Exception e) {
  67 + //e.printStackTrace();
  68 + }
  69 + }
  70 + if(user!=null){
  71 + sysLog.setUserid(user.getUsername());
  72 + sysLog.setUsername(user.getRealname());
  73 + }
  74 + sysLog.setCreateTime(new Date());
  75 + //保存日志(异常捕获处理,防止数据太大存储失败,导致业务失败)JT-238
  76 + try {
  77 + baseCommonMapper.saveLog(sysLog);
  78 + } catch (Exception e) {
  79 + log.warn(" LogContent length : "+sysLog.getLogContent().length());
  80 + log.warn(e.getMessage());
  81 + }
  82 + }
  83 +
  84 + @Override
  85 + public void addLog(String logContent, Integer logType, Integer operateType) {
  86 + addLog(logContent, logType, operateType, null);
  87 + }
  88 +
  89 +
  90 +
  91 +}
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/resources/static/pca.json 0 → 100644
  1 +{
  2 + "86":{
  3 + "110000":"北京市",
  4 + "120000":"天津市",
  5 + "130000":"河北省",
  6 + "140000":"山西省",
  7 + "150000":"内蒙古自治区",
  8 + "210000":"辽宁省",
  9 + "220000":"吉林省",
  10 + "230000":"黑龙江省",
  11 + "310000":"上海市",
  12 + "320000":"江苏省",
  13 + "330000":"浙江省",
  14 + "340000":"安徽省",
  15 + "350000":"福建省",
  16 + "360000":"江西省",
  17 + "370000":"山东省",
  18 + "410000":"河南省",
  19 + "420000":"湖北省",
  20 + "430000":"湖南省",
  21 + "440000":"广东省",
  22 + "450000":"广西壮族自治区",
  23 + "460000":"海南省",
  24 + "500000":"重庆市",
  25 + "510000":"四川省",
  26 + "520000":"贵州省",
  27 + "530000":"云南省",
  28 + "540000":"西藏自治区",
  29 + "610000":"陕西省",
  30 + "620000":"甘肃省",
  31 + "630000":"青海省",
  32 + "640000":"宁夏回族自治区",
  33 + "650000":"新疆维吾尔自治区",
  34 + "710000":"台湾省",
  35 + "910000":"港澳"
  36 + },
  37 + "110000":{"110100":"市辖区"},
  38 + "110100":{"110101":"东城区","110102":"西城区","110105":"朝阳区","110106":"丰台区","110107":"石景山区","110108":"海淀区","110109":"门头沟区","110111":"房山区","110112":"通州区","110113":"顺义区","110114":"昌平区","110115":"大兴区","110116":"怀柔区","110117":"平谷区","110118":"密云区","110119":"延庆区"},
  39 + "120000":{"120100":"市辖区"},
  40 + "120100":{"120101":"和平区","120102":"河东区","120103":"河西区","120104":"南开区","120105":"河北区","120106":"红桥区","120110":"东丽区","120111":"西青区","120112":"津南区","120113":"北辰区","120114":"武清区","120115":"宝坻区","120116":"滨海新区","120117":"宁河区","120118":"静海区","120119":"蓟州区"},"130000":{"130100":"石家庄市","130200":"唐山市","130300":"秦皇岛市","130400":"邯郸市","130500":"邢台市","130600":"保定市","130700":"张家口市","130800":"承德市","130900":"沧州市","131000":"廊坊市","131100":"衡水市","139001":"定州市","139002":"辛集市"},"130100":{"130102":"长安区","130104":"桥西区","130105":"新华区","130107":"井陉矿区","130108":"裕华区","130109":"藁城区","130110":"鹿泉区","130111":"栾城区","130121":"井陉县","130123":"正定县","130125":"行唐县","130126":"灵寿县","130127":"高邑县","130128":"深泽县","130129":"赞皇县","130130":"无极县","130131":"平山县","130132":"元氏县","130133":"赵县","130183":"晋州市","130184":"新乐市"},"130200":{"130202":"路南区","130203":"路北区","130204":"古冶区","130205":"开平区","130207":"丰南区","130208":"丰润区","130209":"曹妃甸区","130223":"滦县","130224":"滦南县","130225":"乐亭县","130227":"迁西县","130229":"玉田县","130281":"遵化市","130283":"迁安市"},"130300":{"130302":"海港区","130303":"山海关区","130304":"北戴河区","130306":"抚宁区","130321":"青龙满族自治县","130322":"昌黎县","130324":"卢龙县"},"130400":{"130402":"邯山区","130403":"丛台区","130404":"复兴区","130406":"峰峰矿区","130421":"邯郸县","130423":"临漳县","130424":"成安县","130425":"大名县","130426":"涉县","130427":"磁县","130428":"肥乡县","130429":"永年县","130430":"邱县","130431":"鸡泽县","130432":"广平县","130433":"馆陶县","130434":"魏县","130435":"曲周县","130481":"武安市"},"130500":{"130502":"桥东区","130503":"桥西区","130521":"邢台县","130522":"临城县","130523":"内丘县","130524":"柏乡县","130525":"隆尧县","130526":"任县","130527":"南和县","130528":"宁晋县","130529":"巨鹿县","130530":"新河县","130531":"广宗县","130532":"平乡县","130533":"威县","130534":"清河县","130535":"临西县","130581":"南宫市","130582":"沙河市"},"130600":{"130602":"竞秀区","130606":"莲池区","130607":"满城区","130608":"清苑区","130609":"徐水区","130623":"涞水县","130624":"阜平县","130626":"定兴县","130627":"唐县","130628":"高阳县","130629":"容城县","130630":"涞源县","130631":"望都县","130632":"安新县","130633":"易县","130634":"曲阳县","130635":"蠡县","130636":"顺平县","130637":"博野县","130638":"雄县","130681":"涿州市","130683":"安国市","130684":"高碑店市"},"130700":{"130702":"桥东区","130703":"桥西区","130705":"宣化区","130706":"下花园区","130708":"万全区","130709":"崇礼区","130722":"张北县","130723":"康保县","130724":"沽源县","130725":"尚义县","130726":"蔚县","130727":"阳原县","130728":"怀安县","130730":"怀来县","130731":"涿鹿县","130732":"赤城县"},"130800":{"130802":"双桥区","130803":"双滦区","130804":"鹰手营子矿区","130821":"承德县","130822":"兴隆县","130823":"平泉县","130824":"滦平县","130825":"隆化县","130826":"丰宁满族自治县","130827":"宽城满族自治县","130828":"围场满族蒙古族自治县"},"130900":{"130902":"新华区","130903":"运河区","130921":"沧县","130922":"青县","130923":"东光县","130924":"海兴县","130925":"盐山县","130926":"肃宁县","130927":"南皮县","130928":"吴桥县","130929":"献县","130930":"孟村回族自治县","130981":"泊头市","130982":"任丘市","130983":"黄骅市","130984":"河间市"},"131000":{"131002":"安次区","131003":"广阳区","131022":"固安县","131023":"永清县","131024":"香河县","131025":"大城县","131026":"文安县","131028":"大厂回族自治县","131081":"霸州市","131082":"三河市"},"131100":{"131102":"桃城区","131103":"冀州区","131121":"枣强县","131122":"武邑县","131123":"武强县","131124":"饶阳县","131125":"安平县","131126":"故城县","131127":"景县","131128":"阜城县","131182":"深州市"},"139001":{"1390011":"留早镇","13900111":"邢邑镇","139001001":"南城区街道","139001002":"北城区街道","139001003":"西城区街道","139001004":"长安路街道","139001101":"清风店镇","139001102":"庞村镇","139001103":"砖路镇","139001104":"明月店镇","139001105":"叮咛店镇","139001106":"东亭镇","139001107":"大辛庄镇","139001108":"东旺镇","139001109":"高蓬镇","139001111":"李亲顾镇","139001112":"子位镇","139001113":"开元镇","139001115":"周村镇","139001116":"息冢镇","139001203":"东留春乡","139001204":"号头庄回族乡","139001205":"杨家庄乡","139001206":"大鹿庄乡","139001208":"西城乡"},"139002":{"1390021":"辛集镇","1390022":"天宫营乡","1390025":"辛集经济开发区","139002101":"旧城镇","139002102":"张古庄镇","139002103":"位伯镇","139002104":"新垒头镇","139002105":"新城镇","139002106":"南智邱镇","139002107":"王口镇","139002201":"前营乡","139002202":"马庄乡","139002203":"和睦井乡","139002204":"田家庄乡","139002205":"中里厢乡","139002206":"小辛庄乡"},"140000":{"140100":"太原市","140200":"大同市","140300":"阳泉市","140400":"长治市","140500":"晋城市","140600":"朔州市","140700":"晋中市","140800":"运城市","140900":"忻州市","141000":"临汾市","141100":"吕梁市"},"140100":{"140105":"小店区","140106":"迎泽区","140107":"杏花岭区","140108":"尖草坪区","140109":"万柏林区","140110":"晋源区","140121":"清徐县","140122":"阳曲县","140123":"娄烦县","140181":"古交市"},"140200":{"140202":"城区","140203":"矿区","140211":"南郊区","140212":"新荣区","140221":"阳高县","140222":"天镇县","140223":"广灵县","140224":"灵丘县","140225":"浑源县","140226":"左云县","140227":"大同县"},"140300":{"140302":"城区","140303":"矿区","140311":"郊区","140321":"平定县","140322":"盂县"},"140400":{"140402":"城区","140411":"郊区","140421":"长治县","140423":"襄垣县","140424":"屯留县","140425":"平顺县","140426":"黎城县","140427":"壶关县","140428":"长子县","140429":"武乡县","140430":"沁县","140431":"沁源县","140481":"潞城市"},"140500":{"140502":"城区","140521":"沁水县","140522":"阳城县","140524":"陵川县","140525":"泽州县","140581":"高平市"},"140600":{"140602":"朔城区","140603":"平鲁区","140621":"山阴县","140622":"应县","140623":"右玉县","140624":"怀仁县"},"140700":{"140702":"榆次区","140721":"榆社县","140722":"左权县","140723":"和顺县","140724":"昔阳县","140725":"寿阳县","140726":"太谷县","140727":"祁县","140728":"平遥县","140729":"灵石县","140781":"介休市"},"140800":{"140802":"盐湖区","140821":"临猗县","140822":"万荣县","140823":"闻喜县","140824":"稷山县","140825":"新绛县","140826":"绛县","140827":"垣曲县","140828":"夏县","140829":"平陆县","140830":"芮城县","140881":"永济市","140882":"河津市"},"140900":{"140902":"忻府区","140921":"定襄县","140922":"五台县","140923":"代县","140924":"繁峙县","140925":"宁武县","140926":"静乐县","140927":"神池县","140928":"五寨县","140929":"岢岚县","140930":"河曲县","140931":"保德县","140932":"偏关县","140981":"原平市"},
  41 + "141000":{"141002":"尧都区","141021":"曲沃县","141022":"翼城县","141023":"襄汾县","141024":"洪洞县","141025":"古县","141026":"安泽县","141027":"浮山县","141028":"吉县","141029":"乡宁县","141030":"大宁县","141031":"隰县","141032":"永和县","141033":"蒲县","141034":"汾西县","141081":"侯马市","141082":"霍州市"},"141100":{"141102":"离石区","141121":"文水县","141122":"交城县","141123":"兴县","141124":"临县","141125":"柳林县","141126":"石楼县","141127":"岚县","141128":"方山县","141129":"中阳县","141130":"交口县","141181":"孝义市","141182":"汾阳市"},"150000":{"150100":"呼和浩特市","150200":"包头市","150300":"乌海市","150400":"赤峰市","150500":"通辽市","150600":"鄂尔多斯市","150700":"呼伦贝尔市","150800":"巴彦淖尔市","150900":"乌兰察布市","152200":"兴安盟","152500":"锡林郭勒盟","152900":"阿拉善盟"},"150100":{"150102":"新城区","150103":"回民区","150104":"玉泉区","150105":"赛罕区","150121":"土默特左旗","150122":"托克托县","150123":"和林格尔县","150124":"清水河县","150125":"武川县"},"150200":{"150202":"东河区","150203":"昆都仑区","150204":"青山区","150205":"石拐区","150206":"白云鄂博矿区","150207":"九原区","150221":"土默特右旗","150222":"固阳县","150223":"达尔罕茂明安联合旗"},"150300":{"150302":"海勃湾区","150303":"海南区","150304":"乌达区"},"150400":{"150402":"红山区","150403":"元宝山区","150404":"松山区","150421":"阿鲁科尔沁旗","150422":"巴林左旗","150423":"巴林右旗","150424":"林西县","150425":"克什克腾旗","150426":"翁牛特旗","150428":"喀喇沁旗","150429":"宁城县","150430":"敖汉旗"},"150500":{"150502":"科尔沁区","150521":"科尔沁左翼中旗","150522":"科尔沁左翼后旗","150523":"开鲁县","150524":"库伦旗","150525":"奈曼旗","150526":"扎鲁特旗","150581":"霍林郭勒市"},"150600":{"150602":"东胜区","150603":"康巴什区","150621":"达拉特旗","150622":"准格尔旗","150623":"鄂托克前旗","150624":"鄂托克旗","150625":"杭锦旗","150626":"乌审旗","150627":"伊金霍洛旗"},"150700":{"150702":"海拉尔区","150703":"扎赉诺尔区","150721":"阿荣旗","150722":"莫力达瓦达斡尔族自治旗","150723":"鄂伦春自治旗","150724":"鄂温克族自治旗","150725":"陈巴尔虎旗","150726":"新巴尔虎左旗","150727":"新巴尔虎右旗","150781":"满洲里市","150782":"牙克石市","150783":"扎兰屯市","150784":"额尔古纳市","150785":"根河市"},"150800":{"150802":"临河区","150821":"五原县","150822":"磴口县","150823":"乌拉特前旗","150824":"乌拉特中旗","150825":"乌拉特后旗","150826":"杭锦后旗"},"150900":{"150902":"集宁区","150921":"卓资县","150922":"化德县","150923":"商都县","150924":"兴和县","150925":"凉城县","150926":"察哈尔右翼前旗","150927":"察哈尔右翼中旗","150928":"察哈尔右翼后旗","150929":"四子王旗","150981":"丰镇市"},"152200":{"152201":"乌兰浩特市","152202":"阿尔山市","152221":"科尔沁右翼前旗","152222":"科尔沁右翼中旗","152223":"扎赉特旗","152224":"突泉县"},"152500":{"152501":"二连浩特市","152502":"锡林浩特市","152522":"阿巴嘎旗","152523":"苏尼特左旗","152524":"苏尼特右旗","152525":"东乌珠穆沁旗","152526":"西乌珠穆沁旗","152527":"太仆寺旗","152528":"镶黄旗","152529":"正镶白旗","152530":"正蓝旗","152531":"多伦县"},"152900":{"152921":"阿拉善左旗","152922":"阿拉善右旗","152923":"额济纳旗"},"210000":{"210100":"沈阳市","210200":"大连市","210300":"鞍山市","210400":"抚顺市","210500":"本溪市","210600":"丹东市","210700":"锦州市","210800":"营口市","210900":"阜新市","211000":"辽阳市","211100":"盘锦市","211200":"铁岭市","211300":"朝阳市","211400":"葫芦岛市"},"210100":{"210102":"和平区","210103":"沈河区","210104":"大东区","210105":"皇姑区","210106":"铁西区","210111":"苏家屯区","210112":"浑南区","210113":"沈北新区","210114":"于洪区","210115":"辽中区","210123":"康平县","210124":"法库县","210181":"新民市"},"210200":{"210202":"中山区","210203":"西岗区","210204":"沙河口区","210211":"甘井子区","210212":"旅顺口区","210213":"金州区","210214":"普兰店区","210224":"长海县","210281":"瓦房店市","210283":"庄河市"},"210300":{"210302":"铁东区","210303":"铁西区","210304":"立山区","210311":"千山区","210321":"台安县","210323":"岫岩满族自治县","210381":"海城市"},"210400":{"210402":"新抚区","210403":"东洲区","210404":"望花区","210411":"顺城区","210421":"抚顺县","210422":"新宾满族自治县","210423":"清原满族自治县"},"210500":{"210502":"平山区","210503":"溪湖区","210504":"明山区","210505":"南芬区","210521":"本溪满族自治县","210522":"桓仁满族自治县"},"210600":{"210602":"元宝区","210603":"振兴区","210604":"振安区","210624":"宽甸满族自治县","210681":"东港市","210682":"凤城市"},"210700":{"210702":"古塔区","210703":"凌河区","210711":"太和区","210726":"黑山县","210727":"义县","210781":"凌海市","210782":"北镇市"},"210800":{"210802":"站前区","210803":"西市区","210804":"鲅鱼圈区","210811":"老边区","210881":"盖州市","210882":"大石桥市"},"210900":{"210902":"海州区","210903":"新邱区","210904":"太平区","210905":"清河门区","210911":"细河区","210921":"阜新蒙古族自治县","210922":"彰武县"},"211000":{"211002":"白塔区","211003":"文圣区","211004":"宏伟区","211005":"弓长岭区","211011":"太子河区","211021":"辽阳县","211081":"灯塔市"},"211100":{"211102":"双台子区","211103":"兴隆台区","211104":"大洼区","211122":"盘山县"},"211200":{"211202":"银州区","211204":"清河区","211221":"铁岭县","211223":"西丰县","211224":"昌图县","211281":"调兵山市","211282":"开原市"},"211300":{"211302":"双塔区","211303":"龙城区","211321":"朝阳县","211322":"建平县","211324":"喀喇沁左翼蒙古族自治县","211381":"北票市","211382":"凌源市"},"211400":{"211402":"连山区","211403":"龙港区","211404":"南票区","211421":"绥中县","211422":"建昌县","211481":"兴城市"},"220000":{"220100":"长春市","220200":"吉林市","220300":"四平市","220400":"辽源市","220500":"通化市","220600":"白山市","220700":"松原市","220800":"白城市","222400":"延边朝鲜族自治州"},"220100":{"220102":"南关区","220103":"宽城区","220104":"朝阳区","220105":"二道区","220106":"绿园区","220112":"双阳区","220113":"九台区","220122":"农安县","220182":"榆树市","220183":"德惠市"},"220200":{"220202":"昌邑区","220203":"龙潭区","220204":"船营区","220211":"丰满区","220221":"永吉县","220281":"蛟河市","220282":"桦甸市","220283":"舒兰市","220284":"磐石市"},"220300":{"220302":"铁西区","220303":"铁东区","220322":"梨树县","220323":"伊通满族自治县","220381":"公主岭市","220382":"双辽市"},"220400":{"220402":"龙山区","220403":"西安区","220421":"东丰县","220422":"东辽县"},"220500":{"220502":"东昌区","220503":"二道江区","220521":"通化县","220523":"辉南县","220524":"柳河县","220581":"梅河口市","220582":"集安市"},"220600":{"220602":"浑江区","220605":"江源区","220621":"抚松县","220622":"靖宇县","220623":"长白朝鲜族自治县","220681":"临江市"},"220700":{"220702":"宁江区","220721":"前郭尔罗斯蒙古族自治县","220722":"长岭县","220723":"乾安县","220781":"扶余市"},"220800":{"220802":"洮北区","220821":"镇赉县","220822":"通榆县","220881":"洮南市","220882":"大安市"},"222400":{"222401":"延吉市","222402":"图们市","222403":"敦化市","222404":"珲春市","222405":"龙井市","222406":"和龙市","222424":"汪清县","222426":"安图县"},"230000":{"230100":"哈尔滨市","230200":"齐齐哈尔市","230300":"鸡西市","230400":"鹤岗市","230500":"双鸭山市","230600":"大庆市","230700":"伊春市","230800":"佳木斯市","230900":"七台河市","231000":"牡丹江市","231100":"黑河市","231200":"绥化市","232700":"大兴安岭地区"},"230100":{"230102":"道里区","230103":"南岗区","230104":"道外区","230108":"平房区","230109":"松北区","230110":"香坊区","230111":"呼兰区","230112":"阿城区","230113":"双城区","230123":"依兰县","230124":"方正县","230125":"宾县","230126":"巴彦县","230127":"木兰县","230128":"通河县","230129":"延寿县","230183":"尚志市","230184":"五常市"},"230200":{"230202":"龙沙区","230203":"建华区","230204":"铁锋区","230205":"昂昂溪区","230206":"富拉尔基区","230207":"碾子山区","230208":"梅里斯达斡尔族区","230221":"龙江县","230223":"依安县","230224":"泰来县","230225":"甘南县","230227":"富裕县","230229":"克山县","230230":"克东县","230231":"拜泉县","230281":"讷河市"},"230300":{"230302":"鸡冠区","230303":"恒山区","230304":"滴道区","230305":"梨树区","230306":"城子河区","230307":"麻山区","230321":"鸡东县","230381":"虎林市","230382":"密山市"},"230400":{"230402":"向阳区","230403":"工农区","230404":"南山区","230405":"兴安区","230406":"东山区","230407":"兴山区","230421":"萝北县","230422":"绥滨县"},"230500":{"230502":"尖山区","230503":"岭东区","230505":"四方台区","230506":"宝山区","230521":"集贤县","230522":"友谊县","230523":"宝清县","230524":"饶河县"},"230600":{"230602":"萨尔图区","230603":"龙凤区","230604":"让胡路区","230605":"红岗区","230606":"大同区","230621":"肇州县","230622":"肇源县","230623":"林甸县","230624":"杜尔伯特蒙古族自治县"},"230700":{"230702":"伊春区","230703":"南岔区","230704":"友好区","230705":"西林区","230706":"翠峦区","230707":"新青区","230708":"美溪区","230709":"金山屯区","230710":"五营区","230711":"乌马河区","230712":"汤旺河区","230713":"带岭区","230714":"乌伊岭区","230715":"红星区","230716":"上甘岭区","230722":"嘉荫县","230781":"铁力市"},"230800":{"230803":"向阳区","230804":"前进区","230805":"东风区","230811":"郊区","230822":"桦南县","230826":"桦川县","230828":"汤原县","230881":"同江市","230882":"富锦市","230883":"抚远市"},"230900":{"230902":"新兴区","230903":"桃山区","230904":"茄子河区","230921":"勃利县"},"231000":{"231002":"东安区","231003":"阳明区","231004":"爱民区","231005":"西安区","231025":"林口县","231081":"绥芬河市","231083":"海林市","231084":"宁安市","231085":"穆棱市","231086":"东宁市"},"231100":{"231102":"爱辉区","231121":"嫩江县","231123":"逊克县","231124":"孙吴县","231181":"北安市","231182":"五大连池市"},"231200":{"231202":"北林区","231221":"望奎县","231222":"兰西县","231223":"青冈县","231224":"庆安县","231225":"明水县","231226":"绥棱县","231281":"安达市","231282":"肇东市","231283":"海伦市"},"232700":{"232721":"呼玛县","232722":"塔河县","232723":"漠河县"},"310000":{"310100":"市辖区"},
  42 + "310100":{"310101":"黄浦区","310104":"徐汇区","310105":"长宁区","310106":"静安区","310107":"普陀区","310109":"虹口区","310110":"杨浦区","310112":"闵行区","310113":"宝山区","310114":"嘉定区","310115":"浦东新区","310116":"金山区","310117":"松江区","310118":"青浦区","310120":"奉贤区","310151":"崇明区"},"320000":{"320100":"南京市","320200":"无锡市","320300":"徐州市","320400":"常州市","320500":"苏州市","320600":"南通市","320700":"连云港市","320800":"淮安市","320900":"盐城市","321000":"扬州市","321100":"镇江市","321200":"泰州市","321300":"宿迁市"},"320100":{"320102":"玄武区","320104":"秦淮区","320105":"建邺区","320106":"鼓楼区","320111":"浦口区","320113":"栖霞区","320114":"雨花台区","320115":"江宁区","320116":"六合区","320117":"溧水区","320118":"高淳区"},
  43 + "320200":{"320205":"锡山区","320206":"惠山区","320211":"滨湖区","320213":"梁溪区","320214":"新吴区","320281":"江阴市","320282":"宜兴市"},"320300":{"320302":"鼓楼区","320303":"云龙区","320305":"贾汪区","320311":"泉山区","320312":"铜山区","320321":"丰县","320322":"沛县","320324":"睢宁县","320381":"新沂市","320382":"邳州市"},
  44 + "320400":{"320402":"天宁区","320404":"钟楼区","320411":"新北区","320412":"武进区","320413":"金坛区","320481":"溧阳市"},"320500":{"320505":"虎丘区","320506":"吴中区","320507":"相城区","320508":"姑苏区","320509":"吴江区","320581":"常熟市","320582":"张家港市","320583":"昆山市","320585":"太仓市"},"320600":{"320602":"崇川区","320611":"港闸区","320612":"通州区","320621":"海安县","320623":"如东县","320681":"启东市","320682":"如皋市","320684":"海门市"},"320700":{"320703":"连云区","320706":"海州区","320707":"赣榆区","320722":"东海县","320723":"灌云县","320724":"灌南县"},"320800":{"320803":"淮安区","320804":"淮阴区","320812":"清江浦区","320813":"洪泽区","320826":"涟水县","320830":"盱眙县","320831":"金湖县"},"320900":{"320902":"亭湖区","320903":"盐都区","320904":"大丰区","320921":"响水县","320922":"滨海县","320923":"阜宁县","320924":"射阳县","320925":"建湖县","320981":"东台市"},"321000":{"321002":"广陵区","321003":"邗江区","321012":"江都区","321023":"宝应县","321081":"仪征市","321084":"高邮市"},"321100":{"321102":"京口区","321111":"润州区","321112":"丹徒区","321181":"丹阳市","321182":"扬中市","321183":"句容市"},"321200":{"321202":"海陵区","321203":"高港区","321204":"姜堰区","321281":"兴化市","321282":"靖江市","321283":"泰兴市"},"321300":{"321302":"宿城区","321311":"宿豫区","321322":"沭阳县","321323":"泗阳县","321324":"泗洪县"},"330000":{"330100":"杭州市","330200":"宁波市","330300":"温州市","330400":"嘉兴市","330500":"湖州市","330600":"绍兴市","330700":"金华市","330800":"衢州市","330900":"舟山市","331000":"台州市","331100":"丽水市"},"330100":{"330102":"上城区","330103":"下城区","330104":"江干区","330105":"拱墅区","330106":"西湖区","330108":"滨江区","330109":"萧山区","330110":"余杭区","330111":"富阳区","330122":"桐庐县","330127":"淳安县","330182":"建德市","330185":"临安市"},"330200":{"330203":"海曙区","330204":"江东区","330205":"江北区","330206":"北仑区","330211":"镇海区","330212":"鄞州区","330225":"象山县","330226":"宁海县","330281":"余姚市","330282":"慈溪市","330283":"奉化市"},"330300":{"330302":"鹿城区","330303":"龙湾区","330304":"瓯海区","330305":"洞头区","330324":"永嘉县","330326":"平阳县","330327":"苍南县","330328":"文成县","330329":"泰顺县","330381":"瑞安市","330382":"乐清市"},"330400":{"330402":"南湖区","330411":"秀洲区","330421":"嘉善县","330424":"海盐县","330481":"海宁市","330482":"平湖市","330483":"桐乡市"},"330500":{"330502":"吴兴区","330503":"南浔区","330521":"德清县","330522":"长兴县","330523":"安吉县"},"330600":{"330602":"越城区","330603":"柯桥区","330604":"上虞区","330624":"新昌县","330681":"诸暨市","330683":"嵊州市"},"330700":{"330702":"婺城区","330703":"金东区","330723":"武义县","330726":"浦江县","330727":"磐安县","330781":"兰溪市","330782":"义乌市","330783":"东阳市","330784":"永康市"},"330800":{"330802":"柯城区","330803":"衢江区","330822":"常山县","330824":"开化县","330825":"龙游县","330881":"江山市"},"330900":{"330902":"定海区","330903":"普陀区","330921":"岱山县","330922":"嵊泗县"},"331000":{"331002":"椒江区","331003":"黄岩区","331004":"路桥区","331021":"玉环县","331022":"三门县","331023":"天台县","331024":"仙居县","331081":"温岭市","331082":"临海市"},"331100":{"331102":"莲都区","331121":"青田县","331122":"缙云县","331123":"遂昌县","331124":"松阳县","331125":"云和县","331126":"庆元县","331127":"景宁畲族自治县","331181":"龙泉市"},"340000":{"340100":"合肥市","340200":"芜湖市","340300":"蚌埠市","340400":"淮南市","340500":"马鞍山市","340600":"淮北市","340700":"铜陵市","340800":"安庆市","341000":"黄山市","341100":"滁州市","341200":"阜阳市","341300":"宿州市","341500":"六安市","341600":"亳州市","341700":"池州市","341800":"宣城市"},"340100":{"340102":"瑶海区","340103":"庐阳区","340104":"蜀山区","340111":"包河区","340121":"长丰县","340122":"肥东县","340123":"肥西县","340124":"庐江县","340181":"巢湖市"},"340200":{"340202":"镜湖区","340203":"弋江区","340207":"鸠江区","340208":"三山区","340221":"芜湖县","340222":"繁昌县","340223":"南陵县","340225":"无为县"},"340300":{"340302":"龙子湖区","340303":"蚌山区","340304":"禹会区","340311":"淮上区","340321":"怀远县","340322":"五河县","340323":"固镇县"},"340400":{"340402":"大通区","340403":"田家庵区","340404":"谢家集区","340405":"八公山区","340406":"潘集区","340421":"凤台县","340422":"寿县"},"340500":{"340503":"花山区","340504":"雨山区","340506":"博望区","340521":"当涂县","340522":"含山县","340523":"和县"},"340600":{"340602":"杜集区","340603":"相山区","340604":"烈山区","340621":"濉溪县"},"340700":{"340705":"铜官区","340706":"义安区","340711":"郊区","340722":"枞阳县"},"340800":{"340802":"迎江区","340803":"大观区","340811":"宜秀区","340822":"怀宁县","340824":"潜山县","340825":"太湖县","340826":"宿松县","340827":"望江县","340828":"岳西县","340881":"桐城市"},"341000":{"341002":"屯溪区","341003":"黄山区","341004":"徽州区","341021":"歙县","341022":"休宁县","341023":"黟县","341024":"祁门县"},"341100":{"341102":"琅琊区","341103":"南谯区","341122":"来安县","341124":"全椒县","341125":"定远县","341126":"凤阳县","341181":"天长市","341182":"明光市"},"341200":{"341202":"颍州区","341203":"颍东区","341204":"颍泉区","341221":"临泉县","341222":"太和县","341225":"阜南县","341226":"颍上县","341282":"界首市"},"341300":{"341302":"埇桥区","341321":"砀山县","341322":"萧县","341323":"灵璧县","341324":"泗县"},"341500":{"341502":"金安区","341503":"裕安区","341504":"叶集区","341522":"霍邱县","341523":"舒城县","341524":"金寨县","341525":"霍山县"},"341600":{"341602":"谯城区","341621":"涡阳县","341622":"蒙城县","341623":"利辛县"},"341700":{"341702":"贵池区","341721":"东至县","341722":"石台县","341723":"青阳县"},"341800":{"341802":"宣州区","341821":"郎溪县","341822":"广德县","341823":"泾县","341824":"绩溪县","341825":"旌德县","341881":"宁国市"},"350000":{"350100":"福州市","350200":"厦门市","350300":"莆田市","350400":"三明市","350500":"泉州市","350600":"漳州市","350700":"南平市","350800":"龙岩市","350900":"宁德市"},"350100":{"350102":"鼓楼区","350103":"台江区","350104":"仓山区","350105":"马尾区","350111":"晋安区","350121":"闽侯县","350122":"连江县","350123":"罗源县","350124":"闽清县","350125":"永泰县","350128":"平潭县","350181":"福清市","350182":"长乐市"},"350200":{"350203":"思明区","350205":"海沧区","350206":"湖里区","350211":"集美区","350212":"同安区","350213":"翔安区"},"350300":{"350302":"城厢区","350303":"涵江区","350304":"荔城区","350305":"秀屿区","350322":"仙游县"},"350400":{"350402":"梅列区","350403":"三元区","350421":"明溪县","350423":"清流县","350424":"宁化县","350425":"大田县","350426":"尤溪县","350427":"沙县","350428":"将乐县","350429":"泰宁县","350430":"建宁县","350481":"永安市"},"350500":{"350502":"鲤城区","350503":"丰泽区","350504":"洛江区","350505":"泉港区","350521":"惠安县","350524":"安溪县","350525":"永春县","350526":"德化县","350527":"金门县","350581":"石狮市","350582":"晋江市","350583":"南安市"},"350600":{"350602":"芗城区","350603":"龙文区","350622":"云霄县","350623":"漳浦县","350624":"诏安县","350625":"长泰县","350626":"东山县","350627":"南靖县","350628":"平和县","350629":"华安县","350681":"龙海市"},"350700":{"350702":"延平区","350703":"建阳区","350721":"顺昌县","350722":"浦城县","350723":"光泽县","350724":"松溪县","350725":"政和县","350781":"邵武市","350782":"武夷山市","350783":"建瓯市"},"350800":{"350802":"新罗区","350803":"永定区","350821":"长汀县","350823":"上杭县","350824":"武平县","350825":"连城县","350881":"漳平市"},"350900":{"350902":"蕉城区","350921":"霞浦县","350922":"古田县","350923":"屏南县","350924":"寿宁县","350925":"周宁县","350926":"柘荣县","350981":"福安市","350982":"福鼎市"},"360000":{"360100":"南昌市","360200":"景德镇市","360300":"萍乡市","360400":"九江市","360500":"新余市","360600":"鹰潭市","360700":"赣州市","360800":"吉安市","360900":"宜春市","361000":"抚州市","361100":"上饶市"},"360100":{"360102":"东湖区","360103":"西湖区","360104":"青云谱区","360105":"湾里区","360111":"青山湖区","360112":"新建区","360121":"南昌县","360123":"安义县","360124":"进贤县"},"360200":{"360202":"昌江区","360203":"珠山区","360222":"浮梁县","360281":"乐平市"},"360300":{"360302":"安源区","360313":"湘东区","360321":"莲花县","360322":"上栗县","360323":"芦溪县"},"360400":{"360402":"濂溪区","360403":"浔阳区","360421":"九江县","360423":"武宁县","360424":"修水县","360425":"永修县","360426":"德安县","360428":"都昌县","360429":"湖口县","360430":"彭泽县","360481":"瑞昌市","360482":"共青城市","360483":"庐山市"},"360500":{"360502":"渝水区","360521":"分宜县"},"360600":{"360602":"月湖区","360622":"余江县","360681":"贵溪市"},"360700":{"360702":"章贡区","360703":"南康区","360721":"赣县","360722":"信丰县","360723":"大余县","360724":"上犹县","360725":"崇义县","360726":"安远县","360727":"龙南县","360728":"定南县","360729":"全南县","360730":"宁都县","360731":"于都县","360732":"兴国县","360733":"会昌县","360734":"寻乌县","360735":"石城县","360781":"瑞金市"},"360800":{"360802":"吉州区","360803":"青原区","360821":"吉安县","360822":"吉水县","360823":"峡江县","360824":"新干县","360825":"永丰县","360826":"泰和县","360827":"遂川县","360828":"万安县","360829":"安福县","360830":"永新县","360881":"井冈山市"},"360900":{"360902":"袁州区","360921":"奉新县","360922":"万载县","360923":"上高县","360924":"宜丰县","360925":"靖安县","360926":"铜鼓县","360981":"丰城市","360982":"樟树市","360983":"高安市"},"361000":{"361002":"临川区","361021":"南城县","361022":"黎川县","361023":"南丰县","361024":"崇仁县","361025":"乐安县","361026":"宜黄县","361027":"金溪县","361028":"资溪县","361029":"东乡县","361030":"广昌县"},"361100":{"361102":"信州区","361103":"广丰区","361121":"上饶县","361123":"玉山县","361124":"铅山县","361125":"横峰县","361126":"弋阳县","361127":"余干县","361128":"鄱阳县","361129":"万年县","361130":"婺源县","361181":"德兴市"},"370000":{"370100":"济南市","370200":"青岛市","370300":"淄博市","370400":"枣庄市","370500":"东营市","370600":"烟台市","370700":"潍坊市","370800":"济宁市","370900":"泰安市","371000":"威海市","371100":"日照市","371200":"莱芜市","371300":"临沂市","371400":"德州市","371500":"聊城市","371600":"滨州市","371700":"菏泽市"},"370100":{"370102":"历下区","370103":"市中区","370104":"槐荫区","370105":"天桥区","370112":"历城区","370113":"长清区","370124":"平阴县","370125":"济阳县","370126":"商河县","370181":"章丘市"},"370200":{"370202":"市南区","370203":"市北区","370211":"黄岛区","370212":"崂山区","370213":"李沧区","370214":"城阳区","370281":"胶州市","370282":"即墨市","370283":"平度市","370285":"莱西市"},"370300":{"370302":"淄川区","370303":"张店区","370304":"博山区","370305":"临淄区","370306":"周村区","370321":"桓台县","370322":"高青县","370323":"沂源县"},"370400":{"370402":"市中区","370403":"薛城区","370404":"峄城区","370405":"台儿庄区","370406":"山亭区","370481":"滕州市"},"370500":{"370502":"东营区","370503":"河口区","370505":"垦利区","370522":"利津县","370523":"广饶县"},"370600":{"370602":"芝罘区","370611":"福山区","370612":"牟平区","370613":"莱山区","370634":"长岛县","370681":"龙口市","370682":"莱阳市","370683":"莱州市","370684":"蓬莱市","370685":"招远市","370686":"栖霞市","370687":"海阳市"},"370700":{"370702":"潍城区","370703":"寒亭区","370704":"坊子区","370705":"奎文区","370724":"临朐县","370725":"昌乐县","370781":"青州市","370782":"诸城市","370783":"寿光市","370784":"安丘市","370785":"高密市","370786":"昌邑市"},"370800":{"370811":"任城区","370812":"兖州区","370826":"微山县","370827":"鱼台县","370828":"金乡县","370829":"嘉祥县","370830":"汶上县","370831":"泗水县","370832":"梁山县","370881":"曲阜市","370883":"邹城市"},"370900":{"370902":"泰山区","370911":"岱岳区","370921":"宁阳县","370923":"东平县","370982":"新泰市","370983":"肥城市"},"371000":{"371002":"环翠区","371003":"文登区","371082":"荣成市","371083":"乳山市"},"371100":{"371102":"东港区","371103":"岚山区","371121":"五莲县","371122":"莒县"},"371200":{"371202":"莱城区","371203":"钢城区"},"371300":{"371302":"兰山区","371311":"罗庄区","371312":"河东区","371321":"沂南县","371322":"郯城县","371323":"沂水县","371324":"兰陵县","371325":"费县","371326":"平邑县","371327":"莒南县","371328":"蒙阴县","371329":"临沭县"},"371400":{"371402":"德城区","371403":"陵城区","371422":"宁津县","371423":"庆云县","371424":"临邑县","371425":"齐河县","371426":"平原县","371427":"夏津县","371428":"武城县","371481":"乐陵市","371482":"禹城市"},"371500":{"371502":"东昌府区","371521":"阳谷县","371522":"莘县","371523":"茌平县","371524":"东阿县","371525":"冠县","371526":"高唐县","371581":"临清市"},"371600":{"371602":"滨城区","371603":"沾化区","371621":"惠民县","371622":"阳信县","371623":"无棣县","371625":"博兴县","371626":"邹平县"},"371700":{"371702":"牡丹区","371703":"定陶区","371721":"曹县","371722":"单县","371723":"成武县","371724":"巨野县","371725":"郓城县","371726":"鄄城县","371728":"东明县"},"410000":{"410100":"郑州市","410200":"开封市","410300":"洛阳市","410400":"平顶山市","410500":"安阳市","410600":"鹤壁市","410700":"新乡市","410800":"焦作市","410900":"濮阳市","411000":"许昌市","411100":"漯河市","411200":"三门峡市","411300":"南阳市","411400":"商丘市","411500":"信阳市","411600":"周口市","411700":"驻马店市","419001":"济源市"},"410100":{"410102":"中原区","410103":"二七区","410104":"管城回族区","410105":"金水区","410106":"上街区","410108":"惠济区","410122":"中牟县","410181":"巩义市","410182":"荥阳市","410183":"新密市","410184":"新郑市","410185":"登封市"},"410200":{"410202":"龙亭区","410203":"顺河回族区","410204":"鼓楼区","410205":"禹王台区","410211":"金明区","410212":"祥符区","410221":"杞县","410222":"通许县","410223":"尉氏县","410225":"兰考县"},"410300":{"410302":"老城区","410303":"西工区","410304":"瀍河回族区","410305":"涧西区","410306":"吉利区","410311":"洛龙区","410322":"孟津县","410323":"新安县","410324":"栾川县","410325":"嵩县","410326":"汝阳县","410327":"宜阳县","410328":"洛宁县","410329":"伊川县","410381":"偃师市"},"410400":{"410402":"新华区","410403":"卫东区","410404":"石龙区","410411":"湛河区","410421":"宝丰县","410422":"叶县","410423":"鲁山县","410425":"郏县","410481":"舞钢市","410482":"汝州市"},"410500":{"410502":"文峰区","410503":"北关区","410505":"殷都区","410506":"龙安区","410522":"安阳县","410523":"汤阴县","410526":"滑县","410527":"内黄县","410581":"林州市"},"410600":{"410602":"鹤山区","410603":"山城区","410611":"淇滨区","410621":"浚县","410622":"淇县"},"410700":{"410702":"红旗区","410703":"卫滨区","410704":"凤泉区","410711":"牧野区","410721":"新乡县","410724":"获嘉县","410725":"原阳县","410726":"延津县","410727":"封丘县","410728":"长垣县","410781":"卫辉市","410782":"辉县市"},"410800":{"410802":"解放区","410803":"中站区","410804":"马村区","410811":"山阳区","410821":"修武县","410822":"博爱县","410823":"武陟县","410825":"温县","410882":"沁阳市","410883":"孟州市"},"410900":{"410902":"华龙区","410922":"清丰县","410923":"南乐县","410926":"范县","410927":"台前县","410928":"濮阳县"},"411000":{"411002":"魏都区","411023":"许昌县","411024":"鄢陵县","411025":"襄城县","411081":"禹州市","411082":"长葛市"},"411100":{"411102":"源汇区","411103":"郾城区","411104":"召陵区","411121":"舞阳县","411122":"临颍县"},"411200":{"411202":"湖滨区","411203":"陕州区","411221":"渑池县","411224":"卢氏县","411281":"义马市","411282":"灵宝市"},"411300":{"411302":"宛城区","411303":"卧龙区","411321":"南召县","411322":"方城县","411323":"西峡县","411324":"镇平县","411325":"内乡县","411326":"淅川县","411327":"社旗县","411328":"唐河县","411329":"新野县","411330":"桐柏县","411381":"邓州市"},"411400":{"411402":"梁园区","411403":"睢阳区","411421":"民权县","411422":"睢县","411423":"宁陵县","411424":"柘城县","411425":"虞城县","411426":"夏邑县","411481":"永城市"},"411500":{"411502":"浉河区","411503":"平桥区","411521":"罗山县","411522":"光山县","411523":"新县","411524":"商城县","411525":"固始县","411526":"潢川县","411527":"淮滨县","411528":"息县"},"411600":{"411602":"川汇区","411621":"扶沟县","411622":"西华县","411623":"商水县","411624":"沈丘县","411625":"郸城县","411626":"淮阳县","411627":"太康县","411628":"鹿邑县","411681":"项城市"},"411700":{"411702":"驿城区","411721":"西平县","411722":"上蔡县","411723":"平舆县","411724":"正阳县","411725":"确山县","411726":"泌阳县","411727":"汝南县","411728":"遂平县","411729":"新蔡县"},"419001":{"4190011":"济源市克井镇","41900111":"济源市下冶镇","419001001":"济源市沁园街道","419001002":"济源市济水街道","419001003":"济源市北海街道","419001004":"济源市天坛街道","419001005":"济源市玉泉街道","419001101":"济源市五龙口镇","419001102":"济源市轵城镇","419001103":"济源市承留镇","419001104":"济源市邵原镇","419001105":"济源市坡头镇","419001106":"济源市梨林镇","419001107":"济源市大峪镇","419001108":"济源市思礼镇","419001109":"济源市王屋镇"},"420000":{"420100":"武汉市","420200":"黄石市","420300":"十堰市","420500":"宜昌市","420600":"襄阳市","420700":"鄂州市","420800":"荆门市","420900":"孝感市","421000":"荆州市","421100":"黄冈市","421200":"咸宁市","421300":"随州市","422800":"恩施土家族苗族自治州","429004":"仙桃市","429005":"潜江市","429006":"天门市","429021":"神农架林区"},"420100":{"420102":"江岸区","420103":"江汉区","420104":"硚口区","420105":"汉阳区","420106":"武昌区","420107":"青山区","420111":"洪山区","420112":"东西湖区","420113":"汉南区","420114":"蔡甸区","420115":"江夏区","420116":"黄陂区","420117":"新洲区"},"420200":{"420202":"黄石港区","420203":"西塞山区","420204":"下陆区","420205":"铁山区","420222":"阳新县","420281":"大冶市"},"420300":{"420302":"茅箭区","420303":"张湾区","420304":"郧阳区","420322":"郧西县","420323":"竹山县","420324":"竹溪县","420325":"房县","420381":"丹江口市"},"420500":{"420502":"西陵区","420503":"伍家岗区","420504":"点军区","420505":"猇亭区","420506":"夷陵区","420525":"远安县","420526":"兴山县","420527":"秭归县","420528":"长阳土家族自治县","420529":"五峰土家族自治县","420581":"宜都市","420582":"当阳市","420583":"枝江市"},"420600":{"420602":"襄城区","420606":"樊城区","420607":"襄州区","420624":"南漳县","420625":"谷城县","420626":"保康县","420682":"老河口市","420683":"枣阳市","420684":"宜城市"},"420700":{"420702":"梁子湖区","420703":"华容区","420704":"鄂城区"},"420800":{"420802":"东宝区","420804":"掇刀区","420821":"京山县","420822":"沙洋县","420881":"钟祥市"},"420900":{"420902":"孝南区","420921":"孝昌县","420922":"大悟县","420923":"云梦县","420981":"应城市","420982":"安陆市","420984":"汉川市"},"421000":{"421002":"沙市区","421003":"荆州区","421022":"公安县","421023":"监利县","421024":"江陵县","421081":"石首市","421083":"洪湖市","421087":"松滋市"},"421100":{"421102":"黄州区","421121":"团风县","421122":"红安县","421123":"罗田县","421124":"英山县","421125":"浠水县","421126":"蕲春县","421127":"黄梅县","421181":"麻城市","421182":"武穴市"},"421200":{"421202":"咸安区","421221":"嘉鱼县","421222":"通城县","421223":"崇阳县","421224":"通山县","421281":"赤壁市"},"421300":{"421303":"曾都区","421321":"随县","421381":"广水市"},"422800":{"422801":"恩施市","422802":"利川市","422822":"建始县","422823":"巴东县","422825":"宣恩县","422826":"咸丰县","422827":"来凤县","422828":"鹤峰县"},"429004":{"4290041":"郑场镇","4290044":"工业园区","42900411":"张沟镇","429004001":"沙嘴街道","429004002":"干河街道","429004003":"龙华山","429004101":"毛嘴镇","429004102":"豆河镇","429004103":"三伏潭镇","429004104":"胡场镇","429004105":"长倘口镇","429004106":"西流河镇","429004107":"沙湖镇","429004108":"杨林尾镇","429004109":"彭场镇","429004111":"郭河镇","429004112":"沔城回族镇","429004113":"通海口镇","429004114":"陈场镇","429004401":"九合垸原种场","429004402":"沙湖原种场","429004404":"五湖渔场","429004405":"赵西垸林场","429004407":"畜禽良种场","429004408":"排湖风景区"},"429005":{"4290051":"竹根滩镇","4290054":"江汉石油管理局","42900545":"周矶管理区","429005001":"园林","429005002":"杨市","429005003":"周矶","429005004":"广华","429005005":"泰丰","429005006":"高场","429005101":"渔洋镇","429005102":"王场镇","429005103":"高石碑镇","429005104":"熊口镇","429005105":"老新镇","429005106":"浩口镇","429005107":"积玉口镇","429005108":"张金镇","429005109":"龙湾镇","429005401":"潜江经济开发区","429005451":"后湖管理区","429005452":"熊口管理区","429005453":"总口管理区","429005454":"白鹭湖管理区","429005455":"运粮湖管理区","429005457":"浩口原种场"},"429006":{"4290061":"多宝镇","42900611":"麻洋镇","42900612":"石河镇","42900645":"蒋湖农场","429006001":"竟陵街道","429006002":"侨乡街道开发区","429006003":"杨林街道","429006101":"拖市镇","429006102":"张港镇","429006103":"蒋场镇","429006104":"汪场镇","429006105":"渔薪镇","429006106":"黄潭镇","429006107":"岳口镇","429006108":"横林镇","429006109":"彭市镇","429006111":"多祥镇","429006112":"干驿镇","429006113":"马湾镇","429006114":"卢市镇","429006115":"小板镇","429006116":"九真镇","429006118":"皂市镇","429006119":"胡市镇","429006121":"佛子山镇","429006201":"净潭乡","429006451":"白茅湖农场","429006452":"沉湖管委会"},"429021":{"4290211":"松柏镇","4290212":"宋洛乡","429021101":"阳日镇","429021102":"木鱼镇","429021103":"红坪镇","429021104":"新华镇","429021105":"九湖镇","429021202":"下谷坪土家族乡"},"430000":{"430100":"长沙市","430200":"株洲市","430300":"湘潭市","430400":"衡阳市","430500":"邵阳市","430600":"岳阳市","430700":"常德市","430800":"张家界市","430900":"益阳市","431000":"郴州市","431100":"永州市","431200":"怀化市","431300":"娄底市","433100":"湘西土家族苗族自治州"},"430100":{"430102":"芙蓉区","430103":"天心区","430104":"岳麓区","430105":"开福区","430111":"雨花区","430112":"望城区","430121":"长沙县","430124":"宁乡县","430181":"浏阳市"},"430200":{"430202":"荷塘区","430203":"芦淞区","430204":"石峰区","430211":"天元区","430221":"株洲县","430223":"攸县","430224":"茶陵县","430225":"炎陵县","430281":"醴陵市"},"430300":{"430302":"雨湖区","430304":"岳塘区","430321":"湘潭县","430381":"湘乡市","430382":"韶山市"},"430400":{"430405":"珠晖区","430406":"雁峰区","430407":"石鼓区","430408":"蒸湘区","430412":"南岳区","430421":"衡阳县","430422":"衡南县","430423":"衡山县","430424":"衡东县","430426":"祁东县","430481":"耒阳市","430482":"常宁市"},"430500":{"430502":"双清区","430503":"大祥区","430511":"北塔区","430521":"邵东县","430522":"新邵县","430523":"邵阳县","430524":"隆回县","430525":"洞口县","430527":"绥宁县","430528":"新宁县","430529":"城步苗族自治县","430581":"武冈市"},"430600":{"430602":"岳阳楼区","430603":"云溪区","430611":"君山区","430621":"岳阳县","430623":"华容县","430624":"湘阴县","430626":"平江县","430681":"汨罗市","430682":"临湘市"},"430700":{"430702":"武陵区","430703":"鼎城区","430721":"安乡县","430722":"汉寿县","430723":"澧县","430724":"临澧县","430725":"桃源县","430726":"石门县","430781":"津市市"},"430800":{"430802":"永定区","430811":"武陵源区","430821":"慈利县","430822":"桑植县"},"430900":{"430902":"资阳区","430903":"赫山区","430921":"南县","430922":"桃江县","430923":"安化县","430981":"沅江市"},"431000":{"431002":"北湖区","431003":"苏仙区","431021":"桂阳县","431022":"宜章县","431023":"永兴县","431024":"嘉禾县","431025":"临武县","431026":"汝城县","431027":"桂东县","431028":"安仁县","431081":"资兴市"},"431100":{"431102":"零陵区","431103":"冷水滩区","431121":"祁阳县","431122":"东安县","431123":"双牌县","431124":"道县","431125":"江永县","431126":"宁远县","431127":"蓝山县","431128":"新田县","431129":"江华瑶族自治县"},"431200":{"431202":"鹤城区","431221":"中方县","431222":"沅陵县","431223":"辰溪县","431224":"溆浦县","431225":"会同县","431226":"麻阳苗族自治县","431227":"新晃侗族自治县","431228":"芷江侗族自治县","431229":"靖州苗族侗族自治县","431230":"通道侗族自治县","431281":"洪江市"},"431300":{"431302":"娄星区","431321":"双峰县","431322":"新化县","431381":"冷水江市","431382":"涟源市"},"433100":{"433101":"吉首市","433122":"泸溪县","433123":"凤凰县","433124":"花垣县","433125":"保靖县","433126":"古丈县","433127":"永顺县","433130":"龙山县"},"440000":{"440100":"广州市","440200":"韶关市","440300":"深圳市","440400":"珠海市","440500":"汕头市","440600":"佛山市","440700":"江门市","440800":"湛江市","440900":"茂名市","441200":"肇庆市","441300":"惠州市","441400":"梅州市","441500":"汕尾市","441600":"河源市","441700":"阳江市","441800":"清远市","441900":"东莞市","442000":"中山市","445100":"潮州市","445200":"揭阳市","445300":"云浮市"},"440100":{"440103":"荔湾区","440104":"越秀区","440105":"海珠区","440106":"天河区","440111":"白云区","440112":"黄埔区","440113":"番禺区","440114":"花都区","440115":"南沙区","440117":"从化区","440118":"增城区"},"440200":{"440203":"武江区","440204":"浈江区","440205":"曲江区","440222":"始兴县","440224":"仁化县","440229":"翁源县","440232":"乳源瑶族自治县","440233":"新丰县","440281":"乐昌市","440282":"南雄市"},"440300":{"440303":"罗湖区","440304":"福田区","440305":"南山区","440306":"宝安区","440307":"龙岗区","440308":"盐田区"},"440400":{"440402":"香洲区","440403":"斗门区","440404":"金湾区"},"440500":{"440507":"龙湖区","440511":"金平区","440512":"濠江区","440513":"潮阳区","440514":"潮南区","440515":"澄海区","440523":"南澳县"},"440600":{"440604":"禅城区","440605":"南海区","440606":"顺德区","440607":"三水区","440608":"高明区"},"440700":{"440703":"蓬江区","440704":"江海区","440705":"新会区","440781":"台山市","440783":"开平市","440784":"鹤山市","440785":"恩平市"},"440800":{"440802":"赤坎区","440803":"霞山区","440804":"坡头区","440811":"麻章区","440823":"遂溪县","440825":"徐闻县","440881":"廉江市","440882":"雷州市","440883":"吴川市"},"440900":{"440902":"茂南区","440904":"电白区","440981":"高州市","440982":"化州市","440983":"信宜市"},"441200":{"441202":"端州区","441203":"鼎湖区","441204":"高要区","441223":"广宁县","441224":"怀集县","441225":"封开县","441226":"德庆县","441284":"四会市"},"441300":{"441302":"惠城区","441303":"惠阳区","441322":"博罗县","441323":"惠东县","441324":"龙门县"},"441400":{"441402":"梅江区","441403":"梅县区","441422":"大埔县","441423":"丰顺县","441424":"五华县","441426":"平远县","441427":"蕉岭县","441481":"兴宁市"},"441500":{"441502":"城区","441521":"海丰县","441523":"陆河县","441581":"陆丰市"},"441600":{"441602":"源城区","441621":"紫金县","441622":"龙川县","441623":"连平县","441624":"和平县","441625":"东源县"},"441700":{"441702":"江城区","441704":"阳东区","441721":"阳西县","441781":"阳春市"},"441800":{"441802":"清城区","441803":"清新区","441821":"佛冈县","441823":"阳山县","441825":"连山壮族瑶族自治县","441826":"连南瑶族自治县","441881":"英德市","441882":"连州市"},"441900":{"441900003":"东城街道","441900004":"南城街道","441900005":"万江街道","441900006":"莞城街道","441900101":"石碣镇","441900102":"石龙镇","441900103":"茶山镇","441900104":"石排镇","441900105":"企石镇","441900106":"横沥镇","441900107":"桥头镇","441900108":"谢岗镇","441900109":"东坑镇","441900110":"常平镇","441900111":"寮步镇","441900112":"樟木头镇","441900113":"大朗镇","441900114":"黄江镇","441900115":"清溪镇","441900116":"塘厦镇","441900117":"凤岗镇","441900118":"大岭山镇","441900119":"长安镇","441900121":"虎门镇","441900122":"厚街镇","441900123":"沙田镇","441900124":"道滘镇","441900125":"洪梅镇","441900126":"麻涌镇","441900127":"望牛墩镇","441900128":"中堂镇","441900129":"高埗镇","441900401":"松山湖管委会","441900402":"虎门港管委会","441900403":"东莞生态园"},"442000":{"442000001":"石岐区街道","442000002":"东区街道","442000003":"火炬开发区街道","442000004":"西区街道","442000005":"南区街道","442000006":"五桂山街道","442000100":"小榄镇","442000101":"黄圃镇","442000102":"民众镇","442000103":"东凤镇","442000104":"东升镇","442000105":"古镇镇","442000106":"沙溪镇","442000107":"坦洲镇","442000108":"港口镇","442000109":"三角镇","442000110":"横栏镇","442000111":"南头镇","442000112":"阜沙镇","442000113":"南朗镇","442000114":"三乡镇","442000115":"板芙镇","442000116":"大涌镇","442000117":"神湾镇"},"445100":{"445102":"湘桥区","445103":"潮安区","445122":"饶平县"},"445200":{"445202":"榕城区","445203":"揭东区","445222":"揭西县","445224":"惠来县","445281":"普宁市"},"445300":{"445302":"云城区","445303":"云安区","445321":"新兴县","445322":"郁南县","445381":"罗定市"},"450000":{"450100":"南宁市","450200":"柳州市","450300":"桂林市","450400":"梧州市","450500":"北海市","450600":"防城港市","450700":"钦州市","450800":"贵港市","450900":"玉林市","451000":"百色市","451100":"贺州市","451200":"河池市","451300":"来宾市","451400":"崇左市"},"450100":{"450102":"兴宁区","450103":"青秀区","450105":"江南区","450107":"西乡塘区","450108":"良庆区","450109":"邕宁区","450110":"武鸣区","450123":"隆安县","450124":"马山县","450125":"上林县","450126":"宾阳县","450127":"横县"},"450200":{"450202":"城中区","450203":"鱼峰区","450204":"柳南区","450205":"柳北区","450206":"柳江区","450222":"柳城县","450223":"鹿寨县","450224":"融安县","450225":"融水苗族自治县","450226":"三江侗族自治县"},"450300":{"450302":"秀峰区","450303":"叠彩区","450304":"象山区","450305":"七星区","450311":"雁山区","450312":"临桂区","450321":"阳朔县","450323":"灵川县","450324":"全州县","450325":"兴安县","450326":"永福县","450327":"灌阳县","450328":"龙胜各族自治县","450329":"资源县","450330":"平乐县","450331":"荔浦县","450332":"恭城瑶族自治县"},"450400":{"450403":"万秀区","450405":"长洲区","450406":"龙圩区","450421":"苍梧县","450422":"藤县","450423":"蒙山县","450481":"岑溪市"},"450500":{"450502":"海城区","450503":"银海区","450512":"铁山港区","450521":"合浦县"},"450600":{"450602":"港口区","450603":"防城区","450621":"上思县","450681":"东兴市"},"450700":{"450702":"钦南区","450703":"钦北区","450721":"灵山县","450722":"浦北县"},"450800":{"450802":"港北区","450803":"港南区","450804":"覃塘区","450821":"平南县","450881":"桂平市"},"450900":{"450902":"玉州区","450903":"福绵区","450921":"容县","450922":"陆川县","450923":"博白县","450924":"兴业县","450981":"北流市"},"451000":{"451002":"右江区","451021":"田阳县","451022":"田东县","451023":"平果县","451024":"德保县","451026":"那坡县","451027":"凌云县","451028":"乐业县","451029":"田林县","451030":"西林县","451031":"隆林各族自治县","451081":"靖西市"},"451100":{"451102":"八步区","451103":"平桂区","451121":"昭平县","451122":"钟山县","451123":"富川瑶族自治县"},"451200":{"451202":"金城江区","451221":"南丹县","451222":"天峨县","451223":"凤山县","451224":"东兰县","451225":"罗城仫佬族自治县","451226":"环江毛南族自治县","451227":"巴马瑶族自治县","451228":"都安瑶族自治县","451229":"大化瑶族自治县","451281":"宜州市"},"451300":{"451302":"兴宾区","451321":"忻城县","451322":"象州县","451323":"武宣县","451324":"金秀瑶族自治县","451381":"合山市"},"451400":{"451402":"江州区","451421":"扶绥县","451422":"宁明县","451423":"龙州县","451424":"大新县","451425":"天等县","451481":"凭祥市"},"460000":{"460100":"海口市","460200":"三亚市","460300":"三沙市","460400":"儋州市","469001":"五指山市","469002":"琼海市","469005":"文昌市","469006":"万宁市","469007":"东方市","469021":"定安县","469022":"屯昌县","469023":"澄迈县","469024":"临高县","469025":"白沙黎族自治县","469026":"昌江黎族自治县","469027":"乐东黎族自治县","469028":"陵水黎族自治县","469029":"保亭黎族苗族自治县","469030":"琼中黎族苗族自治县"},"460100":{"460105":"秀英区","460106":"龙华区","460107":"琼山区","460108":"美兰区"},"460200":{"460202":"海棠区","460203":"吉阳区","460204":"天涯区","460205":"崖州区"},"460300":{"460321":"西沙群岛","460322":"南沙群岛","460323":"中沙群岛的岛礁及其海域"},"460400":{"4604001":"那大镇","4604004":"国营西培农场","4604005":"华南热作学院","46040011":"三都镇","460400101":"和庆镇","460400102":"南丰镇","460400103":"大成镇","460400104":"雅星镇","460400105":"兰洋镇","460400106":"光村镇","460400107":"木棠镇","460400108":"海头镇","460400109":"峨蔓镇","460400111":"王五镇","460400112":"白马井镇","460400113":"中和镇","460400114":"排浦镇","460400115":"东成镇","460400116":"新州镇","460400404":"国营西联农场","460400405":"国营蓝洋农场","460400407":"国营八一农场","460400499":"洋浦经济开发区"},"469001":{"4690011":"通什镇","4690012":"畅好乡","4690014":"畅好农场","469001101":"南圣镇","469001102":"毛阳镇","469001103":"番阳镇","469001201":"毛道乡","469001202":"水满乡"},"469002":{"4690021":"嘉积镇","4690024":"国营东太农场","4690025":"彬村山华侨农场","46900211":"大路镇","469002101":"万泉镇","469002102":"石壁镇","469002103":"中原镇","469002104":"博鳌镇","469002105":"阳江镇","469002106":"龙江镇","469002107":"潭门镇","469002108":"塔洋镇","469002109":"长坡镇","469002111":"会山镇","469002402":"国营东红农场","469002403":"国营东升农场"},"469005":{"4690051":"文城镇","4690054":"国营东路农场","46900511":"昌洒镇","469005101":"重兴镇","469005102":"蓬莱镇","469005103":"会文镇","469005104":"东路镇","469005105":"潭牛镇","469005106":"东阁镇","469005107":"文教镇","469005108":"东郊镇","469005109":"龙楼镇","469005111":"翁田镇","469005112":"抱罗镇","469005113":"冯坡镇","469005114":"锦山镇","469005115":"铺前镇","469005116":"公坡镇","469005401":"国营南阳农场","469005402":"国营罗豆农场"},"469006":{"4690061":"万城镇","4690064":"国营东兴农场","4690065":"兴隆华侨农场","46900611":"南桥镇","469006101":"龙滚镇","469006102":"和乐镇","469006103":"后安镇","469006104":"大茂镇","469006105":"东澳镇","469006106":"礼纪镇","469006107":"长丰镇","469006108":"山根镇","469006109":"北大镇","469006111":"三更罗镇","469006401":"国营东和农场","469006404":"国营新中农场","469006501":"地方国营六连林场"},"469007":{"4690071":"八所镇","4690072":"天安乡","4690074":"国营广坝农场","4690075":"东方华侨农场","469007101":"东河镇","469007102":"大田镇","469007103":"感城镇","469007104":"板桥镇","469007105":"三家镇","469007106":"四更镇","469007107":"新龙镇","469007201":"江边乡"},"469021":{"4690211":"定城镇","4690214":"国营中瑞农场","469021101":"新竹镇","469021102":"龙湖镇","469021103":"黄竹镇","469021104":"雷鸣镇","469021105":"龙门镇","469021106":"龙河镇","469021107":"岭口镇","469021108":"翰林镇","469021109":"富文镇","469021401":"国营南海农场","469021402":"国营金鸡岭农场"},"469022":{"4690221":"屯城镇","4690224":"国营中建农场","469022101":"新兴镇","469022102":"枫木镇","469022103":"乌坡镇","469022104":"南吕镇","469022105":"南坤镇","469022106":"坡心镇","469022107":"西昌镇","469022401":"国营中坤农场"},"469023":{"4690231":"金江镇","4690234":"国营红光农场","46902311":"大丰镇","469023101":"老城镇","469023102":"瑞溪镇","469023103":"永发镇","469023104":"加乐镇","469023105":"文儒镇","469023106":"中兴镇","469023107":"仁兴镇","469023108":"福山镇","469023109":"桥头镇","469023402":"国营西达农场","469023405":"国营金安农场"},"469024":{"4690241":"临城镇","4690244":"国营红华农场","469024101":"波莲镇","469024102":"东英镇","469024103":"博厚镇","469024104":"皇桐镇","469024105":"多文镇","469024106":"和舍镇","469024107":"南宝镇","469024108":"新盈镇","469024109":"调楼镇","469024401":"国营加来农场"},"469025":{"4690251":"牙叉镇","4690252":"细水乡","469025101":"七坊镇","469025102":"邦溪镇","469025103":"打安镇","469025201":"元门乡","469025202":"南开乡","469025203":"阜龙乡","469025204":"青松乡","469025205":"金波乡","469025206":"荣邦乡","469025401":"国营白沙农场","469025404":"国营龙江农场","469025408":"国营邦溪农场"},"469026":{"4690261":"石碌镇","4690262":"王下乡","4690265":"国营霸王岭林场","469026101":"叉河镇","469026102":"十月田镇","469026103":"乌烈镇","469026104":"昌化镇","469026105":"海尾镇","469026106":"七叉镇","469026401":"国营红林农场","469026501":"海南矿业联合有限公司"},"469027":{"4690271":"抱由镇","4690275":"国营尖峰岭林业公司","46902711":"莺歌海镇","469027101":"万冲镇","469027102":"大安镇","469027103":"志仲镇","469027104":"千家镇","469027105":"九所镇","469027106":"利国镇","469027107":"黄流镇","469027108":"佛罗镇","469027109":"尖峰镇","469027401":"国营山荣农场","469027402":"国营乐光农场","469027405":"国营保国农场","469027501":"国营莺歌海盐场"},"469028":{"4690281":"椰林镇","4690282":"提蒙乡","4690284":"国营岭门农场","4690285":"国营吊罗山林业公司","469028101":"光坡镇","469028102":"三才镇","469028103":"英州镇","469028104":"隆广镇","469028105":"文罗镇","469028106":"本号镇","469028107":"新村镇","469028108":"黎安镇","469028201":"群英乡","469028401":"国营南平农场"},"469029":{"4690291":"保城镇","4690292":"六弓乡","469029101":"什玲镇","469029102":"加茂镇","469029103":"响水镇","469029104":"新政镇","469029105":"三道镇","469029201":"南林乡","469029202":"毛感乡","469029401":"国营新星农场","469029402":"海南保亭热带作物研究所","469029403":"国营金江农场","469029405":"国营三道农场"},"469030":{"4690301":"营根镇","4690302":"吊罗山乡","4690305":"海南黎母山省级自然保护区管理站","469030101":"湾岭镇","469030102":"黎母山镇","469030103":"和平镇","469030104":"长征镇","469030105":"红毛镇","469030106":"中平镇","469030201":"上安乡","469030202":"什运乡","469030402":"国营阳江农场","469030403":"国营乌石农场","469030406":"国营加钗农场","469030407":"国营长征农场"},"500000":{"500100":"市辖区","500228":"梁平县","500229":"城口县","500230":"丰都县","500231":"垫江县","500232":"武隆县","500233":"忠县","500235":"云阳县","500236":"奉节县","500237":"巫山县","500238":"巫溪县","500240":"石柱土家族自治县","500241":"秀山土家族苗族自治县","500242":"酉阳土家族苗族自治县","500243":"彭水苗族土家族自治县"},"500100":{"500101":"万州区","500102":"涪陵区","500103":"渝中区","500104":"大渡口区","500105":"江北区","500106":"沙坪坝区","500107":"九龙坡区","500108":"南岸区","500109":"北碚区","500110":"綦江区","500111":"大足区","500112":"渝北区","500113":"巴南区","500114":"黔江区","500115":"长寿区","500116":"江津区","500117":"合川区","500118":"永川区","500119":"南川区","500120":"璧山区","500151":"铜梁区","500152":"潼南区","500153":"荣昌区","500154":"开州区"},"500228":{"5002282":"安胜乡","5002284":"梁平县农场","50022811":"聚奎镇","50022812":"合兴镇","500228001":"梁平县梁山街道","500228002":"梁平县双桂街道","500228101":"仁贤镇","500228102":"礼让镇","500228103":"云龙镇","500228104":"屏锦镇","500228106":"袁驿镇","500228107":"新盛镇","500228108":"福禄镇","500228109":"金带镇","500228111":"明达镇","500228112":"荫平镇","500228113":"和林镇","500228114":"回龙镇","500228115":"碧山镇","500228116":"虎城镇","500228117":"七星镇","500228118":"龙门镇","500228119":"文化镇","500228121":"石安镇","500228122":"柏家镇","500228123":"大观镇","500228124":"竹山镇","500228125":"蟠龙镇","500228126":"星桥镇","500228127":"曲水镇","500228201":"铁门乡","500228202":"龙胜乡","500228203":"复平乡","500228205":"紫照乡","500228401":"梁平县双桂工业园区"},"500229":{"50022911":"咸宜镇","50022921":"双河乡","50022922":"厚坪乡","500229001":"葛城街道","500229002":"复兴街道","500229102":"巴山镇","500229103":"坪坝镇","500229104":"庙坝镇","500229105":"明通镇","500229106":"修齐镇","500229107":"高观镇","500229108":"高燕镇","500229109":"东安镇","500229111":"高楠镇","500229201":"龙田乡","500229202":"北屏乡","500229205":"左岚乡","500229208":"沿河乡","500229211":"蓼子乡","500229212":"鸡鸣乡","500229214":"周溪乡","500229216":"明中乡","500229217":"治平乡","500229219":"岚天乡","500229221":"河鱼乡"},"500230":{"500230":"名山街道","50023011":"兴义镇","50023012":"兴龙镇","50023021":"三建乡","500230101":"虎威镇","500230102":"社坛镇","500230103":"三元镇","500230104":"许明寺镇","500230105":"董家镇","500230106":"树人镇","500230107":"十直镇","500230109":"高家镇","500230111":"双路镇","500230112":"江池镇","500230113":"龙河镇","500230114":"武平镇","500230115":"包鸾镇","500230116":"湛普镇","500230118":"南天湖镇","500230119":"保合镇","500230121":"仁沙镇","500230122":"龙孔镇","500230123":"暨龙镇","500230124":"双龙镇","500230125":"仙女湖镇","500230202":"青龙乡","500230206":"太平坝乡","500230207":"都督乡","500230209":"栗子乡"},"500231":{"50023111":"太平镇","50023112":"裴兴镇","500231001":"桂溪街道","500231002":"桂阳街道","500231101":"新民镇","500231102":"沙坪镇","500231103":"周嘉镇","500231104":"普顺镇","500231105":"永安镇","500231106":"高安镇","500231107":"高峰镇","500231108":"五洞镇","500231109":"澄溪镇","500231111":"鹤游镇","500231112":"坪山镇","500231113":"砚台镇","500231114":"曹回镇","500231115":"杠家镇","500231116":"包家镇","500231117":"白家镇","500231118":"永平镇","500231119":"三溪镇","500231121":"黄沙镇","500231122":"长龙镇","500231202":"沙河乡","500231204":"大石乡"},"500232":{"5002321":"巷口镇","5002322":"凤来乡","50023211":"土坎镇","50023221":"后坪苗族土家族乡","500232101":"火炉镇","500232102":"白马镇","500232103":"鸭江镇","500232104":"长坝镇","500232105":"江口镇","500232106":"平桥镇","500232107":"羊角镇","500232108":"仙女山镇","500232109":"桐梓镇","500232111":"和顺镇","500232112":"双河镇","500232202":"庙垭乡","500232203":"石桥苗族土家族乡","500232205":"黄莺乡","500232206":"沧沟乡","500232207":"文复苗族土家族乡","500232208":"土地乡","500232209":"白云乡","500232211":"浩口苗族仡佬族乡","500232212":"接龙乡","500232213":"赵家乡","500232214":"大洞河乡"},"500233":{"50023311":"官坝镇","50023312":"白石镇","50023321":"兴峰乡","500233001":"忠州街道","500233002":"白公街道","500233101":"新生镇","500233102":"任家镇","500233103":"乌杨镇","500233104":"洋渡镇","500233105":"东溪镇","500233106":"复兴镇","500233107":"石宝镇","500233108":"汝溪镇","500233109":"野鹤镇","500233111":"石黄镇","500233112":"马灌镇","500233113":"金鸡镇","500233114":"新立镇","500233115":"双桂镇","500233116":"拔山镇","500233117":"花桥镇","500233118":"永丰镇","500233119":"三汇镇","500233122":"黄金镇","500233201":"善广乡","500233203":"石子乡","500233204":"磨子土家族乡","500233206":"涂井乡","500233208":"金声乡"},"500235":{"50023513":"桑坪镇","50023514":"蔈草镇","500235001":"双江街道","500235002":"青龙街道","500235003":"人和街道","500235004":"盘龙街道","500235105":"龙角镇","500235107":"故陵镇","500235108":"红狮镇","500235115":"路阳镇","500235116":"农坝镇","500235118":"渠马镇","500235121":"黄石镇","500235122":"巴阳镇","500235123":"沙市镇","500235124":"鱼泉镇","500235125":"凤鸣镇","500235127":"宝坪镇","500235128":"南溪镇","500235129":"双土镇","500235131":"江口镇","500235132":"高阳镇","500235133":"平安镇","500235135":"云阳镇","500235136":"云安镇","500235137":"栖霞镇","500235138":"双龙镇","500235139":"泥溪镇","500235141":"养鹿镇","500235142":"水口镇","500235143":"堰坪镇","500235144":"龙洞镇","500235145":"后叶镇","500235146":"耀灵镇","500235147":"大阳镇","500235208":"外郎乡","500235215":"新津乡","500235216":"普安乡","500235218":"洞鹿乡","500235219":"石门乡","500235239":"上坝乡","500235242":"清水土家族自治乡"},"500236":{"50023612":"康乐镇","50023613":"新民镇","50023627":"康坪乡","500236001":"永安街道","500236002":"鱼复街道","500236003":"夔门街道","500236117":"白帝镇","500236118":"草堂镇","500236119":"汾河镇","500236121":"大树镇","500236122":"竹园镇","500236123":"公平镇","500236124":"朱衣镇","500236125":"甲高镇","500236126":"羊市镇","500236127":"吐祥镇","500236128":"兴隆镇","500236129":"青龙镇","500236131":"永乐镇","500236132":"安坪镇","500236133":"五马镇","500236134":"青莲镇","500236265":"岩湾乡","500236266":"平安乡","500236267":"红土乡","500236269":"石岗乡","500236272":"太和土家族乡","500236274":"鹤峰乡","500236275":"冯坪乡","500236276":"长安土家族乡","500236277":"龙桥土家族乡","500236278":"云雾土家族乡"},"500237":{"5002372":"红椿乡","50023711":"铜鼓镇","50023721":"建坪乡","500237001":"高唐街道","500237002":"龙门街道","500237101":"庙宇镇","500237102":"大昌镇","500237103":"福田镇","500237104":"龙溪镇","500237105":"双龙镇","500237106":"官阳镇","500237107":"骡坪镇","500237108":"抱龙镇","500237109":"官渡镇","500237111":"巫峡镇","500237207":"两坪乡","500237208":"曲尺乡","500237211":"大溪乡","500237214":"金坪乡","500237216":"平河乡","500237219":"当阳乡","500237222":"竹贤乡","500237225":"三溪乡","500237227":"培石乡","500237229":"笃坪乡","500237231":"邓家乡"},"500238":{"5002381":"城厢镇","5002384":"红池坝经济开发区","50023811":"峰灵镇","50023821":"长桂乡","50023824":"双阳乡","500238001":"宁河街道","500238002":"柏杨街道","500238101":"凤凰镇","500238102":"宁厂镇","500238103":"上磺镇","500238104":"古路镇","500238105":"文峰镇","500238106":"徐家镇","500238107":"白鹿镇","500238108":"尖山镇","500238109":"下堡镇","500238111":"塘坊镇","500238112":"朝阳镇","500238113":"田坝镇","500238114":"通城镇","500238115":"菱角镇","500238116":"蒲莲镇","500238117":"土城镇","500238204":"胜利乡","500238207":"大河乡","500238208":"天星乡","500238226":"鱼鳞乡","500238227":"乌龙乡","500238234":"中岗乡","500238237":"花台乡","500238239":"兰英乡","500238242":"中梁乡","500238243":"天元乡"},"500240":{"500240":"下路街道","50024011":"龙沙镇","50024021":"石家乡","500240101":"西沱镇","500240103":"悦崃镇","500240104":"临溪镇","500240105":"黄水镇","500240106":"马武镇","500240107":"沙子镇","500240108":"王场镇","500240109":"沿溪镇","500240111":"鱼池镇","500240112":"三河镇","500240113":"大歇镇","500240114":"桥头镇","500240115":"万朝镇","500240116":"冷水镇","500240117":"黄鹤镇","500240203":"黎场乡","500240204":"三星乡","500240205":"六塘乡","500240207":"三益乡","500240208":"王家乡","500240209":"河嘴乡","500240212":"枫木乡","500240213":"中益乡","500240214":"洗新乡","500240216":"龙潭乡","500240217":"新乐乡","500240218":"金铃乡","500240219":"金竹乡"},"500241":{"50024111":"雅江镇","500241001":"中和街道","500241002":"乌杨街道","500241003":"平凯街道","500241102":"清溪场镇","500241103":"隘口镇","500241104":"溶溪镇","500241105":"官庄镇","500241106":"龙池镇","500241107":"石堤镇","500241108":"峨溶镇","500241109":"洪安镇","500241111":"石耶镇","500241112":"梅江镇","500241113":"兰桥镇","500241114":"膏田镇","500241115":"溪口镇","500241116":"妙泉镇","500241117":"宋农镇","500241118":"里仁镇","500241119":"钟灵镇","500241201":"孝溪乡","500241207":"海洋乡","500241208":"大溪乡","500241211":"涌洞乡","500241214":"中平乡","500241215":"岑溪乡"},"500242":{"5002422":"涂市乡","50024211":"泔溪镇","50024221":"后坪乡","50024222":"清泉乡","500242001":"桃花源街道","500242002":"钟多街道","500242101":"龙潭镇","500242102":"麻旺镇","500242103":"酉酬镇","500242104":"大溪镇","500242105":"兴隆镇","500242106":"黑水镇","500242107":"丁市镇","500242108":"龚滩镇","500242109":"李溪镇","500242111":"酉水河镇","500242112":"苍岭镇","500242113":"小河镇","500242114":"板溪镇","500242202":"铜鼓乡","500242204":"可大乡","500242205":"偏柏乡","500242206":"五福乡","500242207":"木叶乡","500242208":"毛坝乡","500242209":"花田乡","500242211":"天馆乡","500242212":"宜居乡","500242213":"万木乡","500242214":"两罾乡","500242215":"板桥乡","500242216":"官清乡","500242217":"南腰界乡","500242218":"车田乡","500242219":"腴地乡","500242221":"庙溪乡","500242222":"浪坪乡","500242223":"双泉乡","500242224":"楠木乡"},"500243":{"50024311":"万足镇","50024321":"走马乡","500243001":"汉葭街道","500243002":"绍庆街道","500243003":"靛水街道","500243101":"保家镇","500243102":"郁山镇","500243103":"高谷镇","500243104":"桑柘镇","500243105":"鹿角镇","500243106":"黄家镇","500243107":"普子镇","500243108":"龙射镇","500243109":"连湖镇","500243111":"平安镇","500243112":"长生镇","500243113":"新田镇","500243114":"鞍子镇","500243115":"太原镇","500243116":"龙溪镇","500243117":"梅子垭镇","500243118":"大同镇","500243201":"岩东乡","500243202":"鹿鸣乡","500243204":"棣棠乡","500243206":"三义乡","500243207":"联合乡","500243208":"石柳乡","500243211":"芦塘乡","500243213":"乔梓乡","500243217":"诸佛乡","500243219":"桐楼乡","500243222":"善感乡","500243223":"双龙乡","500243224":"石盘乡","500243225":"大垭乡","500243226":"润溪乡","500243227":"朗溪乡","500243228":"龙塘乡"},"510000":{"510100":"成都市","510300":"自贡市","510400":"攀枝花市","510500":"泸州市","510600":"德阳市","510700":"绵阳市","510800":"广元市","510900":"遂宁市","511000":"内江市","511100":"乐山市","511300":"南充市","511400":"眉山市","511500":"宜宾市","511600":"广安市","511700":"达州市","511800":"雅安市","511900":"巴中市","512000":"资阳市","513200":"阿坝藏族羌族自治州","513300":"甘孜藏族自治州","513400":"凉山彝族自治州"},"510100":{"510104":"锦江区","510105":"青羊区","510106":"金牛区","510107":"武侯区","510108":"成华区","510112":"龙泉驿区","510113":"青白江区","510114":"新都区","510115":"温江区","510116":"双流区","510121":"金堂县","510124":"郫县","510129":"大邑县","510131":"蒲江县","510132":"新津县","510181":"都江堰市","510182":"彭州市","510183":"邛崃市","510184":"崇州市","510185":"简阳市"},"510300":{"510302":"自流井区","510303":"贡井区","510304":"大安区","510311":"沿滩区","510321":"荣县","510322":"富顺县"},"510400":{"510402":"东区","510403":"西区","510411":"仁和区","510421":"米易县","510422":"盐边县"},"510500":{"510502":"江阳区","510503":"纳溪区","510504":"龙马潭区","510521":"泸县","510522":"合江县","510524":"叙永县","510525":"古蔺县"},"510600":{"510603":"旌阳区","510623":"中江县","510626":"罗江县","510681":"广汉市","510682":"什邡市","510683":"绵竹市"},"510700":{"510703":"涪城区","510704":"游仙区","510705":"安州区","510722":"三台县","510723":"盐亭县","510725":"梓潼县","510726":"北川羌族自治县","510727":"平武县","510781":"江油市"},"510800":{"510802":"利州区","510811":"昭化区","510812":"朝天区","510821":"旺苍县","510822":"青川县","510823":"剑阁县","510824":"苍溪县"},"510900":{"510903":"船山区","510904":"安居区","510921":"蓬溪县","510922":"射洪县","510923":"大英县"},"511000":{"511002":"市中区","511011":"东兴区","511024":"威远县","511025":"资中县","511028":"隆昌县"},"511100":{"511102":"市中区","511111":"沙湾区","511112":"五通桥区","511113":"金口河区","511123":"犍为县","511124":"井研县","511126":"夹江县","511129":"沐川县","511132":"峨边彝族自治县","511133":"马边彝族自治县","511181":"峨眉山市"},"511300":{"511302":"顺庆区","511303":"高坪区","511304":"嘉陵区","511321":"南部县","511322":"营山县","511323":"蓬安县","511324":"仪陇县","511325":"西充县","511381":"阆中市"},"511400":{"511402":"东坡区","511403":"彭山区","511421":"仁寿县","511423":"洪雅县","511424":"丹棱县","511425":"青神县"},"511500":{"511502":"翠屏区","511503":"南溪区","511521":"宜宾县","511523":"江安县","511524":"长宁县","511525":"高县","511526":"珙县","511527":"筠连县","511528":"兴文县","511529":"屏山县"},"511600":{"511602":"广安区","511603":"前锋区","511621":"岳池县","511622":"武胜县","511623":"邻水县","511681":"华蓥市"},"511700":{"511702":"通川区","511703":"达川区","511722":"宣汉县","511723":"开江县","511724":"大竹县","511725":"渠县","511781":"万源市"},"511800":{"511802":"雨城区","511803":"名山区","511822":"荥经县","511823":"汉源县","511824":"石棉县","511825":"天全县","511826":"芦山县","511827":"宝兴县"},"511900":{"511902":"巴州区","511903":"恩阳区","511921":"通江县","511922":"南江县","511923":"平昌县"},"512000":{"512002":"雁江区","512021":"安岳县","512022":"乐至县"},"513200":{"513201":"马尔康市","513221":"汶川县","513222":"理县","513223":"茂县","513224":"松潘县","513225":"九寨沟县","513226":"金川县","513227":"小金县","513228":"黑水县","513230":"壤塘县","513231":"阿坝县","513232":"若尔盖县","513233":"红原县"},"513300":{"513301":"康定市","513322":"泸定县","513323":"丹巴县","513324":"九龙县","513325":"雅江县","513326":"道孚县","513327":"炉霍县","513328":"甘孜县","513329":"新龙县","513330":"德格县","513331":"白玉县","513332":"石渠县","513333":"色达县","513334":"理塘县","513335":"巴塘县","513336":"乡城县","513337":"稻城县","513338":"得荣县"},"513400":{"513401":"西昌市","513422":"木里藏族自治县","513423":"盐源县","513424":"德昌县","513425":"会理县","513426":"会东县","513427":"宁南县","513428":"普格县","513429":"布拖县","513430":"金阳县","513431":"昭觉县","513432":"喜德县","513433":"冕宁县","513434":"越西县","513435":"甘洛县","513436":"美姑县","513437":"雷波县"},"520000":{"520100":"贵阳市","520200":"六盘水市","520300":"遵义市","520400":"安顺市","520500":"毕节市","520600":"铜仁市","522300":"黔西南布依族苗族自治州","522600":"黔东南苗族侗族自治州","522700":"黔南布依族苗族自治州"},"520100":{"520102":"南明区","520103":"云岩区","520111":"花溪区","520112":"乌当区","520113":"白云区","520115":"观山湖区","520121":"开阳县","520122":"息烽县","520123":"修文县","520181":"清镇市"},"520200":{"520201":"钟山区","520203":"六枝特区","520221":"水城县","520222":"盘县"},"520300":{"520302":"红花岗区","520303":"汇川区","520304":"播州区","520322":"桐梓县","520323":"绥阳县","520324":"正安县","520325":"道真仡佬族苗族自治县","520326":"务川仡佬族苗族自治县","520327":"凤冈县","520328":"湄潭县","520329":"余庆县","520330":"习水县","520381":"赤水市","520382":"仁怀市"},"520400":{"520402":"西秀区","520403":"平坝区","520422":"普定县","520423":"镇宁布依族苗族自治县","520424":"关岭布依族苗族自治县","520425":"紫云苗族布依族自治县"},"520500":{"520502":"七星关区","520521":"大方县","520522":"黔西县","520523":"金沙县","520524":"织金县","520525":"纳雍县","520526":"威宁彝族回族苗族自治县","520527":"赫章县"},"520600":{"520602":"碧江区","520603":"万山区","520621":"江口县","520622":"玉屏侗族自治县","520623":"石阡县","520624":"思南县","520625":"印江土家族苗族自治县","520626":"德江县","520627":"沿河土家族自治县","520628":"松桃苗族自治县"},"522300":{"522301":"兴义市","522322":"兴仁县","522323":"普安县","522324":"晴隆县","522325":"贞丰县","522326":"望谟县","522327":"册亨县","522328":"安龙县"},"522600":{"522601":"凯里市","522622":"黄平县","522623":"施秉县","522624":"三穗县","522625":"镇远县","522626":"岑巩县","522627":"天柱县","522628":"锦屏县","522629":"剑河县","522630":"台江县","522631":"黎平县","522632":"榕江县","522633":"从江县","522634":"雷山县","522635":"麻江县","522636":"丹寨县"},"522700":{"522701":"都匀市","522702":"福泉市","522722":"荔波县","522723":"贵定县","522725":"瓮安县","522726":"独山县","522727":"平塘县","522728":"罗甸县","522729":"长顺县","522730":"龙里县","522731":"惠水县","522732":"三都水族自治县"},"530000":{"530100":"昆明市","530300":"曲靖市","530400":"玉溪市","530500":"保山市","530600":"昭通市","530700":"丽江市","530800":"普洱市","530900":"临沧市","532300":"楚雄彝族自治州","532500":"红河哈尼族彝族自治州","532600":"文山壮族苗族自治州","532800":"西双版纳傣族自治州","532900":"大理白族自治州","533100":"德宏傣族景颇族自治州","533300":"怒江傈僳族自治州","533400":"迪庆藏族自治州"},"530100":{"530102":"五华区","530103":"盘龙区","530111":"官渡区","530112":"西山区","530113":"东川区","530114":"呈贡区","530122":"晋宁县","530124":"富民县","530125":"宜良县","530126":"石林彝族自治县","530127":"嵩明县","530128":"禄劝彝族苗族自治县","530129":"寻甸回族彝族自治县","530181":"安宁市"},"530300":{"530302":"麒麟区","530303":"沾益区","530321":"马龙县","530322":"陆良县","530323":"师宗县","530324":"罗平县","530325":"富源县","530326":"会泽县","530381":"宣威市"},"530400":{"530402":"红塔区","530403":"江川区","530422":"澄江县","530423":"通海县","530424":"华宁县","530425":"易门县","530426":"峨山彝族自治县","530427":"新平彝族傣族自治县","530428":"元江哈尼族彝族傣族自治县"},"530500":{"530502":"隆阳区","530521":"施甸县","530523":"龙陵县","530524":"昌宁县","530581":"腾冲市"},"530600":{"530602":"昭阳区","530621":"鲁甸县","530622":"巧家县","530623":"盐津县","530624":"大关县","530625":"永善县","530626":"绥江县","530627":"镇雄县","530628":"彝良县","530629":"威信县","530630":"水富县"},"530700":{"530702":"古城区","530721":"玉龙纳西族自治县","530722":"永胜县","530723":"华坪县","530724":"宁蒗彝族自治县"},"530800":{"530802":"思茅区","530821":"宁洱哈尼族彝族自治县","530822":"墨江哈尼族自治县","530823":"景东彝族自治县","530824":"景谷傣族彝族自治县","530825":"镇沅彝族哈尼族拉祜族自治县","530826":"江城哈尼族彝族自治县","530827":"孟连傣族拉祜族佤族自治县","530828":"澜沧拉祜族自治县","530829":"西盟佤族自治县"},"530900":{"530902":"临翔区","530921":"凤庆县","530922":"云县","530923":"永德县","530924":"镇康县","530925":"双江拉祜族佤族布朗族傣族自治县","530926":"耿马傣族佤族自治县","530927":"沧源佤族自治县"},"532300":{"532301":"楚雄市","532322":"双柏县","532323":"牟定县","532324":"南华县","532325":"姚安县","532326":"大姚县","532327":"永仁县","532328":"元谋县","532329":"武定县","532331":"禄丰县"},"532500":{"532501":"个旧市","532502":"开远市","532503":"蒙自市","532504":"弥勒市","532523":"屏边苗族自治县","532524":"建水县","532525":"石屏县","532527":"泸西县","532528":"元阳县","532529":"红河县","532530":"金平苗族瑶族傣族自治县","532531":"绿春县","532532":"河口瑶族自治县"},"532600":{"532601":"文山市","532622":"砚山县","532623":"西畴县","532624":"麻栗坡县","532625":"马关县","532626":"丘北县","532627":"广南县","532628":"富宁县"},"532800":{"532801":"景洪市","532822":"勐海县","532823":"勐腊县"},"532900":{"532901":"大理市","532922":"漾濞彝族自治县","532923":"祥云县","532924":"宾川县","532925":"弥渡县","532926":"南涧彝族自治县","532927":"巍山彝族回族自治县","532928":"永平县","532929":"云龙县","532930":"洱源县","532931":"剑川县","532932":"鹤庆县"},"533100":{"533102":"瑞丽市","533103":"芒市","533122":"梁河县","533123":"盈江县","533124":"陇川县"},"533300":{"533301":"泸水市","533323":"福贡县","533324":"贡山独龙族怒族自治县","533325":"兰坪白族普米族自治县"},"533400":{"533401":"香格里拉市","533422":"德钦县","533423":"维西傈僳族自治县"},"540000":{"540100":"拉萨市","540200":"日喀则市","540300":"昌都市","540400":"林芝市","540500":"山南市","542400":"那曲地区","542500":"阿里地区"},"540100":{"540102":"城关区","540103":"堆龙德庆区","540121":"林周县","540122":"当雄县","540123":"尼木县","540124":"曲水县","540126":"达孜县","540127":"墨竹工卡县"},"540200":{"540202":"桑珠孜区","540221":"南木林县","540222":"江孜县","540223":"定日县","540224":"萨迦县","540225":"拉孜县","540226":"昂仁县","540227":"谢通门县","540228":"白朗县","540229":"仁布县","540230":"康马县","540231":"定结县","540232":"仲巴县","540233":"亚东县","540234":"吉隆县","540235":"聂拉木县","540236":"萨嘎县","540237":"岗巴县"},"540300":{"540302":"卡若区","540321":"江达县","540322":"贡觉县","540323":"类乌齐县","540324":"丁青县","540325":"察雅县","540326":"八宿县","540327":"左贡县","540328":"芒康县","540329":"洛隆县","540330":"边坝县"},"540400":{"540402":"巴宜区","540421":"工布江达县","540422":"米林县","540423":"墨脱县","540424":"波密县","540425":"察隅县","540426":"朗县"},"540500":{"540502":"乃东区","540521":"扎囊县","540522":"贡嘎县","540523":"桑日县","540524":"琼结县","540525":"曲松县","540526":"措美县","540527":"洛扎县","540528":"加查县","540529":"隆子县","540530":"错那县","540531":"浪卡子县"},"542400":{"542421":"那曲县","542422":"嘉黎县","542423":"比如县","542424":"聂荣县","542425":"安多县","542426":"申扎县","542427":"索县","542428":"班戈县","542429":"巴青县","542430":"尼玛县","542431":"双湖县"},"542500":{"542521":"普兰县","542522":"札达县","542523":"噶尔县","542524":"日土县","542525":"革吉县","542526":"改则县","542527":"措勤县"},"610000":{"610100":"西安市","610200":"铜川市","610300":"宝鸡市","610400":"咸阳市","610500":"渭南市","610600":"延安市","610700":"汉中市","610800":"榆林市","610900":"安康市","611000":"商洛市"},"610100":{"610102":"新城区","610103":"碑林区","610104":"莲湖区","610111":"灞桥区","610112":"未央区","610113":"雁塔区","610114":"阎良区","610115":"临潼区","610116":"长安区","610117":"高陵区","610122":"蓝田县","610124":"周至县","610125":"户县"},"610200":{"610202":"王益区","610203":"印台区","610204":"耀州区","610222":"宜君县"},"610300":{"610302":"渭滨区","610303":"金台区","610304":"陈仓区","610322":"凤翔县","610323":"岐山县","610324":"扶风县","610326":"眉县","610327":"陇县","610328":"千阳县","610329":"麟游县","610330":"凤县","610331":"太白县"},"610400":{"610402":"秦都区","610403":"杨陵区","610404":"渭城区","610422":"三原县","610423":"泾阳县","610424":"乾县","610425":"礼泉县","610426":"永寿县","610427":"彬县","610428":"长武县","610429":"旬邑县","610430":"淳化县","610431":"武功县","610481":"兴平市"},"610500":{"610502":"临渭区","610503":"华州区","610522":"潼关县","610523":"大荔县","610524":"合阳县","610525":"澄城县","610526":"蒲城县","610527":"白水县","610528":"富平县","610581":"韩城市","610582":"华阴市"},"610600":{"610602":"宝塔区","610603":"安塞区","610621":"延长县","610622":"延川县","610623":"子长县","610625":"志丹县","610626":"吴起县","610627":"甘泉县","610628":"富县","610629":"洛川县","610630":"宜川县","610631":"黄龙县","610632":"黄陵县"},"610700":{"610702":"汉台区","610721":"南郑县","610722":"城固县","610723":"洋县","610724":"西乡县","610725":"勉县","610726":"宁强县","610727":"略阳县","610728":"镇巴县","610729":"留坝县","610730":"佛坪县"},"610800":{"610802":"榆阳区","610803":"横山区","610821":"神木县","610822":"府谷县","610824":"靖边县","610825":"定边县","610826":"绥德县","610827":"米脂县","610828":"佳县","610829":"吴堡县","610830":"清涧县","610831":"子洲县"},"610900":{"610902":"汉滨区","610921":"汉阴县","610922":"石泉县","610923":"宁陕县","610924":"紫阳县","610925":"岚皋县","610926":"平利县","610927":"镇坪县","610928":"旬阳县","610929":"白河县"},"611000":{"611002":"商州区","611021":"洛南县","611022":"丹凤县","611023":"商南县","611024":"山阳县","611025":"镇安县","611026":"柞水县"},"620000":{"620100":"兰州市","620200":"嘉峪关市","620300":"金昌市","620400":"白银市","620500":"天水市","620600":"武威市","620700":"张掖市","620800":"平凉市","620900":"酒泉市","621000":"庆阳市","621100":"定西市","621200":"陇南市","622900":"临夏回族自治州","623000":"甘南藏族自治州"},"620100":{"620102":"城关区","620103":"七里河区","620104":"西固区","620105":"安宁区","620111":"红古区","620121":"永登县","620122":"皋兰县","620123":"榆中县"},"620200":{},"620300":{"620302":"金川区","620321":"永昌县"},"620400":{"620402":"白银区","620403":"平川区","620421":"靖远县","620422":"会宁县","620423":"景泰县"},"620500":{"620502":"秦州区","620503":"麦积区","620521":"清水县","620522":"秦安县","620523":"甘谷县","620524":"武山县","620525":"张家川回族自治县"},"620600":{"620602":"凉州区","620621":"民勤县","620622":"古浪县","620623":"天祝藏族自治县"},"620700":{"620702":"甘州区","620721":"肃南裕固族自治县","620722":"民乐县","620723":"临泽县","620724":"高台县","620725":"山丹县"},"620800":{"620802":"崆峒区","620821":"泾川县","620822":"灵台县","620823":"崇信县","620824":"华亭县","620825":"庄浪县","620826":"静宁县"},"620900":{"620902":"肃州区","620921":"金塔县","620922":"瓜州县","620923":"肃北蒙古族自治县","620924":"阿克塞哈萨克族自治县","620981":"玉门市","620982":"敦煌市"},"621000":{"621002":"西峰区","621021":"庆城县","621022":"环县","621023":"华池县","621024":"合水县","621025":"正宁县","621026":"宁县","621027":"镇原县"},"621100":{"621102":"安定区","621121":"通渭县","621122":"陇西县","621123":"渭源县","621124":"临洮县","621125":"漳县","621126":"岷县"},"621200":{"621202":"武都区","621221":"成县","621222":"文县","621223":"宕昌县","621224":"康县","621225":"西和县","621226":"礼县","621227":"徽县","621228":"两当县"},"622900":{"622901":"临夏市","622921":"临夏县","622922":"康乐县","622923":"永靖县","622924":"广河县","622925":"和政县","622926":"东乡族自治县","622927":"积石山保安族东乡族撒拉族自治县"},"623000":{"623001":"合作市","623021":"临潭县","623022":"卓尼县","623023":"舟曲县","623024":"迭部县","623025":"玛曲县","623026":"碌曲县","623027":"夏河县"},"630000":{"630100":"西宁市","630200":"海东市","632200":"海北藏族自治州","632300":"黄南藏族自治州","632500":"海南藏族自治州","632600":"果洛藏族自治州","632700":"玉树藏族自治州","632800":"海西蒙古族藏族自治州"},"630100":{"630102":"城东区","630103":"城中区","630104":"城西区","630105":"城北区","630121":"大通回族土族自治县","630122":"湟中县","630123":"湟源县"},"630200":{"630202":"乐都区","630203":"平安区","630222":"民和回族土族自治县","630223":"互助土族自治县","630224":"化隆回族自治县","630225":"循化撒拉族自治县"},"632200":{"632221":"门源回族自治县","632222":"祁连县","632223":"海晏县","632224":"刚察县"},"632300":{"632321":"同仁县","632322":"尖扎县","632323":"泽库县","632324":"河南蒙古族自治县"},"632500":{"632521":"共和县","632522":"同德县","632523":"贵德县","632524":"兴海县","632525":"贵南县"},"632600":{"632621":"玛沁县","632622":"班玛县","632623":"甘德县","632624":"达日县","632625":"久治县","632626":"玛多县"},"632700":{"632701":"玉树市","632722":"杂多县","632723":"称多县","632724":"治多县","632725":"囊谦县","632726":"曲麻莱县"},"632800":{"632801":"格尔木市","632802":"德令哈市","632821":"乌兰县","632822":"都兰县","632823":"天峻县"},"640000":{"640100":"银川市","640200":"石嘴山市","640300":"吴忠市","640400":"固原市","640500":"中卫市"},"640100":{"640104":"兴庆区","640105":"西夏区","640106":"金凤区","640121":"永宁县","640122":"贺兰县","640181":"灵武市"},"640200":{"640202":"大武口区","640205":"惠农区","640221":"平罗县"},"640300":{"640302":"利通区","640303":"红寺堡区","640323":"盐池县","640324":"同心县","640381":"青铜峡市"},"640400":{"640402":"原州区","640422":"西吉县","640423":"隆德县","640424":"泾源县","640425":"彭阳县"},"640500":{"640502":"沙坡头区","640521":"中宁县","640522":"海原县"},"650000":{"650100":"乌鲁木齐市","650200":"克拉玛依市","650400":"吐鲁番市","650500":"哈密市","652300":"昌吉回族自治州","652700":"博尔塔拉蒙古自治州","652800":"巴音郭楞蒙古自治州","652900":"阿克苏地区","653000":"克孜勒苏柯尔克孜自治州","653100":"喀什地区","653200":"和田地区","654000":"伊犁哈萨克自治州","654200":"塔城地区","654300":"阿勒泰地区","659001":"石河子市","659002":"阿拉尔市","659003":"图木舒克市","659004":"五家渠市","659006":"铁门关市"},"650100":{"650102":"天山区","650103":"沙依巴克区","650104":"新市区","650105":"水磨沟区","650106":"头屯河区","650107":"达坂城区","650109":"米东区","650121":"乌鲁木齐县"},"650200":{"650202":"独山子区","650203":"克拉玛依区","650204":"白碱滩区","650205":"乌尔禾区"},"650400":{"650402":"高昌区","650421":"鄯善县","650422":"托克逊县"},"650500":{"650502":"伊州区","650521":"巴里坤哈萨克自治县","650522":"伊吾县"},"652300":{"652301":"昌吉市","652302":"阜康市","652323":"呼图壁县","652324":"玛纳斯县","652325":"奇台县","652327":"吉木萨尔县","652328":"木垒哈萨克自治县"},"652700":{"652701":"博乐市","652702":"阿拉山口市","652722":"精河县","652723":"温泉县"},"652800":{"652801":"库尔勒市","652822":"轮台县","652823":"尉犁县","652824":"若羌县","652825":"且末县","652826":"焉耆回族自治县","652827":"和静县","652828":"和硕县","652829":"博湖县"},"652900":{"652901":"阿克苏市","652922":"温宿县","652923":"库车县","652924":"沙雅县","652925":"新和县","652926":"拜城县","652927":"乌什县","652928":"阿瓦提县","652929":"柯坪县"},"653000":{"653001":"阿图什市","653022":"阿克陶县","653023":"阿合奇县","653024":"乌恰县"},"653100":{"653101":"喀什市","653121":"疏附县","653122":"疏勒县","653123":"英吉沙县","653124":"泽普县","653125":"莎车县","653126":"叶城县","653127":"麦盖提县","653128":"岳普湖县","653129":"伽师县","653130":"巴楚县","653131":"塔什库尔干塔吉克自治县"},"653200":{"653201":"和田市","653221":"和田县","653222":"墨玉县","653223":"皮山县","653224":"洛浦县","653225":"策勒县","653226":"于田县","653227":"民丰县"},"654000":{"654002":"伊宁市","654003":"奎屯市","654004":"霍尔果斯市","654021":"伊宁县","654022":"察布查尔锡伯自治县","654023":"霍城县","654024":"巩留县","654025":"新源县","654026":"昭苏县","654027":"特克斯县","654028":"尼勒克县"},"654200":{"654201":"塔城市","654202":"乌苏市","654221":"额敏县","654223":"沙湾县","654224":"托里县","654225":"裕民县","654226":"和布克赛尔蒙古自治县"},"654300":{"654301":"阿勒泰市","654321":"布尔津县","654322":"富蕴县","654323":"福海县","654324":"哈巴河县","654325":"青河县","654326":"吉木乃县"},"659001":{"6590011":"北泉镇","6590015":"兵团一五二团","659001001":"新城街道","659001002":"向阳街道","659001003":"红山街道","659001004":"老街街道","659001005":"东城街道","659001101":"石河子镇"},"659002":{"6590022":"托喀依乡","6590025":"兵团七团","65900252":"兵团三团","659002001":"金银川路街道","659002002":"幸福路街道","659002003":"青松路街道","659002004":"南口街道","659002402":"工业园区","659002501":"兵团八团","659002503":"兵团十团","659002504":"兵团十一团","659002505":"兵团十二团","659002506":"兵团十三团","659002507":"兵团十四团","659002509":"兵团十六团","659002511":"兵团第一师水利水电工程处","659002512":"兵团第一师塔里木灌区水利管理处","659002513":"阿拉尔农场","659002514":"兵团第一师幸福农场","659002515":"中心监狱","659002516":"兵团一团","659002517":"兵团农一师沙井子水利管理处","659002518":"西工业园区管理委员会","659002519":"兵团二团"},"659003":{"65900351":"兵团五十团","659003001":"齐干却勒街道","659003002":"前海街道","659003003":"永安坝街道","659003504":"兵团四十四团","659003509":"兵团四十九团","659003511":"兵团五十一团","659003513":"兵团五十三团","659003514":"兵团图木舒克市喀拉拜勒镇"},"659004":{"6590045":"兵团一零一团","659004001":"军垦路街道","659004002":"青湖路街道","659004003":"人民路街道","659004501":"兵团一零二团","659004502":"兵团一零三团"},
  45 + "659006":{"6590061":"博古其镇","659006101":"双丰镇"},
  46 + "710000":{"710100":"台湾省"},
  47 + "710100":{"710101":"金门","710102":"连江","710103":"苗栗","710104":"南投","710105":"澎湖","710106":"屏东","710107":"台东","710108":"台中","710109":"台南","710110":"台北","710111":"桃园","710112":"云林","710113":"新北","710114":"彰化","710115":"嘉义","710116":"新竹","710117":"花莲","710118":"宜兰","710119":"高雄","710120":"基隆"},
  48 + "910000":{"810000":"香港特别行政区","820000":"澳门特别行政区"},
  49 + "810000":{"810101":"中西区","810102":"东区","810103":"九龙城区","810104":"观塘区","810105":"深水埗区","810106":"湾仔区","810107":"黄大仙区","810108":"油尖旺区","810109":"离岛区","810110":"葵青区","810111":"北区","810112":"西贡区","810113":"沙田区","810114":"屯门区","810115":"大埔区","810116":"荃湾区","810117":"元朗区","810118":"香港","810119":"九龙","810120":"新界"},
  50 + "820000":{"820101":"离岛","820102":"澳门半岛","820103":"凼仔","820104":"路凼城","820105":"路环"}
  51 +}
0 \ No newline at end of file 52 \ No newline at end of file
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/CommonAPI.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/IWpsBaseAPI.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/desform/ISysTranslateAPI.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/dto/FileDownDTO.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/dto/FileUploadDTO.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/dto/LogDTO.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/dto/OnlineAuthDTO.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/dto/message/BusMessageDTO.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/dto/message/BusTemplateMessageDTO.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/dto/message/MessageDTO.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/dto/message/TemplateDTO.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/dto/message/TemplateMessageDTO.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/vo/OaWpsModel.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/api/vo/Result.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/aspect/AutoLogAspect$1.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/aspect/AutoLogAspect.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/aspect/DictAspect.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/aspect/PermissionDataAspect.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/aspect/UrlMatchEnum.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/aspect/annotation/AutoLog.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/aspect/annotation/Dict.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/aspect/annotation/OnlineAuth.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/aspect/annotation/PermissionData.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/constant/CommonConstant.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/constant/CommonSendStatus.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/constant/DataBaseConstant.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/constant/FillRuleConstant.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/constant/ProvinceCityArea$Area.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/constant/ProvinceCityArea.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/constant/ServiceNameConstants.class 0 → 100644
No preview for this file type
juvenile-prosecution-boot/jeecg-boot-base/jeecg-boot-base-core/target/classes/org/jeecg/common/constant/VXESocketConst.class 0 → 100644
No preview for this file type