Prechádzať zdrojové kódy

【情报二期】数据域服务-布控接口开发

peifj 3 mesiacov pred
commit
4ca0e86df0
30 zmenil súbory, kde vykonal 5749 pridanie a 0 odobranie
  1. 212 0
      pom.xml
  2. 28 0
      src/main/java/com/hhwy/QBEQSJYApplication.java
  3. 18 0
      src/main/java/com/hhwy/qbeqsjy/APP.java
  4. 85 0
      src/main/java/com/hhwy/qbeqsjy/common/CharsetKit.java
  5. 226 0
      src/main/java/com/hhwy/qbeqsjy/common/CommonUtil.java
  6. 428 0
      src/main/java/com/hhwy/qbeqsjy/common/Constants.java
  7. 1009 0
      src/main/java/com/hhwy/qbeqsjy/common/Convert.java
  8. 188 0
      src/main/java/com/hhwy/qbeqsjy/common/DateUtils.java
  9. 49 0
      src/main/java/com/hhwy/qbeqsjy/common/DesensitizedUtil.java
  10. 40 0
      src/main/java/com/hhwy/qbeqsjy/common/ExceptionUtil.java
  11. 809 0
      src/main/java/com/hhwy/qbeqsjy/common/GpsCoordinateUtils.java
  12. 516 0
      src/main/java/com/hhwy/qbeqsjy/common/HttpClient.java
  13. 94 0
      src/main/java/com/hhwy/qbeqsjy/common/HttpStatus.java
  14. 55 0
      src/main/java/com/hhwy/qbeqsjy/common/HttpsClient.java
  15. 43 0
      src/main/java/com/hhwy/qbeqsjy/common/SSLClient.java
  16. 217 0
      src/main/java/com/hhwy/qbeqsjy/common/ServletUtils.java
  17. 90 0
      src/main/java/com/hhwy/qbeqsjy/common/StrFormatter.java
  18. 678 0
      src/main/java/com/hhwy/qbeqsjy/common/StringUtils.java
  19. 117 0
      src/main/java/com/hhwy/qbeqsjy/common/TimeTool.java
  20. 69 0
      src/main/java/com/hhwy/qbeqsjy/controller/CtrlController.java
  21. 216 0
      src/main/java/com/hhwy/qbeqsjy/domain/AjaxResult.java
  22. 36 0
      src/main/java/com/hhwy/qbeqsjy/dto/BusinessDTO.java
  23. 284 0
      src/main/java/com/hhwy/qbeqsjy/service/CtrlService.java
  24. 1 0
      src/main/resources/META-INF/spring-devtools.properties
  25. 75 0
      src/main/resources/application.properties
  26. 23 0
      src/main/resources/banner.txt
  27. 38 0
      src/main/resources/i18n/messages.properties
  28. 93 0
      src/main/resources/logback.xml
  29. 7 0
      src/main/webapp/WEB-INF/web.xml
  30. 5 0
      src/main/webapp/index.jsp

+ 212 - 0
pom.xml

@@ -0,0 +1,212 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.hhwy</groupId>
+  <artifactId>QBEQSJY</artifactId>
+
+  <packaging>war</packaging>
+  <version>1.0-SNAPSHOT</version>
+  <name>QBEQSJY Maven Webapp</name>
+  <url>http://maven.apache.org</url>
+
+  <build>
+    <finalName>QBEQSJY</finalName>
+  </build>
+
+  <properties>
+    <maven.compiler.source>8</maven.compiler.source>
+    <maven.compiler.target>8</maven.compiler.target>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+    <java.version>1.8</java.version>
+    <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
+    <druid.version>1.2.23</druid.version>
+    <bitwalker.version>1.21</bitwalker.version>
+    <kaptcha.version>2.3.3</kaptcha.version>
+    <pagehelper.boot.version>1.4.7</pagehelper.boot.version>
+    <fastjson.version>2.0.53</fastjson.version>
+    <oshi.version>6.6.3</oshi.version>
+    <commons.io.version>2.13.0</commons.io.version>
+    <poi.version>4.1.2</poi.version>
+    <velocity.version>2.3</velocity.version>
+    <jwt.version>0.9.1</jwt.version>
+    <jackson.version>2.14.2</jackson.version>
+  </properties>
+
+  <dependencies>
+
+    <!--<dependency>
+      <groupId>com.baomidou</groupId>
+      <artifactId>mybatis-plus-boot-starter</artifactId>
+      <version>3.5.1</version>
+    </dependency>-->
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter</artifactId>
+      <version>2.5.15</version>
+    </dependency>
+
+    <!-- Spring Web -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-web</artifactId>
+      <version>2.5.15</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-jdbc</artifactId>
+      <version>2.5.15</version>
+    </dependency>
+
+    <!-- 阿里数据库连接池 -->
+    <dependency>
+      <groupId>com.alibaba</groupId>
+      <artifactId>druid-spring-boot-starter</artifactId>
+      <version>${druid.version}</version>
+    </dependency>
+
+    <!-- 解析客户端操作系统、浏览器等 -->
+    <dependency>
+      <groupId>eu.bitwalker</groupId>
+      <artifactId>UserAgentUtils</artifactId>
+      <version>${bitwalker.version}</version>
+    </dependency>
+
+    <!-- pagehelper 分页插件 -->
+    <!--<dependency>
+      <groupId>com.github.pagehelper</groupId>
+      <artifactId>pagehelper-spring-boot-starter</artifactId>
+      <version>${pagehelper.boot.version}</version>
+    </dependency>-->
+
+    <!-- 获取系统信息 -->
+    <dependency>
+      <groupId>com.github.oshi</groupId>
+      <artifactId>oshi-core</artifactId>
+      <version>${oshi.version}</version>
+    </dependency>
+
+    <!-- io常用工具类 -->
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>${commons.io.version}</version>
+    </dependency>
+
+    <!-- excel工具 -->
+    <dependency>
+      <groupId>org.apache.poi</groupId>
+      <artifactId>poi-ooxml</artifactId>
+      <version>${poi.version}</version>
+    </dependency>
+
+    <!-- velocity代码生成使用模板 -->
+    <dependency>
+      <groupId>org.apache.velocity</groupId>
+      <artifactId>velocity-engine-core</artifactId>
+      <version>${velocity.version}</version>
+    </dependency>
+
+    <!-- 阿里JSON解析器 -->
+    <dependency>
+      <groupId>com.alibaba.fastjson2</groupId>
+      <artifactId>fastjson2</artifactId>
+      <version>${fastjson.version}</version>
+    </dependency>
+
+    <!-- Token生成与解析-->
+    <dependency>
+      <groupId>io.jsonwebtoken</groupId>
+      <artifactId>jjwt</artifactId>
+      <version>${jwt.version}</version>
+    </dependency>
+
+    <!-- 验证码 -->
+    <dependency>
+      <groupId>pro.fessional</groupId>
+      <artifactId>kaptcha</artifactId>
+      <version>${kaptcha.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>cn.hutool</groupId>
+      <artifactId>hutool-all</artifactId>
+      <version>5.8.16</version>
+    </dependency>
+
+
+    <dependency>
+      <groupId>com.alibaba</groupId>
+      <artifactId>easyexcel</artifactId>
+      <version>3.3.2</version>
+    </dependency>
+
+    <!-- Mysql驱动包 -->
+    <dependency>
+      <groupId>mysql</groupId>
+      <artifactId>mysql-connector-java</artifactId>
+      <version>8.0.30</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <version>1.18.24</version> <!-- 使用最新的稳定版本 -->
+      <scope>provided</scope> <!-- Lombok 在编译时不需要,只在编译时使用 -->
+    </dependency>
+
+    <dependency>
+      <groupId>org.jsoup</groupId>
+      <artifactId>jsoup</artifactId>
+      <version>1.15.1</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+      <version>4.5.6</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.alibaba</groupId>
+      <artifactId>fastjson</artifactId>
+      <version>1.2.31</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.sun.mail</groupId>
+      <artifactId>javax.mail</artifactId>
+      <version>1.6.2</version>
+    </dependency>
+
+    <!-- Jackson Databind -->
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+      <version>${jackson.version}</version>
+    </dependency>
+    <!-- Jackson Annotations -->
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+      <version>${jackson.version}</version>
+    </dependency>
+    <!-- Jackson Core -->
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+      <version>${jackson.version}</version>
+    </dependency>
+    <!-- Jackson JSR310 Data Types -->
+    <dependency>
+      <groupId>com.fasterxml.jackson.datatype</groupId>
+      <artifactId>jackson-datatype-jsr310</artifactId>
+      <version>${jackson.version}</version>
+    </dependency>
+
+  </dependencies>
+
+</project>

+ 28 - 0
src/main/java/com/hhwy/QBEQSJYApplication.java

@@ -0,0 +1,28 @@
+package com.hhwy;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+
+@EnableScheduling
+@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
+public class QBEQSJYApplication {
+
+    public static void main(String[] args)
+    {
+        // System.setProperty("spring.devtools.restart.enabled", "false");
+        SpringApplication.run(QBEQSJYApplication.class, args);
+        System.out.println("(♥◠‿◠)ノ゙  启动成功   ლ(´ڡ`ლ)゙  \n" +
+                " .-------.       ____     __        \n" +
+                " |  _ _   \\      \\   \\   /  /    \n" +
+                " | ( ' )  |       \\  _. /  '       \n" +
+                " |(_ o _) /        _( )_ .'         \n" +
+                " | (_,_).' __  ___(_ o _)'          \n" +
+                " |  |\\ \\  |  ||   |(_,_)'         \n" +
+                " |  | \\ `'   /|   `-'  /           \n" +
+                " |  |  \\    /  \\      /           \n" +
+                " ''-'   `'-'    `-..-'              ");
+    }
+}

+ 18 - 0
src/main/java/com/hhwy/qbeqsjy/APP.java

@@ -0,0 +1,18 @@
+package com.hhwy.qbeqsjy;
+
+import com.alibaba.fastjson.JSONArray;
+import com.hhwy.qbeqsjy.common.CommonUtil;
+
+public class APP {
+
+    public static void main(String[] args) {
+//        String confValueByKey = CommonUtil.getConfValueByKey("1");
+//        System.out.println(confValueByKey);
+
+//        JSONArray jsonArray = JSONArray.parseArray("[\"991C1223\", \"991C1071\", \"991C2304\"]");
+//        System.out.println(jsonArray);
+
+
+
+    }
+}

+ 85 - 0
src/main/java/com/hhwy/qbeqsjy/common/CharsetKit.java

@@ -0,0 +1,85 @@
+package com.hhwy.qbeqsjy.common;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 字符集工具类
+ * 
+ * @author ruoyi
+ */
+public class CharsetKit
+{
+    /** ISO-8859-1 */
+    public static final String ISO_8859_1 = "ISO-8859-1";
+    /** UTF-8 */
+    public static final String UTF_8 = "UTF-8";
+    /** GBK */
+    public static final String GBK = "GBK";
+
+    /** ISO-8859-1 */
+    public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
+    /** UTF-8 */
+    public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
+    /** GBK */
+    public static final Charset CHARSET_GBK = Charset.forName(GBK);
+
+    /**
+     * 转换为Charset对象
+     * 
+     * @param charset 字符集,为空则返回默认字符集
+     * @return Charset
+     */
+    public static Charset charset(String charset)
+    {
+        return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
+    }
+
+    /**
+     * 转换字符串的字符集编码
+     * 
+     * @param source 字符串
+     * @param srcCharset 源字符集,默认ISO-8859-1
+     * @param destCharset 目标字符集,默认UTF-8
+     * @return 转换后的字符集
+     */
+    public static String convert(String source, String srcCharset, String destCharset)
+    {
+        return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
+    }
+
+    /**
+     * 转换字符串的字符集编码
+     * 
+     * @param source 字符串
+     * @param srcCharset 源字符集,默认ISO-8859-1
+     * @param destCharset 目标字符集,默认UTF-8
+     * @return 转换后的字符集
+     */
+    public static String convert(String source, Charset srcCharset, Charset destCharset)
+    {
+        if (null == srcCharset)
+        {
+            srcCharset = StandardCharsets.ISO_8859_1;
+        }
+
+        if (null == destCharset)
+        {
+            destCharset = StandardCharsets.UTF_8;
+        }
+
+        if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
+        {
+            return source;
+        }
+        return new String(source.getBytes(srcCharset), destCharset);
+    }
+
+    /**
+     * @return 系统字符集编码
+     */
+    public static String systemCharset()
+    {
+        return Charset.defaultCharset().name();
+    }
+}

+ 226 - 0
src/main/java/com/hhwy/qbeqsjy/common/CommonUtil.java

@@ -0,0 +1,226 @@
+package com.hhwy.qbeqsjy.common;
+
+import java.io.*;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+
+/**
+ * TODO desc
+ *
+ * @ClassName: CommonUtil
+ * @author: hwang
+ * @date: 2021/3/30 14:48
+ */
+public class CommonUtil {
+
+  private static ResourceBundle bundle;
+
+  static {
+    bundle = ResourceBundle.getBundle("application");
+  }
+
+  /**
+   * 长整型IP转换成正常IP
+   * @param num
+   * @return
+   */
+  public static String intToIp(Long num){
+    if (num < 0L){
+      num += 4294967296L;
+    }
+    StringBuilder sb = new StringBuilder(15);
+    sb.append(num >> 24);
+    sb.append('.');
+    sb.append((num & 16777215L) >> 16);
+    sb.append('.');
+    sb.append((num & 65535L) >> 8);
+    sb.append('.');
+    sb.append(num & 255L);
+    return sb.toString();
+  }
+
+  /**
+   * 字符串判空
+   * @param str
+   * @return
+   */
+  public static boolean isNullOrEmpty(String str)
+  {
+    if (str == null || "null".equals(str.toLowerCase().trim()) || "[null]".equals(str.toLowerCase().trim()) || "[]".equals(str.toLowerCase().trim()))
+    {
+      return true;
+    }
+
+    return str.trim().isEmpty();
+  }
+
+
+  /**
+   * 经纬度计算距离  单位(米)
+   * @param lng1
+   * @param lat1
+   * @param lng2
+   * @param lat2
+   * @return
+   */
+  /*public static double getDistance2(Double lng1, Double lat1, Double lng2, Double lat2){
+    double earth = 6371.393;
+    double radLat1 = rad(lat1);
+    double radLat2 = rad(lat2);
+    double a = radLat1 - radLat2;
+    double b = rad(lng1) - rad(lng2);
+    double s = 2* Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2)+Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));
+    s=s*earth;
+    s=Math.round(s*10000d) / 10000d;
+    s=s*1000;
+    return s;
+  }*/
+
+  /*private static double rad(double d){
+    return d * Math.PI / 180.0;
+  }*/
+
+
+  /**
+   * 递归加载输入文件
+   * @param filePath
+   * @param filelist
+   * @param preStr  文件前缀  contains(preStr)
+   * @return
+   */
+  public static List<String> getFiles(String filePath, List<String> filelist ,String preStr) {
+    File root = new File(filePath);
+    if (root.exists()) {
+      File[] files = root.listFiles();
+      for (File file : files) {
+        if (file.isDirectory()) {
+          getFiles(file.getAbsolutePath(), filelist,preStr);
+        } else {
+          //文件前缀包含fzp的文件
+          if (file.getName().contains(preStr)){
+            filelist.add(file.getAbsolutePath());
+          }
+        }
+      }
+    }
+    return filelist;
+  }
+
+
+
+  /**
+   * 获取当前时间的yyyyMMdd时间格式
+   * @return
+   */
+  public static String getyyyyMMdd(){
+    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
+    return formatter.format(System.currentTimeMillis());
+  }
+
+
+  /**
+   * 获取当前时间的yyyyMMddHHmmss时间格式
+   * @return
+   */
+  public static String getyyyyMMddHHmmss(){
+    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
+    return formatter.format(System.currentTimeMillis());
+  }
+
+
+  /**
+   * 获取当前时间戳的yyyyMMdd时间格式
+   * @return
+   */
+  public static String timestamp2yyyyMMdd(String timestamp){
+    try {
+      DateFormat formatter = new SimpleDateFormat("yyyyMMdd");
+      long ms = Long.parseLong(timestamp);
+      Date date = formatter.parse(formatter.format(ms));
+      String dateStr = formatter.format(date);
+      return dateStr;
+    } catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+
+  /**
+   * 动态获取配置文件中指定 key的值
+   * @return
+   */
+  public static String getConfValueByKey(String key){
+    String value = "";
+    try {                                       //避免中文乱码
+      value = new String(bundle.getString(key).getBytes("ISO-8859-1"), "UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      e.printStackTrace();
+    }
+    return value;
+  }
+
+
+  public static byte[] getTestFile(String filePath) throws IOException {
+    InputStream in = new FileInputStream(filePath);
+    byte[] data = toByteArray(in);
+    in.close();
+    return data;
+  }
+
+
+  public static byte[] toByteArray(InputStream in) throws IOException {
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    byte[] buffer = new byte[1024 * 4];
+    int n = 0;
+    while ((n = in.read(buffer)) != -1) {
+      out.write(buffer, 0, n);
+    }
+    return out.toByteArray();
+  }
+
+
+  /**
+   * 根据 key移除重复的 map
+   * @param list
+   * @param mapKey
+   * @return
+   */
+  public static List<Map<String, Object>> removeRepeatMapByKey(List<Map<String, Object>> list, String mapKey){
+    List<Map<String, Object>> listMap = new ArrayList<>();
+    if(list == null || list.size() == 0){
+      return listMap;
+    }
+    Map<String, Object> msp = new HashMap<>();
+    for (int i = list.size() - 1; i >= 0; i--) {
+      Map<String, Object> map = list.get(i);
+      String idno = (String) map.get(mapKey);
+      map.remove(mapKey);
+      msp.put(idno, map);
+    }
+    Set<String> mspKey = msp.keySet();
+    for (String key : mspKey) {
+      Map<String, Object> newMap = (Map<String, Object>) msp.get(key);
+      newMap.put(mapKey, key);
+      listMap.add(newMap);
+    }
+    return listMap;
+  }
+
+
+  /**
+   * 线程sleep n秒
+   *
+   * @param millis 毫秒数
+   */
+  public static void threadSleep(long millis) {
+    try {
+      Thread.sleep(millis);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+}

+ 428 - 0
src/main/java/com/hhwy/qbeqsjy/common/Constants.java

@@ -0,0 +1,428 @@
+package com.hhwy.qbeqsjy.common;
+
+import io.jsonwebtoken.Claims;
+
+import java.util.Locale;
+
+/**
+ * 通用常量信息
+ * 
+ * @author ruoyi
+ */
+public class Constants
+{
+    /**
+     * UTF-8 字符集
+     */
+    public static final String UTF8 = "UTF-8";
+
+    /**
+     * GBK 字符集
+     */
+    public static final String GBK = "GBK";
+
+    /**
+     * 系统语言
+     */
+    public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE;
+
+    /**
+     * www主域
+     */
+    public static final String WWW = "www.";
+
+    /**
+     * http请求
+     */
+    public static final String HTTP = "http://";
+
+    /**
+     * https请求
+     */
+    public static final String HTTPS = "https://";
+
+    /**
+     * 通用成功标识
+     */
+    public static final String SUCCESS = "0";
+
+    /**
+     * 通用失败标识
+     */
+    public static final String FAIL = "1";
+
+    /**
+     * 登录成功
+     */
+    public static final String LOGIN_SUCCESS = "Success";
+
+    /**
+     * 注销
+     */
+    public static final String LOGOUT = "Logout";
+
+    /**
+     * 注册
+     */
+    public static final String REGISTER = "Register";
+
+    /**
+     * 登录失败
+     */
+    public static final String LOGIN_FAIL = "Error";
+
+    /**
+     * 所有权限标识
+     */
+    public static final String ALL_PERMISSION = "*:*:*";
+
+    /**
+     * 管理员角色权限标识
+     */
+    public static final String SUPER_ADMIN = "admin";
+
+    /**
+     * 角色权限分隔符
+     */
+    public static final String ROLE_DELIMETER = ",";
+
+    /**
+     * 权限标识分隔符
+     */
+    public static final String PERMISSION_DELIMETER = ",";
+
+    /**
+     * 验证码有效期(分钟)
+     */
+    public static final Integer CAPTCHA_EXPIRATION = 2;
+
+    /**
+     * 令牌
+     */
+    public static final String TOKEN = "token";
+
+    /**
+     * 令牌前缀
+     */
+    public static final String TOKEN_PREFIX = "Bearer ";
+
+    /**
+     * 令牌前缀
+     */
+    public static final String LOGIN_USER_KEY = "login_user_key";
+
+    /**
+     * 用户ID
+     */
+    public static final String JWT_USERID = "userid";
+
+    /**
+     * 用户名称
+     */
+    public static final String JWT_USERNAME = Claims.SUBJECT;
+
+    /**
+     * 用户头像
+     */
+    public static final String JWT_AVATAR = "avatar";
+
+    /**
+     * 创建时间
+     */
+    public static final String JWT_CREATED = "created";
+
+    /**
+     * 用户权限
+     */
+    public static final String JWT_AUTHORITIES = "authorities";
+
+    /**
+     * 资源映射路径 前缀
+     */
+    public static final String RESOURCE_PREFIX = "/profile";
+
+    /**
+     * RMI 远程方法调用
+     */
+    public static final String LOOKUP_RMI = "rmi:";
+
+    /**
+     * LDAP 远程方法调用
+     */
+    public static final String LOOKUP_LDAP = "ldap:";
+
+    /**
+     * LDAPS 远程方法调用
+     */
+    public static final String LOOKUP_LDAPS = "ldaps:";
+
+    /**
+     * 自动识别json对象白名单配置(仅允许解析的包名,范围越小越安全)
+     */
+    public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.ruoyi" };
+
+    /**
+     * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
+     */
+    public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.quartz.task" };
+
+    /**
+     * 定时任务违规的字符
+     */
+    public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
+            "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config", "com.ruoyi.generator" };
+
+
+    public static final String PARAMS_EMPTY_MSG = "请求参数为空";
+    public static final String PARAMS_ILLEGAL_MSG = "请求参数非法";
+    public static final String SERVER_ERROR_MSG = "服务端处理请求发生异常";
+    public static final String TASK_RUN_ERROR_MSG = "任务执行失败";
+
+    public static final String CTRL_TODO_MSG = "账号等待布控中,请勿重复发起布控";
+    public static final String STOP_CTRL_TODO_MSG = "账号等待停控中,请勿重复发起停控";
+    public static final String CTRL_FAIL_MSG = "账号布控失败";
+    public static final String STOP_CTRL_FAIL_MSG = "账号停控失败";
+
+    public static final String EMPTY_STRING = "";
+
+    /**
+     * 资源目录信息获取失败
+     */
+    public static final int REQ_RES_CATALOG_FAIL = 1003;
+    /**
+     * 其他异常
+     */
+    public static final int REQ_OTHER_EXCEP = 1999;
+    /**
+     * 其他异常
+     */
+    public static final String QUERY_OTHER_EXCEP = "2999";
+    /**
+     * 查询成功
+     */
+    public static final String QUERY_SUC = "2001";
+    /**
+     * 待布控
+     */
+    public static final String CTRL_TODO = "4";
+    /**
+     * 业务视为‘布控中’
+     */
+    public static final String CTRL_ING = "10";
+    /**
+     * 待停控
+     */
+    public static final String STOP_CTRL_TODO = "5";
+    /**
+     * 业务视为‘停控中’
+     */
+    public static final String STOP_CTRL_ING = "9";
+
+    public static final String CTRL_SUCCESS = "0";
+    public static final String CTRL_FAIL = "1";
+    public static final String STOP_CTRL_SUCCESS = "2";
+    public static final String STOP_CTRL_FAILURE = "3";
+
+
+    public static final int SUCCESSSTATUS = 200;
+    public static final int ERRSTATUS = 400;
+    public static final String STR_NUM_1 = "1";
+
+    public static final long NUM_1539100800 = 1539100800L;
+    public static final double TJ_LON = 117.217;
+    public static final double TJ_LAT = 39.14;
+    public static final long L_1000 = 1000L;
+    public static final Double D_6 = 6.0d;
+    public static final Double D_0 = 0.0d;
+    public static final long L_0 = 0L;
+    public static final long NUMBER_3000L = 3000L;
+    public static final long NUMBER_2000L = 2000L;
+    public static final int NUM_7776000 = 7776000;
+    public static final int NUM_900000 = 900000;
+    public static final int NUM_259200 = 259200;
+    public static final int NUM_180000 = 180000;
+    public static final int NUM_60000 = 60000;
+    public static final int NUM_86400 = 86400;
+    public static final int NUM_23456 = 23456;
+    public static final int NUM_9000 = 9000;
+    public static final int NUM_7200 = 7200;
+    public static final int NUM_6500 = 6500;
+    public static final int NUM_1000 = 1000;
+    public static final int NUM_300 = 300;
+    public static final int NUM_200 = 200;
+    public static final int NUM_180 = 180;
+    public static final int NUM_60 = 60;
+    public static final int NUM_30 = 30;
+    public static final int NUM_25 = 25;
+    public static final int NUM_20 = 20;
+    public static final int NUM_16 = 16;
+    public static final int NUM_14 = 14;
+    public static final int NUM_12 = 12;
+    public static final int NUM_11 = 11;
+    public static final int NUM_10 = 10;
+    public static final int NUM_9 = 9;
+    public static final int NUM_8 = 8;
+    public static final int NUM_7 = 7;
+    public static final int NUM_6 = 6;
+    public static final int NUM_5 = 5;
+    public static final int NUM_4 = 4;
+    public static final int NUM_3 = 3;
+    public static final int NUM_2 = 2;
+    public static final int NUM_1 = 1;
+    public static final int NUM_0 = 0;
+
+    public static final String HENG_XIAN = "-";
+    public static final String MAO_HAO = ":";
+    public static final String KONG_GE = " ";
+
+    public static final String CTRL_PROCESS_SUCESS = "1001";
+    public static final String CTRL_EXIST = "1005";
+    public static final String STOP_CTRL_EXIST = "1006";
+
+    public static final String DATACODE = "6000";
+    public static final String PARSE_FLAG_UNDONE = "0";
+    public static final String PARSE_FLAG_NOT = "1";
+    public static final String PARSE_FLAG_NOINFO = "2";
+    public static final String PARSE_FLAG_DONE = "3";
+    public static final String DATASOURCE_EXTRACT = "1";
+    public static final String IMEI_FLAG_COMPLETE = "1";
+    public static final String IMEI_FLAG_ERROR = "2";
+    public static final String NEWMOBILE_FLAG_UNDONE = "0";
+    public static final String NEWMOBILE_FLAG_PROCESSING = "1";
+    public static final String NEWMOBILE_FLAG_COMPLETE = "2";
+    public static final String NEWMOBILE_TAG_DEFAULT = "0";
+    public static final String NEWMOBILE_TAG_STEADY = "1";
+    public static final String NEWMOBILE_TAG_TEST = "2";
+    public static final String PERSONINFO_FLAG_COMPLETE = "1";
+
+    public static final String QQ_DICT = "1030001";
+    public static final String WX_DICT = "1030036";
+    public static final String ZJLX_DICT_IDNO = "ZJLX-430";
+    public static final String AJRYLX_DICT_DANGSHIREN = "AJRYLX-5";
+    public static final String ACTIVE_TRACE_DICT_HOMETYPE = "1";
+    public static final String ACTIVE_TRACE_DICT_WORKTYPE = "2";
+
+    /*public static final String PROPS_FILE ="config/tj-my-jzdata.properties";*/
+    public static final Integer TIMEOUT = 10;
+    public static final String SPLITSTR = "\u0019";
+    public static final String PHONE_REGEX = "^1[0-9]{10}$";
+    public static final String IDNO_REGEX = "";
+    public static final Integer MAXWAIT = 60000;
+    public static final Integer RUNSMILLIS = 60000;
+    public static final Integer MINTIME = 300000;
+    public static final Integer CONNECTSIZE = 20;
+
+    // 程序名称  日志使用
+    public static final String SERVICE_NAME = "SKPW_DB_TOOL --->";
+
+
+
+    /**
+     * 返回status值对应说明
+     */
+    public static final String STATUS_200_MSG = "成功!";
+    public static final String STATUS_500_MSG = "系统内部处理异常";
+    public static final String STATUS_585_MSG = "参数校验异常";
+    public static final String STATUS_587_MSG = "数据库原始数据异常";
+    public static final String STATUS_588_MSG = "传入token信息异常";
+
+    /**
+     * status值
+     */
+    public static final int STATUS_200 = 200;
+    public static final int STATUS_500 = 500;
+    public static final int STATUS_585 = 585;
+    public static final int STATUS_587 = 587;
+    public static final int STATUS_588 = 588;
+
+
+    //http连接配置
+    public static final int SOCKET_TIME_OUT = 1800000;
+    public static final int CONNECT_TIME_OUT =600000;
+    public static final int REQUEST_TIME_OUT =600000;
+
+
+
+    public static final String  ACTIVE_HOME_TYPE = "1";
+
+    /**
+     * 经纬度查询名址
+     */
+    public static final String GET_LT_ADDR = "http://GIS_IP:GIS_Port/FHGis/geocoder/inverse?";
+    //http://15.88.28.115:9150/FHGis/geocoder/inverse?lon=117.435962&lat=39.672619
+
+    /**
+     * 名址查经纬度
+     */
+    public static final String GET_ADDR_LT = "http://GIS_IP:GIS_Port/FHGis/geocoder/forward?address=";
+    //http://15.88.28.115:9150/FHGis/geocoder/forward?address=宝坻区水苑小区
+
+    /**
+     * 查人员活跃地
+     */
+    public static final String GET_ACTIVE_ADDR = "http://location_Ip:location_Port/trace_detail/v4/location/active/account?";
+    //http://15.88.28.145:8686/trace_detail/v4/location/active/account?accounttype=tel&account=18920718758&starttime=1579752238&endtime=1580875438
+
+    /**
+     * 推荐地址类型: 优先级依次是 1---5   1:最准确   5最差
+     */
+    public static final Integer 	EXACT_ADDR_TYPE_1 = 1;
+    public static final String 	EXACT_ADDR_TYPE_1_VALUE = "活跃居住地推荐(准确度最高)";
+
+    public static final Integer 	EXACT_ADDR_TYPE_2 = 2;
+    public static final String 	EXACT_ADDR_TYPE_2_VALUE = "依据活跃地所属行政区划推荐的明址(可信度适中)";
+
+    public static final Integer 	EXACT_ADDR_TYPE_3 = 3;
+    public static final String 	EXACT_ADDR_TYPE_3_VALUE = "活跃地基站地址(位置可信度高,但无实际住址)";
+
+    public static final Integer 	EXACT_ADDR_TYPE_4 = 4;
+    public static final String 	EXACT_ADDR_TYPE_4_VALUE = "无活跃信息, 推荐系统地址(可信度低)";
+
+    public static final Integer 	EXACT_ADDR_TYPE_5 = -1;
+    public static final String 	EXACT_ADDR_TYPE_5_VALUE = "无名址信息、无活跃信息";
+
+    public static final String MOBILE_ADDR_SERVICE_URL = "http://mobileAddrServiceIP:mobileAddrServicePort/api/v1/addrService/active";
+    public static final String MOBILE_ADDR_SERVICE_URL_BY_KEPLER = "http://keplerIP:keplerIP/gateway/FH_TJ_ADDRESS_EXACT/api/v1/addrService/active";
+
+    // 日志操作类型
+    public static final String LOG_TYPE_INSERT = "INSERT";
+    public static final String LOG_TYPE_UPDATE = "UPDATE";
+    public static final String LOG_TYPE_QUERY = "QUERY";
+    public static final String LOG_TYPE_DELETE = "DELETE";
+    public static final String LOG_TYPE_LOGIN = "LOGIN";
+    public static final String LOG_TYPE_LOGOUT = "LOGOUT";
+    public static final String LOG_TYPE_TREAT = "TREAT";
+    public static final String LOG_TYPE_MONITOR = "MONITOR";
+    public static final String LOG_TYPE_DISMONITOR = "DISMONITOR";
+    public static final String LOG_TYPE_IMPORT = "IMPORT";
+    public static final String LOG_TYPE_EXPORT = "EXPORT";
+    public static final String LOG_TYPE_INTERRUPT = "INTERRUPT";
+    public static final String LOG_TYPE_CANCEL = "CANCEL";
+    public static final String LOG_TYPE_EXEC = "EXEC";
+    public static final String LOG_TYPE_APPROVAL = "APPROVAL";
+    public static final String LOG_TYPE_COMMENT = "COMMENT";
+    public static final String LOG_TYPE_FEEDBACK = "FEEDBACK";
+    public static final String LOG_TYPE_STAMP = "STAMP";
+    public static final String LOG_TYPE_BROWSE = "BROWSE";
+    public static final String LOG_TYPE_REDO = "REDO";
+    public static final String LOG_TYPE_COUNT = "COUNT";
+    public static final String LOG_TYPE_PROJECT = "PROJECT";
+    public static final String LOG_TYPE_BACKUP = "BACKUP";
+    public static final String LOG_TYPE_ENABLED = "ENABLED";
+    public static final String LOG_TYPE_DISABLED = "DISABLED";
+    public static final String LOG_TYPE_UPLOAD = "UPLOAD";
+    public static final String LOG_TYPE_DOWNLOAD = "DOWNLOAD";
+    public static final String LOG_TYPE_REFRESH = "REFRESH";
+    public static final String LOG_TYPE_LOGIN_FAIL = "LOGIN_FAIL";
+    public static final String LOG_TYPE_USE_FUNCTION = "USE_FUNCTION";
+    public static final String LOG_TYPE_QUERY_MATCH_WHITELIST = "QUERY_MATCH_WHITELIST";
+    public static final String LOG_TYPE_MOVE = "MOVE";
+    public static final String LOG_TYPE_ARCHIVECASE = "ARCHIVECASE";
+    public static final String LOG_TYPE_CONTROL = "CONTROL";
+    public static final String LOG_TYPE_HANDOVER = "HANDOVER";
+    public static final String LOG_TYPE_MERGE = "MERGE";
+    public static final String LOG_TYPE_OVERCASE = "OVERCASE";
+    public static final String LOG_TYPE_BATCH_QUERY = "BATCH_QUERY";
+    public static final String LOG_TYPE_RELEASE = "RELEASE";
+    public static final String LOG_TYPE_SHARE = "SHARE";
+}

+ 1009 - 0
src/main/java/com/hhwy/qbeqsjy/common/Convert.java

@@ -0,0 +1,1009 @@
+package com.hhwy.qbeqsjy.common;
+
+import org.apache.commons.lang3.ArrayUtils;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.util.Set;
+
+/**
+ * 类型转换器
+ *
+ * @author ruoyi
+ */
+public class Convert
+{
+    /**
+     * 转换为字符串<br>
+     * 如果给定的值为null,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static String toStr(Object value, String defaultValue)
+    {
+        if (null == value)
+        {
+            return defaultValue;
+        }
+        if (value instanceof String)
+        {
+            return (String) value;
+        }
+        return value.toString();
+    }
+
+    /**
+     * 转换为字符串<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static String toStr(Object value)
+    {
+        return toStr(value, null);
+    }
+
+    /**
+     * 转换为字符<br>
+     * 如果给定的值为null,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Character toChar(Object value, Character defaultValue)
+    {
+        if (null == value)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Character)
+        {
+            return (Character) value;
+        }
+
+        final String valueStr = toStr(value, null);
+        return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
+    }
+
+    /**
+     * 转换为字符<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Character toChar(Object value)
+    {
+        return toChar(value, null);
+    }
+
+    /**
+     * 转换为byte<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Byte toByte(Object value, Byte defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Byte)
+        {
+            return (Byte) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).byteValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Byte.parseByte(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为byte<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Byte toByte(Object value)
+    {
+        return toByte(value, null);
+    }
+
+    /**
+     * 转换为Short<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Short toShort(Object value, Short defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Short)
+        {
+            return (Short) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).shortValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Short.parseShort(valueStr.trim());
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为Short<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Short toShort(Object value)
+    {
+        return toShort(value, null);
+    }
+
+    /**
+     * 转换为Number<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Number toNumber(Object value, Number defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Number)
+        {
+            return (Number) value;
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return NumberFormat.getInstance().parse(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为Number<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Number toNumber(Object value)
+    {
+        return toNumber(value, null);
+    }
+
+    /**
+     * 转换为int<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Integer toInt(Object value, Integer defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Integer)
+        {
+            return (Integer) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).intValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Integer.parseInt(valueStr.trim());
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为int<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Integer toInt(Object value)
+    {
+        return toInt(value, null);
+    }
+
+    /**
+     * 转换为Integer数组<br>
+     *
+     * @param str 被转换的值
+     * @return 结果
+     */
+    public static Integer[] toIntArray(String str)
+    {
+        return toIntArray(",", str);
+    }
+
+    /**
+     * 转换为Long数组<br>
+     *
+     * @param str 被转换的值
+     * @return 结果
+     */
+    public static Long[] toLongArray(String str)
+    {
+        return toLongArray(",", str);
+    }
+
+    /**
+     * 转换为Integer数组<br>
+     *
+     * @param split 分隔符
+     * @param split 被转换的值
+     * @return 结果
+     */
+    public static Integer[] toIntArray(String split, String str)
+    {
+        if (StringUtils.isEmpty(str))
+        {
+            return new Integer[] {};
+        }
+        String[] arr = str.split(split);
+        final Integer[] ints = new Integer[arr.length];
+        for (int i = 0; i < arr.length; i++)
+        {
+            final Integer v = toInt(arr[i], 0);
+            ints[i] = v;
+        }
+        return ints;
+    }
+
+    /**
+     * 转换为Long数组<br>
+     *
+     * @param split 分隔符
+     * @param str 被转换的值
+     * @return 结果
+     */
+    public static Long[] toLongArray(String split, String str)
+    {
+        if (StringUtils.isEmpty(str))
+        {
+            return new Long[] {};
+        }
+        String[] arr = str.split(split);
+        final Long[] longs = new Long[arr.length];
+        for (int i = 0; i < arr.length; i++)
+        {
+            final Long v = toLong(arr[i], null);
+            longs[i] = v;
+        }
+        return longs;
+    }
+
+    /**
+     * 转换为String数组<br>
+     *
+     * @param str 被转换的值
+     * @return 结果
+     */
+    public static String[] toStrArray(String str)
+    {
+        if (StringUtils.isEmpty(str))
+        {
+            return new String[] {};
+        }
+        return toStrArray(",", str);
+    }
+
+    /**
+     * 转换为String数组<br>
+     *
+     * @param split 分隔符
+     * @param split 被转换的值
+     * @return 结果
+     */
+    public static String[] toStrArray(String split, String str)
+    {
+        return str.split(split);
+    }
+
+    /**
+     * 转换为long<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Long toLong(Object value, Long defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Long)
+        {
+            return (Long) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).longValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            // 支持科学计数法
+            return new BigDecimal(valueStr.trim()).longValue();
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为long<br>
+     * 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Long toLong(Object value)
+    {
+        return toLong(value, null);
+    }
+
+    /**
+     * 转换为double<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Double toDouble(Object value, Double defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Double)
+        {
+            return (Double) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).doubleValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            // 支持科学计数法
+            return new BigDecimal(valueStr.trim()).doubleValue();
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为double<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Double toDouble(Object value)
+    {
+        return toDouble(value, null);
+    }
+
+    /**
+     * 转换为Float<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Float toFloat(Object value, Float defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Float)
+        {
+            return (Float) value;
+        }
+        if (value instanceof Number)
+        {
+            return ((Number) value).floatValue();
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Float.parseFloat(valueStr.trim());
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为Float<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Float toFloat(Object value)
+    {
+        return toFloat(value, null);
+    }
+
+    /**
+     * 转换为boolean<br>
+     * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static Boolean toBool(Object value, Boolean defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof Boolean)
+        {
+            return (Boolean) value;
+        }
+        String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        valueStr = valueStr.trim().toLowerCase();
+        switch (valueStr)
+        {
+            case "true":
+            case "yes":
+            case "ok":
+            case "1":
+                return true;
+            case "false":
+            case "no":
+            case "0":
+                return false;
+            default:
+                return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为boolean<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static Boolean toBool(Object value)
+    {
+        return toBool(value, null);
+    }
+
+    /**
+     * 转换为Enum对象<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     *
+     * @param clazz Enum的Class
+     * @param value 值
+     * @param defaultValue 默认值
+     * @return Enum
+     */
+    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (clazz.isAssignableFrom(value.getClass()))
+        {
+            @SuppressWarnings("unchecked")
+            E myE = (E) value;
+            return myE;
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return Enum.valueOf(clazz, valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为Enum对象<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     *
+     * @param clazz Enum的Class
+     * @param value 值
+     * @return Enum
+     */
+    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value)
+    {
+        return toEnum(clazz, value, null);
+    }
+
+    /**
+     * 转换为BigInteger<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static BigInteger toBigInteger(Object value, BigInteger defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof BigInteger)
+        {
+            return (BigInteger) value;
+        }
+        if (value instanceof Long)
+        {
+            return BigInteger.valueOf((Long) value);
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return new BigInteger(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为BigInteger<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static BigInteger toBigInteger(Object value)
+    {
+        return toBigInteger(value, null);
+    }
+
+    /**
+     * 转换为BigDecimal<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @param defaultValue 转换错误时的默认值
+     * @return 结果
+     */
+    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue)
+    {
+        if (value == null)
+        {
+            return defaultValue;
+        }
+        if (value instanceof BigDecimal)
+        {
+            return (BigDecimal) value;
+        }
+        if (value instanceof Long)
+        {
+            return new BigDecimal((Long) value);
+        }
+        if (value instanceof Double)
+        {
+            return BigDecimal.valueOf((Double) value);
+        }
+        if (value instanceof Integer)
+        {
+            return new BigDecimal((Integer) value);
+        }
+        final String valueStr = toStr(value, null);
+        if (StringUtils.isEmpty(valueStr))
+        {
+            return defaultValue;
+        }
+        try
+        {
+            return new BigDecimal(valueStr);
+        }
+        catch (Exception e)
+        {
+            return defaultValue;
+        }
+    }
+
+    /**
+     * 转换为BigDecimal<br>
+     * 如果给定的值为空,或者转换失败,返回默认值<br>
+     * 转换失败不会报错
+     *
+     * @param value 被转换的值
+     * @return 结果
+     */
+    public static BigDecimal toBigDecimal(Object value)
+    {
+        return toBigDecimal(value, null);
+    }
+
+    /**
+     * 将对象转为字符串<br>
+     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+     *
+     * @param obj 对象
+     * @return 字符串
+     */
+    public static String utf8Str(Object obj)
+    {
+        return str(obj, CharsetKit.CHARSET_UTF_8);
+    }
+
+    /**
+     * 将对象转为字符串<br>
+     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+     *
+     * @param obj 对象
+     * @param charsetName 字符集
+     * @return 字符串
+     */
+    public static String str(Object obj, String charsetName)
+    {
+        return str(obj, Charset.forName(charsetName));
+    }
+
+    /**
+     * 将对象转为字符串<br>
+     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+     *
+     * @param obj 对象
+     * @param charset 字符集
+     * @return 字符串
+     */
+    public static String str(Object obj, Charset charset)
+    {
+        if (null == obj)
+        {
+            return null;
+        }
+
+        if (obj instanceof String)
+        {
+            return (String) obj;
+        }
+        else if (obj instanceof byte[])
+        {
+            return str((byte[]) obj, charset);
+        }
+        else if (obj instanceof Byte[])
+        {
+            byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
+            return str(bytes, charset);
+        }
+        else if (obj instanceof ByteBuffer)
+        {
+            return str((ByteBuffer) obj, charset);
+        }
+        return obj.toString();
+    }
+
+    /**
+     * 将byte数组转为字符串
+     *
+     * @param bytes byte数组
+     * @param charset 字符集
+     * @return 字符串
+     */
+    public static String str(byte[] bytes, String charset)
+    {
+        return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
+    }
+
+    /**
+     * 解码字节码
+     *
+     * @param data 字符串
+     * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
+     * @return 解码后的字符串
+     */
+    public static String str(byte[] data, Charset charset)
+    {
+        if (data == null)
+        {
+            return null;
+        }
+
+        if (null == charset)
+        {
+            return new String(data);
+        }
+        return new String(data, charset);
+    }
+
+    /**
+     * 将编码的byteBuffer数据转换为字符串
+     *
+     * @param data 数据
+     * @param charset 字符集,如果为空使用当前系统字符集
+     * @return 字符串
+     */
+    public static String str(ByteBuffer data, String charset)
+    {
+        if (data == null)
+        {
+            return null;
+        }
+
+        return str(data, Charset.forName(charset));
+    }
+
+    /**
+     * 将编码的byteBuffer数据转换为字符串
+     *
+     * @param data 数据
+     * @param charset 字符集,如果为空使用当前系统字符集
+     * @return 字符串
+     */
+    public static String str(ByteBuffer data, Charset charset)
+    {
+        if (null == charset)
+        {
+            charset = Charset.defaultCharset();
+        }
+        return charset.decode(data).toString();
+    }
+
+    // ----------------------------------------------------------------------- 全角半角转换
+    /**
+     * 半角转全角
+     *
+     * @param input String.
+     * @return 全角字符串.
+     */
+    public static String toSBC(String input)
+    {
+        return toSBC(input, null);
+    }
+
+    /**
+     * 半角转全角
+     *
+     * @param input String
+     * @param notConvertSet 不替换的字符集合
+     * @return 全角字符串.
+     */
+    public static String toSBC(String input, Set<Character> notConvertSet)
+    {
+        char[] c = input.toCharArray();
+        for (int i = 0; i < c.length; i++)
+        {
+            if (null != notConvertSet && notConvertSet.contains(c[i]))
+            {
+                // 跳过不替换的字符
+                continue;
+            }
+
+            if (c[i] == ' ')
+            {
+                c[i] = '\u3000';
+            }
+            else if (c[i] < '\177')
+            {
+                c[i] = (char) (c[i] + 65248);
+
+            }
+        }
+        return new String(c);
+    }
+
+    /**
+     * 全角转半角
+     *
+     * @param input String.
+     * @return 半角字符串
+     */
+    public static String toDBC(String input)
+    {
+        return toDBC(input, null);
+    }
+
+    /**
+     * 替换全角为半角
+     *
+     * @param text 文本
+     * @param notConvertSet 不替换的字符集合
+     * @return 替换后的字符
+     */
+    public static String toDBC(String text, Set<Character> notConvertSet)
+    {
+        char[] c = text.toCharArray();
+        for (int i = 0; i < c.length; i++)
+        {
+            if (null != notConvertSet && notConvertSet.contains(c[i]))
+            {
+                // 跳过不替换的字符
+                continue;
+            }
+
+            if (c[i] == '\u3000')
+            {
+                c[i] = ' ';
+            }
+            else if (c[i] > '\uFF00' && c[i] < '\uFF5F')
+            {
+                c[i] = (char) (c[i] - 65248);
+            }
+        }
+        String returnString = new String(c);
+
+        return returnString;
+    }
+
+    /**
+     * 数字金额大写转换 先写个完整的然后将如零拾替换成零
+     *
+     * @param n 数字
+     * @return 中文大写数字
+     */
+    public static String digitUppercase(double n)
+    {
+        String[] fraction = { "角", "分" };
+        String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
+        String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } };
+
+        String head = n < 0 ? "负" : "";
+        n = Math.abs(n);
+
+        String s = "";
+        for (int i = 0; i < fraction.length; i++)
+        {
+            // 优化double计算精度丢失问题
+            BigDecimal nNum = new BigDecimal(n);
+            BigDecimal decimal = new BigDecimal(10);
+            BigDecimal scale = nNum.multiply(decimal).setScale(2, RoundingMode.HALF_EVEN);
+            double d = scale.doubleValue();
+            s += (digit[(int) (Math.floor(d * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
+        }
+        if (s.length() < 1)
+        {
+            s = "整";
+        }
+        int integerPart = (int) Math.floor(n);
+
+        for (int i = 0; i < unit[0].length && integerPart > 0; i++)
+        {
+            String p = "";
+            for (int j = 0; j < unit[1].length && n > 0; j++)
+            {
+                p = digit[integerPart % 10] + unit[1][j] + p;
+                integerPart = integerPart / 10;
+            }
+            s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
+        }
+        return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
+    }
+}

+ 188 - 0
src/main/java/com/hhwy/qbeqsjy/common/DateUtils.java

@@ -0,0 +1,188 @@
+package com.hhwy.qbeqsjy.common;
+
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+import java.lang.management.ManagementFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.*;
+import java.util.Date;
+
+/**
+ * 时间工具类
+ * 
+ * @author ruoyi
+ */
+public class DateUtils extends org.apache.commons.lang3.time.DateUtils
+{
+    public static String YYYY = "yyyy";
+
+    public static String YYYY_MM = "yyyy-MM";
+
+    public static String YYYY_MM_DD = "yyyy-MM-dd";
+
+    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+    private static String[] parsePatterns = {
+            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
+            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
+            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+
+    /**
+     * 获取当前Date型日期
+     * 
+     * @return Date() 当前日期
+     */
+    public static Date getNowDate()
+    {
+        return new Date();
+    }
+
+    /**
+     * 获取当前日期, 默认格式为yyyy-MM-dd
+     * 
+     * @return String
+     */
+    public static String getDate()
+    {
+        return dateTimeNow(YYYY_MM_DD);
+    }
+
+    public static final String getTime()
+    {
+        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+    }
+
+    public static final String dateTimeNow()
+    {
+        return dateTimeNow(YYYYMMDDHHMMSS);
+    }
+
+    public static final String dateTimeNow(final String format)
+    {
+        return parseDateToStr(format, new Date());
+    }
+
+    public static final String dateTime(final Date date)
+    {
+        return parseDateToStr(YYYY_MM_DD, date);
+    }
+
+    public static final String parseDateToStr(final String format, final Date date)
+    {
+        return new SimpleDateFormat(format).format(date);
+    }
+
+    public static final Date dateTime(final String format, final String ts)
+    {
+        try
+        {
+            return new SimpleDateFormat(format).parse(ts);
+        }
+        catch (ParseException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 日期路径 即年/月/日 如2018/08/08
+     */
+    public static final String datePath()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyy/MM/dd");
+    }
+
+    /**
+     * 日期路径 即年/月/日 如20180808
+     */
+    public static final String dateTime()
+    {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyyMMdd");
+    }
+
+    /**
+     * 日期型字符串转化为日期 格式
+     */
+    public static Date parseDate(Object str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        try
+        {
+            return parseDate(str.toString(), parsePatterns);
+        }
+        catch (ParseException e)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * 获取服务器启动时间
+     */
+    public static Date getServerStartDate()
+    {
+        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+        return new Date(time);
+    }
+
+    /**
+     * 计算相差天数
+     */
+    public static int differentDaysByMillisecond(Date date1, Date date2)
+    {
+        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
+    }
+
+    /**
+     * 计算时间差
+     *
+     * @param endDate 最后时间
+     * @param startTime 开始时间
+     * @return 时间差(天/小时/分钟)
+     */
+    public static String timeDistance(Date endDate, Date startTime)
+    {
+        long nd = 1000 * 24 * 60 * 60;
+        long nh = 1000 * 60 * 60;
+        long nm = 1000 * 60;
+        // long ns = 1000;
+        // 获得两个时间的毫秒时间差异
+        long diff = endDate.getTime() - startTime.getTime();
+        // 计算差多少天
+        long day = diff / nd;
+        // 计算差多少小时
+        long hour = diff % nd / nh;
+        // 计算差多少分钟
+        long min = diff % nd % nh / nm;
+        // 计算差多少秒//输出结果
+        // long sec = diff % nd % nh % nm / ns;
+        return day + "天" + hour + "小时" + min + "分钟";
+    }
+
+    /**
+     * 增加 LocalDateTime ==> Date
+     */
+    public static Date toDate(LocalDateTime temporalAccessor)
+    {
+        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+
+    /**
+     * 增加 LocalDate ==> Date
+     */
+    public static Date toDate(LocalDate temporalAccessor)
+    {
+        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
+        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+}

+ 49 - 0
src/main/java/com/hhwy/qbeqsjy/common/DesensitizedUtil.java

@@ -0,0 +1,49 @@
+package com.hhwy.qbeqsjy.common;
+
+/**
+ * 脱敏工具类
+ *
+ * @author ruoyi
+ */
+public class DesensitizedUtil
+{
+    /**
+     * 密码的全部字符都用*代替,比如:******
+     *
+     * @param password 密码
+     * @return 脱敏后的密码
+     */
+    public static String password(String password)
+    {
+        if (StringUtils.isBlank(password))
+        {
+            return StringUtils.EMPTY;
+        }
+        return StringUtils.repeat('*', password.length());
+    }
+
+    /**
+     * 车牌中间用*代替,如果是错误的车牌,不处理
+     *
+     * @param carLicense 完整的车牌号
+     * @return 脱敏后的车牌
+     */
+    public static String carLicense(String carLicense)
+    {
+        if (StringUtils.isBlank(carLicense))
+        {
+            return StringUtils.EMPTY;
+        }
+        // 普通车牌
+        if (carLicense.length() == 7)
+        {
+            carLicense = StringUtils.hide(carLicense, 3, 6);
+        }
+        else if (carLicense.length() == 8)
+        {
+            // 新能源车牌
+            carLicense = StringUtils.hide(carLicense, 3, 7);
+        }
+        return carLicense;
+    }
+}

+ 40 - 0
src/main/java/com/hhwy/qbeqsjy/common/ExceptionUtil.java

@@ -0,0 +1,40 @@
+package com.hhwy.qbeqsjy.common;
+
+import org.apache.commons.lang3.exception.ExceptionUtils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * 错误信息处理类。
+ *
+ * @author ruoyi
+ */
+public class ExceptionUtil
+{
+    /**
+     * 获取exception的详细错误信息。
+     */
+    public static String getExceptionMessage(Throwable e)
+    {
+        StringWriter sw = new StringWriter();
+        e.printStackTrace(new PrintWriter(sw, true));
+        return sw.toString();
+    }
+
+    public static String getRootErrorMessage(Exception e)
+    {
+        Throwable root = ExceptionUtils.getRootCause(e);
+        root = (root == null ? e : root);
+        if (root == null)
+        {
+            return "";
+        }
+        String msg = root.getMessage();
+        if (msg == null)
+        {
+            return "null";
+        }
+        return StringUtils.defaultString(msg);
+    }
+}

+ 809 - 0
src/main/java/com/hhwy/qbeqsjy/common/GpsCoordinateUtils.java

@@ -0,0 +1,809 @@
+package com.hhwy.qbeqsjy.common;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 地图坐标转换
+ */
+public class GpsCoordinateUtils {
+
+    private static final double PI = 3.1415926535897932384626433832795;
+    //    private static final double PI = 3.14159265358979324;
+    private static final double A = 6378245.0;
+    private static final double EE = 0.00669342162296594323;
+
+    /**
+     * 地球坐标系 WGS-84 to 火星坐标系 GCJ-02
+     *
+     * @param latitude  纬度
+     * @param longitude 经度
+     * @return [纬度, 经度]
+     */
+    public static double[] calWGS84toGCJ02(double latitude, double longitude) {
+        Point dev = calDev(latitude, longitude);
+        double retLat = latitude + dev.getLatitude();
+        double retLon = longitude + dev.getLongitude();
+        return new double[]{retLat, retLon};
+    }
+
+    /**
+     * 地球坐标系 WGS-84 to 百度坐标系 BD-09
+     *
+     * @param latitude  纬度
+     * @param longitude 经度
+     * @return [纬度, 经度]
+     */
+    public static double[] calWGS84toBD09(double latitude, double longitude) {
+        Point dev = calDev(latitude, longitude);
+        double retLat = latitude + dev.getLatitude();
+        double retLon = longitude + dev.getLongitude();
+        return calGCJ02toBD09(retLat, retLon);
+    }
+
+    /**
+     * 火星坐标系 GCJ-02 to 地球坐标系 WGS-84
+     *
+     * @param latitude  纬度
+     * @param longitude 经度
+     * @return [纬度, 经度]
+     */
+    public static double[] calGCJ02toWGS84(double latitude, double longitude) {
+        Point dev = calDev(latitude, longitude);
+        double retLat = latitude - dev.getLatitude();
+        double retLon = longitude - dev.getLongitude();
+        dev = calDev(retLat, retLon);
+        retLat = latitude - dev.getLatitude();
+        retLon = longitude - dev.getLongitude();
+        return new double[]{retLat, retLon};
+    }
+
+    /**
+     * 百度坐标系 BD-09 to 地球坐标系 WGS-84
+     *
+     * @param latitude  纬度
+     * @param longitude 经度
+     * @return [纬度, 经度]
+     */
+    public static double[] calBD09toWGS84(double latitude, double longitude) {
+        double[] gcj = calBD09toGCJ02(latitude, longitude);
+        return calGCJ02toWGS84(gcj[0], gcj[1]);
+    }
+
+    private static Point calDev(double latitude, double longitude) {
+        if (isOutOfChina(latitude, longitude, false)) {
+            return new Point(latitude, latitude);
+        }
+        double dLat = calLat(longitude - 105.0, latitude - 35.0);
+        double dLon = calLon(longitude - 105.0, latitude - 35.0);
+        double radLat = latitude / 180.0 * PI;
+        double magic = Math.sin(radLat);
+        magic = 1 - EE * magic * magic;
+        double sqrtMagic = Math.sqrt(magic);
+        dLat = (dLat * 180.0) / ((A * (1 - EE)) / (magic * sqrtMagic) * PI);
+        dLon = (dLon * 180.0) / (A / sqrtMagic * Math.cos(radLat) * PI);
+        return new Point(dLat, dLon);
+    }
+
+    private static double calLat(double x, double y) {
+        double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
+        ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
+        ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0;
+        ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
+        return ret;
+    }
+
+    private static double calLon(double x, double y) {
+        double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
+        ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
+        ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0;
+        ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0;
+        return ret;
+    }
+
+    /**
+     * 火星坐标系 GCJ-02 to 百度坐标系 BD-09
+     *
+     * @param latitude  纬度
+     * @param longitude 经度
+     * @return [纬度, 经度]
+     */
+    public static double[] calGCJ02toBD09(double latitude, double longitude) {
+        double x = longitude, y = latitude;
+        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * PI);
+        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * PI);
+        double retLat = z * Math.sin(theta) + 0.006;
+        double retLon = z * Math.cos(theta) + 0.0065;
+        return new double[]{retLat, retLon};
+    }
+
+    /**
+     * 百度坐标系 BD-09 to 火星坐标系 GCJ-02
+     *
+     * @param latitude  纬度
+     * @param longitude 经度
+     * @return [纬度, 经度]
+     */
+    public static double[] calBD09toGCJ02(double latitude, double longitude) {
+        double x = longitude - 0.0065, y = latitude - 0.006;
+        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * PI);
+        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * PI);
+        double retLat = z * Math.sin(theta);
+        double retLon = z * Math.cos(theta);
+        return new double[]{retLat, retLon};
+    }
+
+    /**
+     * 判断坐标是否在国内
+     *
+     * @param latitude
+     * @param longitude
+     * @param precision 是否精确判断范围
+     * @return true 在国外,false 在国内
+     */
+    public static boolean isOutOfChina(double latitude, double longitude, boolean precision) {
+        if (precision) {
+            return CHINA_POLYGON.stream().noneMatch(point -> pointInPolygon(point, latitude, longitude));
+        } else {
+            if (longitude < 72.004 || longitude > 137.8347) {
+                return true;
+            }
+            if (latitude < 0.8293 || latitude > 55.8271) {
+                return true;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * 检查坐标点是否在多边形区域内
+     *
+     * @param polygon   多边形
+     * @param latitude  纬度
+     * @param longitude 经度
+     * @return true 在多边形区域内,false 在多边形区域外
+     */
+    private static boolean pointInPolygon(Point[] polygon, double latitude, double longitude) {
+        int i, j = polygon.length - 1;
+        boolean oddNodes = false;
+        for (i = 0; i < polygon.length; i++) {
+            if ((polygon[i].getLatitude() < latitude && polygon[j].getLatitude() >= latitude
+                    || polygon[j].getLatitude() < latitude && polygon[i].getLatitude() >= latitude)
+                    && (polygon[i].getLongitude() <= longitude || polygon[j].getLongitude() <= longitude)) {
+                if (polygon[i].getLongitude()
+                        + (latitude - polygon[i].getLatitude()) / (polygon[j].getLatitude() - polygon[i].getLatitude())
+                        * (polygon[j].getLongitude() - polygon[i].getLongitude())
+                        < longitude) {
+                    oddNodes = !oddNodes;
+                }
+            }
+            j = i;
+        }
+        return oddNodes;
+    }
+
+    static class Point {
+        private double longitude;
+        private double latitude;
+
+        Point(double latitude, double longitude) {
+            this.longitude = longitude;
+            this.latitude = latitude;
+        }
+
+        public double getLongitude() {
+            return longitude;
+        }
+
+        public void setLongitude(double longitude) {
+            this.longitude = longitude;
+        }
+
+        public double getLatitude() {
+            return latitude;
+        }
+
+        public void setLatitude(double latitude) {
+            this.latitude = latitude;
+        }
+
+        @Override
+        public String toString() {
+            return longitude + "," + latitude;
+        }
+    }
+
+    //region 中国行政边界的WGS84坐标数据
+    //Mainland
+    private static final Point[] MAINLAND = new Point[]{
+            new Point(27.32083, 88.91693),
+            new Point(27.54243, 88.76464),
+            new Point(28.00805, 88.83575),
+            new Point(28.1168, 88.62435),
+            new Point(27.86605, 88.14279),
+            new Point(27.82305, 87.19275),
+            new Point(28.11166, 86.69527),
+            new Point(27.90888, 86.45137),
+            new Point(28.15805, 86.19769),
+            new Point(27.88625, 86.0054),
+            new Point(28.27916, 85.72137),
+            new Point(28.30666, 85.11095),
+            new Point(28.59104, 85.19518),
+            new Point(28.54444, 84.84665),
+            new Point(28.73402, 84.48623),
+            new Point(29.26097, 84.11651),
+            new Point(29.18902, 83.5479),
+            new Point(29.63166, 83.19109),
+            new Point(30.06923, 82.17525),
+            new Point(30.33444, 82.11123),
+            new Point(30.385, 81.42623),
+            new Point(30.01194, 81.23221),
+            new Point(30.20435, 81.02536),
+            new Point(30.57552, 80.207),
+            new Point(30.73374, 80.25423),
+            new Point(30.96583, 79.86304),
+            new Point(30.95708, 79.55429),
+            new Point(31.43729, 79.08082),
+            new Point(31.30895, 78.76825),
+            new Point(31.96847, 78.77075),
+            new Point(32.24304, 78.47594),
+            new Point(32.5561, 78.40595),
+            new Point(32.63902, 78.74623),
+            new Point(32.35083, 78.9711),
+            new Point(32.75666, 79.52874),
+            new Point(33.09944, 79.37511),
+            new Point(33.42863, 78.93623),
+            new Point(33.52041, 78.81387),
+            new Point(34.06833, 78.73581),
+            new Point(34.35001, 78.98535),
+            new Point(34.6118, 78.33707),
+            new Point(35.28069, 78.02305),
+            new Point(35.49902, 78.0718),
+            new Point(35.50133, 77.82393),
+            new Point(35.6125, 76.89526),
+            new Point(35.90665, 76.55304),
+            new Point(35.81458, 76.18061),
+            new Point(36.07082, 75.92887),
+            new Point(36.23751, 76.04166),
+            new Point(36.66343, 75.85984),
+            new Point(36.73169, 75.45179),
+            new Point(36.91156, 75.39902),
+            new Point(36.99719, 75.14787),
+            new Point(37.02782, 74.56543),
+            new Point(37.17, 74.39089),
+            new Point(37.23733, 74.91574),
+            new Point(37.40659, 75.18748),
+            new Point(37.65243, 74.9036),
+            new Point(38.47256, 74.85442),
+            new Point(38.67438, 74.35471),
+            new Point(38.61271, 73.81401),
+            new Point(38.88653, 73.70818),
+            new Point(38.97256, 73.85235),
+            new Point(39.23569, 73.62005),
+            new Point(39.45483, 73.65569),
+            new Point(39.59965, 73.95471),
+            new Point(39.76896, 73.8429),
+            new Point(40.04202, 73.99096),
+            new Point(40.32792, 74.88089),
+            new Point(40.51723, 74.8588),
+            new Point(40.45042, 75.23394),
+            new Point(40.64452, 75.58284),
+            new Point(40.298, 75.70374),
+            new Point(40.35324, 76.3344),
+            new Point(41.01258, 76.87067),
+            new Point(41.04079, 78.08083),
+            new Point(41.39286, 78.39554),
+            new Point(42.03954, 80.24513),
+            new Point(42.19622, 80.23402),
+            new Point(42.63245, 80.15804),
+            new Point(42.81565, 80.25796),
+            new Point(42.88545, 80.57226),
+            new Point(43.02906, 80.38405),
+            new Point(43.1683, 80.81526),
+            new Point(44.11378, 80.36887),
+            new Point(44.6358, 80.38499),
+            new Point(44.73408, 80.51589),
+            new Point(44.90282, 79.87106),
+            new Point(45.3497, 81.67928),
+            new Point(45.15748, 81.94803),
+            new Point(45.13303, 82.56638),
+            new Point(45.43581, 82.64624),
+            new Point(45.5831, 82.32179),
+            new Point(47.20061, 83.03443),
+            new Point(46.97332, 83.93026),
+            new Point(46.99361, 84.67804),
+            new Point(46.8277, 84.80318),
+            new Point(47.0591, 85.52257),
+            new Point(47.26221, 85.70139),
+            new Point(47.93721, 85.53707),
+            new Point(48.39333, 85.76596),
+            new Point(48.54277, 86.59791),
+            new Point(49.1102, 86.87602),
+            new Point(49.09262, 87.34821),
+            new Point(49.17295, 87.8407),
+            new Point(48.98304, 87.89291),
+            new Point(48.88103, 87.7611),
+            new Point(48.73499, 88.05942),
+            new Point(48.56541, 87.99194),
+            new Point(48.40582, 88.51679),
+            new Point(48.21193, 88.61179),
+            new Point(47.99374, 89.08514),
+            new Point(47.88791, 90.07096),
+            new Point(46.95221, 90.9136),
+            new Point(46.57735, 91.07027),
+            new Point(46.29694, 90.92151),
+            new Point(46.01735, 91.02651),
+            new Point(45.57972, 90.68193),
+            new Point(45.25305, 90.89694),
+            new Point(45.07729, 91.56088),
+            new Point(44.95721, 93.5547),
+            new Point(44.35499, 94.71735),
+            new Point(44.29416, 95.41061),
+            new Point(44.01937, 95.34109),
+            new Point(43.99311, 95.53339),
+            new Point(43.28388, 95.87901),
+            new Point(42.73499, 96.38206),
+            new Point(42.79583, 97.1654),
+            new Point(42.57194, 99.51012),
+            new Point(42.67707, 100.8425),
+            new Point(42.50972, 101.8147),
+            new Point(42.23333, 102.0772),
+            new Point(41.88721, 103.4164),
+            new Point(41.87721, 104.5267),
+            new Point(41.67068, 104.5237),
+            new Point(41.58666, 105.0065),
+            new Point(42.46624, 107.4758),
+            new Point(42.42999, 109.3107),
+            new Point(42.64576, 110.1064),
+            new Point(43.31694, 110.9897),
+            new Point(43.69221, 111.9583),
+            new Point(44.37527, 111.4214),
+            new Point(45.04944, 111.873),
+            new Point(45.08055, 112.4272),
+            new Point(44.8461, 112.853),
+            new Point(44.74527, 113.638),
+            new Point(45.38943, 114.5453),
+            new Point(45.4586, 115.7019),
+            new Point(45.72193, 116.2104),
+            new Point(46.29583, 116.5855),
+            new Point(46.41888, 117.3755),
+            new Point(46.57069, 117.425),
+            new Point(46.53645, 117.8455),
+            new Point(46.73638, 118.3147),
+            new Point(46.59895, 119.7068),
+            new Point(46.71513, 119.9315),
+            new Point(46.90221, 119.9225),
+            new Point(47.66499, 119.125),
+            new Point(47.99475, 118.5393),
+            new Point(48.01125, 117.8046),
+            new Point(47.65741, 117.3827),
+            new Point(47.88805, 116.8747),
+            new Point(47.87819, 116.2624),
+            new Point(47.69186, 115.9231),
+            new Point(47.91749, 115.5944),
+            new Point(48.14353, 115.5491),
+            new Point(48.25249, 115.8358),
+            new Point(48.52055, 115.8111),
+            new Point(49.83047, 116.7114),
+            new Point(49.52058, 117.8747),
+            new Point(49.92263, 118.5746),
+            new Point(50.09631, 119.321),
+            new Point(50.33028, 119.36),
+            new Point(50.39027, 119.1386),
+            new Point(51.62083, 120.0641),
+            new Point(52.115, 120.7767),
+            new Point(52.34423, 120.6259),
+            new Point(52.54267, 120.7122),
+            new Point(52.58805, 120.0819),
+            new Point(52.76819, 120.0314),
+            new Point(53.26374, 120.8307),
+            new Point(53.54361, 123.6147),
+            new Point(53.18832, 124.4933),
+            new Point(53.05027, 125.62),
+            new Point(52.8752, 125.6573),
+            new Point(52.75722, 126.0968),
+            new Point(52.5761, 125.9943),
+            new Point(52.12694, 126.555),
+            new Point(51.99437, 126.4412),
+            new Point(51.38138, 126.9139),
+            new Point(51.26555, 126.8176),
+            new Point(51.31923, 126.9689),
+            new Point(51.05825, 126.9331),
+            new Point(50.74138, 127.2919),
+            new Point(50.31472, 127.334),
+            new Point(50.20856, 127.5861),
+            new Point(49.80588, 127.515),
+            new Point(49.58665, 127.838),
+            new Point(49.58443, 128.7119),
+            new Point(49.34676, 129.1118),
+            new Point(49.4158, 129.4902),
+            new Point(48.86464, 130.2246),
+            new Point(48.86041, 130.674),
+            new Point(48.60576, 130.5236),
+            new Point(48.3268, 130.824),
+            new Point(48.10839, 130.6598),
+            new Point(47.68721, 130.9922),
+            new Point(47.71027, 132.5211),
+            new Point(48.09888, 133.0827),
+            new Point(48.06888, 133.4843),
+            new Point(48.39112, 134.4153),
+            new Point(48.26713, 134.7408),
+            new Point(47.99207, 134.5576),
+            new Point(47.70027, 134.7608),
+            new Point(47.32333, 134.1825),
+            new Point(46.64017, 133.9977),
+            new Point(46.47888, 133.8472),
+            new Point(46.25363, 133.9016),
+            new Point(45.82347, 133.4761),
+            new Point(45.62458, 133.4702),
+            new Point(45.45083, 133.1491),
+            new Point(45.05694, 133.0253),
+            new Point(45.34582, 131.8684),
+            new Point(44.97388, 131.4691),
+            new Point(44.83649, 130.953),
+            new Point(44.05193, 131.298),
+            new Point(43.53624, 131.1912),
+            new Point(43.38958, 131.3104),
+            new Point(42.91645, 131.1285),
+            new Point(42.74485, 130.4327),
+            new Point(42.42186, 130.6044),
+            new Point(42.71416, 130.2468),
+            new Point(42.88794, 130.2514),
+            new Point(43.00457, 129.9046),
+            new Point(42.43582, 129.6955),
+            new Point(42.44624, 129.3493),
+            new Point(42.02736, 128.9269),
+            new Point(42.00124, 128.0566),
+            new Point(41.58284, 128.3002),
+            new Point(41.38124, 128.1529),
+            new Point(41.47249, 127.2708),
+            new Point(41.79222, 126.9047),
+            new Point(41.61176, 126.5661),
+            new Point(40.89694, 126.0118),
+            new Point(40.47037, 124.8851),
+            new Point(40.09362, 124.3736),
+            new Point(39.82777, 124.128),
+            new Point(39.8143, 123.2422),
+            new Point(39.67388, 123.2167),
+            new Point(38.99638, 121.648),
+            new Point(38.8611, 121.6982),
+            new Point(38.71909, 121.1873),
+            new Point(38.91221, 121.0887),
+            new Point(39.09013, 121.6794),
+            new Point(39.2186, 121.5994),
+            new Point(39.35166, 121.7511),
+            new Point(39.52847, 121.2283),
+            new Point(39.62322, 121.533),
+            new Point(39.81138, 121.4683),
+            new Point(40.00305, 121.881),
+            new Point(40.50562, 122.2987),
+            new Point(40.73874, 122.0521),
+            new Point(40.92194, 121.1775),
+            new Point(40.1961, 120.4468),
+            new Point(39.87242, 119.5264),
+            new Point(39.15693, 118.9715),
+            new Point(39.04083, 118.3273),
+            new Point(39.19846, 117.889),
+            new Point(38.67555, 117.5364),
+            new Point(38.38666, 117.6722),
+            new Point(38.16721, 118.0281),
+            new Point(38.1529, 118.8378),
+            new Point(37.87832, 119.0355),
+            new Point(37.30054, 118.9566),
+            new Point(37.14361, 119.2328),
+            new Point(37.15138, 119.7672),
+            new Point(37.35228, 119.8529),
+            new Point(37.83499, 120.7371),
+            new Point(37.42458, 121.58),
+            new Point(37.55256, 122.1282),
+            new Point(37.41833, 122.1814),
+            new Point(37.39624, 122.5586),
+            new Point(37.20999, 122.5972),
+            new Point(37.02583, 122.4005),
+            new Point(37.01978, 122.5392),
+            new Point(36.89361, 122.5047),
+            new Point(36.84298, 122.1923),
+            new Point(37.00027, 121.9566),
+            new Point(36.75889, 121.5944),
+            new Point(36.61666, 120.7764),
+            new Point(36.52638, 120.96),
+            new Point(36.37582, 120.8753),
+            new Point(36.42277, 120.7062),
+            new Point(36.14075, 120.6956),
+            new Point(36.0419, 120.3436),
+            new Point(36.26345, 120.3078),
+            new Point(36.19998, 120.0889),
+            new Point(35.95943, 120.2378),
+            new Point(35.57893, 119.6475),
+            new Point(34.88499, 119.1761),
+            new Point(34.31145, 120.2487),
+            new Point(32.97499, 120.8858),
+            new Point(32.63889, 120.8375),
+            new Point(32.42958, 121.3348),
+            new Point(32.11333, 121.4412),
+            new Point(32.02166, 121.7066),
+            new Point(31.67833, 121.8275),
+            new Point(31.86639, 120.9444),
+            new Point(32.09361, 120.6019),
+            new Point(31.94555, 120.099),
+            new Point(32.30638, 119.8267),
+            new Point(32.26277, 119.6317),
+            new Point(31.90388, 120.1364),
+            new Point(31.98833, 120.7026),
+            new Point(31.81944, 120.7196),
+            new Point(31.30889, 121.6681),
+            new Point(30.97986, 121.8828),
+            new Point(30.85305, 121.8469),
+            new Point(30.56889, 120.9915),
+            new Point(30.33555, 120.8144),
+            new Point(30.39298, 120.4586),
+            new Point(30.19694, 120.15),
+            new Point(30.31027, 120.5082),
+            new Point(30.06465, 120.7916),
+            new Point(30.30458, 121.2808),
+            new Point(29.96305, 121.6778),
+            new Point(29.88211, 122.1196),
+            new Point(29.51167, 121.4483),
+            new Point(29.58916, 121.9744),
+            new Point(29.19527, 121.9336),
+            new Point(29.18388, 121.8119),
+            new Point(29.37236, 121.7969),
+            new Point(29.19729, 121.7444),
+            new Point(29.29111, 121.5611),
+            new Point(29.1634, 121.4135),
+            new Point(29.02194, 121.6914),
+            new Point(28.9359, 121.4908),
+            new Point(28.72798, 121.6113),
+            new Point(28.84215, 121.1464),
+            new Point(28.66993, 121.4844),
+            new Point(28.34722, 121.6417),
+            new Point(28.13889, 121.3419),
+            new Point(28.38277, 121.1651),
+            new Point(27.98222, 120.9353),
+            new Point(28.07944, 120.5908),
+            new Point(27.87229, 120.84),
+            new Point(27.59319, 120.5812),
+            new Point(27.45083, 120.6655),
+            new Point(27.20777, 120.5075),
+            new Point(27.28278, 120.1896),
+            new Point(27.14764, 120.4211),
+            new Point(26.89805, 120.0332),
+            new Point(26.64465, 120.128),
+            new Point(26.51778, 119.8603),
+            new Point(26.78823, 120.0733),
+            new Point(26.64888, 119.8668),
+            new Point(26.79611, 119.7879),
+            new Point(26.75625, 119.5503),
+            new Point(26.44222, 119.8204),
+            new Point(26.47388, 119.5775),
+            new Point(26.33861, 119.658),
+            new Point(26.36777, 119.9489),
+            new Point(25.99694, 119.4253),
+            new Point(26.14041, 119.0975),
+            new Point(25.93788, 119.354),
+            new Point(25.99069, 119.7058),
+            new Point(25.67996, 119.5807),
+            new Point(25.68222, 119.4522),
+            new Point(25.35333, 119.6454),
+            new Point(25.60649, 119.3149),
+            new Point(25.42097, 119.1053),
+            new Point(25.25319, 119.3526),
+            new Point(25.17208, 119.2726),
+            new Point(25.2426, 118.8749),
+            new Point(24.97194, 118.9866),
+            new Point(24.88291, 118.5729),
+            new Point(24.75673, 118.7631),
+            new Point(24.52861, 118.5953),
+            new Point(24.53638, 118.2397),
+            new Point(24.68194, 118.1688),
+            new Point(24.44024, 118.0199),
+            new Point(24.46019, 117.7947),
+            new Point(24.25875, 118.1237),
+            new Point(23.62437, 117.1957),
+            new Point(23.65919, 116.9179),
+            new Point(23.355, 116.7603),
+            new Point(23.42024, 116.5322),
+            new Point(23.23666, 116.7871),
+            new Point(23.21083, 116.5139),
+            new Point(22.93902, 116.4817),
+            new Point(22.73916, 115.7978),
+            new Point(22.88416, 115.6403),
+            new Point(22.65889, 115.5367),
+            new Point(22.80833, 115.1614),
+            new Point(22.70277, 114.8889),
+            new Point(22.53305, 114.8722),
+            new Point(22.64027, 114.718),
+            new Point(22.81402, 114.7782),
+            new Point(22.69972, 114.5208),
+            new Point(22.50423, 114.6136),
+            new Point(22.55004, 114.2223),
+            new Point(22.42993, 114.3885),
+            new Point(22.26056, 114.2961),
+            new Point(22.36736, 113.9056),
+            new Point(22.50874, 114.0337),
+            new Point(22.47444, 113.8608),
+            new Point(22.83458, 113.606),
+            new Point(23.05027, 113.5253),
+            new Point(23.11724, 113.8219),
+            new Point(23.05083, 113.4793),
+            new Point(22.87986, 113.3629),
+            new Point(22.54944, 113.5648),
+            new Point(22.18701, 113.5527),
+            new Point(22.56701, 113.1687),
+            new Point(22.17965, 113.3868),
+            new Point(22.04069, 113.2226),
+            new Point(22.20485, 113.0848),
+            new Point(21.8693, 112.94),
+            new Point(21.96472, 112.824),
+            new Point(21.70139, 112.2819),
+            new Point(21.91611, 111.8921),
+            new Point(21.75139, 111.9669),
+            new Point(21.77819, 111.6762),
+            new Point(21.61264, 111.7832),
+            new Point(21.5268, 111.644),
+            new Point(21.52528, 111.0285),
+            new Point(21.21138, 110.5328),
+            new Point(21.37322, 110.3944),
+            new Point(20.84381, 110.1594),
+            new Point(20.84083, 110.3755),
+            new Point(20.64, 110.3239),
+            new Point(20.48618, 110.5274),
+            new Point(20.24611, 110.2789),
+            new Point(20.2336, 109.9244),
+            new Point(20.4318, 110.0069),
+            new Point(20.92416, 109.6629),
+            new Point(21.44694, 109.9411),
+            new Point(21.50569, 109.6605),
+            new Point(21.72333, 109.5733),
+            new Point(21.49499, 109.5344),
+            new Point(21.39666, 109.1428),
+            new Point(21.58305, 109.1375),
+            new Point(21.61611, 108.911),
+            new Point(21.79889, 108.8702),
+            new Point(21.59888, 108.7403),
+            new Point(21.93562, 108.4692),
+            new Point(21.59014, 108.5125),
+            new Point(21.68999, 108.3336),
+            new Point(21.51444, 108.2447),
+            new Point(21.54241, 107.99),
+            new Point(21.66694, 107.7831),
+            new Point(21.60526, 107.3627),
+            new Point(22.03083, 106.6933),
+            new Point(22.45682, 106.5517),
+            new Point(22.76389, 106.7875),
+            new Point(22.86694, 106.7029),
+            new Point(22.91253, 105.8771),
+            new Point(23.32416, 105.3587),
+            new Point(23.18027, 104.9075),
+            new Point(22.81805, 104.7319),
+            new Point(22.6875, 104.3747),
+            new Point(22.79812, 104.1113),
+            new Point(22.50387, 103.9687),
+            new Point(22.78287, 103.6538),
+            new Point(22.58436, 103.5224),
+            new Point(22.79451, 103.3337),
+            new Point(22.43652, 103.0304),
+            new Point(22.77187, 102.4744),
+            new Point(22.39629, 102.1407),
+            new Point(22.49777, 101.7415),
+            new Point(22.20916, 101.5744),
+            new Point(21.83444, 101.7653),
+            new Point(21.14451, 101.786),
+            new Point(21.17687, 101.2919),
+            new Point(21.57264, 101.1482),
+            new Point(21.76903, 101.099),
+            new Point(21.47694, 100.6397),
+            new Point(21.43546, 100.2057),
+            new Point(21.72555, 99.97763),
+            new Point(22.05018, 99.95741),
+            new Point(22.15592, 99.16785),
+            new Point(22.93659, 99.56484),
+            new Point(23.08204, 99.5113),
+            new Point(23.18916, 98.92747),
+            new Point(23.97076, 98.67991),
+            new Point(24.16007, 98.89073),
+            new Point(23.92999, 97.54762),
+            new Point(24.26055, 97.7593),
+            new Point(24.47666, 97.54305),
+            new Point(24.73992, 97.55255),
+            new Point(25.61527, 98.19109),
+            new Point(25.56944, 98.36137),
+            new Point(25.85597, 98.7104),
+            new Point(26.12527, 98.56944),
+            new Point(26.18472, 98.73109),
+            new Point(26.79166, 98.77777),
+            new Point(27.52972, 98.69699),
+            new Point(27.6725, 98.45888),
+            new Point(27.54014, 98.31992),
+            new Point(28.14889, 98.14499),
+            new Point(28.54652, 97.55887),
+            new Point(28.22277, 97.34888),
+            new Point(28.46749, 96.65387),
+            new Point(28.35111, 96.40193),
+            new Point(28.525, 96.34027),
+            new Point(28.79569, 96.61373),
+            new Point(29.05666, 96.47083),
+            new Point(28.90138, 96.17532),
+            new Point(29.05972, 96.14888),
+            new Point(29.25757, 96.39172),
+            new Point(29.46444, 96.08315),
+            new Point(29.03527, 95.38777),
+            new Point(29.33346, 94.64751),
+            new Point(29.07348, 94.23456),
+            new Point(28.6692, 93.96172),
+            new Point(28.61876, 93.35194),
+            new Point(28.3193, 93.22205),
+            new Point(28.1419, 92.71044),
+            new Point(27.86194, 92.54498),
+            new Point(27.76472, 91.65776),
+            new Point(27.945, 91.66277),
+            new Point(28.08111, 91.30138),
+            new Point(27.96999, 91.08693),
+            new Point(28.07958, 90.3765),
+            new Point(28.24257, 90.38898),
+            new Point(28.32369, 89.99819),
+            new Point(28.05777, 89.48749),
+            new Point(27.32083, 88.91693)
+    };
+
+    //Taiwan
+    private static final Point[] TAIWAN = new Point[]{
+            new Point(25.13474, 121.4441),
+            new Point(25.28361, 121.5632),
+            new Point(25.00722, 122.0004),
+            new Point(24.85028, 121.8182),
+            new Point(24.47638, 121.8397),
+            new Point(23.0875, 121.3556),
+            new Point(21.92791, 120.7196),
+            new Point(22.31277, 120.6103),
+            new Point(22.54044, 120.3071),
+            new Point(23.04437, 120.0539),
+            new Point(23.61708, 120.1112),
+            new Point(25.00166, 121.0017),
+            new Point(25.13474, 121.4441)
+    };
+
+    //Hainan
+    private static final Point[] HAINAN = new Point[]{
+            new Point(19.52888, 110.855),
+            new Point(19.16761, 110.4832),
+            new Point(18.80083, 110.5255),
+            new Point(18.3852, 110.0503),
+            new Point(18.39152, 109.7594),
+            new Point(18.19777, 109.7036),
+            new Point(18.50562, 108.6871),
+            new Point(19.28028, 108.6283),
+            new Point(19.76, 109.2939),
+            new Point(19.7236, 109.1653),
+            new Point(19.89972, 109.2572),
+            new Point(19.82861, 109.4658),
+            new Point(19.99389, 109.6108),
+            new Point(20.13361, 110.6655),
+            new Point(19.97861, 110.9425),
+            new Point(19.63829, 111.0215),
+            new Point(19.52888, 110.855)
+    };
+
+    //Chongming
+    private static final Point[] CHONGMING = new Point[]{
+            new Point(31.80054, 121.2039),
+            new Point(31.49972, 121.8736),
+            new Point(31.53111, 121.5464),
+            new Point(31.80054, 121.2039)
+    };
+    //endregion
+
+    /**
+     * 中国行政边界的WGS84坐标数据,
+     * 光线投射算法 (Ray casting algorithm) 获得,
+     * 沿海、国界周边地区可能会有误差,更高精度需要调整坐标点
+     */
+    private static final List<Point[]> CHINA_POLYGON = new ArrayList<>();
+
+    static {
+        CHINA_POLYGON.add(MAINLAND);
+        CHINA_POLYGON.add(TAIWAN);
+        CHINA_POLYGON.add(HAINAN);
+        CHINA_POLYGON.add(CHONGMING);
+    }
+}

+ 516 - 0
src/main/java/com/hhwy/qbeqsjy/common/HttpClient.java

@@ -0,0 +1,516 @@
+package com.hhwy.qbeqsjy.common;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpStatus;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.*;
+import org.apache.http.entity.InputStreamEntity;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * http操作类 <功能详细描述>
+ *
+ * @author nzhou
+ * @version [版本号, 2016年6月7日]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public class HttpClient {
+    /**
+     * 日志
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(HttpClient.class);
+
+    /**
+     * socket超时
+     */
+    private static final int SOCKET_TIMEOUT = 180000;
+
+    /**
+     * 连接超时
+     */
+    private static final int CONN_TIMEOUT = 600000;
+
+    private CloseableHttpClient httpClient;
+
+    private RequestConfig requestConfig;
+
+    /**
+     * 构造客户端连接对象 <功能详细描述>
+     *
+     * @see [类、类#方法、类#成员]
+     */
+    public HttpClient() {
+        try {
+            this.httpClient = HttpClients.createDefault();
+            this.requestConfig = RequestConfig.custom().setSocketTimeout(SOCKET_TIMEOUT)
+                    .setConnectTimeout(CONN_TIMEOUT).setConnectionRequestTimeout(CONN_TIMEOUT).build();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 发送POST请求 <功能详细描述>
+     *
+     * @param url	路径
+     * @param body	消息体
+     * @return
+     * @throws UnsupportedEncodingException
+     * @see [类、类#方法、类#成员]
+     */
+    public String postResource(String url, String body, Map<String, Object> headerParamsMap) {
+        HttpPost postMethod = new HttpPost(url);
+
+        if(headerParamsMap != null && headerParamsMap.size() > 0){
+            Set<String> keys = headerParamsMap.keySet();
+            for (String key : keys) {
+                postMethod.setHeader(key, headerParamsMap.get(key).toString());
+            }
+        }
+        postMethod.setConfig(this.requestConfig);
+        postMethod.setHeader("Content-Charset", "UTF-8");
+        postMethod.setHeader("Accept-Charset", "UTF-8");
+        postMethod.setHeader("Content-Type", "application/json");
+        postMethod.setEntity(new StringEntity(body, "utf-8"));
+
+        CloseableHttpResponse response = null;
+        String content = null;
+        try {
+            response = this.httpClient.execute(postMethod);
+            int httpStatus = response.getStatusLine().getStatusCode();
+            if (httpStatus != HttpStatus.SC_OK) {
+                // 返回的是失败响应
+                LOG.error(
+                        String.format("Failed to execute post method '%s', caused by: it's response statuscode is %d!",
+                                url, httpStatus));
+            }
+            HttpEntity entity = response.getEntity();
+            if (entity != null) {
+                content = EntityUtils.toString(entity, "UTF-8");
+                EntityUtils.consume(entity);
+            }
+        } catch (Exception e) {
+            LOG.error("url:" + url + "请求出错!", e);
+            e.printStackTrace();
+        } finally {
+            if (response != null) {
+                try {
+                    response.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            postMethod.releaseConnection();
+        }
+        return content;
+    }
+
+
+    public String postResourceTXWA(String url, String body, String token, String resourceUrl) {
+        HttpPost postMethod = new HttpPost(url);
+        postMethod.setConfig(this.requestConfig);
+        postMethod.setHeader("Content-Charset", "UTF-8");
+        postMethod.setHeader("Accept-Charset", "UTF-8");
+        postMethod.setHeader("Content-Type", CommonUtil.getConfValueByKey("TXWA_REQUEST_Content-Type"));
+        //添加token头信息
+        if(StringUtils.isNotBlank(token)){
+            postMethod.setHeader("token", token);
+        }
+        if(StringUtils.isNotBlank(resourceUrl)){
+            postMethod.setHeader("resourceUrl", resourceUrl);
+        }
+        postMethod.setEntity(new StringEntity(body, "utf-8"));
+
+        CloseableHttpResponse response = null;
+        String content = null;
+        try {
+            response = this.httpClient.execute(postMethod);
+            int httpStatus = response.getStatusLine().getStatusCode();
+            if (httpStatus != HttpStatus.SC_OK) {
+                // 返回的是失败响应
+                LOG.error(
+                        String.format("Failed to execute post method '%s', caused by: it's response statuscode is %d!",
+                                url, httpStatus));
+            }
+            HttpEntity entity = response.getEntity();
+            if (entity != null) {
+                content = EntityUtils.toString(entity, "UTF-8");
+                EntityUtils.consume(entity);
+            }
+        } catch (Exception e) {
+            LOG.error("url:" + url + "请求出错!", e);
+            e.printStackTrace();
+        } finally {
+            if (response != null) {
+                try {
+                    response.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            postMethod.releaseConnection();
+        }
+        return content;
+    }
+
+
+    /**
+     * 发送POST请求 <功能详细描述>
+     *
+     * @param url	路径
+     * @param body	消息体
+     * @return
+     * @throws UnsupportedEncodingException
+     * @see [类、类#方法、类#成员]
+     */
+    public String postResourceXHJSON(String url, String body) {
+        HttpPost postMethod = new HttpPost(url);
+
+        postMethod.setConfig(this.requestConfig);
+        postMethod.setHeader("Content-Charset", "UTF-8");
+        postMethod.setHeader("Accept-Charset", "UTF-8");
+        postMethod.setHeader("Content-Type", "application/json");
+        postMethod.setHeader("requestType", CommonUtil.getConfValueByKey("XH_requestType"));
+        postMethod.setHeader("serviceID", CommonUtil.getConfValueByKey("XH_serviceId"));
+        postMethod.setHeader("secretKey", CommonUtil.getConfValueByKey("XH_secretKey"));
+        postMethod.setEntity(new StringEntity(body, "utf-8"));
+
+        CloseableHttpResponse response = null;
+        String content = null;
+        try {
+            response = this.httpClient.execute(postMethod);
+            int httpStatus = response.getStatusLine().getStatusCode();
+            if (httpStatus != HttpStatus.SC_OK  || httpStatus != HttpStatus.SC_NO_CONTENT) {
+                // 返回的是失败响应
+                LOG.error(
+                        String.format("Failed to execute post method '%s', caused by: it's response statuscode is %d!",
+                                url, httpStatus));
+            }
+            HttpEntity entity = response.getEntity();
+            if (entity != null) {
+                content = EntityUtils.toString(entity, "UTF-8");
+                EntityUtils.consume(entity);
+            }
+        } catch (Exception e) {
+            LOG.error("url:" + url + "请求出错!", e);
+            e.printStackTrace();
+        } finally {
+            if (response != null) {
+                try {
+                    response.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            postMethod.releaseConnection();
+        }
+        return content;
+    }
+
+
+    /**
+     * 发送POST请求 <功能详细描述>
+     *
+     * @param url	路径
+     * @param requestXML	消息体
+     * @return
+     * @throws UnsupportedEncodingException
+     * @see [类、类#方法、类#成员]
+     */
+    public int postResourceXHxml(String url, String requestXML) {
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        CloseableHttpResponse response = null;
+        int httpStatus = 500;
+        try {
+            InputStreamEntity reqEntity = new InputStreamEntity(new ByteArrayInputStream(requestXML.getBytes()));
+            reqEntity.setContentType("application/xml");
+            reqEntity.setContentEncoding("utf-8");
+            reqEntity.setChunked(true);
+            HttpUriRequest request = RequestBuilder.post()
+                    .setUri(url)
+                    .setEntity(reqEntity)
+                    .setHeader("Content-Type", "application/xml")
+                    .setHeader("requestType", CommonUtil.getConfValueByKey("XH_requestType"))
+                    .setHeader("serviceID", CommonUtil.getConfValueByKey("XH_serviceId"))
+                    .setHeader("secretKey", CommonUtil.getConfValueByKey("XH_secretKey"))
+                    .build();
+            LOG.info("请求星火服务注册接口,url:{}", url);
+            response = httpClient.execute(request);
+            httpStatus = response.getStatusLine().getStatusCode();
+            LOG.info("响应码:{}", httpStatus);
+        } catch (Exception e) {
+            LOG.error("url:" + url + "请求出错!", e);
+            e.printStackTrace();
+        }finally {
+            if (response != null) {
+                try {
+                    response.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (httpClient != null) {
+                try {
+                    httpClient.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return httpStatus;
+    }
+
+    public int postResourceFirexml(String url, String requestXML) {
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        CloseableHttpResponse response = null;
+        int httpStatus = 500;
+        try {
+            InputStreamEntity reqEntity = new InputStreamEntity(new ByteArrayInputStream(requestXML.getBytes()));
+            reqEntity.setContentType("application/xml");
+            reqEntity.setContentEncoding("utf-8");
+            reqEntity.setChunked(true);
+            HttpUriRequest request = RequestBuilder.post()
+                    .setUri(url)
+                    .setEntity(reqEntity)
+                    .setHeader("Content-Type", "application/xml")
+                    .setHeader("requestType", CommonUtil.getConfValueByKey("fire_requestType"))
+                    .setHeader("serviceID", CommonUtil.getConfValueByKey("fire_serviceId"))
+                    .setHeader("secretKey", CommonUtil.getConfValueByKey("fire_secretKey"))
+                    .build();
+            LOG.info("请求星火服务注册接口,url:{}", url);
+            response = httpClient.execute(request);
+            httpStatus = response.getStatusLine().getStatusCode();
+            LOG.info("响应码:{}", httpStatus);
+        } catch (Exception e) {
+            LOG.error("url:" + url + "请求出错!", e);
+            e.printStackTrace();
+        }finally {
+            if (response != null) {
+                try {
+                    response.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (httpClient != null) {
+                try {
+                    httpClient.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return httpStatus;
+    }
+
+
+    /**
+     * 发送PUT请求 <功能详细描述>
+     *
+     * @param url	路径
+     * @param requestXML	消息体
+     * @return
+     * @throws UnsupportedEncodingException
+     * @see [类、类#方法、类#成员]
+     */
+    public int putResourceXHxml(String url, String requestXML) {
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        CloseableHttpResponse response = null;
+        int httpStatus = 500;
+        try {
+            InputStreamEntity reqEntity = new InputStreamEntity(new ByteArrayInputStream(requestXML.getBytes()));
+            reqEntity.setContentType("application/xml");
+            reqEntity.setContentEncoding("utf-8");
+            reqEntity.setChunked(true);
+            HttpUriRequest request = RequestBuilder.put()
+                    .setUri(url)
+                    .setEntity(reqEntity)
+                    .setHeader("Content-Type", "application/xml")
+                    .setHeader("requestType", CommonUtil.getConfValueByKey("XH_requestType"))
+                    .setHeader("serviceID", CommonUtil.getConfValueByKey("XH_serviceId"))
+                    .setHeader("secretKey", CommonUtil.getConfValueByKey("XH_secretKey"))
+                    .build();
+            LOG.info("请求星火服务续约接口,url:{}", url);
+            response = httpClient.execute(request);
+            httpStatus = response.getStatusLine().getStatusCode();
+            LOG.info("响应码:{}", httpStatus);
+        } catch (Exception e) {
+            LOG.error("url:" + url + "请求出错!", e);
+            e.printStackTrace();
+        }finally {
+            if (response != null) {
+                try {
+                    response.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (httpClient != null) {
+                try {
+                    httpClient.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return httpStatus;
+    }
+
+    public int putResourceFirexml(String url, String requestXML) {
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        CloseableHttpResponse response = null;
+        int httpStatus = 500;
+        try {
+            InputStreamEntity reqEntity = new InputStreamEntity(new ByteArrayInputStream(requestXML.getBytes()));
+            reqEntity.setContentType("application/xml");
+            reqEntity.setContentEncoding("utf-8");
+            reqEntity.setChunked(true);
+            HttpUriRequest request = RequestBuilder.put()
+                    .setUri(url)
+                    .setEntity(reqEntity)
+                    .setHeader("Content-Type", "application/xml")
+                    .setHeader("requestType", CommonUtil.getConfValueByKey("fire_requestType"))
+                    .setHeader("serviceID", CommonUtil.getConfValueByKey("fire_serviceId"))
+                    .setHeader("secretKey", CommonUtil.getConfValueByKey("fire_secretKey"))
+                    .build();
+            LOG.info("请求星火服务续约接口,url:{}", url);
+            response = httpClient.execute(request);
+            httpStatus = response.getStatusLine().getStatusCode();
+            LOG.info("响应码:{}", httpStatus);
+        } catch (Exception e) {
+            LOG.error("url:" + url + "请求出错!", e);
+            e.printStackTrace();
+        }finally {
+            if (response != null) {
+                try {
+                    response.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (httpClient != null) {
+                try {
+                    httpClient.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return httpStatus;
+    }
+
+    public String postResourceFWKFPT(String url, List<NameValuePair> nameValuePairs, Map<String, Object> headerParamsMap) {
+        HttpPost postMethod = new HttpPost(url);
+        postMethod.setConfig(this.requestConfig);
+
+        if(headerParamsMap != null && headerParamsMap.size() > 0){
+            Set<String> keys = headerParamsMap.keySet();
+            for (String key : keys) {
+                postMethod.setHeader(key, headerParamsMap.get(key).toString());
+            }
+        }
+
+        CloseableHttpResponse response = null;
+        String content = null;
+        try {
+            postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs, "utf-8"));
+            response = this.httpClient.execute(postMethod);
+            int httpStatus = response.getStatusLine().getStatusCode();
+            if (httpStatus != HttpStatus.SC_OK) {
+                // 返回的是失败响应
+                LOG.error(
+                        String.format("Failed to execute post method '%s', caused by: it's response statuscode is %d!",
+                                url, httpStatus));
+            }
+            HttpEntity entity = response.getEntity();
+            if (entity != null) {
+                content = EntityUtils.toString(entity, "UTF-8");
+                EntityUtils.consume(entity);
+            }
+        } catch (Exception e) {
+            LOG.error("url:" + url + "请求出错!", e);
+            e.printStackTrace();
+        } finally {
+            if (response != null) {
+                try {
+                    response.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            postMethod.releaseConnection();
+        }
+        return content;
+    }
+
+
+
+    /**
+     * 发送GET请求 <功能详细描述>
+     *
+     * @param url	get请求的url
+     * @return
+     * @see [类、类#方法、类#成员]
+     */
+    public String sendGetRequst(String url, Map<String, Object> headerParamsMap) {
+        HttpGet httpGet = new HttpGet(url);
+        if(headerParamsMap != null && headerParamsMap.size() > 0){
+            Set<String> keys = headerParamsMap.keySet();
+            for (String key : keys) {
+                httpGet.setHeader(key, headerParamsMap.get(key).toString());
+            }
+        }
+        CloseableHttpResponse response = null;
+        String content = null;
+        // 执行get请求
+        try {
+            response = this.httpClient.execute(httpGet);
+            HttpEntity entity = response.getEntity();
+            // 打印响应状态
+            int httpStatus = response.getStatusLine().getStatusCode();
+            if (httpStatus != HttpStatus.SC_OK) {
+                // 返回的是失败响应
+                LOG.error(
+                        String.format("Failed to execute post method '%s', caused by: it's response statuscode is %d!",
+                                url, httpStatus));
+            }
+            if (null != entity) {
+                // 打印响应内容长度
+                // 打印响应内容
+                content = EntityUtils.toString(entity);
+                EntityUtils.consume(entity); // 关闭资源
+            }
+        } catch (IOException e) {
+            LOG.error("url:" + url + "请求出错!", e);
+            e.printStackTrace();
+        } finally {
+            if (response != null) {
+                try {
+                    response.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    LOG.error("", e);
+                }
+            }
+            httpGet.releaseConnection();
+        }
+        return content;
+    }
+
+}

+ 94 - 0
src/main/java/com/hhwy/qbeqsjy/common/HttpStatus.java

@@ -0,0 +1,94 @@
+package com.hhwy.qbeqsjy.common;
+
+/**
+ * 返回状态码
+ * 
+ * @author ruoyi
+ */
+public class HttpStatus
+{
+    /**
+     * 操作成功
+     */
+    public static final int SUCCESS = 200;
+
+    /**
+     * 对象创建成功
+     */
+    public static final int CREATED = 201;
+
+    /**
+     * 请求已经被接受
+     */
+    public static final int ACCEPTED = 202;
+
+    /**
+     * 操作已经执行成功,但是没有返回数据
+     */
+    public static final int NO_CONTENT = 204;
+
+    /**
+     * 资源已被移除
+     */
+    public static final int MOVED_PERM = 301;
+
+    /**
+     * 重定向
+     */
+    public static final int SEE_OTHER = 303;
+
+    /**
+     * 资源没有被修改
+     */
+    public static final int NOT_MODIFIED = 304;
+
+    /**
+     * 参数列表错误(缺少,格式不匹配)
+     */
+    public static final int BAD_REQUEST = 400;
+
+    /**
+     * 未授权
+     */
+    public static final int UNAUTHORIZED = 401;
+
+    /**
+     * 访问受限,授权过期
+     */
+    public static final int FORBIDDEN = 403;
+
+    /**
+     * 资源,服务未找到
+     */
+    public static final int NOT_FOUND = 404;
+
+    /**
+     * 不允许的http方法
+     */
+    public static final int BAD_METHOD = 405;
+
+    /**
+     * 资源冲突,或者资源被锁
+     */
+    public static final int CONFLICT = 409;
+
+    /**
+     * 不支持的数据,媒体类型
+     */
+    public static final int UNSUPPORTED_TYPE = 415;
+
+    /**
+     * 系统内部错误
+     */
+    public static final int ERROR = 500;
+
+    /**
+     * 接口未实现
+     */
+    public static final int NOT_IMPLEMENTED = 501;
+
+    /**
+     * 系统警告消息
+     */
+    public static final int WARN = 601;
+}

+ 55 - 0
src/main/java/com/hhwy/qbeqsjy/common/HttpsClient.java

@@ -0,0 +1,55 @@
+package com.hhwy.qbeqsjy.common;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public class HttpsClient {
+
+    /**
+     * 发送post请求
+     * @param url
+     * @param paramsMap
+     * @param charset
+     * @return
+     */
+    public String sendPost(String url, Map<String, String> paramsMap, String charset){
+        HttpClient httpClient = null;
+        HttpPost httpPost = null;
+        String result = null;
+        try{
+            httpClient = new SSLClient();
+            httpPost = new HttpPost(url);
+            ArrayList<NameValuePair> list = new ArrayList<>();
+            Iterator iterator = paramsMap.entrySet().iterator();
+            while (iterator.hasNext()){
+                Entry<String, String> elem = (Entry<String, String>) iterator.next();
+                list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
+            }
+            if(list.size() > 0){
+                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, charset);
+                httpPost.setEntity(entity);
+            }
+            HttpResponse response = httpClient.execute(httpPost);
+            if(response != null){
+                HttpEntity resEntity = response.getEntity();
+                if(resEntity != null){
+                    result = EntityUtils.toString(resEntity, charset);
+                }
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return result;
+    }
+}

+ 43 - 0
src/main/java/com/hhwy/qbeqsjy/common/SSLClient.java

@@ -0,0 +1,43 @@
+package com.hhwy.qbeqsjy.common;
+
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.impl.client.DefaultHttpClient;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+
+public class SSLClient extends DefaultHttpClient {
+
+    public SSLClient() throws Exception{
+        super();
+        SSLContext ctx = SSLContext.getInstance("TLSv1.2");
+        X509TrustManager tm = new X509TrustManager(){
+
+            @Override
+            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
+            }
+
+            @Override
+            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
+            }
+
+            @Override
+            public X509Certificate[] getAcceptedIssuers() {
+                return null;
+            }
+        };
+        ctx.init(null, new TrustManager[]{tm}, null);
+        SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+        ClientConnectionManager ccm = this.getConnectionManager();
+        SchemeRegistry sr = ccm.getSchemeRegistry();
+        sr.register(new Scheme("https", 443, ssf));
+
+    }
+}

+ 217 - 0
src/main/java/com/hhwy/qbeqsjy/common/ServletUtils.java

@@ -0,0 +1,217 @@
+package com.hhwy.qbeqsjy.common;
+
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 客户端工具类
+ * 
+ * @author ruoyi
+ */
+public class ServletUtils
+{
+    /**
+     * 获取String参数
+     */
+    public static String getParameter(String name)
+    {
+        return getRequest().getParameter(name);
+    }
+
+    /**
+     * 获取String参数
+     */
+    public static String getParameter(String name, String defaultValue)
+    {
+        return Convert.toStr(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取Integer参数
+     */
+    public static Integer getParameterToInt(String name)
+    {
+        return Convert.toInt(getRequest().getParameter(name));
+    }
+
+    /**
+     * 获取Integer参数
+     */
+    public static Integer getParameterToInt(String name, Integer defaultValue)
+    {
+        return Convert.toInt(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取Boolean参数
+     */
+    public static Boolean getParameterToBool(String name)
+    {
+        return Convert.toBool(getRequest().getParameter(name));
+    }
+
+    /**
+     * 获取Boolean参数
+     */
+    public static Boolean getParameterToBool(String name, Boolean defaultValue)
+    {
+        return Convert.toBool(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获得所有请求参数
+     *
+     * @param request 请求对象{@link ServletRequest}
+     * @return Map
+     */
+    public static Map<String, String[]> getParams(ServletRequest request)
+    {
+        final Map<String, String[]> map = request.getParameterMap();
+        return Collections.unmodifiableMap(map);
+    }
+
+    /**
+     * 获得所有请求参数
+     *
+     * @param request 请求对象{@link ServletRequest}
+     * @return Map
+     */
+    public static Map<String, String> getParamMap(ServletRequest request)
+    {
+        Map<String, String> params = new HashMap<>();
+        for (Map.Entry<String, String[]> entry : getParams(request).entrySet())
+        {
+            params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
+        }
+        return params;
+    }
+
+    /**
+     * 获取request
+     */
+    public static HttpServletRequest getRequest()
+    {
+        return getRequestAttributes().getRequest();
+    }
+
+    /**
+     * 获取response
+     */
+    public static HttpServletResponse getResponse()
+    {
+        return getRequestAttributes().getResponse();
+    }
+
+    /**
+     * 获取session
+     */
+    public static HttpSession getSession()
+    {
+        return getRequest().getSession();
+    }
+
+    public static ServletRequestAttributes getRequestAttributes()
+    {
+        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
+        return (ServletRequestAttributes) attributes;
+    }
+
+    /**
+     * 将字符串渲染到客户端
+     * 
+     * @param response 渲染对象
+     * @param string 待渲染的字符串
+     */
+    public static void renderString(HttpServletResponse response, String string)
+    {
+        try
+        {
+            response.setStatus(200);
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+            response.getWriter().print(string);
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 是否是Ajax异步请求
+     * 
+     * @param request
+     */
+    public static boolean isAjaxRequest(HttpServletRequest request)
+    {
+        String accept = request.getHeader("accept");
+        if (accept != null && accept.contains("application/json"))
+        {
+            return true;
+        }
+
+        String xRequestedWith = request.getHeader("X-Requested-With");
+        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest"))
+        {
+            return true;
+        }
+
+        String uri = request.getRequestURI();
+        if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
+        {
+            return true;
+        }
+
+        String ajax = request.getParameter("__ajax");
+        return StringUtils.inStringIgnoreCase(ajax, "json", "xml");
+    }
+
+    /**
+     * 内容编码
+     * 
+     * @param str 内容
+     * @return 编码后的内容
+     */
+    public static String urlEncode(String str)
+    {
+        try
+        {
+            return URLEncoder.encode(str, Constants.UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return StringUtils.EMPTY;
+        }
+    }
+
+    /**
+     * 内容解码
+     * 
+     * @param str 内容
+     * @return 解码后的内容
+     */
+    public static String urlDecode(String str)
+    {
+        try
+        {
+            return URLDecoder.decode(str, Constants.UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return StringUtils.EMPTY;
+        }
+    }
+}

+ 90 - 0
src/main/java/com/hhwy/qbeqsjy/common/StrFormatter.java

@@ -0,0 +1,90 @@
+package com.hhwy.qbeqsjy.common;
+
+/**
+ * 字符串格式化
+ * 
+ * @author ruoyi
+ */
+public class StrFormatter
+{
+    public static final String EMPTY_JSON = "{}";
+    public static final char C_BACKSLASH = '\\';
+    public static final char C_DELIM_START = '{';
+    public static final char C_DELIM_END = '}';
+
+    /**
+     * 格式化字符串<br>
+     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
+     * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
+     * 例:<br>
+     * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     * 
+     * @param strPattern 字符串模板
+     * @param argArray 参数列表
+     * @return 结果
+     */
+    public static String format(final String strPattern, final Object... argArray)
+    {
+        if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
+        {
+            return strPattern;
+        }
+        final int strPatternLength = strPattern.length();
+
+        // 初始化定义好的长度以获得更好的性能
+        StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
+
+        int handledPosition = 0;
+        int delimIndex;// 占位符所在位置
+        for (int argIndex = 0; argIndex < argArray.length; argIndex++)
+        {
+            delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
+            if (delimIndex == -1)
+            {
+                if (handledPosition == 0)
+                {
+                    return strPattern;
+                }
+                else
+                { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
+                    sbuf.append(strPattern, handledPosition, strPatternLength);
+                    return sbuf.toString();
+                }
+            }
+            else
+            {
+                if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
+                {
+                    if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
+                    {
+                        // 转义符之前还有一个转义符,占位符依旧有效
+                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
+                        sbuf.append(Convert.utf8Str(argArray[argIndex]));
+                        handledPosition = delimIndex + 2;
+                    }
+                    else
+                    {
+                        // 占位符被转义
+                        argIndex--;
+                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
+                        sbuf.append(C_DELIM_START);
+                        handledPosition = delimIndex + 1;
+                    }
+                }
+                else
+                {
+                    // 正常占位符
+                    sbuf.append(strPattern, handledPosition, delimIndex);
+                    sbuf.append(Convert.utf8Str(argArray[argIndex]));
+                    handledPosition = delimIndex + 2;
+                }
+            }
+        }
+        // 加入最后一个占位符后所有的字符
+        sbuf.append(strPattern, handledPosition, strPattern.length());
+
+        return sbuf.toString();
+    }
+}

+ 678 - 0
src/main/java/com/hhwy/qbeqsjy/common/StringUtils.java

@@ -0,0 +1,678 @@
+package com.hhwy.qbeqsjy.common;
+
+import org.springframework.util.AntPathMatcher;
+
+import java.util.*;
+
+/**
+ * 字符串工具类
+ * 
+ * @author ruoyi
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+    /** 空字符串 */
+    private static final String NULLSTR = "";
+
+    /** 下划线 */
+    private static final char SEPARATOR = '_';
+
+    /** 星号 */
+    private static final char ASTERISK = '*';
+
+    /**
+     * 获取参数不为空值
+     * 
+     * @param value defaultValue 要判断的value
+     * @return value 返回值
+     */
+    public static <T> T nvl(T value, T defaultValue)
+    {
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * * 判断一个Collection是否为空, 包含List,Set,Queue
+     * 
+     * @param coll 要判断的Collection
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Collection<?> coll)
+    {
+        return isNull(coll) || coll.isEmpty();
+    }
+
+    /**
+     * * 判断一个Collection是否非空,包含List,Set,Queue
+     * 
+     * @param coll 要判断的Collection
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Collection<?> coll)
+    {
+        return !isEmpty(coll);
+    }
+
+    /**
+     * * 判断一个对象数组是否为空
+     * 
+     * @param objects 要判断的对象数组
+     ** @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Object[] objects)
+    {
+        return isNull(objects) || (objects.length == 0);
+    }
+
+    /**
+     * * 判断一个对象数组是否非空
+     * 
+     * @param objects 要判断的对象数组
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Object[] objects)
+    {
+        return !isEmpty(objects);
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     * 
+     * @param map 要判断的Map
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Map<?, ?> map)
+    {
+        return isNull(map) || map.isEmpty();
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     * 
+     * @param map 要判断的Map
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Map<?, ?> map)
+    {
+        return !isEmpty(map);
+    }
+
+    /**
+     * * 判断一个字符串是否为空串
+     * 
+     * @param str String
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(String str)
+    {
+        return isNull(str) || NULLSTR.equals(str.trim());
+    }
+
+    /**
+     * * 判断一个字符串是否为非空串
+     * 
+     * @param str String
+     * @return true:非空串 false:空串
+     */
+    public static boolean isNotEmpty(String str)
+    {
+        return !isEmpty(str);
+    }
+
+    /**
+     * * 判断一个对象是否为空
+     * 
+     * @param object Object
+     * @return true:为空 false:非空
+     */
+    public static boolean isNull(Object object)
+    {
+        return object == null;
+    }
+
+    /**
+     * * 判断一个对象是否非空
+     * 
+     * @param object Object
+     * @return true:非空 false:空
+     */
+    public static boolean isNotNull(Object object)
+    {
+        return !isNull(object);
+    }
+
+    /**
+     * * 判断一个对象是否是数组类型(Java基本型别的数组)
+     * 
+     * @param object 对象
+     * @return true:是数组 false:不是数组
+     */
+    public static boolean isArray(Object object)
+    {
+        return isNotNull(object) && object.getClass().isArray();
+    }
+
+    /**
+     * 去空格
+     */
+    public static String trim(String str)
+    {
+        return (str == null ? "" : str.trim());
+    }
+
+    /**
+     * 替换指定字符串的指定区间内字符为"*"
+     *
+     * @param str 字符串
+     * @param startInclude 开始位置(包含)
+     * @param endExclude 结束位置(不包含)
+     * @return 替换后的字符串
+     */
+    public static String hide(CharSequence str, int startInclude, int endExclude)
+    {
+        if (isEmpty(str))
+        {
+            return NULLSTR;
+        }
+        final int strLength = str.length();
+        if (startInclude > strLength)
+        {
+            return NULLSTR;
+        }
+        if (endExclude > strLength)
+        {
+            endExclude = strLength;
+        }
+        if (startInclude > endExclude)
+        {
+            // 如果起始位置大于结束位置,不替换
+            return NULLSTR;
+        }
+        final char[] chars = new char[strLength];
+        for (int i = 0; i < strLength; i++)
+        {
+            if (i >= startInclude && i < endExclude)
+            {
+                chars[i] = ASTERISK;
+            }
+            else
+            {
+                chars[i] = str.charAt(i);
+            }
+        }
+        return new String(chars);
+    }
+
+    /**
+     * 截取字符串
+     * 
+     * @param str 字符串
+     * @param start 开始
+     * @return 结果
+     */
+    public static String substring(final String str, int start)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (start > str.length())
+        {
+            return NULLSTR;
+        }
+
+        return str.substring(start);
+    }
+
+    /**
+     * 截取字符串
+     * 
+     * @param str 字符串
+     * @param start 开始
+     * @param end 结束
+     * @return 结果
+     */
+    public static String substring(final String str, int start, int end)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (end < 0)
+        {
+            end = str.length() + end;
+        }
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (end > str.length())
+        {
+            end = str.length();
+        }
+
+        if (start > end)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (end < 0)
+        {
+            end = 0;
+        }
+
+        return str.substring(start, end);
+    }
+
+    /**
+     * 判断是否为空,并且不是空白字符
+     * 
+     * @param str 要判断的value
+     * @return 结果
+     */
+    public static boolean hasText(String str)
+    {
+        return (str != null && !str.isEmpty() && containsText(str));
+    }
+
+    private static boolean containsText(CharSequence str)
+    {
+        int strLen = str.length();
+        for (int i = 0; i < strLen; i++)
+        {
+            if (!Character.isWhitespace(str.charAt(i)))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 格式化文本, {} 表示占位符<br>
+     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
+     * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
+     * 例:<br>
+     * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     * 
+     * @param template 文本模板,被替换的部分用 {} 表示
+     * @param params 参数值
+     * @return 格式化后的文本
+     */
+    public static String format(String template, Object... params)
+    {
+        if (isEmpty(params) || isEmpty(template))
+        {
+            return template;
+        }
+        return StrFormatter.format(template, params);
+    }
+
+    /**
+     * 是否为http(s)://开头
+     * 
+     * @param link 链接
+     * @return 结果
+     */
+    public static boolean ishttp(String link)
+    {
+        return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
+    }
+
+    /**
+     * 字符串转set
+     * 
+     * @param str 字符串
+     * @param sep 分隔符
+     * @return set集合
+     */
+    public static final Set<String> str2Set(String str, String sep)
+    {
+        return new HashSet<String>(str2List(str, sep, true, false));
+    }
+
+    /**
+     * 字符串转list
+     * 
+     * @param str 字符串
+     * @param sep 分隔符
+     * @param filterBlank 过滤纯空白
+     * @param trim 去掉首尾空白
+     * @return list集合
+     */
+    public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
+    {
+        List<String> list = new ArrayList<String>();
+        if (StringUtils.isEmpty(str))
+        {
+            return list;
+        }
+
+        // 过滤空白字符串
+        if (filterBlank && StringUtils.isBlank(str))
+        {
+            return list;
+        }
+        String[] split = str.split(sep);
+        for (String string : split)
+        {
+            if (filterBlank && StringUtils.isBlank(string))
+            {
+                continue;
+            }
+            if (trim)
+            {
+                string = string.trim();
+            }
+            list.add(string);
+        }
+
+        return list;
+    }
+
+    /**
+     * 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
+     *
+     * @param collection 给定的集合
+     * @param array 给定的数组
+     * @return boolean 结果
+     */
+    public static boolean containsAny(Collection<String> collection, String... array)
+    {
+        if (isEmpty(collection) || isEmpty(array))
+        {
+            return false;
+        }
+        else
+        {
+            for (String str : array)
+            {
+                if (collection.contains(str))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
+     *
+     * @param cs 指定字符串
+     * @param searchCharSequences 需要检查的字符串数组
+     * @return 是否包含任意一个字符串
+     */
+    public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
+    {
+        if (isEmpty(cs) || isEmpty(searchCharSequences))
+        {
+            return false;
+        }
+        for (CharSequence testStr : searchCharSequences)
+        {
+            if (containsIgnoreCase(cs, testStr))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 驼峰转下划线命名
+     */
+    public static String toUnderScoreCase(String str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        // 前置字符是否大写
+        boolean preCharIsUpperCase = true;
+        // 当前字符是否大写
+        boolean curreCharIsUpperCase = true;
+        // 下一字符是否大写
+        boolean nexteCharIsUpperCase = true;
+        for (int i = 0; i < str.length(); i++)
+        {
+            char c = str.charAt(i);
+            if (i > 0)
+            {
+                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
+            }
+            else
+            {
+                preCharIsUpperCase = false;
+            }
+
+            curreCharIsUpperCase = Character.isUpperCase(c);
+
+            if (i < (str.length() - 1))
+            {
+                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
+            }
+
+            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 是否包含字符串
+     * 
+     * @param str 验证字符串
+     * @param strs 字符串组
+     * @return 包含返回true
+     */
+    public static boolean inStringIgnoreCase(String str, String... strs)
+    {
+        if (str != null && strs != null)
+        {
+            for (String s : strs)
+            {
+                if (str.equalsIgnoreCase(trim(s)))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
+     * 
+     * @param name 转换前的下划线大写方式命名的字符串
+     * @return 转换后的驼峰式命名的字符串
+     */
+    public static String convertToCamelCase(String name)
+    {
+        StringBuilder result = new StringBuilder();
+        // 快速检查
+        if (name == null || name.isEmpty())
+        {
+            // 没必要转换
+            return "";
+        }
+        else if (!name.contains("_"))
+        {
+            // 不含下划线,仅将首字母大写
+            return name.substring(0, 1).toUpperCase() + name.substring(1);
+        }
+        // 用下划线将原始字符串分割
+        String[] camels = name.split("_");
+        for (String camel : camels)
+        {
+            // 跳过原始字符串中开头、结尾的下换线或双重下划线
+            if (camel.isEmpty())
+            {
+                continue;
+            }
+            // 首字母大写
+            result.append(camel.substring(0, 1).toUpperCase());
+            result.append(camel.substring(1).toLowerCase());
+        }
+        return result.toString();
+    }
+
+    /**
+     * 驼峰式命名法
+     * 例如:user_name->userName
+     */
+    public static String toCamelCase(String s)
+    {
+        if (s == null)
+        {
+            return null;
+        }
+        if (s.indexOf(SEPARATOR) == -1)
+        {
+            return s;
+        }
+        s = s.toLowerCase();
+        StringBuilder sb = new StringBuilder(s.length());
+        boolean upperCase = false;
+        for (int i = 0; i < s.length(); i++)
+        {
+            char c = s.charAt(i);
+
+            if (c == SEPARATOR)
+            {
+                upperCase = true;
+            }
+            else if (upperCase)
+            {
+                sb.append(Character.toUpperCase(c));
+                upperCase = false;
+            }
+            else
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
+     * 
+     * @param str 指定字符串
+     * @param strs 需要检查的字符串数组
+     * @return 是否匹配
+     */
+    public static boolean matches(String str, List<String> strs)
+    {
+        if (isEmpty(str) || isEmpty(strs))
+        {
+            return false;
+        }
+        for (String pattern : strs)
+        {
+            if (isMatch(pattern, str))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 判断url是否与规则配置: 
+     * ? 表示单个字符; 
+     * * 表示一层路径内的任意字符串,不可跨层级; 
+     * ** 表示任意层路径;
+     * 
+     * @param pattern 匹配规则
+     * @param url 需要匹配的url
+     * @return
+     */
+    public static boolean isMatch(String pattern, String url)
+    {
+        AntPathMatcher matcher = new AntPathMatcher();
+        return matcher.match(pattern, url);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T cast(Object obj)
+    {
+        return (T) obj;
+    }
+
+    /**
+     * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
+     * 
+     * @param num 数字对象
+     * @param size 字符串指定长度
+     * @return 返回数字的字符串格式,该字符串为指定长度。
+     */
+    public static final String padl(final Number num, final int size)
+    {
+        return padl(num.toString(), size, '0');
+    }
+
+    /**
+     * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
+     * 
+     * @param s 原始字符串
+     * @param size 字符串指定长度
+     * @param c 用于补齐的字符
+     * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
+     */
+    public static final String padl(final String s, final int size, final char c)
+    {
+        final StringBuilder sb = new StringBuilder(size);
+        if (s != null)
+        {
+            final int len = s.length();
+            if (s.length() <= size)
+            {
+                for (int i = size - len; i > 0; i--)
+                {
+                    sb.append(c);
+                }
+                sb.append(s);
+            }
+            else
+            {
+                return s.substring(len - size, len);
+            }
+        }
+        else
+        {
+            for (int i = size; i > 0; i--)
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+}

+ 117 - 0
src/main/java/com/hhwy/qbeqsjy/common/TimeTool.java

@@ -0,0 +1,117 @@
+package com.hhwy.qbeqsjy.common;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author YHG 20181101
+ */
+public class TimeTool {
+
+
+	
+	/**
+	 * 获取当前时间的绝对秒
+	 * @return nowTimeStamp
+	 */
+	public static Long getNowTimeStamp(){
+		Date date = new Date();
+		Long nowTimeStamp = date.getTime() / Constants.NUM_1000;
+		return nowTimeStamp;
+	}
+	
+	/**
+	 * 获取今天0点0分0秒的绝对秒
+	 * @return todayStartTimeStamp
+	 */
+	public static Long getTodayStartTimeStamp(){
+		Date date = new Date();
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+		String todayDate = sdf.format(date);
+		Long todayStartTimeStamp = Constants.NUM_1539100800;
+		try {
+			todayStartTimeStamp = sdf.parse(todayDate).getTime() / Constants.NUM_1000;
+		} catch (ParseException e) {
+			e.printStackTrace();
+		}
+		return todayStartTimeStamp;
+	}
+	
+	/**
+	 * 获取从当前时间向前推若干天的绝对秒
+	 * @param days 向前推的天数
+	 * @return
+	 */
+	public static Long getTimeStampBeforeToday(int days){
+		Calendar c = Calendar.getInstance();
+		c.add(Calendar.DAY_OF_YEAR, -days);
+		return c.getTimeInMillis() / Constants.NUM_1000;
+	}
+	
+	/**
+	 * 将绝对秒转换为时间字符串(时间字符串格式为yyyy-MM-dd HH:mm:ss)
+	 * @param timeStamp 绝对秒
+	 * @return dateString 时间字符串
+	 */
+	public static String timeStampToDateString(Long timeStamp) {
+	    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+	    String dateString = sdf.format(timeStamp * Constants.NUM_1000);
+	    return dateString;
+	}
+
+	/**
+	 * 将绝对秒转换为时间字符串(时间字符串格式为yyyy-MM-dd)
+	 * @param timeStamp 绝对秒
+	 * @return dateString 时间字符串
+	 */
+	public static String timeStampToDateString2(Long timeStamp) {
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+		String dateString = sdf.format(timeStamp * Constants.NUM_1000);
+		return dateString;
+	}
+
+	public static String timeStampToDateString3(Long timeStamp) {
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+		String dateString = sdf.format(timeStamp * Constants.NUM_1000);
+		return dateString;
+	}
+	
+	/**
+	 * 将时间字符串转换为绝对秒(时间字符串格式为yyyy-MM-dd HH:mm:ss)
+	 * @param dateString 时间字符串
+	 * @return timeStamp 绝对秒
+	 */
+	public static int dateStringToTimeStamp(String dateString){
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+		Date date = null;
+		try {
+			date = sdf.parse(dateString);
+		} catch (ParseException e) {
+			e.printStackTrace();
+			return 0;
+		}
+		int timeStamp = (int) (date.getTime() / Constants.NUM_1000);
+		return timeStamp;
+	}
+
+	/**
+	 * 将时间字符串转换为绝对秒(时间字符串格式为yyyyMMdd)
+	 * @param dateString 时间字符串
+	 * @return timeStamp 绝对秒
+	 */
+	public static int dateStringToTimeStamp2(String dateString){
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+		Date date = null;
+		try {
+			date = sdf.parse(dateString);
+		} catch (ParseException e) {
+			e.printStackTrace();
+			return 0;
+		}
+		int timeStamp = (int) (date.getTime() / Constants.NUM_1000);
+		return timeStamp;
+	}
+	
+}

+ 69 - 0
src/main/java/com/hhwy/qbeqsjy/controller/CtrlController.java

@@ -0,0 +1,69 @@
+package com.hhwy.qbeqsjy.controller;
+
+import com.hhwy.qbeqsjy.common.Constants;
+import com.hhwy.qbeqsjy.domain.AjaxResult;
+import com.hhwy.qbeqsjy.dto.BusinessDTO;
+import com.hhwy.qbeqsjy.service.CtrlService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+
+
+@Slf4j
+@RestController
+@RequestMapping("/api/v1/ctrl")
+public class CtrlController {
+
+    @Value("${clue.type.list}")
+    private String accountTypeList;
+    @Value("${sys.id.list}")
+    private String sysIdList;
+    @Autowired
+    private CtrlService ctrlService;
+
+
+    /**
+     * 下发布控任务
+     * @param businessDTO
+     * @return
+     */
+    @PostMapping("/submitCtrlTask")
+    public AjaxResult submitCtrlTask(@RequestBody BusinessDTO businessDTO){
+        String taskId = businessDTO.getTaskId();
+        String account = businessDTO.getAccount();
+        String accountType = businessDTO.getAccountType();
+        String sysId = businessDTO.getSysId();
+        if(StringUtils.isBlank(taskId) || StringUtils.isBlank(account) || StringUtils.isBlank(accountType) || StringUtils.isBlank(sysId)){
+            return AjaxResult.error(Constants.PARAMS_EMPTY_MSG);
+        }
+        if(!accountTypeList.contains(accountType) || !sysIdList.contains(sysId)){
+            return AjaxResult.error(Constants.PARAMS_ILLEGAL_MSG);
+        }
+        return ctrlService.ctrl(businessDTO);
+    }
+
+
+    /**
+     * 停止布控任务
+     * @param businessDTO
+     * @return
+     */
+    @PostMapping("/stopCtrlTask")
+    public AjaxResult stopCtrlTask(@RequestBody BusinessDTO businessDTO){
+        String taskId = businessDTO.getTaskId();
+        String account = businessDTO.getAccount();
+        String accountType = businessDTO.getAccountType();
+        String sysId = businessDTO.getSysId();
+        if(StringUtils.isBlank(taskId) || StringUtils.isBlank(account) || StringUtils.isBlank(accountType) || StringUtils.isBlank(sysId)){
+            return AjaxResult.error(Constants.PARAMS_EMPTY_MSG);
+        }
+        if(!accountTypeList.contains(accountType) || !sysIdList.contains(sysId)){
+            return AjaxResult.error(Constants.PARAMS_ILLEGAL_MSG);
+        }
+        return ctrlService.stopCtrl(businessDTO);
+    }
+
+
+}

+ 216 - 0
src/main/java/com/hhwy/qbeqsjy/domain/AjaxResult.java

@@ -0,0 +1,216 @@
+package com.hhwy.qbeqsjy.domain;
+
+import java.util.HashMap;
+import java.util.Objects;
+import com.hhwy.qbeqsjy.common.StringUtils;
+import com.hhwy.qbeqsjy.common.HttpStatus;
+
+/**
+ * 操作消息提醒
+ * 
+ * @author ruoyi
+ */
+public class AjaxResult extends HashMap<String, Object>
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 状态码 */
+    public static final String CODE_TAG = "code";
+
+    /** 返回内容 */
+    public static final String MSG_TAG = "msg";
+
+    /** 数据对象 */
+    public static final String DATA_TAG = "data";
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
+     */
+    public AjaxResult()
+    {
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象
+     * 
+     * @param code 状态码
+     * @param msg 返回内容
+     */
+    public AjaxResult(int code, String msg)
+    {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+    }
+
+    /**
+     * 初始化一个新创建的 AjaxResult 对象
+     * 
+     * @param code 状态码
+     * @param msg 返回内容
+     * @param data 数据对象
+     */
+    public AjaxResult(int code, String msg, Object data)
+    {
+        super.put(CODE_TAG, code);
+        super.put(MSG_TAG, msg);
+        if (StringUtils.isNotNull(data))
+        {
+            super.put(DATA_TAG, data);
+        }
+    }
+
+    /**
+     * 返回成功消息
+     * 
+     * @return 成功消息
+     */
+    public static AjaxResult success()
+    {
+        return AjaxResult.success("操作成功");
+    }
+
+    /**
+     * 返回成功数据
+     * 
+     * @return 成功消息
+     */
+    public static AjaxResult success(Object data)
+    {
+        return AjaxResult.success("操作成功", data);
+    }
+
+    /**
+     * 返回成功消息
+     * 
+     * @param msg 返回内容
+     * @return 成功消息
+     */
+    public static AjaxResult success(String msg)
+    {
+        return AjaxResult.success(msg, null);
+    }
+
+    /**
+     * 返回成功消息
+     * 
+     * @param msg 返回内容
+     * @param data 数据对象
+     * @return 成功消息
+     */
+    public static AjaxResult success(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.SUCCESS, msg, data);
+    }
+
+    /**
+     * 返回警告消息
+     *
+     * @param msg 返回内容
+     * @return 警告消息
+     */
+    public static AjaxResult warn(String msg)
+    {
+        return AjaxResult.warn(msg, null);
+    }
+
+    /**
+     * 返回警告消息
+     *
+     * @param msg 返回内容
+     * @param data 数据对象
+     * @return 警告消息
+     */
+    public static AjaxResult warn(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.WARN, msg, data);
+    }
+
+    /**
+     * 返回错误消息
+     * 
+     * @return 错误消息
+     */
+    public static AjaxResult error()
+    {
+        return AjaxResult.error("操作失败");
+    }
+
+    /**
+     * 返回错误消息
+     * 
+     * @param msg 返回内容
+     * @return 错误消息
+     */
+    public static AjaxResult error(String msg)
+    {
+        return AjaxResult.error(msg, null);
+    }
+
+    /**
+     * 返回错误消息
+     * 
+     * @param msg 返回内容
+     * @param data 数据对象
+     * @return 错误消息
+     */
+    public static AjaxResult error(String msg, Object data)
+    {
+        return new AjaxResult(HttpStatus.ERROR, msg, data);
+    }
+
+    /**
+     * 返回错误消息
+     * 
+     * @param code 状态码
+     * @param msg 返回内容
+     * @return 错误消息
+     */
+    public static AjaxResult error(int code, String msg)
+    {
+        return new AjaxResult(code, msg, null);
+    }
+
+    /**
+     * 是否为成功消息
+     *
+     * @return 结果
+     */
+    public boolean isSuccess()
+    {
+        return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
+    }
+
+    /**
+     * 是否为警告消息
+     *
+     * @return 结果
+     */
+    public boolean isWarn()
+    {
+        return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
+    }
+
+    /**
+     * 是否为错误消息
+     *
+     * @return 结果
+     */
+    public boolean isError()
+    {
+        return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
+    }
+
+    /**
+     * 方便链式调用
+     *
+     * @param key 键
+     * @param value 值
+     * @return 数据对象
+     */
+    @Override
+    public AjaxResult put(String key, Object value)
+    {
+        super.put(key, value);
+        return this;
+    }
+}

+ 36 - 0
src/main/java/com/hhwy/qbeqsjy/dto/BusinessDTO.java

@@ -0,0 +1,36 @@
+package com.hhwy.qbeqsjy.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+/**
+ * 业务数据DTO对象
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class BusinessDTO {
+
+    // 任务编号
+    private String taskId;
+    // 线索值
+    private String account;
+    // 线索类型编码
+    private String accountType;
+    // 系统ID
+    private String sysId;
+    // 开始布控时间
+    private String startCtrlTime;
+    // 停止布控时间
+    private String endCtrlTime;
+    // 布控资源编码集合
+    private String resourceIdList;
+    // 布控区域编号集合
+    private String areaIdList;
+
+
+
+
+}

+ 284 - 0
src/main/java/com/hhwy/qbeqsjy/service/CtrlService.java

@@ -0,0 +1,284 @@
+package com.hhwy.qbeqsjy.service;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.hhwy.qbeqsjy.common.CommonUtil;
+import com.hhwy.qbeqsjy.common.Constants;
+import com.hhwy.qbeqsjy.common.HttpClient;
+import com.hhwy.qbeqsjy.common.TimeTool;
+import com.hhwy.qbeqsjy.domain.AjaxResult;
+import com.hhwy.qbeqsjy.dto.BusinessDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import java.util.HashMap;
+import java.util.Map;
+
+@Slf4j
+@Service
+public class CtrlService {
+
+    @Value("${from.areacode}")
+    private String fromAreaCode;
+    @Value("${to.areacode}")
+    private String toAreaCode;
+    @Value("${to.sys}")
+    private String toSys;
+    @Value("${end.ctrl.time}")
+    private String defaultEndCtrlTime;
+    @Value("${serv.ver}")
+    private String servVer;
+    @Value("${sysuserid}")
+    private String sysUserId;
+    @Value("${uniCtrl.add.url}")
+    private String uniCtrlAddUrl;
+    @Value("${uniCtrl.del.url}")
+    private String uniCtrlDelUrl;
+    @Value("${uniCtrl.query.url}")
+    private String uniCtrlQueryUrl;
+    private HttpClient httpClient = new HttpClient();
+
+
+    /**
+     * 调用烽火【统一布控】接口,下发布控任务
+     * @param businessDTO
+     * @return
+     */
+    public AjaxResult ctrl(BusinessDTO businessDTO){
+        String taskId = businessDTO.getTaskId();
+        String account = businessDTO.getAccount();
+        String accountType = businessDTO.getAccountType();
+        String clueIdSrc = fromAreaCode.concat(taskId).concat("_").concat(accountType).concat(account);
+        try{
+            // 1.调用布控接口,下发布控任务
+            JSONObject resJSONObj = doCtrl(httpClient, businessDTO);
+            String statusCode = resJSONObj.getString("statuscode");
+            String message = resJSONObj.getString("message");
+            if (Constants.CTRL_PROCESS_SUCESS.equals(statusCode)) {
+                // 2.布控请求处理成功(不代表实际布控成功,需查询线索布控状态信息)
+                String clueId = resJSONObj.getString("clue_id");
+                log.info("【布控请求处理成功】 clueId:{}", clueId);
+                // 3.查询线索实际布控状态
+                log.info("【查询线索布控状态】 clueId:{}", clueId);
+                String status = queryCtrlStatus(httpClient, businessDTO);
+                if(Constants.CTRL_SUCCESS.equals(status)){
+                    log.info("【线索布控状态: 成功】 clueId:{}", clueId);
+                    Map<String, Object> resultMap = new HashMap<>();
+                    resultMap.put("clueId", clueId);
+                    return AjaxResult.success(resultMap);
+                }else if(Constants.CTRL_TODO.equals(status)){
+                    log.info("【线索布控状态: 待布控】 clueId:{}", clueId);
+                    return AjaxResult.success(Constants.CTRL_TODO_MSG);
+                }else {
+                    log.info("【线索布控状态: 失败】 clueId: {}, 响应码:{}", clueId, status);
+                    return AjaxResult.error(Constants.CTRL_FAIL_MSG);
+                }
+            } else if (Constants.CTRL_EXIST.equals(statusCode)){
+                log.error("【线索已经在控,无需再次发起布控】 clueId:{}", clueIdSrc);
+                return AjaxResult.success(message);
+            } else {
+                // 如果布控请求处理失败,则直接返回异常信息,无需查询线索布控状态
+                log.error("【线索布控请求处理失败】 clueId:{}, 响应码:{}, 异常信息:{}", clueIdSrc, statusCode, message);
+                return AjaxResult.error(message);
+            }
+        } catch (Exception e){
+            log.error("【下发布控任务发生异常】 异常信息:", e);
+        }
+        return AjaxResult.error(Constants.SERVER_ERROR_MSG);
+    }
+
+
+    /**
+     * 调用烽火【统一布控】接口,下发停控任务
+     * @param businessDTO
+     * @return
+     */
+    public AjaxResult stopCtrl(BusinessDTO businessDTO){
+        String taskId = businessDTO.getTaskId();
+        String account = businessDTO.getAccount();
+        String accountType = businessDTO.getAccountType();
+        String clueIdSrc = fromAreaCode.concat(taskId).concat("_").concat(accountType).concat(account);
+        try{
+            // 调用停控接口
+            JSONObject responseJSONObj = doStopCtrl(httpClient, businessDTO);
+            String statusCode = responseJSONObj.getString("statuscode");
+            String message = responseJSONObj.getString("message");
+            if (Constants.CTRL_PROCESS_SUCESS.equals(statusCode)) {
+                String clueId = responseJSONObj.getString("clue_id");
+                log.info("【线索停控请求处理成功】 clueId:{}", clueId);
+                log.info("【查询线索停控状态】 clueId:{}", clueId);
+                String status = queryCtrlStatus(httpClient, businessDTO);
+                if(Constants.STOP_CTRL_SUCCESS.equals(status)){
+                    log.info("【线索停控状态: 成功】 clueId:{}", clueId);
+                    Map<String, Object> resultMap = new HashMap<>();
+                    resultMap.put("clueId", clueId);
+                    return AjaxResult.success(resultMap);
+                }else if(Constants.STOP_CTRL_TODO.equals(status)){
+                    log.info("【线索停控状态: 待停控】 clueId: {}", clueId);
+                    return AjaxResult.success(Constants.STOP_CTRL_TODO_MSG);
+                }else {
+                    log.info("【线索停控: 失败】 clueId: {}, 响应码:{}", clueId, status);
+                    return AjaxResult.error(Constants.STOP_CTRL_FAIL_MSG);
+                }
+            } else if (Constants.STOP_CTRL_EXIST.equals(statusCode)){
+                log.error("【线索已经停控,无需再次发起停控】 clueId:{}", clueIdSrc);
+                return AjaxResult.success(message);
+
+            } else {
+                // 如果停控请求处理失败,则直接返回异常信息,无需查询线索停控状态
+                log.error("【线索停控请求处理失败】 clueId:{}, 响应码:{}, 异常信息:{}", clueIdSrc, statusCode, message);
+                return AjaxResult.error(message);
+            }
+        } catch (Exception e){
+            log.error("【下发停控任务发生异常】 异常信息:", e);
+        }
+        return AjaxResult.error(Constants.SERVER_ERROR_MSG);
+    }
+
+
+    /**
+     * 调用烽火【统一布控】接口, 下发布控请求 - 布控失败时,重试3次
+     * @param httpClient
+     * @param businessDTO
+     * @return
+     */
+    public JSONObject doCtrl(HttpClient httpClient, BusinessDTO businessDTO) {
+        // 构建请求参数
+        String resourceIdList = businessDTO.getResourceIdList();
+        JSONObject params = new JSONObject();
+        // 将配置文件中的数据资源业务ID转换为烽火盘古平台数据资源编码
+        if(StringUtils.isNotBlank(resourceIdList) && resourceIdList.split(",").length > 0){
+            String[] resourceIdArray = resourceIdList.split(",");
+            String[] resourceCodeArray = new String[resourceIdArray.length];
+            for (int i = 0; i < resourceIdArray.length; i++) {
+                String resourceId = resourceIdArray[i];
+                String resourceCode = CommonUtil.getConfValueByKey(resourceId);
+                if(StringUtils.isNotBlank(resourceCode)){
+                    resourceCodeArray[i] = resourceCode;
+                }
+            }
+            params.put("resid_list", resourceCodeArray);
+        } else {
+            throw new RuntimeException("待布控数据资源列表为空,布控任务下发失败");
+        }
+        String taskId = businessDTO.getTaskId();
+        String account = businessDTO.getAccount();
+        String accountType = businessDTO.getAccountType();
+        String clueId = fromAreaCode.concat(taskId).concat("_").concat(accountType).concat(account);
+        String sysId = businessDTO.getSysId();
+        String endCtrlTime = businessDTO.getEndCtrlTime();
+
+        params.put("clue_id", clueId);
+        params.put("from_areacode", fromAreaCode);
+        params.put("to_areacode", JSONArray.parseArray(toAreaCode));
+        params.put("from_sys", sysId);
+        params.put("to_sys", JSONArray.parseArray(toSys));
+        params.put("sysuserid", sysUserId);
+        params.put("serv_ver", servVer);
+        params.put("property_type", accountType);
+        params.put("property_value", account);
+        if(StringUtils.isNotBlank(endCtrlTime)){
+            params.put("end_ctrl_time", TimeTool.dateStringToTimeStamp(endCtrlTime));
+        } else {
+            params.put("end_ctrl_time", defaultEndCtrlTime);
+        }
+        JSONObject response = new JSONObject();
+        int n = Constants.NUM_0;
+        while (n <= Constants.NUM_3) {
+            String responseStr = httpClient.postResource(uniCtrlAddUrl, params.toJSONString(), null);
+            response = JSONObject.parseObject(responseStr);
+//            log.info(response.toJSONString());
+            int statusCode = response.getInteger("statuscode");
+            if (statusCode != Constants.REQ_RES_CATALOG_FAIL && statusCode != Constants.REQ_OTHER_EXCEP) {
+                break;
+            }
+            n++;
+            log.error("处理布控请求发生异常,正在重试,布控线索ID:{}, 响应信息:{}", clueId, response);
+            CommonUtil.threadSleep(Constants.NUMBER_3000L);
+        }
+        return response;
+    }
+
+
+    /**
+     * 调用烽火【统一布控】接口, 下发停控请求 - 布控失败时,重试3次
+     * @param httpClient
+     * @param businessDTO
+     * @return
+     */
+    public JSONObject doStopCtrl(HttpClient httpClient, BusinessDTO businessDTO) {
+        JSONObject params = new JSONObject();
+        String taskId = businessDTO.getTaskId();
+        String account = businessDTO.getAccount();
+        String accountType = businessDTO.getAccountType();
+        String sysId = businessDTO.getSysId();
+        String clueId = fromAreaCode.concat(taskId).concat("_").concat(accountType).concat(account);
+        params.put("clue_id", clueId);
+        params.put("from_areacode", fromAreaCode);
+        params.put("from_sys", sysId);
+        params.put("serv_ver", servVer);
+        params.put("sysuserid", sysUserId);
+        JSONObject response = new JSONObject();
+        int n = Constants.NUM_0;
+        while (n <= Constants.NUM_3) {
+            String responseStr = httpClient.postResource(uniCtrlDelUrl, params.toJSONString(), null);
+            response = JSONObject.parseObject(responseStr);
+            int statusCode = response.getInteger("statuscode");
+            if (statusCode != Constants.REQ_RES_CATALOG_FAIL && statusCode != Constants.REQ_OTHER_EXCEP) {
+                break;
+            }
+            n++;
+            log.error("处理停控请求发生异常, 正在重试, 停控线索ID: {}, 响应信息: {}", clueId, response);
+            CommonUtil.threadSleep(Constants.NUMBER_2000L);
+        }
+        return response;
+    }
+
+
+    /**
+     * 调用烽火【统一布控】接口, 查询线索布/停控状态 - 查询失败时,重试3次
+     * @param httpClient
+     * @param businessDTO 需要查询状态的布控内容
+     * @return String 布/停控状态
+     */
+    public String queryCtrlStatus(HttpClient httpClient, BusinessDTO businessDTO) {
+        JSONObject params = new JSONObject();
+        String taskId = businessDTO.getTaskId();
+        String account = businessDTO.getAccount();
+        String accountType = businessDTO.getAccountType();
+        String sysId = businessDTO.getSysId();
+        String clueId = fromAreaCode.concat(taskId).concat("_").concat(accountType).concat(account);
+        params.put("clue_id", clueId);
+        params.put("from_areacode", fromAreaCode);
+        params.put("from_sys", sysId);
+        params.put("serv_ver", servVer);
+        int n = 0;
+        int m = 0;
+        String status = "0";
+        while (n <= Constants.NUM_3) {
+            String responseStr = httpClient.postResource(uniCtrlQueryUrl, params.toJSONString(), null);
+            JSONObject response = JSONObject.parseObject(responseStr);
+            String statusCode = response.getString("statuscode"); // 查询响应状态码
+            status = response.getString("status");// 布控状态码
+            // 根据查询结果做不同处理
+            if (Constants.QUERY_OTHER_EXCEP.equals(statusCode)) { //其他异常,间隔1s,重试3次
+                n++;
+                log.error("查询布/停控状态异常, 响应状态:2999, 重试第{}次, 布/停控线索ID:{}", n, clueId);
+            } else if (Constants.QUERY_SUC.equals(statusCode) && (Constants.CTRL_TODO.equals(status)  || Constants.CTRL_ING.equals(status) || Constants.STOP_CTRL_TODO.equals(status) || Constants.STOP_CTRL_ING.equals(status))) {
+                m++;
+                log.info("查询布/停控状态中, 响应状态:{}, 布/停控状态:{}, 重试第{}次, 布/停控线索ID:{}", statusCode, status, m, clueId);
+                if (m > Constants.NUM_10) {
+                    break;
+                }
+            } else { //其他情况直接返回查询结果
+                log.info("查询布/停控状态完成, 响应状态:{}, 布/停控状态:{}, 布/停控线索ID:{}", statusCode, status, clueId);
+                break;
+            }
+            CommonUtil.threadSleep(Constants.NUMBER_2000L);
+        }
+        return status;
+    }
+
+
+}

+ 1 - 0
src/main/resources/META-INF/spring-devtools.properties

@@ -0,0 +1 @@
+restart.include.json=/com.alibaba.fastjson2.*.jar

+ 75 - 0
src/main/resources/application.properties

@@ -0,0 +1,75 @@
+# \u670D\u52A1\u914D\u7F6E
+server.port=2535
+server.servlet.context-path=/qbeqsjy
+server.tomcat.uri-encoding=UTF-8
+server.tomcat.accept-count=1000
+server.tomcat.threads.max=800
+server.tomcat.threads.min-spare=100
+
+# \u6570\u636E\u5E93\u914D\u7F6E\uFF08\u66FF\u6362\u9AD8\u65AFDB\uFF09
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+spring.datasource.url=jdbc:mysql://1.94.209.147:3396/dcuc_zdrgk_ruoyi?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
+spring.datasource.username=dcuc
+spring.datasource.password=123
+
+# \u4E1A\u52A1\u914D\u7F6E
+# \u7EBF\u7D22\u7C7B\u578B\u7F16\u7801\u5217\u8868 - \u624B\u673A\u53F7,\u8EAB\u4EFD\u8BC1\u53F7
+clue.type.list=D201005,D310111
+
+# \u70FD\u706B - \u3010\u7EDF\u4E00\u5E03\u63A7\u3011\u670D\u52A1\u914D\u7F6E
+# \u6388\u6743\u7CFB\u7EDFID\u5217\u8868
+sys.id.list=QBEQSJYCTRL,
+# \u8BF7\u6C42\u5730\u5E02
+from.areacode=120000
+# \u76EE\u7684\u5730\u5E02
+to.areacode=[]
+# \u76EE\u7684\u7CFB\u7EDF
+to.sys=["27"]
+# \u5E03\u63A7\u622A\u6B62\u65F6\u95F4\uFF08-1\uFF1A\u9ED8\u8BA4\u6C38\u4E45\u5E03\u63A7\uFF09
+end.ctrl.time=-1
+# \u73B0\u573A\u670D\u52A1\u7248\u672C\u53F7
+serv.ver=2.1
+# \u8B66\u5458ID
+sysuserid=fenghuo
+# \u4E0B\u53D1\u5E03\u63A7\u63A5\u53E3url
+uniCtrl.add.url=http://130.0.46.141:8090/lokiRest/uniCtrl/monitor/add
+# \u505C\u6B62\u5E03\u63A7\u63A5\u53E3url
+uniCtrl.del.url=http://130.0.46.141:8090/lokiRest/uniCtrl/monitor/del
+# \u5E03\u63A7\u7ED3\u679C\u67E5\u8BE2\u63A5\u53E3url
+uniCtrl.query.url=http://130.0.46.141:8090/lokiRest/unictrl/query/status
+
+# \u534E\u4E3A - kafka\u914D\u7F6E
+# \u4E1A\u52A1topic\u540D\u79F0
+topic.name=UNICTRL_DATA_QBEQSJYCTRL_V1.0
+
+# \u5E03\u63A7\u8D44\u6E90\u5217\u8868
+# \u4E1A\u52A1ID\uFF1A\u70FD\u706B\u76D8\u53E4\u5E73\u53F0\u6570\u636E\u8D44\u6E90\u6807\u8BC6\u7B26
+1=134B102
+2=
+3=
+4=
+5=
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 23 - 0
src/main/resources/banner.txt

@@ -0,0 +1,23 @@
+Spring Boot Version: ${spring-boot.version}
+////////////////////////////////////////////////////////////////////
+//                          _ooOoo_                               //
+//                         o8888888o                              //
+//                         88" . "88                              //
+//                         (| ^_^ |)                              //
+//                         O\  =  /O                              //
+//                      ____/`---'\____                           //
+//                    .'  \\|     |//  `.                         //
+//                   /  \\|||  :  |||//  \                        //
+//                  /  _||||| -:- |||||-  \                       //
+//                  |   | \\\  -  /// |   |                       //
+//                  | \_|  ''\---/''  |   |                       //
+//                  \  .-\__  `-`  ___/-. /                       //
+//                ___`. .'  /--.--\  `. . ___                     //
+//              ."" '<  `.___\_<|>_/___.'  >'"".                  //
+//            | | :  `- \`.;`\ _ /`;.`/ - ` : | |                 //
+//            \  \ `-.   \_ __\ /__ _/   .-` /  /                 //
+//      ========`-.____`-.___\_____/___.-`____.-'========         //
+//                           `=---='                              //
+//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
+//             佛祖保佑       永不宕机      永无BUG               //
+////////////////////////////////////////////////////////////////////

+ 38 - 0
src/main/resources/i18n/messages.properties

@@ -0,0 +1,38 @@
+#错误消息
+not.null=* 必须填写
+user.jcaptcha.error=验证码错误
+user.jcaptcha.expire=验证码已失效
+user.not.exists=用户不存在/密码错误
+user.password.not.match=用户不存在/密码错误
+user.password.retry.limit.count=密码输入错误{0}次
+user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
+user.password.delete=对不起,您的账号已被删除
+user.blocked=用户已封禁,请联系管理员
+role.blocked=角色已封禁,请联系管理员
+login.blocked=很遗憾,访问IP已被列入系统黑名单
+user.logout.success=退出成功
+
+length.not.valid=长度必须在{min}到{max}个字符之间
+
+user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
+user.password.not.valid=* 5-50个字符
+ 
+user.email.not.valid=邮箱格式错误
+user.mobile.phone.number.not.valid=手机号格式错误
+user.login.success=登录成功
+user.register.success=注册成功
+user.notfound=请重新登录
+user.forcelogout=管理员强制退出,请重新登录
+user.unknown.error=未知错误,请重新登录
+
+##文件上传消息
+upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB!
+upload.filename.exceed.length=上传的文件名最长{0}个字符
+
+##权限
+no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
+no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
+no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
+no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
+no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
+no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]

+ 93 - 0
src/main/resources/logback.xml

@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 日志存放路径 -->
+	<property name="log.path" value="/home/ruoyi/logs" />
+    <!-- 日志输出格式 -->
+	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
+
+	<!-- 控制台输出 -->
+	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+	</appender>
+	
+	<!-- 系统日志输出 -->
+	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-info.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+		</rollingPolicy>
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+	</appender>
+	
+	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-error.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>ERROR</level>
+			<!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+			<!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+	
+	<!-- 用户访问日志输出  -->
+    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<file>${log.path}/sys-user.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+	
+	<!-- 系统模块日志级别控制  -->
+	<logger name="com.ruoyi" level="info" />
+	<!-- Spring日志级别控制  -->
+	<logger name="org.springframework" level="warn" />
+
+	<root level="info">
+		<appender-ref ref="console" />
+	</root>
+	
+	<!--系统操作日志-->
+    <root level="info">
+        <appender-ref ref="file_info" />
+        <appender-ref ref="file_error" />
+    </root>
+	
+	<!--系统用户操作日志-->
+    <logger name="sys-user" level="info">
+        <appender-ref ref="sys-user"/>
+    </logger>
+</configuration> 

+ 7 - 0
src/main/webapp/WEB-INF/web.xml

@@ -0,0 +1,7 @@
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd" >
+
+<web-app>
+  <display-name>Archetype Created Web Application</display-name>
+</web-app>

+ 5 - 0
src/main/webapp/index.jsp

@@ -0,0 +1,5 @@
+<html>
+<body>
+<h2>Hello World!</h2>
+</body>
+</html>