Эх сурвалжийг харах

能源管理后端-初始化

0027008907 1 жил өмнө
commit
de8d650fa9
100 өөрчлөгдсөн 14096 нэмэгдсэн , 0 устгасан
  1. 44 0
      .gitignore
  2. 416 0
      zhny_admin/pom.xml
  3. 170 0
      zhny_admin/sql/quartz.sql
  4. 242 0
      zhny_admin/sql/ztmap.html
  5. 708 0
      zhny_admin/sql/ztmap_20210210.sql
  6. 21 0
      zhny_admin/src/main/java/com/ztmap/ZTMapApplication.java
  7. 18 0
      zhny_admin/src/main/java/com/ztmap/ZTMapServletInitializer.java
  8. 49 0
      zhny_admin/src/main/java/com/ztmap/common/constant/CommonMap.java
  9. 127 0
      zhny_admin/src/main/java/com/ztmap/common/constant/Constants.java
  10. 111 0
      zhny_admin/src/main/java/com/ztmap/common/constant/GenConstants.java
  11. 27 0
      zhny_admin/src/main/java/com/ztmap/common/constant/PermissionConstants.java
  12. 29 0
      zhny_admin/src/main/java/com/ztmap/common/constant/RepairStatus.java
  13. 65 0
      zhny_admin/src/main/java/com/ztmap/common/constant/ScheduleConstants.java
  14. 79 0
      zhny_admin/src/main/java/com/ztmap/common/constant/ShiroConstants.java
  15. 54 0
      zhny_admin/src/main/java/com/ztmap/common/constant/SupportDataType.java
  16. 105 0
      zhny_admin/src/main/java/com/ztmap/common/constant/UserConstants.java
  17. 30 0
      zhny_admin/src/main/java/com/ztmap/common/exception/BusinessException.java
  18. 15 0
      zhny_admin/src/main/java/com/ztmap/common/exception/DemoModeException.java
  19. 26 0
      zhny_admin/src/main/java/com/ztmap/common/exception/UtilException.java
  20. 103 0
      zhny_admin/src/main/java/com/ztmap/common/exception/base/BaseException.java
  21. 19 0
      zhny_admin/src/main/java/com/ztmap/common/exception/file/FileException.java
  22. 16 0
      zhny_admin/src/main/java/com/ztmap/common/exception/file/FileNameLengthLimitExceededException.java
  23. 16 0
      zhny_admin/src/main/java/com/ztmap/common/exception/file/FileSizeLimitExceededException.java
  24. 81 0
      zhny_admin/src/main/java/com/ztmap/common/exception/file/InvalidExtensionException.java
  25. 34 0
      zhny_admin/src/main/java/com/ztmap/common/exception/job/TaskException.java
  26. 16 0
      zhny_admin/src/main/java/com/ztmap/common/exception/user/CaptchaException.java
  27. 17 0
      zhny_admin/src/main/java/com/ztmap/common/exception/user/RoleBlockedException.java
  28. 16 0
      zhny_admin/src/main/java/com/ztmap/common/exception/user/UserBlockedException.java
  29. 16 0
      zhny_admin/src/main/java/com/ztmap/common/exception/user/UserDeleteException.java
  30. 18 0
      zhny_admin/src/main/java/com/ztmap/common/exception/user/UserException.java
  31. 16 0
      zhny_admin/src/main/java/com/ztmap/common/exception/user/UserNotExistsException.java
  32. 16 0
      zhny_admin/src/main/java/com/ztmap/common/exception/user/UserPasswordNotMatchException.java
  33. 16 0
      zhny_admin/src/main/java/com/ztmap/common/exception/user/UserPasswordRetryLimitCountException.java
  34. 16 0
      zhny_admin/src/main/java/com/ztmap/common/exception/user/UserPasswordRetryLimitExceedException.java
  35. 231 0
      zhny_admin/src/main/java/com/ztmap/common/redis/RedisCache.java
  36. 55 0
      zhny_admin/src/main/java/com/ztmap/common/utils/AddressUtils.java
  37. 114 0
      zhny_admin/src/main/java/com/ztmap/common/utils/Arith.java
  38. 197 0
      zhny_admin/src/main/java/com/ztmap/common/utils/CacheUtils.java
  39. 138 0
      zhny_admin/src/main/java/com/ztmap/common/utils/CookieUtils.java
  40. 184 0
      zhny_admin/src/main/java/com/ztmap/common/utils/DateUtils.java
  41. 40 0
      zhny_admin/src/main/java/com/ztmap/common/utils/ExceptionUtil.java
  42. 194 0
      zhny_admin/src/main/java/com/ztmap/common/utils/IpUtils.java
  43. 134 0
      zhny_admin/src/main/java/com/ztmap/common/utils/LogUtils.java
  44. 54 0
      zhny_admin/src/main/java/com/ztmap/common/utils/MapDataUtil.java
  45. 136 0
      zhny_admin/src/main/java/com/ztmap/common/utils/Md5Utils.java
  46. 26 0
      zhny_admin/src/main/java/com/ztmap/common/utils/MessageUtils.java
  47. 28 0
      zhny_admin/src/main/java/com/ztmap/common/utils/OutputProcessor.java
  48. 38 0
      zhny_admin/src/main/java/com/ztmap/common/utils/PositionUtil.java
  49. 98 0
      zhny_admin/src/main/java/com/ztmap/common/utils/RSAUtil.java
  50. 164 0
      zhny_admin/src/main/java/com/ztmap/common/utils/ServletUtils.java
  51. 1684 0
      zhny_admin/src/main/java/com/ztmap/common/utils/ShapeReader.java
  52. 408 0
      zhny_admin/src/main/java/com/ztmap/common/utils/StringUtils.java
  53. 99 0
      zhny_admin/src/main/java/com/ztmap/common/utils/Threads.java
  54. 137 0
      zhny_admin/src/main/java/com/ztmap/common/utils/TreeUtils.java
  55. 110 0
      zhny_admin/src/main/java/com/ztmap/common/utils/bean/BeanUtils.java
  56. 19 0
      zhny_admin/src/main/java/com/ztmap/common/utils/domain/ExcelCellData.java
  57. 35 0
      zhny_admin/src/main/java/com/ztmap/common/utils/domain/ExcelDefinition.java
  58. 26 0
      zhny_admin/src/main/java/com/ztmap/common/utils/domain/ExcelRowData.java
  59. 73 0
      zhny_admin/src/main/java/com/ztmap/common/utils/domain/SpatialDataInfo.java
  60. 76 0
      zhny_admin/src/main/java/com/ztmap/common/utils/file/FileTypeUtils.java
  61. 240 0
      zhny_admin/src/main/java/com/ztmap/common/utils/file/FileUploadUtils.java
  62. 203 0
      zhny_admin/src/main/java/com/ztmap/common/utils/file/FileUtils.java
  63. 100 0
      zhny_admin/src/main/java/com/ztmap/common/utils/file/ImageUtils.java
  64. 59 0
      zhny_admin/src/main/java/com/ztmap/common/utils/file/MimeTypeUtils.java
  65. 155 0
      zhny_admin/src/main/java/com/ztmap/common/utils/html/EscapeUtil.java
  66. 570 0
      zhny_admin/src/main/java/com/ztmap/common/utils/html/HTMLFilter.java
  67. 262 0
      zhny_admin/src/main/java/com/ztmap/common/utils/http/HttpUtils.java
  68. 210 0
      zhny_admin/src/main/java/com/ztmap/common/utils/modbus/ModbusMasterTCP.java
  69. 1125 0
      zhny_admin/src/main/java/com/ztmap/common/utils/poi/ExcelUtil.java
  70. 410 0
      zhny_admin/src/main/java/com/ztmap/common/utils/reflect/ReflectUtils.java
  71. 30 0
      zhny_admin/src/main/java/com/ztmap/common/utils/security/AuthorizationUtils.java
  72. 36 0
      zhny_admin/src/main/java/com/ztmap/common/utils/security/CipherUtils.java
  73. 77 0
      zhny_admin/src/main/java/com/ztmap/common/utils/security/PermissionUtils.java
  74. 75 0
      zhny_admin/src/main/java/com/ztmap/common/utils/security/ShiroUtils.java
  75. 146 0
      zhny_admin/src/main/java/com/ztmap/common/utils/spring/SpringUtils.java
  76. 37 0
      zhny_admin/src/main/java/com/ztmap/common/utils/sql/SqlUtil.java
  77. 87 0
      zhny_admin/src/main/java/com/ztmap/common/utils/text/CharsetKit.java
  78. 1013 0
      zhny_admin/src/main/java/com/ztmap/common/utils/text/Convert.java
  79. 93 0
      zhny_admin/src/main/java/com/ztmap/common/utils/text/StrFormatter.java
  80. 49 0
      zhny_admin/src/main/java/com/ztmap/common/utils/uuid/IdUtils.java
  81. 484 0
      zhny_admin/src/main/java/com/ztmap/common/utils/uuid/UUID.java
  82. 97 0
      zhny_admin/src/main/java/com/ztmap/common/xss/XssFilter.java
  83. 39 0
      zhny_admin/src/main/java/com/ztmap/common/xss/XssHttpServletRequestWrapper.java
  84. 166 0
      zhny_admin/src/main/java/com/ztmap/framework/aspectj/DataScopeAspect.java
  85. 72 0
      zhny_admin/src/main/java/com/ztmap/framework/aspectj/DataSourceAspect.java
  86. 264 0
      zhny_admin/src/main/java/com/ztmap/framework/aspectj/LogAspect.java
  87. 28 0
      zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/annotation/DataScope.java
  88. 28 0
      zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/annotation/DataSource.java
  89. 165 0
      zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/annotation/Excel.java
  90. 18 0
      zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/annotation/Excels.java
  91. 41 0
      zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/annotation/Log.java
  92. 20 0
      zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/enums/BusinessStatus.java
  93. 60 0
      zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/enums/BusinessType.java
  94. 19 0
      zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/enums/DataSourceType.java
  95. 25 0
      zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/enums/OperatorType.java
  96. 20 0
      zhny_admin/src/main/java/com/ztmap/framework/config/ApplicationConfig.java
  97. 83 0
      zhny_admin/src/main/java/com/ztmap/framework/config/CaptchaConfig.java
  98. 128 0
      zhny_admin/src/main/java/com/ztmap/framework/config/DruidConfig.java
  99. 46 0
      zhny_admin/src/main/java/com/ztmap/framework/config/FilterConfig.java
  100. 66 0
      zhny_admin/src/main/java/com/ztmap/framework/config/GenConfig.java

+ 44 - 0
.gitignore

@@ -0,0 +1,44 @@
+# Intellij project files
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# Maven
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+
+# Eclipse
+.metadata/
+.settings/
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+.project
+.classpath
+.loadpath

+ 416 - 0
zhny_admin/pom.xml

@@ -0,0 +1,416 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.ztmap</groupId>
+    <artifactId>zhny_admin</artifactId>
+    <version>2.0.0</version>
+    <packaging>jar</packaging>
+
+    <name>zhny_admin</name>
+    <url></url>
+    <description>智慧能源后台管理平台</description>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.2.13.RELEASE</version>
+        <relativePath />
+    </parent>
+
+    <properties>
+        <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>
+        <shiro.version>1.7.1</shiro.version>
+        <thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version>
+        <mybatis.spring.boot.starter.version>2.1.4</mybatis.spring.boot.starter.version>
+        <pagehelper.spring.boot.starter.version>1.3.0</pagehelper.spring.boot.starter.version>
+        <fastjson.version>1.2.75</fastjson.version>
+        <druid.version>1.2.4</druid.version>
+        <commons.io.version>2.5</commons.io.version>
+        <commons.fileupload.version>1.3.3</commons.fileupload.version>
+        <bitwalker.version>1.21</bitwalker.version>
+        <velocity.version>1.7</velocity.version>
+        <kaptcha.version>2.3.2</kaptcha.version>
+        <swagger.version>2.9.2</swagger.version>
+        <poi.version>4.1.2</poi.version>
+        <oshi.version>5.6.0</oshi.version>
+        <jna.version>5.7.0</jna.version>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.8.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.locationtech.jts</groupId>
+            <artifactId>jts-core</artifactId>
+            <version>1.18.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.gavaghan</groupId>
+            <artifactId>geodesy</artifactId>
+            <version>1.1.3</version>
+        </dependency>
+
+        <!-- SpringBoot 核心包 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+
+        <!-- SpringBoot 测试 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- SpringBoot 拦截器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+
+        <!-- SpringBoot Web容器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <!-- SpringBoot集成thymeleaf模板 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-thymeleaf</artifactId>
+        </dependency>
+
+        <!-- spring-boot-devtools -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional> <!-- 表示依赖不会传递 -->
+        </dependency>
+        <!-- 计算两个坐标距离数 -->
+        <dependency>
+            <groupId>org.gavaghan</groupId>
+            <artifactId>geodesy</artifactId>
+            <version>1.1.3</version>
+        </dependency>
+
+        <!-- Mysql驱动包 -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <!-- SpringBoot集成mybatis框架 -->
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>${mybatis.spring.boot.starter.version}</version>
+        </dependency>
+
+        <!-- pagehelper 分页插件 -->
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>${pagehelper.spring.boot.starter.version}</version>
+        </dependency>
+
+        <!--阿里数据库连接池 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+            <version>${druid.version}</version>
+        </dependency>
+
+        <!--常用工具类 -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>4.1.12</version>
+        </dependency>
+
+        <!--io常用工具类 -->
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons.io.version}</version>
+        </dependency>
+
+        <!--文件上传工具类 -->
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>${commons.fileupload.version}</version>
+        </dependency>
+
+        <!--Shiro核心框架 -->
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-core</artifactId>
+            <version>${shiro.version}</version>
+        </dependency>
+
+        <!-- Shiro使用Spring框架 -->
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-spring</artifactId>
+            <version>${shiro.version}</version>
+        </dependency>
+
+        <!-- Shiro使用EhCache缓存框架 -->
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-ehcache</artifactId>
+            <version>${shiro.version}</version>
+        </dependency>
+
+        <!-- thymeleaf模板引擎和shiro框架的整合 -->
+        <dependency>
+            <groupId>com.github.theborakompanioni</groupId>
+            <artifactId>thymeleaf-extras-shiro</artifactId>
+            <version>${thymeleaf.extras.shiro.version}</version>
+        </dependency>
+
+        <!-- 阿里JSON解析器 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+        <!-- redis 缓存操作 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <!--Token生成与解析-->
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+
+        <!-- 解析客户端操作系统、浏览器等 -->
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+            <version>${bitwalker.version}</version>
+        </dependency>
+
+        <!--Spring框架基本的核心工具-->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+        </dependency>
+
+        <!-- modbus -->
+        <dependency>
+            <groupId>com.digitalpetri.modbus</groupId>
+            <artifactId>modbus-master-tcp</artifactId>
+            <version>1.1.0</version>
+        </dependency>
+
+<!--        <dependency>-->
+<!--            <groupId>com.infiniteautomation</groupId>-->
+<!--            <artifactId>modbus4j</artifactId>-->
+<!--            <version>3.0.3</version>-->
+<!--        </dependency>-->
+        <!-- 定时任务 -->
+        <dependency>
+            <groupId>org.quartz-scheduler</groupId>
+            <artifactId>quartz</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.mchange</groupId>
+                    <artifactId>c3p0</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!--velocity代码生成使用模板 -->
+        <dependency>
+            <groupId>org.apache.velocity</groupId>
+            <artifactId>velocity</artifactId>
+            <version>${velocity.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>commons-collections</groupId>
+                    <artifactId>commons-collections</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!--验证码 -->
+        <dependency>
+            <groupId>com.github.penggle</groupId>
+            <artifactId>kaptcha</artifactId>
+            <version>${kaptcha.version}</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>javax.servlet-api</artifactId>
+                    <groupId>javax.servlet</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jsoup</groupId>
+            <artifactId>jsoup</artifactId>
+            <version>1.13.1</version>
+        </dependency>
+
+        <!-- swagger2-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>${swagger.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>io.swagger</groupId>
+                    <artifactId>swagger-annotations</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>io.swagger</groupId>
+                    <artifactId>swagger-models</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!--防止进入swagger页面报类型转换错误,排除2.9.2中的引用,手动增加1.5.21版本-->
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <version>1.5.21</version>
+        </dependency>
+        
+         <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-models</artifactId>
+            <version>1.5.21</version>
+        </dependency>
+        
+        <!-- swagger2-UI-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>${swagger.version}</version>
+        </dependency>
+
+        <!-- 获取系统信息 -->
+        <dependency>
+            <groupId>com.github.oshi</groupId>
+            <artifactId>oshi-core</artifactId>
+            <version>${oshi.version}</version>
+        </dependency>
+
+        <!-- excel工具 -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>${poi.version}</version>
+        </dependency>
+
+        <!-- 海康综合安防管理平台 -->
+        <dependency>
+            <groupId>com.hikvision.ga</groupId>
+            <artifactId>artemis-http-client</artifactId>
+            <version>1.1.3</version>
+        </dependency>
+
+        <!--   geotools相关pom     -->
+        <dependency>
+            <groupId>com.vividsolutions</groupId>
+            <artifactId>jts</artifactId>
+            <version>1.13</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.gdal</groupId>
+            <artifactId>gdal</artifactId>
+            <version>3.2.0</version>
+        </dependency>
+
+        <!--<dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-epsg-hsql</artifactId>
+            <version>20.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-main</artifactId>
+            <version>20.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-cql</artifactId>
+            <version>20.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-shapefile</artifactId>
+            <version>20.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.geotools</groupId>
+            <artifactId>gt-opengis</artifactId>
+            <version>20.0</version>
+        </dependency>-->
+
+    </dependencies>
+
+    <build>
+    <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>public</id>
+            <name>aliyun nexus</name>
+            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>public</id>
+            <name>aliyun nexus</name>
+            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
+</project>

+ 170 - 0
zhny_admin/sql/quartz.sql

@@ -0,0 +1,170 @@
+-- ----------------------------
+-- 1、存储每一个已配置的 jobDetail 的详细信息
+-- ----------------------------
+drop table if exists QRTZ_JOB_DETAILS;
+create table QRTZ_JOB_DETAILS (
+    sched_name           varchar(120)    not null,
+    job_name             varchar(200)    not null,
+    job_group            varchar(200)    not null,
+    description          varchar(250)    null,
+    job_class_name       varchar(250)    not null,
+    is_durable           varchar(1)      not null,
+    is_nonconcurrent     varchar(1)      not null,
+    is_update_data       varchar(1)      not null,
+    requests_recovery    varchar(1)      not null,
+    job_data             blob            null,
+    primary key (sched_name,job_name,job_group)
+) engine=innodb default charset=utf8;
+
+-- ----------------------------
+-- 2、 存储已配置的 Trigger 的信息
+-- ----------------------------
+drop table if exists QRTZ_TRIGGERS;
+create table QRTZ_TRIGGERS (
+    sched_name           varchar(120)    not null,
+    trigger_name         varchar(200)    not null,
+    trigger_group        varchar(200)    not null,
+    job_name             varchar(200)    not null,
+    job_group            varchar(200)    not null,
+    description          varchar(250)    null,
+    next_fire_time       bigint(13)      null,
+    prev_fire_time       bigint(13)      null,
+    priority             integer         null,
+    trigger_state        varchar(16)     not null,
+    trigger_type         varchar(8)      not null,
+    start_time           bigint(13)      not null,
+    end_time             bigint(13)      null,
+    calendar_name        varchar(200)    null,
+    misfire_instr        smallint(2)     null,
+    job_data             blob            null,
+    primary key (sched_name,trigger_name,trigger_group),
+    foreign key (sched_name,job_name,job_group) references QRTZ_JOB_DETAILS(sched_name,job_name,job_group)
+) engine=innodb default charset=utf8;
+
+-- ----------------------------
+-- 3、 存储简单的 Trigger,包括重复次数,间隔,以及已触发的次数
+-- ----------------------------
+drop table if exists QRTZ_SIMPLE_TRIGGERS;
+create table QRTZ_SIMPLE_TRIGGERS (
+    sched_name           varchar(120)    not null,
+    trigger_name         varchar(200)    not null,
+    trigger_group        varchar(200)    not null,
+    repeat_count         bigint(7)       not null,
+    repeat_interval      bigint(12)      not null,
+    times_triggered      bigint(10)      not null,
+    primary key (sched_name,trigger_name,trigger_group),
+    foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group)
+) engine=innodb default charset=utf8;
+
+-- ----------------------------
+-- 4、 存储 Cron Trigger,包括 Cron 表达式和时区信息
+-- ---------------------------- 
+drop table if exists QRTZ_CRON_TRIGGERS;
+create table QRTZ_CRON_TRIGGERS (
+    sched_name           varchar(120)    not null,
+    trigger_name         varchar(200)    not null,
+    trigger_group        varchar(200)    not null,
+    cron_expression      varchar(200)    not null,
+    time_zone_id         varchar(80),
+    primary key (sched_name,trigger_name,trigger_group),
+    foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group)
+) engine=innodb default charset=utf8;
+
+-- ----------------------------
+-- 5、 Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型,JobStore 并不知道如何存储实例的时候)
+-- ---------------------------- 
+drop table if exists QRTZ_BLOB_TRIGGERS;
+create table QRTZ_BLOB_TRIGGERS (
+    sched_name           varchar(120)    not null,
+    trigger_name         varchar(200)    not null,
+    trigger_group        varchar(200)    not null,
+    blob_data            blob            null,
+    primary key (sched_name,trigger_name,trigger_group),
+    foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group)
+) engine=innodb default charset=utf8;
+
+-- ----------------------------
+-- 6、 以 Blob 类型存储存放日历信息, quartz可配置一个日历来指定一个时间范围
+-- ---------------------------- 
+drop table if exists QRTZ_CALENDARS;
+create table QRTZ_CALENDARS (
+    sched_name           varchar(120)    not null,
+    calendar_name        varchar(200)    not null,
+    calendar             blob            not null,
+    primary key (sched_name,calendar_name)
+) engine=innodb default charset=utf8;
+
+-- ----------------------------
+-- 7、 存储已暂停的 Trigger 组的信息
+-- ---------------------------- 
+drop table if exists QRTZ_PAUSED_TRIGGER_GRPS;
+create table QRTZ_PAUSED_TRIGGER_GRPS (
+    sched_name           varchar(120)    not null,
+    trigger_group        varchar(200)    not null,
+    primary key (sched_name,trigger_group)
+) engine=innodb default charset=utf8;
+
+-- ----------------------------
+-- 8、 存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息
+-- ---------------------------- 
+drop table if exists QRTZ_FIRED_TRIGGERS;
+create table QRTZ_FIRED_TRIGGERS (
+    sched_name           varchar(120)    not null,
+    entry_id             varchar(95)     not null,
+    trigger_name         varchar(200)    not null,
+    trigger_group        varchar(200)    not null,
+    instance_name        varchar(200)    not null,
+    fired_time           bigint(13)      not null,
+    sched_time           bigint(13)      not null,
+    priority             integer         not null,
+    state                varchar(16)     not null,
+    job_name             varchar(200)    null,
+    job_group            varchar(200)    null,
+    is_nonconcurrent     varchar(1)      null,
+    requests_recovery    varchar(1)      null,
+    primary key (sched_name,entry_id)
+) engine=innodb default charset=utf8;
+
+-- ----------------------------
+-- 9、 存储少量的有关 Scheduler 的状态信息,假如是用于集群中,可以看到其他的 Scheduler 实例
+-- ---------------------------- 
+drop table if exists QRTZ_SCHEDULER_STATE; 
+create table QRTZ_SCHEDULER_STATE (
+    sched_name           varchar(120)    not null,
+    instance_name        varchar(200)    not null,
+    last_checkin_time    bigint(13)      not null,
+    checkin_interval     bigint(13)      not null,
+    primary key (sched_name,instance_name)
+) engine=innodb default charset=utf8;
+
+-- ----------------------------
+-- 10、 存储程序的悲观锁的信息(假如使用了悲观锁)
+-- ---------------------------- 
+drop table if exists QRTZ_LOCKS;
+create table QRTZ_LOCKS (
+    sched_name           varchar(120)    not null,
+    lock_name            varchar(40)     not null,
+    primary key (sched_name,lock_name)
+) engine=innodb default charset=utf8;
+
+drop table if exists QRTZ_SIMPROP_TRIGGERS;
+create table QRTZ_SIMPROP_TRIGGERS (
+    sched_name           varchar(120)    not null,
+    trigger_name         varchar(200)    not null,
+    trigger_group        varchar(200)    not null,
+    str_prop_1           varchar(512)    null,
+    str_prop_2           varchar(512)    null,
+    str_prop_3           varchar(512)    null,
+    int_prop_1           int             null,
+    int_prop_2           int             null,
+    long_prop_1          bigint          null,
+    long_prop_2          bigint          null,
+    dec_prop_1           numeric(13,4)   null,
+    dec_prop_2           numeric(13,4)   null,
+    bool_prop_1          varchar(1)      null,
+    bool_prop_2          varchar(1)      null,
+    primary key (sched_name,trigger_name,trigger_group),
+    foreign key (sched_name,trigger_name,trigger_group) references QRTZ_TRIGGERS(sched_name,trigger_name,trigger_group)
+) engine=innodb default charset=utf8;
+
+commit;

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 242 - 0
zhny_admin/sql/ztmap.html


+ 708 - 0
zhny_admin/sql/ztmap_20210210.sql

@@ -0,0 +1,708 @@
+-- ----------------------------
+-- 1、部门表
+-- ----------------------------
+drop table if exists sys_dept;
+create table sys_dept (
+  dept_id           bigint(20)      not null auto_increment    comment '部门id',
+  parent_id         bigint(20)      default 0                  comment '父部门id',
+  ancestors         varchar(50)     default ''                 comment '祖级列表',
+  dept_name         varchar(30)     default ''                 comment '部门名称',
+  order_num         int(4)          default 0                  comment '显示顺序',
+  leader            varchar(20)     default null               comment '负责人',
+  phone             varchar(11)     default null               comment '联系电话',
+  email             varchar(50)     default null               comment '邮箱',
+  status            char(1)         default '0'                comment '部门状态(0正常 1停用)',
+  del_flag          char(1)         default '0'                comment '删除标志(0代表存在 2代表删除)',
+  create_by         varchar(64)     default ''                 comment '创建者',
+  create_time 	    datetime                                   comment '创建时间',
+  update_by         varchar(64)     default ''                 comment '更新者',
+  update_time       datetime                                   comment '更新时间',
+  primary key (dept_id)
+) engine=innodb auto_increment=200 comment = '部门表';
+
+-- ----------------------------
+-- 初始化-部门表数据
+-- ----------------------------
+insert into sys_dept values(100,  0,   '0',          '臻图科技',   0, '臻图', '15888888888', 'ztmap@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(101,  100, '0,100',      '上海总公司', 1, '臻图', '15888888888', 'ztmap@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(102,  100, '0,100',      '青岛分公司', 2, '臻图', '15888888888', 'ztmap@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(103,  101, '0,100,101',  '研发部门',   1, '臻图', '15888888888', 'ztmap@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(104,  101, '0,100,101',  '市场部门',   2, '臻图', '15888888888', 'ztmap@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(105,  101, '0,100,101',  '测试部门',   3, '臻图', '15888888888', 'ztmap@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(106,  101, '0,100,101',  '财务部门',   4, '臻图', '15888888888', 'ztmap@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(107,  101, '0,100,101',  '运维部门',   5, '臻图', '15888888888', 'ztmap@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(108,  102, '0,100,102',  '市场部门',   1, '臻图', '15888888888', 'ztmap@qq.com', '0', '0', 'admin', sysdate(), '', null);
+insert into sys_dept values(109,  102, '0,100,102',  '财务部门',   2, '臻图', '15888888888', 'ztmap@qq.com', '0', '0', 'admin', sysdate(), '', null);
+
+
+-- ----------------------------
+-- 2、用户信息表
+-- ----------------------------
+drop table if exists sys_user;
+create table sys_user (
+  user_id           bigint(20)      not null auto_increment    comment '用户ID',
+  dept_id           bigint(20)      default null               comment '部门ID',
+  login_name        varchar(30)     not null                   comment '登录账号',
+  user_name         varchar(30)     default ''                 comment '用户昵称',
+  user_type         varchar(2)      default '00'               comment '用户类型(00系统用户 01注册用户)',
+  email             varchar(50)     default ''                 comment '用户邮箱',
+  phonenumber       varchar(11)     default ''                 comment '手机号码',
+  sex               char(1)         default '0'                comment '用户性别(0男 1女 2未知)',
+  avatar            varchar(100)    default ''                 comment '头像路径',
+  password          varchar(50)     default ''                 comment '密码',
+  salt              varchar(20)     default ''                 comment '盐加密',
+  status            char(1)         default '0'                comment '帐号状态(0正常 1停用)',
+  del_flag          char(1)         default '0'                comment '删除标志(0代表存在 2代表删除)',
+  login_ip          varchar(128)    default ''                 comment '最后登录IP',
+  login_date        datetime                                   comment '最后登录时间',
+  pwd_update_date   datetime                                   comment '密码最后更新时间',
+  create_by         varchar(64)     default ''                 comment '创建者',
+  create_time       datetime                                   comment '创建时间',
+  update_by         varchar(64)     default ''                 comment '更新者',
+  update_time       datetime                                   comment '更新时间',
+  remark            varchar(500)    default null               comment '备注',
+  primary key (user_id)
+) engine=innodb auto_increment=100 comment = '用户信息表';
+
+-- ----------------------------
+-- 初始化-用户信息表数据
+-- ----------------------------
+insert into sys_user values(1,  103, 'admin', '臻图', '00', 'ztmap@ztmapinfo.com', '15888888888', '1', '', 'c2ba1079999d65936339ecdd27b03746', 'a82e22', '0', '0', '127.0.0.1', sysdate(), sysdate(), 'admin', sysdate(), '', null, '管理员');
+
+-- ----------------------------
+-- 3、岗位信息表
+-- ----------------------------
+drop table if exists sys_post;
+create table sys_post
+(
+  post_id       bigint(20)      not null auto_increment    comment '岗位ID',
+  post_code     varchar(64)     not null                   comment '岗位编码',
+  post_name     varchar(50)     not null                   comment '岗位名称',
+  post_sort     int(4)          not null                   comment '显示顺序',
+  status        char(1)         not null                   comment '状态(0正常 1停用)',
+  create_by     varchar(64)     default ''                 comment '创建者',
+  create_time   datetime                                   comment '创建时间',
+  update_by     varchar(64)     default ''			       comment '更新者',
+  update_time   datetime                                   comment '更新时间',
+  remark        varchar(500)    default null               comment '备注',
+  primary key (post_id)
+) engine=innodb comment = '岗位信息表';
+
+-- ----------------------------
+-- 初始化-岗位信息表数据
+-- ----------------------------
+insert into sys_post values(1, 'ceo',  '董事长',    1, '0', 'admin', sysdate(), '', null, '');
+insert into sys_post values(2, 'se',   '项目经理',  2, '0', 'admin', sysdate(), '', null, '');
+insert into sys_post values(3, 'hr',   '人力资源',  3, '0', 'admin', sysdate(), '', null, '');
+insert into sys_post values(4, 'user', '普通员工',  4, '0', 'admin', sysdate(), '', null, '');
+
+
+-- ----------------------------
+-- 4、角色信息表
+-- ----------------------------
+drop table if exists sys_role;
+create table sys_role (
+  role_id           bigint(20)      not null auto_increment    comment '角色ID',
+  role_name         varchar(30)     not null                   comment '角色名称',
+  role_key          varchar(100)    not null                   comment '角色权限字符串',
+  role_sort         int(4)          not null                   comment '显示顺序',
+  data_scope        char(1)         default '1'                comment '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)',
+  status            char(1)         not null                   comment '角色状态(0正常 1停用)',
+  del_flag          char(1)         default '0'                comment '删除标志(0代表存在 2代表删除)',
+  create_by         varchar(64)     default ''                 comment '创建者',
+  create_time       datetime                                   comment '创建时间',
+  update_by         varchar(64)     default ''                 comment '更新者',
+  update_time       datetime                                   comment '更新时间',
+  remark            varchar(500)    default null               comment '备注',
+  primary key (role_id)
+) engine=innodb auto_increment=100 comment = '角色信息表';
+
+-- ----------------------------
+-- 初始化-角色信息表数据
+-- ----------------------------
+insert into sys_role values('1', '超级管理员', 'admin',  1, 1, '0', '0', 'admin', sysdate(), '', null, '超级管理员');
+insert into sys_role values('2', '普通角色',   'common', 2, 2, '0', '0', 'admin', sysdate(), '', null, '普通角色');
+
+
+-- ----------------------------
+-- 5、菜单权限表
+-- ----------------------------
+drop table if exists sys_menu;
+create table sys_menu (
+  menu_id           bigint(20)      not null auto_increment    comment '菜单ID',
+  menu_name         varchar(50)     not null                   comment '菜单名称',
+  parent_id         bigint(20)      default 0                  comment '父菜单ID',
+  order_num         int(4)          default 0                  comment '显示顺序',
+  url               varchar(200)    default '#'                comment '请求地址',
+  target            varchar(20)     default ''                 comment '打开方式(menuItem页签 menuBlank新窗口)',
+  menu_type         char(1)         default ''                 comment '菜单类型(M目录 C菜单 F按钮)',
+  visible           char(1)         default 0                  comment '菜单状态(0显示 1隐藏)',
+  is_refresh        char(1)         default 1                  comment '是否刷新(0刷新 1不刷新)',
+  perms             varchar(100)    default null               comment '权限标识',
+  icon              varchar(100)    default '#'                comment '菜单图标',
+  create_by         varchar(64)     default ''                 comment '创建者',
+  create_time       datetime                                   comment '创建时间',
+  update_by         varchar(64)     default ''                 comment '更新者',
+  update_time       datetime                                   comment '更新时间',
+  remark            varchar(500)    default ''                 comment '备注',
+  primary key (menu_id)
+) engine=innodb auto_increment=2000 comment = '菜单权限表';
+
+-- ----------------------------
+-- 初始化-菜单信息表数据
+-- ----------------------------
+-- 一级菜单
+insert into sys_menu values('1', '系统管理', '0', '1', '#',                '',          'M', '0', '1', '', 'fa fa-gear',           'admin', sysdate(), '', null, '系统管理目录');
+insert into sys_menu values('2', '系统监控', '0', '2', '#',                '',          'M', '0', '1', '', 'fa fa-video-camera',   'admin', sysdate(), '', null, '系统监控目录');
+insert into sys_menu values('3', '系统工具', '0', '3', '#',                '',          'M', '0', '1', '', 'fa fa-bars',           'admin', sysdate(), '', null, '系统工具目录');
+-- 二级菜单
+insert into sys_menu values('100',  '用户管理', '1', '1', '/system/user',          '', 'C', '0', '1', 'system:user:view',         'fa fa-user-o',          'admin', sysdate(), '', null, '用户管理菜单');
+insert into sys_menu values('101',  '角色管理', '1', '2', '/system/role',          '', 'C', '0', '1', 'system:role:view',         'fa fa-user-secret',     'admin', sysdate(), '', null, '角色管理菜单');
+insert into sys_menu values('102',  '菜单管理', '1', '3', '/system/menu',          '', 'C', '0', '1', 'system:menu:view',         'fa fa-th-list',         'admin', sysdate(), '', null, '菜单管理菜单');
+insert into sys_menu values('103',  '部门管理', '1', '4', '/system/dept',          '', 'C', '0', '1', 'system:dept:view',         'fa fa-outdent',         'admin', sysdate(), '', null, '部门管理菜单');
+insert into sys_menu values('104',  '岗位管理', '1', '5', '/system/post',          '', 'C', '0', '1', 'system:post:view',         'fa fa-address-card-o',  'admin', sysdate(), '', null, '岗位管理菜单');
+insert into sys_menu values('105',  '字典管理', '1', '6', '/system/dict',          '', 'C', '0', '1', 'system:dict:view',         'fa fa-bookmark-o',      'admin', sysdate(), '', null, '字典管理菜单');
+insert into sys_menu values('106',  '参数设置', '1', '7', '/system/config',        '', 'C', '0', '1', 'system:config:view',       'fa fa-sun-o',           'admin', sysdate(), '', null, '参数设置菜单');
+insert into sys_menu values('107',  '通知公告', '1', '8', '/system/notice',        '', 'C', '0', '1', 'system:notice:view',       'fa fa-bullhorn',        'admin', sysdate(), '', null, '通知公告菜单');
+insert into sys_menu values('108',  '日志管理', '1', '9', '#',                     '', 'M', '0', '1', '',                         'fa fa-pencil-square-o', 'admin', sysdate(), '', null, '日志管理菜单');
+insert into sys_menu values('109',  '在线用户', '2', '1', '/monitor/online',       '', 'C', '0', '1', 'monitor:online:view',      'fa fa-user-circle',     'admin', sysdate(), '', null, '在线用户菜单');
+insert into sys_menu values('110',  '定时任务', '2', '2', '/monitor/job',          '', 'C', '0', '1', 'monitor:job:view',         'fa fa-tasks',           'admin', sysdate(), '', null, '定时任务菜单');
+insert into sys_menu values('111',  '数据监控', '2', '3', '/monitor/data',         '', 'C', '0', '1', 'monitor:data:view',        'fa fa-bug',             'admin', sysdate(), '', null, '数据监控菜单');
+insert into sys_menu values('112',  '服务监控', '2', '4', '/monitor/server',       '', 'C', '0', '1', 'monitor:server:view',      'fa fa-server',          'admin', sysdate(), '', null, '服务监控菜单');
+insert into sys_menu values('113',  '缓存监控', '2', '5', '/monitor/cache',        '', 'C', '0', '1', 'monitor:cache:view',       'fa fa-cube',            'admin', sysdate(), '', null, '缓存监控菜单');
+insert into sys_menu values('114',  '表单构建', '3', '1', '/tool/build',           '', 'C', '0', '1', 'tool:build:view',          'fa fa-wpforms',         'admin', sysdate(), '', null, '表单构建菜单');
+insert into sys_menu values('115',  '代码生成', '3', '2', '/tool/gen',             '', 'C', '0', '1', 'tool:gen:view',            'fa fa-code',            'admin', sysdate(), '', null, '代码生成菜单');
+insert into sys_menu values('116',  '系统接口', '3', '3', '/tool/swagger',         '', 'C', '0', '1', 'tool:swagger:view',        'fa fa-gg',              'admin', sysdate(), '', null, '系统接口菜单');
+-- 三级菜单
+insert into sys_menu values('500',  '操作日志', '108', '1', '/monitor/operlog',    '', 'C', '0', '1', 'monitor:operlog:view',     'fa fa-address-book',    'admin', sysdate(), '', null, '操作日志菜单');
+insert into sys_menu values('501',  '登录日志', '108', '2', '/monitor/logininfor', '', 'C', '0', '1', 'monitor:logininfor:view',  'fa fa-file-image-o',    'admin', sysdate(), '', null, '登录日志菜单');
+-- 用户管理按钮
+insert into sys_menu values('1000', '用户查询', '100', '1',  '#', '',  'F', '0', '1', 'system:user:list',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1001', '用户新增', '100', '2',  '#', '',  'F', '0', '1', 'system:user:add',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1002', '用户修改', '100', '3',  '#', '',  'F', '0', '1', 'system:user:edit',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1003', '用户删除', '100', '4',  '#', '',  'F', '0', '1', 'system:user:remove',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1004', '用户导出', '100', '5',  '#', '',  'F', '0', '1', 'system:user:export',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1005', '用户导入', '100', '6',  '#', '',  'F', '0', '1', 'system:user:import',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1006', '重置密码', '100', '7',  '#', '',  'F', '0', '1', 'system:user:resetPwd',    '#', 'admin', sysdate(), '', null, '');
+-- 角色管理按钮
+insert into sys_menu values('1007', '角色查询', '101', '1',  '#', '',  'F', '0', '1', 'system:role:list',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1008', '角色新增', '101', '2',  '#', '',  'F', '0', '1', 'system:role:add',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1009', '角色修改', '101', '3',  '#', '',  'F', '0', '1', 'system:role:edit',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1010', '角色删除', '101', '4',  '#', '',  'F', '0', '1', 'system:role:remove',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1011', '角色导出', '101', '5',  '#', '',  'F', '0', '1', 'system:role:export',      '#', 'admin', sysdate(), '', null, '');
+-- 菜单管理按钮
+insert into sys_menu values('1012', '菜单查询', '102', '1',  '#', '',  'F', '0', '1', 'system:menu:list',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1013', '菜单新增', '102', '2',  '#', '',  'F', '0', '1', 'system:menu:add',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1014', '菜单修改', '102', '3',  '#', '',  'F', '0', '1', 'system:menu:edit',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1015', '菜单删除', '102', '4',  '#', '',  'F', '0', '1', 'system:menu:remove',      '#', 'admin', sysdate(), '', null, '');
+-- 部门管理按钮
+insert into sys_menu values('1016', '部门查询', '103', '1',  '#', '',  'F', '0', '1', 'system:dept:list',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1017', '部门新增', '103', '2',  '#', '',  'F', '0', '1', 'system:dept:add',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1018', '部门修改', '103', '3',  '#', '',  'F', '0', '1', 'system:dept:edit',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1019', '部门删除', '103', '4',  '#', '',  'F', '0', '1', 'system:dept:remove',      '#', 'admin', sysdate(), '', null, '');
+-- 岗位管理按钮
+insert into sys_menu values('1020', '岗位查询', '104', '1',  '#', '',  'F', '0', '1', 'system:post:list',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1021', '岗位新增', '104', '2',  '#', '',  'F', '0', '1', 'system:post:add',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1022', '岗位修改', '104', '3',  '#', '',  'F', '0', '1', 'system:post:edit',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1023', '岗位删除', '104', '4',  '#', '',  'F', '0', '1', 'system:post:remove',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1024', '岗位导出', '104', '5',  '#', '',  'F', '0', '1', 'system:post:export',      '#', 'admin', sysdate(), '', null, '');
+-- 字典管理按钮
+insert into sys_menu values('1025', '字典查询', '105', '1',  '#', '',  'F', '0', '1', 'system:dict:list',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1026', '字典新增', '105', '2',  '#', '',  'F', '0', '1', 'system:dict:add',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1027', '字典修改', '105', '3',  '#', '',  'F', '0', '1', 'system:dict:edit',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1028', '字典删除', '105', '4',  '#', '',  'F', '0', '1', 'system:dict:remove',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1029', '字典导出', '105', '5',  '#', '',  'F', '0', '1', 'system:dict:export',      '#', 'admin', sysdate(), '', null, '');
+-- 参数设置按钮
+insert into sys_menu values('1030', '参数查询', '106', '1',  '#', '',  'F', '0', '1', 'system:config:list',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1031', '参数新增', '106', '2',  '#', '',  'F', '0', '1', 'system:config:add',       '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1032', '参数修改', '106', '3',  '#', '',  'F', '0', '1', 'system:config:edit',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1033', '参数删除', '106', '4',  '#', '',  'F', '0', '1', 'system:config:remove',    '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1034', '参数导出', '106', '5',  '#', '',  'F', '0', '1', 'system:config:export',    '#', 'admin', sysdate(), '', null, '');
+-- 通知公告按钮
+insert into sys_menu values('1035', '公告查询', '107', '1',  '#', '',  'F', '0', '1', 'system:notice:list',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1036', '公告新增', '107', '2',  '#', '',  'F', '0', '1', 'system:notice:add',       '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1037', '公告修改', '107', '3',  '#', '',  'F', '0', '1', 'system:notice:edit',      '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1038', '公告删除', '107', '4',  '#', '',  'F', '0', '1', 'system:notice:remove',    '#', 'admin', sysdate(), '', null, '');
+-- 操作日志按钮
+insert into sys_menu values('1039', '操作查询', '500', '1',  '#', '',  'F', '0', '1', 'monitor:operlog:list',    '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1040', '操作删除', '500', '2',  '#', '',  'F', '0', '1', 'monitor:operlog:remove',  '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1041', '详细信息', '500', '3',  '#', '',  'F', '0', '1', 'monitor:operlog:detail',  '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1042', '日志导出', '500', '4',  '#', '',  'F', '0', '1', 'monitor:operlog:export',  '#', 'admin', sysdate(), '', null, '');
+-- 登录日志按钮
+insert into sys_menu values('1043', '登录查询', '501', '1',  '#', '',  'F', '0', '1', 'monitor:logininfor:list',         '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1044', '登录删除', '501', '2',  '#', '',  'F', '0', '1', 'monitor:logininfor:remove',       '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1045', '日志导出', '501', '3',  '#', '',  'F', '0', '1', 'monitor:logininfor:export',       '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1046', '账户解锁', '501', '4',  '#', '',  'F', '0', '1', 'monitor:logininfor:unlock',       '#', 'admin', sysdate(), '', null, '');
+-- 在线用户按钮
+insert into sys_menu values('1047', '在线查询', '109', '1',  '#', '',  'F', '0', '1', 'monitor:online:list',             '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1048', '批量强退', '109', '2',  '#', '',  'F', '0', '1', 'monitor:online:batchForceLogout', '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1049', '单条强退', '109', '3',  '#', '',  'F', '0', '1', 'monitor:online:forceLogout',      '#', 'admin', sysdate(), '', null, '');
+-- 定时任务按钮
+insert into sys_menu values('1050', '任务查询', '110', '1',  '#', '',  'F', '0', '1', 'monitor:job:list',                '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1051', '任务新增', '110', '2',  '#', '',  'F', '0', '1', 'monitor:job:add',                 '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1052', '任务修改', '110', '3',  '#', '',  'F', '0', '1', 'monitor:job:edit',                '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1053', '任务删除', '110', '4',  '#', '',  'F', '0', '1', 'monitor:job:remove',              '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1054', '状态修改', '110', '5',  '#', '',  'F', '0', '1', 'monitor:job:changeStatus',        '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1055', '任务详细', '110', '6',  '#', '',  'F', '0', '1', 'monitor:job:detail',              '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1056', '任务导出', '110', '7',  '#', '',  'F', '0', '1', 'monitor:job:export',              '#', 'admin', sysdate(), '', null, '');
+-- 代码生成按钮
+insert into sys_menu values('1057', '生成查询', '115', '1',  '#', '',  'F', '0', '1', 'tool:gen:list',     '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1058', '生成修改', '115', '2',  '#', '',  'F', '0', '1', 'tool:gen:edit',     '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1059', '生成删除', '115', '3',  '#', '',  'F', '0', '1', 'tool:gen:remove',   '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1060', '预览代码', '115', '4',  '#', '',  'F', '0', '1', 'tool:gen:preview',  '#', 'admin', sysdate(), '', null, '');
+insert into sys_menu values('1061', '生成代码', '115', '5',  '#', '',  'F', '0', '1', 'tool:gen:code',     '#', 'admin', sysdate(), '', null, '');
+
+
+-- ----------------------------
+-- 6、用户和角色关联表  用户N-1角色
+-- ----------------------------
+drop table if exists sys_user_role;
+create table sys_user_role (
+  user_id   bigint(20) not null comment '用户ID',
+  role_id   bigint(20) not null comment '角色ID',
+  primary key(user_id, role_id)
+) engine=innodb comment = '用户和角色关联表';
+
+-- ----------------------------
+-- 初始化-用户和角色关联表数据
+-- ----------------------------
+insert into sys_user_role values ('1', '1');
+insert into sys_user_role values ('2', '2');
+
+
+-- ----------------------------
+-- 7、角色和菜单关联表  角色1-N菜单
+-- ----------------------------
+drop table if exists sys_role_menu;
+create table sys_role_menu (
+  role_id   bigint(20) not null comment '角色ID',
+  menu_id   bigint(20) not null comment '菜单ID',
+  primary key(role_id, menu_id)
+) engine=innodb comment = '角色和菜单关联表';
+
+-- ----------------------------
+-- 初始化-角色和菜单关联表数据
+-- ----------------------------
+insert into sys_role_menu values ('2', '1');
+insert into sys_role_menu values ('2', '2');
+insert into sys_role_menu values ('2', '3');
+insert into sys_role_menu values ('2', '100');
+insert into sys_role_menu values ('2', '101');
+insert into sys_role_menu values ('2', '102');
+insert into sys_role_menu values ('2', '103');
+insert into sys_role_menu values ('2', '104');
+insert into sys_role_menu values ('2', '105');
+insert into sys_role_menu values ('2', '106');
+insert into sys_role_menu values ('2', '107');
+insert into sys_role_menu values ('2', '108');
+insert into sys_role_menu values ('2', '109');
+insert into sys_role_menu values ('2', '110');
+insert into sys_role_menu values ('2', '111');
+insert into sys_role_menu values ('2', '112');
+insert into sys_role_menu values ('2', '113');
+insert into sys_role_menu values ('2', '114');
+insert into sys_role_menu values ('2', '115');
+insert into sys_role_menu values ('2', '116');
+insert into sys_role_menu values ('2', '500');
+insert into sys_role_menu values ('2', '501');
+insert into sys_role_menu values ('2', '1000');
+insert into sys_role_menu values ('2', '1001');
+insert into sys_role_menu values ('2', '1002');
+insert into sys_role_menu values ('2', '1003');
+insert into sys_role_menu values ('2', '1004');
+insert into sys_role_menu values ('2', '1005');
+insert into sys_role_menu values ('2', '1006');
+insert into sys_role_menu values ('2', '1007');
+insert into sys_role_menu values ('2', '1008');
+insert into sys_role_menu values ('2', '1009');
+insert into sys_role_menu values ('2', '1010');
+insert into sys_role_menu values ('2', '1011');
+insert into sys_role_menu values ('2', '1012');
+insert into sys_role_menu values ('2', '1013');
+insert into sys_role_menu values ('2', '1014');
+insert into sys_role_menu values ('2', '1015');
+insert into sys_role_menu values ('2', '1016');
+insert into sys_role_menu values ('2', '1017');
+insert into sys_role_menu values ('2', '1018');
+insert into sys_role_menu values ('2', '1019');
+insert into sys_role_menu values ('2', '1020');
+insert into sys_role_menu values ('2', '1021');
+insert into sys_role_menu values ('2', '1022');
+insert into sys_role_menu values ('2', '1023');
+insert into sys_role_menu values ('2', '1024');
+insert into sys_role_menu values ('2', '1025');
+insert into sys_role_menu values ('2', '1026');
+insert into sys_role_menu values ('2', '1027');
+insert into sys_role_menu values ('2', '1028');
+insert into sys_role_menu values ('2', '1029');
+insert into sys_role_menu values ('2', '1030');
+insert into sys_role_menu values ('2', '1031');
+insert into sys_role_menu values ('2', '1032');
+insert into sys_role_menu values ('2', '1033');
+insert into sys_role_menu values ('2', '1034');
+insert into sys_role_menu values ('2', '1035');
+insert into sys_role_menu values ('2', '1036');
+insert into sys_role_menu values ('2', '1037');
+insert into sys_role_menu values ('2', '1038');
+insert into sys_role_menu values ('2', '1039');
+insert into sys_role_menu values ('2', '1040');
+insert into sys_role_menu values ('2', '1041');
+insert into sys_role_menu values ('2', '1042');
+insert into sys_role_menu values ('2', '1043');
+insert into sys_role_menu values ('2', '1044');
+insert into sys_role_menu values ('2', '1045');
+insert into sys_role_menu values ('2', '1046');
+insert into sys_role_menu values ('2', '1047');
+insert into sys_role_menu values ('2', '1048');
+insert into sys_role_menu values ('2', '1049');
+insert into sys_role_menu values ('2', '1050');
+insert into sys_role_menu values ('2', '1051');
+insert into sys_role_menu values ('2', '1052');
+insert into sys_role_menu values ('2', '1053');
+insert into sys_role_menu values ('2', '1054');
+insert into sys_role_menu values ('2', '1055');
+insert into sys_role_menu values ('2', '1056');
+insert into sys_role_menu values ('2', '1057');
+insert into sys_role_menu values ('2', '1058');
+insert into sys_role_menu values ('2', '1059');
+insert into sys_role_menu values ('2', '1060');
+insert into sys_role_menu values ('2', '1061');
+
+-- ----------------------------
+-- 8、角色和部门关联表  角色1-N部门
+-- ----------------------------
+drop table if exists sys_role_dept;
+create table sys_role_dept (
+  role_id   bigint(20) not null comment '角色ID',
+  dept_id   bigint(20) not null comment '部门ID',
+  primary key(role_id, dept_id)
+) engine=innodb comment = '角色和部门关联表';
+
+-- ----------------------------
+-- 初始化-角色和部门关联表数据
+-- ----------------------------
+insert into sys_role_dept values ('2', '100');
+insert into sys_role_dept values ('2', '101');
+insert into sys_role_dept values ('2', '105');
+
+-- ----------------------------
+-- 9、用户与岗位关联表  用户1-N岗位
+-- ----------------------------
+drop table if exists sys_user_post;
+create table sys_user_post
+(
+  user_id   bigint(20) not null comment '用户ID',
+  post_id   bigint(20) not null comment '岗位ID',
+  primary key (user_id, post_id)
+) engine=innodb comment = '用户与岗位关联表';
+
+-- ----------------------------
+-- 初始化-用户与岗位关联表数据
+-- ----------------------------
+insert into sys_user_post values ('1', '1');
+insert into sys_user_post values ('2', '2');
+
+
+-- ----------------------------
+-- 10、操作日志记录
+-- ----------------------------
+drop table if exists sys_oper_log;
+create table sys_oper_log (
+  oper_id           bigint(20)      not null auto_increment    comment '日志主键',
+  title             varchar(50)     default ''                 comment '模块标题',
+  business_type     int(2)          default 0                  comment '业务类型(0其它 1新增 2修改 3删除)',
+  method            varchar(100)    default ''                 comment '方法名称',
+  request_method    varchar(10)     default ''                 comment '请求方式',
+  operator_type     int(1)          default 0                  comment '操作类别(0其它 1后台用户 2手机端用户)',
+  oper_name         varchar(50)     default ''                 comment '操作人员',
+  dept_name         varchar(50)     default ''                 comment '部门名称',
+  oper_url          varchar(255)    default ''                 comment '请求URL',
+  oper_ip           varchar(128)    default ''                 comment '主机地址',
+  oper_location     varchar(255)    default ''                 comment '操作地点',
+  oper_param        varchar(2000)   default ''                 comment '请求参数',
+  json_result       varchar(2000)   default ''                 comment '返回参数',
+  status            int(1)          default 0                  comment '操作状态(0正常 1异常)',
+  error_msg         varchar(2000)   default ''                 comment '错误消息',
+  oper_time         datetime                                   comment '操作时间',
+  primary key (oper_id)
+) engine=innodb auto_increment=100 comment = '操作日志记录';
+
+
+-- ----------------------------
+-- 11、字典类型表
+-- ----------------------------
+drop table if exists sys_dict_type;
+create table sys_dict_type
+(
+  dict_id          bigint(20)      not null auto_increment    comment '字典主键',
+  dict_name        varchar(100)    default ''                 comment '字典名称',
+  dict_type        varchar(100)    default ''                 comment '字典类型',
+  status           char(1)         default '0'                comment '状态(0正常 1停用)',
+  create_by        varchar(64)     default ''                 comment '创建者',
+  create_time      datetime                                   comment '创建时间',
+  update_by        varchar(64)     default ''                 comment '更新者',
+  update_time      datetime                                   comment '更新时间',
+  remark           varchar(500)    default null               comment '备注',
+  primary key (dict_id),
+  unique (dict_type)
+) engine=innodb auto_increment=100 comment = '字典类型表';
+
+insert into sys_dict_type values(1,  '用户性别', 'sys_user_sex',        '0', 'admin', sysdate(), '', null, '用户性别列表');
+insert into sys_dict_type values(2,  '菜单状态', 'sys_show_hide',       '0', 'admin', sysdate(), '', null, '菜单状态列表');
+insert into sys_dict_type values(3,  '系统开关', 'sys_normal_disable',  '0', 'admin', sysdate(), '', null, '系统开关列表');
+insert into sys_dict_type values(4,  '任务状态', 'sys_job_status',      '0', 'admin', sysdate(), '', null, '任务状态列表');
+insert into sys_dict_type values(5,  '任务分组', 'sys_job_group',       '0', 'admin', sysdate(), '', null, '任务分组列表');
+insert into sys_dict_type values(6,  '系统是否', 'sys_yes_no',          '0', 'admin', sysdate(), '', null, '系统是否列表');
+insert into sys_dict_type values(7,  '通知类型', 'sys_notice_type',     '0', 'admin', sysdate(), '', null, '通知类型列表');
+insert into sys_dict_type values(8,  '通知状态', 'sys_notice_status',   '0', 'admin', sysdate(), '', null, '通知状态列表');
+insert into sys_dict_type values(9,  '操作类型', 'sys_oper_type',       '0', 'admin', sysdate(), '', null, '操作类型列表');
+insert into sys_dict_type values(10, '系统状态', 'sys_common_status',   '0', 'admin', sysdate(), '', null, '登录状态列表');
+
+
+-- ----------------------------
+-- 12、字典数据表
+-- ----------------------------
+drop table if exists sys_dict_data;
+create table sys_dict_data
+(
+  dict_code        bigint(20)      not null auto_increment    comment '字典编码',
+  dict_sort        int(4)          default 0                  comment '字典排序',
+  dict_label       varchar(100)    default ''                 comment '字典标签',
+  dict_value       varchar(100)    default ''                 comment '字典键值',
+  dict_type        varchar(100)    default ''                 comment '字典类型',
+  css_class        varchar(100)    default null               comment '样式属性(其他样式扩展)',
+  list_class       varchar(100)    default null               comment '表格回显样式',
+  is_default       char(1)         default 'N'                comment '是否默认(Y是 N否)',
+  status           char(1)         default '0'                comment '状态(0正常 1停用)',
+  create_by        varchar(64)     default ''                 comment '创建者',
+  create_time      datetime                                   comment '创建时间',
+  update_by        varchar(64)     default ''                 comment '更新者',
+  update_time      datetime                                   comment '更新时间',
+  remark           varchar(500)    default null               comment '备注',
+  primary key (dict_code)
+) engine=innodb auto_increment=100 comment = '字典数据表';
+
+insert into sys_dict_data values(1,  1,  '男',       '0',       'sys_user_sex',        '',   '',        'Y', '0', 'admin', sysdate(), '', null, '性别男');
+insert into sys_dict_data values(2,  2,  '女',       '1',       'sys_user_sex',        '',   '',        'N', '0', 'admin', sysdate(), '', null, '性别女');
+insert into sys_dict_data values(3,  3,  '未知',     '2',       'sys_user_sex',        '',   '',        'N', '0', 'admin', sysdate(), '', null, '性别未知');
+insert into sys_dict_data values(4,  1,  '显示',     '0',       'sys_show_hide',       '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '显示菜单');
+insert into sys_dict_data values(5,  2,  '隐藏',     '1',       'sys_show_hide',       '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '隐藏菜单');
+insert into sys_dict_data values(6,  1,  '正常',     '0',       'sys_normal_disable',  '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态');
+insert into sys_dict_data values(7,  2,  '停用',     '1',       'sys_normal_disable',  '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '停用状态');
+insert into sys_dict_data values(8,  1,  '正常',     '0',       'sys_job_status',      '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态');
+insert into sys_dict_data values(9,  2,  '暂停',     '1',       'sys_job_status',      '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '停用状态');
+insert into sys_dict_data values(10, 1,  '默认',     'DEFAULT', 'sys_job_group',       '',   '',        'Y', '0', 'admin', sysdate(), '', null, '默认分组');
+insert into sys_dict_data values(11, 2,  '系统',     'SYSTEM',  'sys_job_group',       '',   '',        'N', '0', 'admin', sysdate(), '', null, '系统分组');
+insert into sys_dict_data values(12, 1,  '是',       'Y',       'sys_yes_no',          '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '系统默认是');
+insert into sys_dict_data values(13, 2,  '否',       'N',       'sys_yes_no',          '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '系统默认否');
+insert into sys_dict_data values(14, 1,  '通知',     '1',       'sys_notice_type',     '',   'warning', 'Y', '0', 'admin', sysdate(), '', null, '通知');
+insert into sys_dict_data values(15, 2,  '公告',     '2',       'sys_notice_type',     '',   'success', 'N', '0', 'admin', sysdate(), '', null, '公告');
+insert into sys_dict_data values(16, 1,  '正常',     '0',       'sys_notice_status',   '',   'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态');
+insert into sys_dict_data values(17, 2,  '关闭',     '1',       'sys_notice_status',   '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '关闭状态');
+insert into sys_dict_data values(18, 99, '其他',     '0',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate(), '', null, '其他操作');
+insert into sys_dict_data values(19, 1,  '新增',     '1',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate(), '', null, '新增操作');
+insert into sys_dict_data values(20, 2,  '修改',     '2',       'sys_oper_type',       '',   'info',    'N', '0', 'admin', sysdate(), '', null, '修改操作');
+insert into sys_dict_data values(21, 3,  '删除',     '3',       'sys_oper_type',       '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '删除操作');
+insert into sys_dict_data values(22, 4,  '授权',     '4',       'sys_oper_type',       '',   'primary', 'N', '0', 'admin', sysdate(), '', null, '授权操作');
+insert into sys_dict_data values(23, 5,  '导出',     '5',       'sys_oper_type',       '',   'warning', 'N', '0', 'admin', sysdate(), '', null, '导出操作');
+insert into sys_dict_data values(24, 6,  '导入',     '6',       'sys_oper_type',       '',   'warning', 'N', '0', 'admin', sysdate(), '', null, '导入操作');
+insert into sys_dict_data values(25, 7,  '强退',     '7',       'sys_oper_type',       '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '强退操作');
+insert into sys_dict_data values(26, 8,  '生成代码', '8',       'sys_oper_type',       '',   'warning', 'N', '0', 'admin', sysdate(), '', null, '生成操作');
+insert into sys_dict_data values(27, 9,  '清空数据', '9',       'sys_oper_type',       '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '清空操作');
+insert into sys_dict_data values(28, 1,  '成功',     '0',       'sys_common_status',   '',   'primary', 'N', '0', 'admin', sysdate(), '', null, '正常状态');
+insert into sys_dict_data values(29, 2,  '失败',     '1',       'sys_common_status',   '',   'danger',  'N', '0', 'admin', sysdate(), '', null, '停用状态');
+
+
+-- ----------------------------
+-- 13、参数配置表
+-- ----------------------------
+drop table if exists sys_config;
+create table sys_config (
+  config_id         int(5)          not null auto_increment    comment '参数主键',
+  config_name       varchar(100)    default ''                 comment '参数名称',
+  config_key        varchar(100)    default ''                 comment '参数键名',
+  config_value      varchar(500)    default ''                 comment '参数键值',
+  config_type       char(1)         default 'N'                comment '系统内置(Y是 N否)',
+  create_by         varchar(64)     default ''                 comment '创建者',
+  create_time       datetime                                   comment '创建时间',
+  update_by         varchar(64)     default ''                 comment '更新者',
+  update_time       datetime                                   comment '更新时间',
+  remark            varchar(500)    default null               comment '备注',
+  primary key (config_id)
+) engine=innodb auto_increment=100 comment = '参数配置表';
+
+insert into sys_config values(1, '主框架页-默认皮肤样式名称',     'sys.index.skinName',               'skin-blue',     'Y', 'admin', sysdate(), '', null, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow');
+insert into sys_config values(2, '用户管理-账号初始密码',         'sys.user.initPassword',            '123456',        'Y', 'admin', sysdate(), '', null, '初始化密码 123456');
+insert into sys_config values(3, '主框架页-侧边栏主题',           'sys.index.sideTheme',              'theme-dark',    'Y', 'admin', sysdate(), '', null, '深黑主题theme-dark,浅色主题theme-light,深蓝主题theme-blue');
+insert into sys_config values(4, '账号自助-是否开启用户注册功能', 'sys.account.registerUser',         'false',         'Y', 'admin', sysdate(), '', null, '是否开启注册用户功能(true开启,false关闭)');
+insert into sys_config values(5, '用户管理-密码字符范围',         'sys.account.chrtype',              '0',             'Y', 'admin', sysdate(), '', null, '默认任意字符范围,0任意(密码可以输入任意字符),1数字(密码只能为0-9数字),2英文字母(密码只能为a-z和A-Z字母),3字母和数字(密码必须包含字母,数字),4字母数字和特殊字符(目前支持的特殊字符包括:~!@#$%^&*()-=_+)');
+insert into sys_config values(6, '用户管理-初始密码修改策略',     'sys.account.initPasswordModify',   '0',             'Y', 'admin', sysdate(), '', null, '0:初始密码修改策略关闭,没有任何提示,1:提醒用户,如果未修改初始密码,则在登录时就会提醒修改密码对话框');
+insert into sys_config values(7, '用户管理-账号密码更新周期',     'sys.account.passwordValidateDays', '0',             'Y', 'admin', sysdate(), '', null, '密码更新周期(填写数字,数据初始化值为0不限制,若修改必须为大于0小于365的正整数),如果超过这个周期登录系统时,则在登录时就会提醒修改密码对话框');
+insert into sys_config values(8, '主框架页-菜单导航显示风格',     'sys.index.menuStyle',              'default',       'Y', 'admin', sysdate(), '', null, '菜单导航显示风格(default为左侧导航菜单,topnav为顶部导航菜单)');
+insert into sys_config values(9, '主框架页-是否开启页脚',         'sys.index.ignoreFooter',           'true',          'Y', 'admin', sysdate(), '', null, '是否开启底部页脚显示(true显示,false隐藏)');
+
+
+-- ----------------------------
+-- 14、系统访问记录
+-- ----------------------------
+drop table if exists sys_logininfor;
+create table sys_logininfor (
+  info_id        bigint(20)     not null auto_increment   comment '访问ID',
+  login_name     varchar(50)    default ''                comment '登录账号',
+  ipaddr         varchar(128)   default ''                comment '登录IP地址',
+  login_location varchar(255)   default ''                comment '登录地点',
+  browser        varchar(50)    default ''                comment '浏览器类型',
+  os             varchar(50)    default ''                comment '操作系统',
+  status         char(1)        default '0'               comment '登录状态(0成功 1失败)',
+  msg            varchar(255)   default ''                comment '提示消息',
+  login_time     datetime                                 comment '访问时间',
+  primary key (info_id)
+) engine=innodb auto_increment=100 comment = '系统访问记录';
+
+
+-- ----------------------------
+-- 15、在线用户记录
+-- ----------------------------
+drop table if exists sys_user_online;
+create table sys_user_online (
+  sessionId         varchar(50)   default ''                comment '用户会话id',
+  login_name        varchar(50)   default ''                comment '登录账号',
+  dept_name         varchar(50)   default ''                comment '部门名称',
+  ipaddr            varchar(128)  default ''                comment '登录IP地址',
+  login_location    varchar(255)  default ''                comment '登录地点',
+  browser           varchar(50)   default ''                comment '浏览器类型',
+  os                varchar(50)   default ''                comment '操作系统',
+  status            varchar(10)   default ''                comment '在线状态on_line在线off_line离线',
+  start_timestamp   datetime                                comment 'session创建时间',
+  last_access_time  datetime                                comment 'session最后访问时间',
+  expire_time       int(5)        default 0                 comment '超时时间,单位为分钟',
+  primary key (sessionId)
+) engine=innodb comment = '在线用户记录';
+
+
+-- ----------------------------
+-- 16、定时任务调度表
+-- ----------------------------
+drop table if exists sys_job;
+create table sys_job (
+  job_id              bigint(20)    not null auto_increment    comment '任务ID',
+  job_name            varchar(64)   default ''                 comment '任务名称',
+  job_group           varchar(64)   default 'DEFAULT'          comment '任务组名',
+  invoke_target       varchar(500)  not null                   comment '调用目标字符串',
+  cron_expression     varchar(255)  default ''                 comment 'cron执行表达式',
+  misfire_policy      varchar(20)   default '3'                comment '计划执行错误策略(1立即执行 2执行一次 3放弃执行)',
+  concurrent          char(1)       default '1'                comment '是否并发执行(0允许 1禁止)',
+  status              char(1)       default '0'                comment '状态(0正常 1暂停)',
+  create_by           varchar(64)   default ''                 comment '创建者',
+  create_time         datetime                                 comment '创建时间',
+  update_by           varchar(64)   default ''                 comment '更新者',
+  update_time         datetime                                 comment '更新时间',
+  remark              varchar(500)  default ''                 comment '备注信息',
+  primary key (job_id, job_name, job_group)
+) engine=innodb auto_increment=100 comment = '定时任务调度表';
+
+insert into sys_job values(1, '系统默认(无参)', 'DEFAULT', 'ztTask.ztNoParams',        '0/10 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, '');
+insert into sys_job values(2, '系统默认(有参)', 'DEFAULT', 'ztTask.ztParams(\'ztmap\')',  '0/15 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, '');
+insert into sys_job values(3, '系统默认(多参)', 'DEFAULT', 'ztTask.ztMultipleParams(\'ztmap\', true, 2000L, 316.50D, 100)',  '0/20 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, '');
+
+
+-- ----------------------------
+-- 17、定时任务调度日志表
+-- ----------------------------
+drop table if exists sys_job_log;
+create table sys_job_log (
+  job_log_id          bigint(20)     not null auto_increment    comment '任务日志ID',
+  job_name            varchar(64)    not null                   comment '任务名称',
+  job_group           varchar(64)    not null                   comment '任务组名',
+  invoke_target       varchar(500)   not null                   comment '调用目标字符串',
+  job_message         varchar(500)                              comment '日志信息',
+  status              char(1)        default '0'                comment '执行状态(0正常 1失败)',
+  exception_info      varchar(2000)  default ''                 comment '异常信息',
+  create_time         datetime                                  comment '创建时间',
+  primary key (job_log_id)
+) engine=innodb comment = '定时任务调度日志表';
+
+
+-- ----------------------------
+-- 18、通知公告表
+-- ----------------------------
+drop table if exists sys_notice;
+create table sys_notice (
+  notice_id         int(4)          not null auto_increment    comment '公告ID',
+  notice_title      varchar(50)     not null                   comment '公告标题',
+  notice_type       char(1)         not null                   comment '公告类型(1通知 2公告)',
+  notice_content    varchar(2000)   default null               comment '公告内容',
+  status            char(1)         default '0'                comment '公告状态(0正常 1关闭)',
+  create_by         varchar(64)     default ''                 comment '创建者',
+  create_time       datetime                                   comment '创建时间',
+  update_by         varchar(64)     default ''                 comment '更新者',
+  update_time       datetime                                   comment '更新时间',
+  remark            varchar(255)    default null               comment '备注',
+  primary key (notice_id)
+) engine=innodb auto_increment=10 comment = '通知公告表';
+
+-- ----------------------------
+-- 初始化-公告信息表数据
+-- ----------------------------
+insert into sys_notice values('1', '温馨提醒:2018-07-01 臻图新版本发布啦', '2', '新版本内容', '0', 'admin', sysdate(), '', null, '管理员');
+insert into sys_notice values('2', '维护通知:2018-07-01 臻图系统凌晨维护', '1', '维护内容',   '0', 'admin', sysdate(), '', null, '管理员');
+
+
+-- ----------------------------
+-- 19、代码生成业务表
+-- ----------------------------
+drop table if exists gen_table;
+create table gen_table (
+  table_id             bigint(20)      not null auto_increment    comment '编号',
+  table_name           varchar(200)    default ''                 comment '表名称',
+  table_comment        varchar(500)    default ''                 comment '表描述',
+  sub_table_name       varchar(64)     default null               comment '关联子表的表名',
+  sub_table_fk_name    varchar(64)     default null               comment '子表关联的外键名',
+  class_name           varchar(100)    default ''                 comment '实体类名称',
+  tpl_category         varchar(200)    default 'crud'             comment '使用的模板(crud单表操作 tree树表操作 sub主子表操作)',
+  package_name         varchar(100)                               comment '生成包路径',
+  module_name          varchar(30)                                comment '生成模块名',
+  business_name        varchar(30)                                comment '生成业务名',
+  function_name        varchar(50)                                comment '生成功能名',
+  function_author      varchar(50)                                comment '生成功能作者',
+  gen_type             char(1)         default '0'                comment '生成代码方式(0zip压缩包 1自定义路径)',
+  gen_path             varchar(200)    default '/'                comment '生成路径(不填默认项目路径)',
+  options              varchar(1000)                              comment '其它生成选项',
+  create_by            varchar(64)     default ''                 comment '创建者',
+  create_time 	       datetime                                   comment '创建时间',
+  update_by            varchar(64)     default ''                 comment '更新者',
+  update_time          datetime                                   comment '更新时间',
+  remark               varchar(500)    default null               comment '备注',
+  primary key (table_id)
+) engine=innodb auto_increment=1 comment = '代码生成业务表';
+
+
+-- ----------------------------
+-- 20、代码生成业务表字段
+-- ----------------------------
+drop table if exists gen_table_column;
+create table gen_table_column (
+  column_id         bigint(20)      not null auto_increment    comment '编号',
+  table_id          varchar(64)                                comment '归属表编号',
+  column_name       varchar(200)                               comment '列名称',
+  column_comment    varchar(500)                               comment '列描述',
+  column_type       varchar(100)                               comment '列类型',
+  java_type         varchar(500)                               comment 'JAVA类型',
+  java_field        varchar(200)                               comment 'JAVA字段名',
+  is_pk             char(1)                                    comment '是否主键(1是)',
+  is_increment      char(1)                                    comment '是否自增(1是)',
+  is_required       char(1)                                    comment '是否必填(1是)',
+  is_insert         char(1)                                    comment '是否为插入字段(1是)',
+  is_edit           char(1)                                    comment '是否编辑字段(1是)',
+  is_list           char(1)                                    comment '是否列表字段(1是)',
+  is_query          char(1)                                    comment '是否查询字段(1是)',
+  query_type        varchar(200)    default 'EQ'               comment '查询方式(等于、不等于、大于、小于、范围)',
+  html_type         varchar(200)                               comment '显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)',
+  dict_type         varchar(200)    default ''                 comment '字典类型',
+  sort              int                                        comment '排序',
+  create_by         varchar(64)     default ''                 comment '创建者',
+  create_time 	    datetime                                   comment '创建时间',
+  update_by         varchar(64)     default ''                 comment '更新者',
+  update_time       datetime                                   comment '更新时间',
+  primary key (column_id)
+) engine=innodb auto_increment=1 comment = '代码生成业务表字段';

+ 21 - 0
zhny_admin/src/main/java/com/ztmap/ZTMapApplication.java

@@ -0,0 +1,21 @@
+package com.ztmap;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+
+/**
+ * 启动程序
+ * 
+ * @author ztmap
+ */
+@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
+public class ZTMapApplication
+{
+    public static void main(String[] args)
+    {
+        // System.setProperty("spring.devtools.restart.enabled", "false");
+        SpringApplication.run(ZTMapApplication.class, args);
+        System.out.println("智慧能源后台启动成功");
+    }
+}

+ 18 - 0
zhny_admin/src/main/java/com/ztmap/ZTMapServletInitializer.java

@@ -0,0 +1,18 @@
+package com.ztmap;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+/**
+ * web容器中进行部署
+ * 
+ * @author ztmap
+ */
+public class ZTMapServletInitializer extends SpringBootServletInitializer
+{
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
+    {
+        return application.sources(ZTMapApplication.class);
+    }
+}

+ 49 - 0
zhny_admin/src/main/java/com/ztmap/common/constant/CommonMap.java

@@ -0,0 +1,49 @@
+package com.ztmap.common.constant;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 通用数据库映射Map数据
+ * 
+ * @author ztmap
+ */
+public class CommonMap
+{
+    /** 状态编码转换 */
+    public static Map<String, String> javaTypeMap = new HashMap<String, String>();
+
+    static
+    {
+        initJavaTypeMap();
+    }
+
+    /**
+     * 返回状态映射
+     */
+    public static void initJavaTypeMap()
+    {
+        javaTypeMap.put("tinyint", "Integer");
+        javaTypeMap.put("smallint", "Integer");
+        javaTypeMap.put("mediumint", "Integer");
+        javaTypeMap.put("int", "Integer");
+        javaTypeMap.put("number", "Integer");
+        javaTypeMap.put("integer", "integer");
+        javaTypeMap.put("bigint", "Long");
+        javaTypeMap.put("float", "Float");
+        javaTypeMap.put("double", "Double");
+        javaTypeMap.put("decimal", "BigDecimal");
+        javaTypeMap.put("bit", "Boolean");
+        javaTypeMap.put("char", "String");
+        javaTypeMap.put("varchar", "String");
+        javaTypeMap.put("varchar2", "String");
+        javaTypeMap.put("tinytext", "String");
+        javaTypeMap.put("text", "String");
+        javaTypeMap.put("mediumtext", "String");
+        javaTypeMap.put("longtext", "String");
+        javaTypeMap.put("time", "Date");
+        javaTypeMap.put("date", "Date");
+        javaTypeMap.put("datetime", "Date");
+        javaTypeMap.put("timestamp", "Date");
+    }
+}

+ 127 - 0
zhny_admin/src/main/java/com/ztmap/common/constant/Constants.java

@@ -0,0 +1,127 @@
+package com.ztmap.common.constant;
+
+/**
+ * 通用常量信息
+ * 
+ * @author ztmap
+ */
+public class Constants
+{
+    /**
+     * UTF-8 字符集
+     */
+    public static final String UTF8 = "UTF-8";
+
+    /**
+     * GBK 字符集
+     */
+    public static final String GBK = "GBK";
+
+    /**
+     * 通用成功标识
+     */
+    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 PAGE_NUM = "pageNum";
+
+    /**
+     * 每页显示记录数
+     */
+    public static final String PAGE_SIZE = "pageSize";
+
+    /**
+     * 排序列
+     */
+    public static final String ORDER_BY_COLUMN = "orderByColumn";
+
+    /**
+     * 排序的方向 "desc" 或者 "asc".
+     */
+    public static final String IS_ASC = "isAsc";
+    
+    /**
+     * 系统用户授权缓存
+     */
+    public static final String SYS_AUTH_CACHE = "sys-authCache";
+
+    /**
+     * 参数管理 cache name
+     */
+    public static final String SYS_CONFIG_CACHE = "sys-config";
+
+    /**
+     * 参数管理 cache key
+     */
+    public static final String SYS_CONFIG_KEY = "sys_config:";
+
+    /**
+     * 字典管理 cache name
+     */
+    public static final String SYS_DICT_CACHE = "sys-dict";
+
+    /**
+     * 字典管理 cache key
+     */
+    public static final String SYS_DICT_KEY = "sys_dict:";
+
+    /**
+     * 资源映射路径 前缀
+     */
+    public static final String RESOURCE_PREFIX = "/profile";
+
+    /**
+     * 登录用户KEY
+     */
+    public static final String LOGIN_USER_KEY = "login_user_key";
+
+    /**
+     * TOKEN前缀
+     */
+    public static final String TOKEN_PREFIX = "Bearer ";
+
+    /**
+     * 登录TOKEN格式
+     */
+    public static final String LOGIN_TOKEN_KEY = "login_tokens:";
+
+    /**
+     * 字典农田水利相关
+     */
+    public static final String 	IRRIGATION_AND_WATER_CONSERVANCY="Irrigation_and_water_conservancy";
+    /**
+     * 字典渔业生产相关
+     */
+    public static final String FISHERY_PRODUCTION="fishery_production";
+    /**
+     * 企业类型
+     */
+    public static final String ENTERPRISE_TYPE="enterprise_type";
+}

+ 111 - 0
zhny_admin/src/main/java/com/ztmap/common/constant/GenConstants.java

@@ -0,0 +1,111 @@
+package com.ztmap.common.constant;
+
+/**
+ * 代码生成通用常量
+ * 
+ * @author ztmap
+ */
+public class GenConstants
+{
+    /** 单表(增删改查) */
+    public static final String TPL_CRUD = "crud";
+
+    /** 树表(增删改查) */
+    public static final String TPL_TREE = "tree";
+
+    /** 主子表(增删改查) */
+    public static final String TPL_SUB = "sub";
+
+    /** 树编码字段 */
+    public static final String TREE_CODE = "treeCode";
+
+    /** 树父编码字段 */
+    public static final String TREE_PARENT_CODE = "treeParentCode";
+
+    /** 树名称字段 */
+    public static final String TREE_NAME = "treeName";
+
+    /** 上级菜单ID字段 */
+    public static final String PARENT_MENU_ID = "parentMenuId";
+
+    /** 上级菜单名称字段 */
+    public static final String PARENT_MENU_NAME = "parentMenuName";
+
+    /** 数据库字符串类型 */
+    public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
+
+    /** 数据库文本类型 */
+    public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
+
+    /** 数据库时间类型 */
+    public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
+
+    /** 数据库数字类型 */
+    public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
+            "bit", "bigint", "float", "double", "decimal" };
+
+    /** 页面不需要编辑字段 */
+    public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
+
+    /** 页面不需要显示的列表字段 */
+    public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
+            "update_time" };
+
+    /** 页面不需要查询字段 */
+    public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
+            "update_time", "remark" };
+
+    /** Entity基类字段 */
+    public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
+
+    /** Tree基类字段 */
+    public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors" };
+
+    /** 文本框 */
+    public static final String HTML_INPUT = "input";
+
+    /** 文本域 */
+    public static final String HTML_TEXTAREA = "textarea";
+
+    /** 下拉框 */
+    public static final String HTML_SELECT = "select";
+
+    /** 单选框 */
+    public static final String HTML_RADIO = "radio";
+
+    /** 复选框 */
+    public static final String HTML_CHECKBOX = "checkbox";
+
+    /** 日期控件 */
+    public static final String HTML_DATETIME = "datetime";
+
+    /** 上传控件 */
+    public static final String HTML_UPLOAD = "upload";
+
+    /** 富文本控件 */
+    public static final String HTML_SUMMERNOTE = "summernote";
+
+    /** 字符串类型 */
+    public static final String TYPE_STRING = "String";
+
+    /** 整型 */
+    public static final String TYPE_INTEGER = "Integer";
+
+    /** 长整型 */
+    public static final String TYPE_LONG = "Long";
+
+    /** 浮点型 */
+    public static final String TYPE_DOUBLE = "Double";
+
+    /** 高精度计算类型 */
+    public static final String TYPE_BIGDECIMAL = "BigDecimal";
+
+    /** 时间类型 */
+    public static final String TYPE_DATE = "Date";
+
+    /** 模糊查询 */
+    public static final String QUERY_LIKE = "LIKE";
+
+    /** 需要 */
+    public static final String REQUIRE = "1";
+}

+ 27 - 0
zhny_admin/src/main/java/com/ztmap/common/constant/PermissionConstants.java

@@ -0,0 +1,27 @@
+package com.ztmap.common.constant;
+
+/**
+ * 权限通用常量
+ * 
+ * @author ztmap
+ */
+public class PermissionConstants
+{
+    /** 新增权限 */
+    public static final String ADD_PERMISSION = "add";
+
+    /** 修改权限 */
+    public static final String EDIT_PERMISSION = "edit";
+
+    /** 删除权限 */
+    public static final String REMOVE_PERMISSION = "remove";
+    
+    /** 导出权限 */
+    public static final String EXPORT_PERMISSION = "export";
+
+    /** 显示权限 */
+    public static final String VIEW_PERMISSION = "view";
+
+    /** 查询权限 */
+    public static final String LIST_PERMISSION = "list";
+}

+ 29 - 0
zhny_admin/src/main/java/com/ztmap/common/constant/RepairStatus.java

@@ -0,0 +1,29 @@
+package com.ztmap.common.constant;
+
+public class RepairStatus {
+    /**
+     * 待指派
+     */
+    public static final int PENDINGREVIEW = 1;
+    /**
+     * 待处理
+     */
+    public static final int TOBEPROCESSED = 2;
+    /**
+     * 退回
+     */
+    public static final int GOBACK = 3;
+    /**
+     * 维修中
+     */
+    public static final int INMAINTENANCE = 4;
+    /**
+     * 待审核
+     */
+    public static final int PENDING = 5;
+    /**
+     * 完成
+     */
+    public static final int COMPLETE = 6;
+
+}

+ 65 - 0
zhny_admin/src/main/java/com/ztmap/common/constant/ScheduleConstants.java

@@ -0,0 +1,65 @@
+package com.ztmap.common.constant;
+
+/**
+ * 任务调度通用常量
+ * 
+ * @author ztmap
+ */
+public class ScheduleConstants
+{
+    public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
+
+    /** 执行目标key */
+    public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
+
+    /** 默认 */
+    public static final String MISFIRE_DEFAULT = "0";
+
+    /** 立即触发执行 */
+    public static final String MISFIRE_IGNORE_MISFIRES = "1";
+
+    /** 触发一次执行 */
+    public static final String MISFIRE_FIRE_AND_PROCEED = "2";
+
+    /** 不触发立即执行 */
+    public static final String MISFIRE_DO_NOTHING = "3";
+
+    /**
+     * 每天凌晨30分执行一次
+     */
+    public static final String RUN_DAY = "0 30 0 * * ? ";
+
+    /**
+     * 每周一凌晨30分执行一次
+     */
+    public static final String RUN_WEEK= "0 30 0 ? * MON";
+
+    /**
+     * 每月一号凌晨30分执行一次
+     */
+    public static final String RUN_MONTH= "0 30 0 1 * ?";
+
+    public enum Status
+    {
+        /**
+         * 正常
+         */
+        NORMAL("1"),
+        /**
+         * 暂停
+         */
+        PAUSE("2");
+
+        private String value;
+
+        private Status(String value)
+        {
+            this.value = value;
+        }
+
+        public String getValue()
+        {
+            return value;
+        }
+    }
+}

+ 79 - 0
zhny_admin/src/main/java/com/ztmap/common/constant/ShiroConstants.java

@@ -0,0 +1,79 @@
+package com.ztmap.common.constant;
+
+/**
+ * Shiro通用常量
+ * 
+ * @author ztmap
+ */
+public class ShiroConstants
+{
+    /**
+     * 当前登录的用户
+     */
+    public static final String CURRENT_USER = "currentUser";
+
+    /**
+     * 用户名字段
+     */
+    public static final String CURRENT_USERNAME = "username";
+
+    /**
+     * 锁定屏幕字段
+     */
+    public static final String LOCK_SCREEN = "lockscreen";
+
+    /**
+     * 消息key
+     */
+    public static final String MESSAGE = "message";
+
+    /**
+     * 错误key
+     */
+    public static final String ERROR = "errorMsg";
+
+    /**
+     * 编码格式
+     */
+    public static final String ENCODING = "UTF-8";
+
+    /**
+     * 当前在线会话
+     */
+    public static final String ONLINE_SESSION = "online_session";
+
+    /**
+     * 验证码key
+     */
+    public static final String CURRENT_CAPTCHA = "captcha";
+
+    /**
+     * 验证码开关
+     */
+    public static final String CURRENT_ENABLED = "captchaEnabled";
+
+    /**
+     * 验证码类型
+     */
+    public static final String CURRENT_TYPE = "captchaType";
+
+    /**
+     * 验证码
+     */
+    public static final String CURRENT_VALIDATECODE = "validateCode";
+
+    /**
+     * 验证码错误
+     */
+    public static final String CAPTCHA_ERROR = "captchaError";
+
+    /**
+     * 登录记录缓存
+     */
+    public static final String LOGINRECORDCACHE = "loginRecordCache";
+
+    /**
+     * 系统活跃用户缓存
+     */
+    public static final String SYS_USERCACHE = "sys-userCache";
+}

+ 54 - 0
zhny_admin/src/main/java/com/ztmap/common/constant/SupportDataType.java

@@ -0,0 +1,54 @@
+package com.ztmap.common.constant;
+
+public enum SupportDataType {
+	ShapeType {
+		@Override
+		public String toString() {
+			return "ShapeType";
+		}
+	},
+	StringType {
+		@Override
+		public String toString() {
+			return "StringType";
+		}
+	},
+	NumberType {
+		@Override
+		public String toString() {
+			return "NumberType";
+		}
+	},
+	DateType {
+		@Override
+		public String toString() {
+			return "DateType";
+		}
+	},
+	TimeType {
+		@Override
+		public String toString() {
+			return "TimeType";
+		}
+	};
+	public abstract String toString();
+	public static SupportDataType fromString(String name){
+		if("NumberType".equals(name)){
+			return NumberType;
+		}
+		if("DateType".equals(name)){
+			return DateType;
+		}
+		if("TimeType".equals(name)){
+			return TimeType;
+		}
+		if("StringType".equals(name)){
+			return StringType;
+		}
+		if("ShapeType".equals(name)){
+			return ShapeType;
+		}
+		return null;
+		
+	}
+}

+ 105 - 0
zhny_admin/src/main/java/com/ztmap/common/constant/UserConstants.java

@@ -0,0 +1,105 @@
+package com.ztmap.common.constant;
+
+/**
+ * 用户常量信息
+ * 
+ * @author ztmap
+ */
+public class UserConstants
+{
+    /** 正常状态 */
+    public static final String NORMAL = "0";
+
+    /** 异常状态 */
+    public static final String EXCEPTION = "1";
+
+    /** 用户封禁状态 */
+    public static final String USER_DISABLE = "1";
+
+    /** 角色封禁状态 */
+    public static final String ROLE_DISABLE = "1";
+
+    /** 部门正常状态 */
+    public static final String DEPT_NORMAL = "0";
+
+    /** 部门停用状态 */
+    public static final String DEPT_DISABLE = "1";
+
+    /** 字典正常状态 */
+    public static final String DICT_NORMAL = "0";
+
+    /** 是否为系统默认(是) */
+    public static final String YES = "Y";
+
+    /**
+     * 用户名长度限制
+     */
+    public static final int USERNAME_MIN_LENGTH = 2;
+    public static final int USERNAME_MAX_LENGTH = 20;
+
+    /** 登录名称是否唯一的返回结果码 */
+    public final static String USER_NAME_UNIQUE = "0";
+    public final static String USER_NAME_NOT_UNIQUE = "1";
+
+    /** 手机号码是否唯一的返回结果 */
+    public final static String USER_PHONE_UNIQUE = "0";
+    public final static String USER_PHONE_NOT_UNIQUE = "1";
+
+    /** e-mail 是否唯一的返回结果 */
+    public final static String USER_EMAIL_UNIQUE = "0";
+    public final static String USER_EMAIL_NOT_UNIQUE = "1";
+
+    /** 部门名称是否唯一的返回结果码 */
+    public final static String DEPT_NAME_UNIQUE = "0";
+    public final static String DEPT_NAME_NOT_UNIQUE = "1";
+
+    /** 角色名称是否唯一的返回结果码 */
+    public final static String ROLE_NAME_UNIQUE = "0";
+    public final static String ROLE_NAME_NOT_UNIQUE = "1";
+
+    /** 岗位名称是否唯一的返回结果码 */
+    public final static String POST_NAME_UNIQUE = "0";
+    public final static String POST_NAME_NOT_UNIQUE = "1";
+
+    /** 角色权限是否唯一的返回结果码 */
+    public final static String ROLE_KEY_UNIQUE = "0";
+    public final static String ROLE_KEY_NOT_UNIQUE = "1";
+
+    /** 岗位编码是否唯一的返回结果码 */
+    public final static String POST_CODE_UNIQUE = "0";
+    public final static String POST_CODE_NOT_UNIQUE = "1";
+
+    /** 菜单名称是否唯一的返回结果码 */
+    public final static String MENU_NAME_UNIQUE = "0";
+    public final static String MENU_NAME_NOT_UNIQUE = "1";
+
+    /** 字典类型是否唯一的返回结果码 */
+    public final static String DICT_TYPE_UNIQUE = "0";
+    public final static String DICT_TYPE_NOT_UNIQUE = "1";
+
+    /** 参数键名是否唯一的返回结果码 */
+    public final static String CONFIG_KEY_UNIQUE = "0";
+    public final static String CONFIG_KEY_NOT_UNIQUE = "1";
+
+    /**
+     * 密码长度限制
+     */
+    public static final int PASSWORD_MIN_LENGTH = 5;
+    public static final int PASSWORD_MAX_LENGTH = 20;
+
+    /**
+     * 用户类型
+     */
+    public static final String SYSTEM_USER_TYPE = "00";
+    public static final String REGISTER_USER_TYPE = "01";
+
+    /**
+     * 手机号码格式限制
+     */
+    public static final String MOBILE_PHONE_NUMBER_PATTERN = "^0{0,1}(13[0-9]|15[0-9]|14[0-9]|18[0-9])[0-9]{8}$";
+
+    /**
+     * 邮箱格式限制
+     */
+    public static final String EMAIL_PATTERN = "^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?";
+}

+ 30 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/BusinessException.java

@@ -0,0 +1,30 @@
+package com.ztmap.common.exception;
+
+/**
+ * 业务异常
+ * 
+ * @author ztmap
+ */
+public class BusinessException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    protected final String message;
+
+    public BusinessException(String message)
+    {
+        this.message = message;
+    }
+
+    public BusinessException(String message, Throwable e)
+    {
+        super(message, e);
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return message;
+    }
+}

+ 15 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/DemoModeException.java

@@ -0,0 +1,15 @@
+package com.ztmap.common.exception;
+
+/**
+ * 演示模式异常
+ * 
+ * @author ztmap
+ */
+public class DemoModeException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public DemoModeException()
+    {
+    }
+}

+ 26 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/UtilException.java

@@ -0,0 +1,26 @@
+package com.ztmap.common.exception;
+
+/**
+ * 工具类异常
+ * 
+ * @author ztmap
+ */
+public class UtilException extends RuntimeException
+{
+    private static final long serialVersionUID = 8247610319171014183L;
+
+    public UtilException(Throwable e)
+    {
+        super(e.getMessage(), e);
+    }
+
+    public UtilException(String message)
+    {
+        super(message);
+    }
+
+    public UtilException(String message, Throwable throwable)
+    {
+        super(message, throwable);
+    }
+}

+ 103 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/base/BaseException.java

@@ -0,0 +1,103 @@
+package com.ztmap.common.exception.base;
+
+import org.springframework.util.StringUtils;
+import com.ztmap.common.utils.MessageUtils;
+
+/**
+ * 基础异常
+ * 
+ * @author ztmap
+ */
+public class BaseException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 所属模块
+     */
+    private String module;
+
+    /**
+     * 错误码
+     */
+    private String code;
+
+    /**
+     * 错误码对应的参数
+     */
+    private Object[] args;
+
+    /**
+     * 错误消息
+     */
+    private String defaultMessage;
+
+    public BaseException(String module, String code, Object[] args, String defaultMessage)
+    {
+        this.module = module;
+        this.code = code;
+        this.args = args;
+        this.defaultMessage = defaultMessage;
+    }
+
+    public BaseException(String module, String code, Object[] args)
+    {
+        this(module, code, args, null);
+    }
+
+    public BaseException(String module, String defaultMessage)
+    {
+        this(module, null, null, defaultMessage);
+    }
+
+    public BaseException(String code, Object[] args)
+    {
+        this(null, code, args, null);
+    }
+
+    public BaseException(String defaultMessage)
+    {
+        this(null, null, null, defaultMessage);
+    }
+
+    @Override
+    public String getMessage()
+    {
+        String message = null;
+        if (!StringUtils.isEmpty(code))
+        {
+            message = MessageUtils.message(code, args);
+        }
+        if (message == null)
+        {
+            message = defaultMessage;
+        }
+        return message;
+    }
+
+    public String getModule()
+    {
+        return module;
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public Object[] getArgs()
+    {
+        return args;
+    }
+
+    public String getDefaultMessage()
+    {
+        return defaultMessage;
+    }
+
+    @Override
+    public String toString()
+    {
+        return this.getClass() + "{" + "module='" + module + '\'' + ", message='" + getMessage() + '\'' + '}';
+    }
+}

+ 19 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/file/FileException.java

@@ -0,0 +1,19 @@
+package com.ztmap.common.exception.file;
+
+import com.ztmap.common.exception.base.BaseException;
+
+/**
+ * 文件信息异常类
+ * 
+ * @author ztmap
+ */
+public class FileException extends BaseException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileException(String code, Object[] args)
+    {
+        super("file", code, args, null);
+    }
+
+}

+ 16 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/file/FileNameLengthLimitExceededException.java

@@ -0,0 +1,16 @@
+package com.ztmap.common.exception.file;
+
+/**
+ * 文件名称超长限制异常类
+ * 
+ * @author ztmap
+ */
+public class FileNameLengthLimitExceededException extends FileException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileNameLengthLimitExceededException(int defaultFileNameLength)
+    {
+        super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
+    }
+}

+ 16 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/file/FileSizeLimitExceededException.java

@@ -0,0 +1,16 @@
+package com.ztmap.common.exception.file;
+
+/**
+ * 文件名大小限制异常类
+ * 
+ * @author ztmap
+ */
+public class FileSizeLimitExceededException extends FileException
+{
+    private static final long serialVersionUID = 1L;
+
+    public FileSizeLimitExceededException(long defaultMaxSize)
+    {
+        super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
+    }
+}

+ 81 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/file/InvalidExtensionException.java

@@ -0,0 +1,81 @@
+package com.ztmap.common.exception.file;
+
+import java.util.Arrays;
+import org.apache.commons.fileupload.FileUploadException;
+
+/**
+ * 文件上传 误异常类
+ * 
+ * @author ztmap
+ */
+public class InvalidExtensionException extends FileUploadException
+{
+    private static final long serialVersionUID = 1L;
+
+    private String[] allowedExtension;
+    private String extension;
+    private String filename;
+
+    public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
+    {
+        super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]");
+        this.allowedExtension = allowedExtension;
+        this.extension = extension;
+        this.filename = filename;
+    }
+
+    public String[] getAllowedExtension()
+    {
+        return allowedExtension;
+    }
+
+    public String getExtension()
+    {
+        return extension;
+    }
+
+    public String getFilename()
+    {
+        return filename;
+    }
+
+    public static class InvalidImageExtensionException extends InvalidExtensionException
+    {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
+        {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidFlashExtensionException extends InvalidExtensionException
+    {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
+        {
+            super(allowedExtension, extension, filename);
+        }
+    }
+
+    public static class InvalidMediaExtensionException extends InvalidExtensionException
+    {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
+        {
+            super(allowedExtension, extension, filename);
+        }
+    }
+    
+    public static class InvalidVideoExtensionException extends InvalidExtensionException
+    {
+        private static final long serialVersionUID = 1L;
+
+        public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
+        {
+            super(allowedExtension, extension, filename);
+        }
+    }
+}

+ 34 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/job/TaskException.java

@@ -0,0 +1,34 @@
+package com.ztmap.common.exception.job;
+
+/**
+ * 计划策略异常
+ * 
+ * @author ztmap
+ */
+public class TaskException extends Exception
+{
+    private static final long serialVersionUID = 1L;
+
+    private Code code;
+
+    public TaskException(String msg, Code code)
+    {
+        this(msg, code, null);
+    }
+
+    public TaskException(String msg, Code code, Exception nestedEx)
+    {
+        super(msg, nestedEx);
+        this.code = code;
+    }
+
+    public Code getCode()
+    {
+        return code;
+    }
+
+    public enum Code
+    {
+        TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE
+    }
+}

+ 16 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/user/CaptchaException.java

@@ -0,0 +1,16 @@
+package com.ztmap.common.exception.user;
+
+/**
+ * 验证码错误异常类
+ * 
+ * @author ztmap
+ */
+public class CaptchaException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public CaptchaException()
+    {
+        super("user.jcaptcha.error", null);
+    }
+}

+ 17 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/user/RoleBlockedException.java

@@ -0,0 +1,17 @@
+package com.ztmap.common.exception.user;
+
+/**
+ * 角色锁定异常类
+ * 
+ * @author ztmap
+ */
+public class RoleBlockedException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public RoleBlockedException()
+    {
+        super("role.blocked", null);
+    }
+
+}

+ 16 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/user/UserBlockedException.java

@@ -0,0 +1,16 @@
+package com.ztmap.common.exception.user;
+
+/**
+ * 用户锁定异常类
+ * 
+ * @author ztmap
+ */
+public class UserBlockedException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserBlockedException()
+    {
+        super("user.blocked", null);
+    }
+}

+ 16 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/user/UserDeleteException.java

@@ -0,0 +1,16 @@
+package com.ztmap.common.exception.user;
+
+/**
+ * 用户账号已被删除
+ * 
+ * @author ztmap
+ */
+public class UserDeleteException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserDeleteException()
+    {
+        super("user.password.delete", null);
+    }
+}

+ 18 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/user/UserException.java

@@ -0,0 +1,18 @@
+package com.ztmap.common.exception.user;
+
+import com.ztmap.common.exception.base.BaseException;
+
+/**
+ * 用户信息异常类
+ * 
+ * @author ztmap
+ */
+public class UserException extends BaseException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserException(String code, Object[] args)
+    {
+        super("user", code, args, null);
+    }
+}

+ 16 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/user/UserNotExistsException.java

@@ -0,0 +1,16 @@
+package com.ztmap.common.exception.user;
+
+/**
+ * 用户不存在异常类
+ * 
+ * @author ztmap
+ */
+public class UserNotExistsException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserNotExistsException()
+    {
+        super("user.not.exists", null);
+    }
+}

+ 16 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/user/UserPasswordNotMatchException.java

@@ -0,0 +1,16 @@
+package com.ztmap.common.exception.user;
+
+/**
+ * 用户密码不正确或不符合规范异常类
+ * 
+ * @author ztmap
+ */
+public class UserPasswordNotMatchException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordNotMatchException()
+    {
+        super("user.password.not.match", null);
+    }
+}

+ 16 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/user/UserPasswordRetryLimitCountException.java

@@ -0,0 +1,16 @@
+package com.ztmap.common.exception.user;
+
+/**
+ * 用户错误记数异常类
+ * 
+ * @author ztmap
+ */
+public class UserPasswordRetryLimitCountException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordRetryLimitCountException(int retryLimitCount)
+    {
+        super("user.password.retry.limit.count", new Object[] { retryLimitCount });
+    }
+}

+ 16 - 0
zhny_admin/src/main/java/com/ztmap/common/exception/user/UserPasswordRetryLimitExceedException.java

@@ -0,0 +1,16 @@
+package com.ztmap.common.exception.user;
+
+/**
+ * 用户错误最大次数异常类
+ * 
+ * @author ztmap
+ */
+public class UserPasswordRetryLimitExceedException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordRetryLimitExceedException(int retryLimitCount)
+    {
+        super("user.password.retry.limit.exceed", new Object[] { retryLimitCount });
+    }
+}

+ 231 - 0
zhny_admin/src/main/java/com/ztmap/common/redis/RedisCache.java

@@ -0,0 +1,231 @@
+package com.ztmap.common.redis;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.BoundSetOperations;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * spring redis 工具类
+ *
+ * @author ztmap
+ **/
+@SuppressWarnings(value = { "unchecked", "rawtypes" })
+@Component
+public class RedisCache
+{
+    @Autowired
+    public RedisTemplate redisTemplate;
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key 缓存的键值
+     * @param value 缓存的值
+     */
+    public <T> void setCacheObject(final String key, final T value)
+    {
+        redisTemplate.opsForValue().set(key, value);
+    }
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key 缓存的键值
+     * @param value 缓存的值
+     * @param timeout 时间
+     * @param timeUnit 时间颗粒度
+     */
+    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
+    {
+        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key Redis键
+     * @param timeout 超时时间
+     * @return true=设置成功;false=设置失败
+     */
+    public boolean expire(final String key, final long timeout)
+    {
+        return expire(key, timeout, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key Redis键
+     * @param timeout 超时时间
+     * @param unit 时间单位
+     * @return true=设置成功;false=设置失败
+     */
+    public boolean expire(final String key, final long timeout, final TimeUnit unit)
+    {
+        return redisTemplate.expire(key, timeout, unit);
+    }
+
+    /**
+     * 获得缓存的基本对象。
+     *
+     * @param key 缓存键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> T getCacheObject(final String key)
+    {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        return operation.get(key);
+    }
+
+    /**
+     * 删除单个对象
+     *
+     * @param key
+     */
+    public boolean deleteObject(final String key)
+    {
+        return redisTemplate.delete(key);
+    }
+
+    /**
+     * 删除集合对象
+     *
+     * @param collection 多个对象
+     * @return
+     */
+    public long deleteObject(final Collection collection)
+    {
+        return redisTemplate.delete(collection);
+    }
+
+    /**
+     * 缓存List数据
+     *
+     * @param key 缓存的键值
+     * @param dataList 待缓存的List数据
+     * @return 缓存的对象
+     */
+    public <T> long setCacheList(final String key, final List<T> dataList)
+    {
+        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
+        return count == null ? 0 : count;
+    }
+
+    /**
+     * 获得缓存的list对象
+     *
+     * @param key 缓存的键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> List<T> getCacheList(final String key)
+    {
+        return redisTemplate.opsForList().range(key, 0, -1);
+    }
+
+    /**
+     * 缓存Set
+     *
+     * @param key 缓存键值
+     * @param dataSet 缓存的数据
+     * @return 缓存数据的对象
+     */
+    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
+    {
+        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
+        Iterator<T> it = dataSet.iterator();
+        while (it.hasNext())
+        {
+            setOperation.add(it.next());
+        }
+        return setOperation;
+    }
+
+    /**
+     * 获得缓存的set
+     *
+     * @param key
+     * @return
+     */
+    public <T> Set<T> getCacheSet(final String key)
+    {
+        return redisTemplate.opsForSet().members(key);
+    }
+
+    /**
+     * 缓存Map
+     *
+     * @param key
+     * @param dataMap
+     */
+    public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
+    {
+        if (dataMap != null) {
+            redisTemplate.opsForHash().putAll(key, dataMap);
+        }
+    }
+
+    /**
+     * 获得缓存的Map
+     *
+     * @param key
+     * @return
+     */
+    public <T> Map<String, T> getCacheMap(final String key)
+    {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * 往Hash中存入数据
+     *
+     * @param key Redis键
+     * @param hKey Hash键
+     * @param value 值
+     */
+    public <T> void setCacheMapValue(final String key, final String hKey, final T value)
+    {
+        redisTemplate.opsForHash().put(key, hKey, value);
+    }
+
+    /**
+     * 获取Hash中的数据
+     *
+     * @param key Redis键
+     * @param hKey Hash键
+     * @return Hash中的对象
+     */
+    public <T> T getCacheMapValue(final String key, final String hKey)
+    {
+        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
+        return opsForHash.get(key, hKey);
+    }
+
+    /**
+     * 获取多个Hash中的数据
+     *
+     * @param key Redis键
+     * @param hKeys Hash键集合
+     * @return Hash对象集合
+     */
+    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
+    {
+        return redisTemplate.opsForHash().multiGet(key, hKeys);
+    }
+
+    /**
+     * 获得缓存的基本对象列表
+     *
+     * @param pattern 字符串前缀
+     * @return 对象列表
+     */
+    public Collection<String> keys(final String pattern)
+    {
+        return redisTemplate.keys(pattern);
+    }
+}

+ 55 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/AddressUtils.java

@@ -0,0 +1,55 @@
+package com.ztmap.common.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.alibaba.fastjson.JSONObject;
+import com.ztmap.common.constant.Constants;
+import com.ztmap.common.utils.http.HttpUtils;
+import com.ztmap.framework.config.ZTMapConfig;
+
+/**
+ * 获取地址类
+ * 
+ * @author ztmap
+ */
+public class AddressUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
+
+    // IP地址查询
+    public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
+
+    // 未知地址
+    public static final String UNKNOWN = "XX XX";
+
+    public static String getRealAddressByIP(String ip)
+    {
+        String address = UNKNOWN;
+        // 内网不查询
+        if (IpUtils.internalIp(ip))
+        {
+            return "内网IP";
+        }
+        if (ZTMapConfig.isAddressEnabled())
+        {
+            try
+            {
+                String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);
+                if (StringUtils.isEmpty(rspStr))
+                {
+                    log.error("获取地理位置异常 {}", ip);
+                    return UNKNOWN;
+                }
+                JSONObject obj = JSONObject.parseObject(rspStr);
+                String region = obj.getString("pro");
+                String city = obj.getString("city");
+                return String.format("%s %s", region, city);
+            }
+            catch (Exception e)
+            {
+                log.error("获取地理位置异常 {}", e);
+            }
+        }
+        return address;
+    }
+}

+ 114 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/Arith.java

@@ -0,0 +1,114 @@
+package com.ztmap.common.utils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * 精确的浮点数运算
+ * 
+ * @author ztmap
+ */
+public class Arith
+{
+
+    /** 默认除法运算精度 */
+    private static final int DEF_DIV_SCALE = 10;
+
+    /** 这个类不能实例化 */
+    private Arith()
+    {
+    }
+
+    /**
+     * 提供精确的加法运算。
+     * @param v1 被加数
+     * @param v2 加数
+     * @return 两个参数的和
+     */
+    public static double add(double v1, double v2)
+    {
+        BigDecimal b1 = new BigDecimal(Double.toString(v1));
+        BigDecimal b2 = new BigDecimal(Double.toString(v2));
+        return b1.add(b2).doubleValue();
+    }
+
+    /**
+     * 提供精确的减法运算。
+     * @param v1 被减数
+     * @param v2 减数
+     * @return 两个参数的差
+     */
+    public static double sub(double v1, double v2)
+    {
+        BigDecimal b1 = new BigDecimal(Double.toString(v1));
+        BigDecimal b2 = new BigDecimal(Double.toString(v2));
+        return b1.subtract(b2).doubleValue();
+    }
+
+    /**
+     * 提供精确的乘法运算。
+     * @param v1 被乘数
+     * @param v2 乘数
+     * @return 两个参数的积
+     */
+    public static double mul(double v1, double v2)
+    {
+        BigDecimal b1 = new BigDecimal(Double.toString(v1));
+        BigDecimal b2 = new BigDecimal(Double.toString(v2));
+        return b1.multiply(b2).doubleValue();
+    }
+
+    /**
+     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
+     * 小数点以后10位,以后的数字四舍五入。
+     * @param v1 被除数
+     * @param v2 除数
+     * @return 两个参数的商
+     */
+    public static double div(double v1, double v2)
+    {
+        return div(v1, v2, DEF_DIV_SCALE);
+    }
+
+    /**
+     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
+     * 定精度,以后的数字四舍五入。
+     * @param v1 被除数
+     * @param v2 除数
+     * @param scale 表示表示需要精确到小数点以后几位。
+     * @return 两个参数的商
+     */
+    public static double div(double v1, double v2, int scale)
+    {
+        if (scale < 0)
+        {
+            throw new IllegalArgumentException(
+                    "The scale must be a positive integer or zero");
+        }
+        BigDecimal b1 = new BigDecimal(Double.toString(v1));
+        BigDecimal b2 = new BigDecimal(Double.toString(v2));
+        if (b1.compareTo(BigDecimal.ZERO) == 0)
+        {
+            return BigDecimal.ZERO.doubleValue();
+        }
+        return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
+    }
+
+    /**
+     * 提供精确的小数位四舍五入处理。
+     * @param v 需要四舍五入的数字
+     * @param scale 小数点后保留几位
+     * @return 四舍五入后的结果
+     */
+    public static double round(double v, int scale)
+    {
+        if (scale < 0)
+        {
+            throw new IllegalArgumentException(
+                    "The scale must be a positive integer or zero");
+        }
+        BigDecimal b = new BigDecimal(Double.toString(v));
+        BigDecimal one = BigDecimal.ONE;
+        return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
+    }
+}

+ 197 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/CacheUtils.java

@@ -0,0 +1,197 @@
+package com.ztmap.common.utils;
+
+import java.util.Iterator;
+import java.util.Set;
+import org.apache.shiro.cache.Cache;
+import org.apache.shiro.cache.CacheManager;
+import org.apache.shiro.cache.ehcache.EhCacheManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ztmap.common.utils.spring.SpringUtils;
+
+/**
+ * Cache工具类
+ * 
+ * @author ztmap
+ */
+public class CacheUtils
+{
+    private static Logger logger = LoggerFactory.getLogger(CacheUtils.class);
+
+    private static CacheManager cacheManager = SpringUtils.getBean(CacheManager.class);
+
+    private static final String SYS_CACHE = "sys-cache";
+
+    /**
+     * 获取SYS_CACHE缓存
+     * 
+     * @param key
+     * @return
+     */
+    public static Object get(String key)
+    {
+        return get(SYS_CACHE, key);
+    }
+
+    /**
+     * 获取SYS_CACHE缓存
+     * 
+     * @param key
+     * @param defaultValue
+     * @return
+     */
+    public static Object get(String key, Object defaultValue)
+    {
+        Object value = get(key);
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * 写入SYS_CACHE缓存
+     * 
+     * @param key
+     * @return
+     */
+    public static void put(String key, Object value)
+    {
+        put(SYS_CACHE, key, value);
+    }
+
+    /**
+     * 从SYS_CACHE缓存中移除
+     * 
+     * @param key
+     * @return
+     */
+    public static void remove(String key)
+    {
+        remove(SYS_CACHE, key);
+    }
+
+    /**
+     * 获取缓存
+     * 
+     * @param cacheName
+     * @param key
+     * @return
+     */
+    public static Object get(String cacheName, String key)
+    {
+        return getCache(cacheName).get(getKey(key));
+    }
+
+    /**
+     * 获取缓存
+     * 
+     * @param cacheName
+     * @param key
+     * @param defaultValue
+     * @return
+     */
+    public static Object get(String cacheName, String key, Object defaultValue)
+    {
+        Object value = get(cacheName, getKey(key));
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * 写入缓存
+     * 
+     * @param cacheName
+     * @param key
+     * @param value
+     */
+    public static void put(String cacheName, String key, Object value)
+    {
+        getCache(cacheName).put(getKey(key), value);
+    }
+
+    /**
+     * 从缓存中移除
+     * 
+     * @param cacheName
+     * @param key
+     */
+    public static void remove(String cacheName, String key)
+    {
+        getCache(cacheName).remove(getKey(key));
+    }
+
+    /**
+     * 从缓存中移除所有
+     * 
+     * @param cacheName
+     */
+    public static void removeAll(String cacheName)
+    {
+        Cache<String, Object> cache = getCache(cacheName);
+        Set<String> keys = cache.keys();
+        for (Iterator<String> it = keys.iterator(); it.hasNext();)
+        {
+            cache.remove(it.next());
+        }
+        logger.info("清理缓存: {} => {}", cacheName, keys);
+    }
+
+    /**
+     * 从缓存中移除指定key
+     * 
+     * @param keys
+     */
+    public static void removeByKeys(Set<String> keys)
+    {
+        removeByKeys(SYS_CACHE, keys);
+    }
+
+    /**
+     * 从缓存中移除指定key
+     * 
+     * @param cacheName
+     * @param keys
+     */
+    public static void removeByKeys(String cacheName, Set<String> keys)
+    {
+        for (Iterator<String> it = keys.iterator(); it.hasNext();)
+        {
+            remove(it.next());
+        }
+        logger.info("清理缓存: {} => {}", cacheName, keys);
+    }
+
+    /**
+     * 获取缓存键名
+     * 
+     * @param key
+     * @return
+     */
+    private static String getKey(String key)
+    {
+        return key;
+    }
+
+    /**
+     * 获得一个Cache,没有则显示日志。
+     * 
+     * @param cacheName
+     * @return
+     */
+    public static Cache<String, Object> getCache(String cacheName)
+    {
+        Cache<String, Object> cache = cacheManager.getCache(cacheName);
+        if (cache == null)
+        {
+            throw new RuntimeException("当前系统中没有定义“" + cacheName + "”这个缓存。");
+        }
+        return cache;
+    }
+
+    /**
+     * 获取所有缓存
+     * 
+     * @return 缓存组
+     */
+    public static String[] getCacheNames()
+    {
+        return ((EhCacheManager) cacheManager).getCacheManager().getCacheNames();
+    }
+}

+ 138 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/CookieUtils.java

@@ -0,0 +1,138 @@
+package com.ztmap.common.utils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Cookie工具类
+ * 
+ * @author ztmap
+ */
+public class CookieUtils
+{
+    /**
+     * 设置 Cookie(生成时间为1天)
+     * 
+     * @param name 名称
+     * @param value 值
+     */
+    public static void setCookie(HttpServletResponse response, String name, String value)
+    {
+        setCookie(response, name, value, 60 * 60 * 24);
+    }
+
+    /**
+     * 设置 Cookie
+     * 
+     * @param name 名称
+     * @param value 值
+     * @param maxAge 生存时间(单位秒)
+     * @param uri 路径
+     */
+    public static void setCookie(HttpServletResponse response, String name, String value, String path)
+    {
+        setCookie(response, name, value, path, 60 * 60 * 24);
+    }
+
+    /**
+     * 设置 Cookie
+     * 
+     * @param name 名称
+     * @param value 值
+     * @param maxAge 生存时间(单位秒)
+     * @param uri 路径
+     */
+    public static void setCookie(HttpServletResponse response, String name, String value, int maxAge)
+    {
+        setCookie(response, name, value, "/", maxAge);
+    }
+
+    /**
+     * 设置 Cookie
+     * 
+     * @param name 名称
+     * @param value 值
+     * @param maxAge 生存时间(单位秒)
+     * @param uri 路径
+     */
+    public static void setCookie(HttpServletResponse response, String name, String value, String path, int maxAge)
+    {
+        Cookie cookie = new Cookie(name, null);
+        cookie.setPath(path);
+        cookie.setMaxAge(maxAge);
+        try
+        {
+            cookie.setValue(URLEncoder.encode(value, "utf-8"));
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            e.printStackTrace();
+        }
+        response.addCookie(cookie);
+    }
+
+    /**
+     * 获得指定Cookie的值
+     * 
+     * @param name 名称
+     * @return 值
+     */
+    public static String getCookie(HttpServletRequest request, String name)
+    {
+        return getCookie(request, null, name, false);
+    }
+
+    /**
+     * 获得指定Cookie的值,并删除。
+     * 
+     * @param name 名称
+     * @return 值
+     */
+    public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name)
+    {
+        return getCookie(request, response, name, true);
+    }
+
+    /**
+     * 获得指定Cookie的值
+     * 
+     * @param request 请求对象
+     * @param response 响应对象
+     * @param name 名字
+     * @param isRemove 是否移除
+     * @return 值
+     */
+    public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name,
+            boolean isRemove)
+    {
+        String value = null;
+        Cookie[] cookies = request.getCookies();
+        if (cookies != null)
+        {
+            for (Cookie cookie : cookies)
+            {
+                if (cookie.getName().equals(name))
+                {
+                    try
+                    {
+                        value = URLDecoder.decode(cookie.getValue(), "utf-8");
+                    }
+                    catch (UnsupportedEncodingException e)
+                    {
+                        e.printStackTrace();
+                    }
+                    if (isRemove)
+                    {
+                        cookie.setMaxAge(0);
+                        response.addCookie(cookie);
+                    }
+                }
+            }
+        }
+        return value;
+    }
+}

+ 184 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/DateUtils.java

@@ -0,0 +1,184 @@
+package com.ztmap.common.utils;
+
+import java.lang.management.ManagementFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+/**
+ * 时间工具类
+ * 
+ * @author ztmap
+ */
+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)));
+    }
+
+    /**
+     * 计算两个时间差
+     */
+    public static String getDatePoor(Date endDate, Date nowDate)
+    {
+        long nd = 1000 * 24 * 60 * 60;
+        long nh = 1000 * 60 * 60;
+        long nm = 1000 * 60;
+        // long ns = 1000;
+        // 获得两个时间的毫秒时间差异
+        long diff = endDate.getTime() - nowDate.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 + "分钟";
+    }
+
+    /**
+     * 获取周几
+     * @return
+     */
+    public static String obtainWeek(){
+        String[] weekDays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(new Date());
+        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
+        if (w < 0)
+            w = 0;
+        return weekDays[w];
+    }
+
+    public static int getDayCount(){
+        Calendar instance = Calendar.getInstance();
+        instance.setTime(new Date());
+        return instance.getActualMaximum(Calendar.DAY_OF_MONTH);
+    }
+}

+ 40 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/ExceptionUtil.java

@@ -0,0 +1,40 @@
+package com.ztmap.common.utils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+
+/**
+ * 错误信息处理类。
+ *
+ * @author ztmap
+ */
+public class ExceptionUtil
+{
+    /**
+     * 获取exception的详细错误信息。
+     */
+    public static String getExceptionMessage(Throwable e)
+    {
+        StringWriter sw = new StringWriter();
+        e.printStackTrace(new PrintWriter(sw, true));
+        String str = sw.toString();
+        return str;
+    }
+
+    public static String getRootErrorMseeage(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);
+    }
+}

+ 194 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/IpUtils.java

@@ -0,0 +1,194 @@
+package com.ztmap.common.utils;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 获取IP方法
+ * 
+ * @author ztmap
+ */
+public class IpUtils
+{
+    public static String getIpAddr(HttpServletRequest request)
+    {
+        if (request == null)
+        {
+            return "unknown";
+        }
+        String ip = request.getHeader("x-forwarded-for");
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+        {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+        {
+            ip = request.getHeader("X-Forwarded-For");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+        {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+        {
+            ip = request.getHeader("X-Real-IP");
+        }
+
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+        {
+            ip = request.getRemoteAddr();
+        }
+
+        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
+    }
+
+    public static boolean internalIp(String ip)
+    {
+        byte[] addr = textToNumericFormatV4(ip);
+        return internalIp(addr) || "127.0.0.1".equals(ip);
+    }
+
+    private static boolean internalIp(byte[] addr)
+    {
+        if (StringUtils.isNull(addr) || addr.length < 2)
+        {
+            return true;
+        }
+        final byte b0 = addr[0];
+        final byte b1 = addr[1];
+        // 10.x.x.x/8
+        final byte SECTION_1 = 0x0A;
+        // 172.16.x.x/12
+        final byte SECTION_2 = (byte) 0xAC;
+        final byte SECTION_3 = (byte) 0x10;
+        final byte SECTION_4 = (byte) 0x1F;
+        // 192.168.x.x/16
+        final byte SECTION_5 = (byte) 0xC0;
+        final byte SECTION_6 = (byte) 0xA8;
+        switch (b0)
+        {
+            case SECTION_1:
+                return true;
+            case SECTION_2:
+                if (b1 >= SECTION_3 && b1 <= SECTION_4)
+                {
+                    return true;
+                }
+            case SECTION_5:
+                switch (b1)
+                {
+                    case SECTION_6:
+                        return true;
+                }
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * 将IPv4地址转换成字节
+     * 
+     * @param text IPv4地址
+     * @return byte 字节
+     */
+    public static byte[] textToNumericFormatV4(String text)
+    {
+        if (text.length() == 0)
+        {
+            return null;
+        }
+
+        byte[] bytes = new byte[4];
+        String[] elements = text.split("\\.", -1);
+        try
+        {
+            long l;
+            int i;
+            switch (elements.length)
+            {
+                case 1:
+                    l = Long.parseLong(elements[0]);
+                    if ((l < 0L) || (l > 4294967295L)) {
+                        return null;
+                    }
+                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
+                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
+                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 2:
+                    l = Integer.parseInt(elements[0]);
+                    if ((l < 0L) || (l > 255L)) {
+                        return null;
+                    }
+                    bytes[0] = (byte) (int) (l & 0xFF);
+                    l = Integer.parseInt(elements[1]);
+                    if ((l < 0L) || (l > 16777215L)) {
+                        return null;
+                    }
+                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
+                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 3:
+                    for (i = 0; i < 2; ++i)
+                    {
+                        l = Integer.parseInt(elements[i]);
+                        if ((l < 0L) || (l > 255L)) {
+                            return null;
+                        }
+                        bytes[i] = (byte) (int) (l & 0xFF);
+                    }
+                    l = Integer.parseInt(elements[2]);
+                    if ((l < 0L) || (l > 65535L)) {
+                        return null;
+                    }
+                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
+                    bytes[3] = (byte) (int) (l & 0xFF);
+                    break;
+                case 4:
+                    for (i = 0; i < 4; ++i)
+                    {
+                        l = Integer.parseInt(elements[i]);
+                        if ((l < 0L) || (l > 255L)) {
+                            return null;
+                        }
+                        bytes[i] = (byte) (int) (l & 0xFF);
+                    }
+                    break;
+                default:
+                    return null;
+            }
+        }
+        catch (NumberFormatException e)
+        {
+            return null;
+        }
+        return bytes;
+    }
+
+    public static String getHostIp()
+    {
+        try
+        {
+            return InetAddress.getLocalHost().getHostAddress();
+        }
+        catch (UnknownHostException e)
+        {
+        }
+        return "127.0.0.1";
+    }
+
+    public static String getHostName()
+    {
+        try
+        {
+            return InetAddress.getLocalHost().getHostName();
+        }
+        catch (UnknownHostException e)
+        {
+        }
+        return "未知";
+    }
+}

+ 134 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/LogUtils.java

@@ -0,0 +1,134 @@
+package com.ztmap.common.utils;
+
+import com.alibaba.fastjson.JSON;
+import org.apache.shiro.SecurityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.servlet.http.HttpServletRequest;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Map;
+
+/**
+ * 处理并记录日志文件
+ * 
+ * @author ztmap
+ */
+public class LogUtils
+{
+    public static final Logger ERROR_LOG = LoggerFactory.getLogger("sys-error");
+    public static final Logger ACCESS_LOG = LoggerFactory.getLogger("sys-access");
+
+    /**
+     * 记录访问日志 [username][jsessionid][ip][accept][UserAgent][url][params][Referer]
+     *
+     * @param request
+     */
+    public static void logAccess(HttpServletRequest request)
+    {
+        String username = getUsername();
+        String jsessionId = request.getRequestedSessionId();
+        String ip = IpUtils.getIpAddr(request);
+        String accept = request.getHeader("accept");
+        String userAgent = request.getHeader("User-Agent");
+        String url = request.getRequestURI();
+        String params = getParams(request);
+
+        StringBuilder s = new StringBuilder();
+        s.append(getBlock(username));
+        s.append(getBlock(jsessionId));
+        s.append(getBlock(ip));
+        s.append(getBlock(accept));
+        s.append(getBlock(userAgent));
+        s.append(getBlock(url));
+        s.append(getBlock(params));
+        s.append(getBlock(request.getHeader("Referer")));
+        getAccessLog().info(s.toString());
+    }
+
+    /**
+     * 记录异常错误 格式 [exception]
+     *
+     * @param message
+     * @param e
+     */
+    public static void logError(String message, Throwable e)
+    {
+        String username = getUsername();
+        StringBuilder s = new StringBuilder();
+        s.append(getBlock("exception"));
+        s.append(getBlock(username));
+        s.append(getBlock(message));
+        ERROR_LOG.error(s.toString(), e);
+    }
+
+    /**
+     * 记录页面错误 错误日志记录 [page/eception][username][statusCode][errorMessage][servletName][uri][exceptionName][ip][exception]
+     *
+     * @param request
+     */
+    public static void logPageError(HttpServletRequest request)
+    {
+        String username = getUsername();
+
+        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
+        String message = (String) request.getAttribute("javax.servlet.error.message");
+        String uri = (String) request.getAttribute("javax.servlet.error.request_uri");
+        Throwable t = (Throwable) request.getAttribute("javax.servlet.error.exception");
+
+        if (statusCode == null)
+        {
+            statusCode = 0;
+        }
+
+        StringBuilder s = new StringBuilder();
+        s.append(getBlock(t == null ? "page" : "exception"));
+        s.append(getBlock(username));
+        s.append(getBlock(statusCode));
+        s.append(getBlock(message));
+        s.append(getBlock(IpUtils.getIpAddr(request)));
+
+        s.append(getBlock(uri));
+        s.append(getBlock(request.getHeader("Referer")));
+        StringWriter sw = new StringWriter();
+
+        while (t != null)
+        {
+            t.printStackTrace(new PrintWriter(sw));
+            t = t.getCause();
+        }
+        s.append(getBlock(sw.toString()));
+        getErrorLog().error(s.toString());
+
+    }
+
+    public static String getBlock(Object msg)
+    {
+        if (msg == null)
+        {
+            msg = "";
+        }
+        return "[" + msg.toString() + "]";
+    }
+
+    protected static String getParams(HttpServletRequest request)
+    {
+        Map<String, String[]> params = request.getParameterMap();
+        return JSON.toJSONString(params);
+    }
+
+    protected static String getUsername()
+    {
+        return (String) SecurityUtils.getSubject().getPrincipal();
+    }
+
+    public static Logger getAccessLog()
+    {
+        return ACCESS_LOG;
+    }
+
+    public static Logger getErrorLog()
+    {
+        return ERROR_LOG;
+    }
+}

+ 54 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/MapDataUtil.java

@@ -0,0 +1,54 @@
+package com.ztmap.common.utils;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Map通用处理方法
+ * 
+ * @author ztmap
+ */
+public class MapDataUtil
+{
+    public static Map<String, Object> convertDataMap(HttpServletRequest request)
+    {
+        Map<String, String[]> properties = request.getParameterMap();
+        Map<String, Object> returnMap = new HashMap<String, Object>();
+        Iterator<?> entries = properties.entrySet().iterator();
+        Map.Entry<?, ?> entry;
+        String name = "";
+        String value = "";
+        while (entries.hasNext())
+        {
+            entry = (Entry<?, ?>) entries.next();
+            name = (String) entry.getKey();
+            Object valueObj = entry.getValue();
+            if (null == valueObj)
+            {
+                value = "";
+            }
+            else if (valueObj instanceof String[])
+            {
+                String[] values = (String[]) valueObj;
+                value = "";
+                for (int i = 0; i < values.length; i++)
+                {
+                    value += values[i] + ",";
+                }
+                if (value.length() > 0)
+                {
+                    value = value.substring(0, value.length() - 1);
+                }
+            }
+            else
+            {
+                value = valueObj.toString();
+            }
+            returnMap.put(name, value);
+        }
+        return returnMap;
+    }
+}

+ 136 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/Md5Utils.java

@@ -0,0 +1,136 @@
+package com.ztmap.common.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.security.MessageDigest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Md5加密方法
+ * 
+ * @author ztmap
+ */
+public class Md5Utils
+{
+    private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
+
+    private static byte[] md5(String s)
+    {
+        MessageDigest algorithm;
+        try
+        {
+            algorithm = MessageDigest.getInstance("MD5");
+            algorithm.reset();
+            algorithm.update(s.getBytes("UTF-8"));
+            byte[] messageDigest = algorithm.digest();
+            return messageDigest;
+        }
+        catch (Exception e)
+        {
+            log.error("MD5 Error...", e);
+        }
+        return null;
+    }
+
+    private static final String toHex(byte hash[])
+    {
+        if (hash == null)
+        {
+            return null;
+        }
+        StringBuffer buf = new StringBuffer(hash.length * 2);
+        int i;
+
+        for (i = 0; i < hash.length; i++)
+        {
+            if ((hash[i] & 0xff) < 0x10)
+            {
+                buf.append("0");
+            }
+            buf.append(Long.toString(hash[i] & 0xff, 16));
+        }
+        return buf.toString();
+    }
+
+    public static String hash(String s)
+    {
+        try
+        {
+            return new String(toHex(md5(s)).getBytes("UTF-8"), "UTF-8");
+        }
+        catch (Exception e)
+        {
+            log.error("not supported charset...{}", e);
+            return s;
+        }
+    }
+
+    private static char[] base64EncodeChars = new char[] { 'A', 'B', 'C', 'D',
+            'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
+            'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+            'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
+            'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+            '4', '5', '6', '7', '8', '9', '+', '/', };
+
+    private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59,
+            60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+            10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1,
+            -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+            38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1,
+            -1, -1 };
+    /**
+     * 对密码进行解密
+     * */
+    public static byte[] decode(String str) {
+        byte[] data = str.getBytes();
+        int len = data.length;
+        ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
+        int i = 0;
+        int b1, b2, b3, b4;
+
+        while (i < len) {
+            do {
+                b1 = base64DecodeChars[data[i++]];
+            } while (i < len && b1 == -1);
+            if (b1 == -1) {
+                break;
+            }
+
+            do {
+                b2 = base64DecodeChars[data[i++]];
+            } while (i < len && b2 == -1);
+            if (b2 == -1) {
+                break;
+            }
+            buf.write((int) ((b1 << 2) | ((b2 & 0x30) >>> 4)));
+
+            do {
+                b3 = data[i++];
+                if (b3 == 61) {
+                    return buf.toByteArray();
+                }
+                b3 = base64DecodeChars[b3];
+            } while (i < len && b3 == -1);
+            if (b3 == -1) {
+                break;
+            }
+            buf.write((int) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));
+
+            do {
+                b4 = data[i++];
+                if (b4 == 61) {
+                    return buf.toByteArray();
+                }
+                b4 = base64DecodeChars[b4];
+            } while (i < len && b4 == -1);
+            if (b4 == -1) {
+                break;
+            }
+            buf.write((int) (((b3 & 0x03) << 6) | b4));
+        }
+        return buf.toByteArray();
+    }
+}

+ 26 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/MessageUtils.java

@@ -0,0 +1,26 @@
+package com.ztmap.common.utils;
+
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
+import com.ztmap.common.utils.spring.SpringUtils;
+
+/**
+ * 获取i18n资源文件
+ * 
+ * @author ztmap
+ */
+public class MessageUtils
+{
+    /**
+     * 根据消息键和参数 获取消息 委托给spring messageSource
+     *
+     * @param code 消息键
+     * @param args 参数
+     * @return 获取国际化翻译值
+     */
+    public static String message(String code, Object... args)
+    {
+        MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
+        return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
+    }
+}

+ 28 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/OutputProcessor.java

@@ -0,0 +1,28 @@
+package com.ztmap.common.utils;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class OutputProcessor extends Thread {
+
+    private InputStream inputStream;
+
+    public OutputProcessor(InputStream inputStream) {
+        this.inputStream = inputStream;
+    }
+
+    @Override
+    public void run() {
+        try {
+            InputStreamReader isr = new InputStreamReader(inputStream);
+            BufferedReader br = new BufferedReader(isr);
+            String line;
+            while ((line = br.readLine()) != null) {
+                System.out.println(line);
+            }
+        } catch (Exception e) {
+            System.out.println(e.getMessage());
+        }
+    }
+}

+ 38 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/PositionUtil.java

@@ -0,0 +1,38 @@
+package com.ztmap.common.utils;
+
+public class PositionUtil {
+ 
+    private static final double EARTH_RADIUS = 6378.137; // 6378.137为地球半径(单位:千米)
+ 
+    // Java 计算两个GPS坐标点之间的距离
+    // lat1、lng1 表示A点经纬度,lat2、lng2 表示B点经纬度,计算出来的结果单位为千米
+    public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
+        double radLat1 = rad(lat1);
+        double radLat2 = rad(lat2);
+        double a = radLat1 - radLat2;      // a 是两坐标点的纬度之差
+        double b = rad(lng1) - rad(lng2);  // b 是两坐标点的经度之差
+ 
+        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_RADIUS;
+        System.out.println("s = " + s + "千米"); // 单位:千米
+ 
+        s = Math.round(s * 1000); // 转为米,用 Math.round() 取整
+//        s = s/1000; // 米转千米
+        return s;
+    }
+ 
+    // 角度转弧度
+    // 把用角度表示的角转换为近似相等的用弧度表示的角 Math.toRadians。
+    // 经纬度是以度数(0-360)表示。如果要把度数转换为弧度(0-2π),要除以360再乘以2ππ(相当于,乘以π/ 180)。
+    private static double rad(double d) {  return d * Math.PI / 180.0; }
+ 
+    public static void main(String[] args) {
+        // 济南中铁大厦入口 117.117852,36.672557
+        // 济南中铁北边红绿灯路口 117.117654,36.674579
+        // double dist1 = getDistance(117.117852,36.672557, 117.117654,36.674579) ;
+        double dist1 = getDistance(102.49797,24.24909, 102.49791,24.24925) ;
+        System.out.println("两点相距:" + dist1 + "千米");
+    }
+ 
+}

+ 98 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/RSAUtil.java

@@ -0,0 +1,98 @@
+package com.ztmap.common.utils;
+
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.Cipher;
+import java.security.*;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.HashMap;
+import java.util.Map;
+
+public class RSAUtil {
+    //public static String PRIVATE_KEY="MIIEoQIBAAMMMMMMMMMMMMMMMMFbuiAmYG/VOym6ZDftCy2R4oJvkP7MgS1nsxBRdnb0eAU/abVy1Wk2y1d6ZsiF35Shpy235WfkIVc9cRX71LpNxetfMiFAJSqSZ2XbNJTBWZEah/r0rBgRSAkC6NbFsgdWi6VbPGDVM+Y2pM8wQjrUi3ZCTE9SSchv/grbl/OJm/T5uaYP0VqoOV0Zzi89bqjby9XexInyCj+1hxy7+9NP1brx5qHRAuiidbtqHzVOyKpsKGPh2fJugbVhzUoqM6ebL/j1y8w92obMj3snsgykqj5T2kfSiiMxAgMBAAECggEALujqfMixJEyl+IP6TV3kG61S63EFdHrmFv+GW3b8TdUWA3VABEF9p1nHH29SirBwG1Kqd5A9Wxg2v37hVSz2Mx2gaFv4HsFna4eZfY6ZoJmfr7ag7gw1+aqit9opmmNOcVBNUoLjiZLkQiihZpATvofJZEY/epnmKudABg+9ZN86vnbA2DFnYmVLbZvWwhGyr7AnvDO+678PtpIaWL4yxRA+p+6CxQd5ZkQf8E6VGeU4qSmbksjN+fav1SwDm4hGSBvHP6r2dWZ7MITg4DomavOwCJseh9AVX9LUtygumjY/NdYoUXkyoSeniQwL/uMd1ewB9Qi8jrJj9NAxUbsXDQKBgQCe2zRMi+R5u35FL2jWs/gAgT7KQ8d0vlv/eAOD2filiEGRoTgdzAXuGY0vytICf11HZ/y0qhPuiDuNIOnvIa9kj2zHawVBbm6Fl6J6GP874V894Bh3J3oWn9ilMIfEjvM4Jlg6aKPiht1EiykLgvIim4qaFj8UTBMMkaqUZJjw6wKBgQCWBurdYj59dZ6XOlYZTDNjJriTm4MdOZrvxAOnYIdvtDcVhqWNcocR0OXYilwehLxnsbExbE3En4OmUbZZe2pOvQ96OojUQHP4vwFUD3dm6gS87yT9nwDkMFgNETVbxVUI2SYsmtPnI8NgkkSiJfbj3Jlfe4ZCu4gwWJfD2WJVUwKBgDZW4XL1v3fsrOrZptEaytDRZTsnKElE/I9M7Fbj7uwgyd0Y+usmaTjjQKqChIgaLTxJ0+Ww8BR+QXCrO5pzOV36uckVULzrG59TGV8OwfAnzb6Ks5O+y0KF90O6cBbKl2QzqaaBON46J+JUf/vSFSXFcwn2Zil5RGLeSS1to+t1AoGAcq6NAHfmDt9HQJC+Wg4uxd9GfscEneV380oiBOM8BH59EP5hNNPUPiEyYam6KzYKEzX4njAM7n2FFDEoNBSsOc45s5RlHeK7A+12JXzBKDFBN++SljDibIwr8qkx4Znhm6bqkHQ2AV0ML5j/z/c3WA08TInPItnZjCNct8BHc7MCgYAsV4y3/CtQEmxk3wQr8ng/4LZtHuXdojh8ZQ74b3gQqO/iml6XdzZJRN/fmO+ikDAY6jPQAW4RsqZ1l8W1pKbzCvuTW6jGoUyti+Lrt3HDF9SlZMHk4gc/tq1/ad4lIgHbCxBJv7UvP6YDQX+7itJmpmYmhTuYuJ11ZnAZg9qCQg==";
+    public static String PRIVATE_KEY="MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJY/eYAthnT2YLneAMH2rCLOJnI1aVqC6esntjFR3cas1SwAVpox0C4M+lN5QRpjN2QfZvQS4eVY/m81/EAc1ZZZri6s0jpWQ1QTtkUuDCxuCkJaAPhq6rpR+SI8eE8MGrSXuXcvuSlWoZN18Oonwp7aZsozzcynjMzQQyTOQDpNAgMBAAECgYBaUpJSMgwQqESBuCowcIAO9Gs8YUuSc/z3twnaIGL4mtIT/6gQTj3eUULzh4NRv69+6znTJL7UR2m9pXCdgjgLm3cdxa6qxNp9I+NrGmQfvhZZiOeU3zUr8URtu+wtFxHWh91Rp+pcAYaaIApMSYsiafmTUDd03ENtD9qCEy0NAQJBANpkI6GIe2bclAg5G62gwiBR6VLB/UsESiDf9WOdw5Wtdsjr2F/Be1VuE40yMDGD88j8RdOquUw3KvKXMBJLVy0CQQCwHzbzc4llfz80R0am54+qHjxQGuF0BTD6ebnSJgeP9P7zOxXUtfYoK8UApCKkcPzG7Otd7DotKMn2QxuryGOhAkBBojbTJSFxGHmkvwUCeX3eGL/2jzaAhRmCJ8yn05IkOa2pVLgCjzNxyVM27A5v0yhBDxAtPPHTZgESRz27QclBAkAi0JjROSaQ3L2GvQw3VBDvJPjxMM8eWyRabxOPehsGlvyK4kQnfyzAth5ESS3b6cXeINlKALdjU+vQdWWT6JHhAkAsfeZrgJQq61MBT/baYbavNQL6kB18whnxGnMxpXJ3tzON4Pcz9Z9j2vxJHCicJ1jm0bX+Sj+lapoEgUo11lrw";
+    public static String PUBLIC_KEY="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCWP3mALYZ09mC53gDB9qwiziZyNWlagunrJ7YxUd3GrNUsAFaaMdAuDPpTeUEaYzdkH2b0EuHlWP5vNfxAHNWWWa4urNI6VkNUE7ZFLgwsbgpCWgD4auq6UfkiPHhPDBq0l7l3L7kpVqGTdfDqJ8Ke2mbKM83Mp4zM0EMkzkA6TQIDAQAB";
+    private static Map<Integer, String> keyMap = new HashMap<Integer, String>();  //用于封装随机产生的公钥与私钥
+    public static void main(String[] args) throws Exception {
+        //生成公钥和私钥
+        genKeyPair();
+        //加密字符串
+        String message = "testmsg";
+        System.out.println("随机生成的公钥为:" + keyMap.get(0));
+        System.out.println("随机生成的私钥为:" + keyMap.get(1));
+        String messageEn = encrypt(message,keyMap.get(0));
+        System.out.println("明文:"+message);
+        System.out.println("加密后的字符串为:" + messageEn);
+        String messageDe = decrypt(messageEn,keyMap.get(1));
+        System.out.println("还原后的字符串为:" + messageDe);
+    }
+
+    /**
+     * 随机生成密钥对
+     * @throws NoSuchAlgorithmException
+     */
+    public static void genKeyPair() throws NoSuchAlgorithmException {
+        // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
+        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
+        // 初始化密钥对生成器,密钥大小为96-1024位
+        keyPairGen.initialize(1024,new SecureRandom());
+        // 生成一个密钥对,保存在keyPair中
+        KeyPair keyPair = keyPairGen.generateKeyPair();
+        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私钥
+        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公钥
+        String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
+        // 得到私钥字符串
+        String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
+        // 将公钥和私钥保存到Map
+        keyMap.put(0,publicKeyString);  //0表示公钥
+        keyMap.put(1,privateKeyString);  //1表示私钥
+    }
+    /**
+     * RSA公钥加密
+     *
+     * @param str
+     *            加密字符串
+     * @param publicKey
+     *            公钥
+     * @return 密文
+     * @throws Exception
+     *             加密过程中的异常信息
+     */
+    public static String encrypt( String str, String publicKey ) throws Exception{
+        //base64编码的公钥
+        byte[] decoded = Base64.decodeBase64(publicKey);
+        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
+        //RSA加密
+        Cipher cipher = Cipher.getInstance("RSA");
+        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
+        String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
+        return outStr;
+    }
+
+    /**
+     * RSA私钥解密
+     *
+     * @param str
+     *            加密字符串
+     * @param privateKey
+     *            私钥
+     * @return 铭文
+     * @throws Exception
+     *             解密过程中的异常信息
+     */
+    public static String decrypt(String str, String privateKey) throws Exception{
+        //64位解码加密后的字符串
+        byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
+        //base64编码的私钥
+        byte[] decoded = Base64.decodeBase64(privateKey);
+        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
+        //RSA解密
+        Cipher cipher = Cipher.getInstance("RSA");
+        cipher.init(Cipher.DECRYPT_MODE, priKey);
+        String outStr = new String(cipher.doFinal(inputByte));
+        return outStr;
+    }
+}

+ 164 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/ServletUtils.java

@@ -0,0 +1,164 @@
+package com.ztmap.common.utils;
+
+import java.io.IOException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import com.ztmap.common.utils.text.Convert;
+
+/**
+ * 客户端工具类
+ * 
+ * @author ztmap
+ */
+public class ServletUtils
+{
+    /**
+     * 定义移动端请求的所有可能类型
+     */
+    private final static String[] agent = { "Android", "iPhone", "iPod", "iPad", "Windows Phone", "MQQBrowser" };
+
+    /**
+     * 获取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);
+    }
+
+    /**
+     * 获取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 待渲染的字符串
+     * @return null
+     */
+    public static String renderString(HttpServletResponse response, String string)
+    {
+        try
+        {
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+            response.getWriter().print(string);
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 是否是Ajax异步请求
+     * 
+     * @param request
+     */
+    public static boolean isAjaxRequest(HttpServletRequest request)
+    {
+        String accept = request.getHeader("accept");
+        if (accept != null && accept.indexOf("application/json") != -1)
+        {
+            return true;
+        }
+
+        String xRequestedWith = request.getHeader("X-Requested-With");
+        if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1)
+        {
+            return true;
+        }
+
+        String uri = request.getRequestURI();
+        if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
+        {
+            return true;
+        }
+
+        String ajax = request.getParameter("__ajax");
+        if (StringUtils.inStringIgnoreCase(ajax, "json", "xml"))
+        {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 判断User-Agent 是不是来自于手机
+     */
+    public static boolean checkAgentIsMobile(String ua)
+    {
+        boolean flag = false;
+        if (!ua.contains("Windows NT") || (ua.contains("Windows NT") && ua.contains("compatible; MSIE 9.0;")))
+        {
+            // 排除 苹果桌面系统
+            if (!ua.contains("Windows NT") && !ua.contains("Macintosh"))
+            {
+                for (String item : agent)
+                {
+                    if (ua.contains(item))
+                    {
+                        flag = true;
+                        break;
+                    }
+                }
+            }
+        }
+        return flag;
+    }
+}

+ 1684 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/ShapeReader.java

@@ -0,0 +1,1684 @@
+package com.ztmap.common.utils;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.ztmap.common.constant.SupportDataType;
+import com.ztmap.common.utils.domain.ExcelCellData;
+import com.ztmap.common.utils.domain.ExcelDefinition;
+import com.ztmap.common.utils.domain.ExcelRowData;
+import com.ztmap.common.utils.domain.SpatialDataInfo;
+import org.gdal.gdal.Band;
+import org.gdal.gdal.ColorTable;
+import org.gdal.gdal.Dataset;
+import org.gdal.gdal.gdal;
+import org.gdal.gdalconst.gdalconstConstants;
+import org.gdal.ogr.*;
+import org.gdal.osr.SpatialReference;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ShapeReader {
+
+    private static ShapeReader instance;
+
+    private ShapeReader(String code) {
+        //System.out.println(System.getProperty("java.library.path"));
+        //注册所有的驱动
+        ogr.RegisterAll();
+        //为了支持中文路径,请添加下面这句代码
+        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
+        //为了使属性表字段支持中文,请添加下面这句
+        gdal.SetConfigOption("SHAPE_ENCODING", code);
+        //TODO: 设定data目录,待调整
+        //F:\release-1800-x64-gdal-2-2-1-mapserver-7-0-6\bin
+        gdal.SetConfigOption("GDAL_DATA","F:\\release-1928-x64-dev\\release-1928-x64\\bin\\gdal-data" );
+    }
+
+//	private static class ShapeReaderHolder {
+//		private static ShapeReader reader = new ShapeReader();
+//	}
+
+    public static ShapeReader getIntance(String code) {
+
+        if (instance == null) {
+            instance = new ShapeReader(code);
+        }
+
+        return instance;
+    }
+
+    // D:\\shapes\\云南区县shp\\YN_V_G_QX_Project.shp
+    public Layer readLayerFromShp(String strVectorFile) {
+        // 打开文件
+        DataSource ds = ogr.Open(strVectorFile, 0);
+
+        // 读取图层字段信息
+        Layer extentLayer = ds.GetLayer(0);
+
+        return extentLayer;
+    }
+
+    public List<ExcelRowData> buildExcelRowsFromLayer(Layer extentLayer, int first, int lastrow, boolean ignoreGeom) {
+        FeatureDefn def = extentLayer.GetLayerDefn();
+        int fields_count = def.GetFieldCount();
+        FieldDefn field_def = null;
+        ArrayList<FieldDefn> fields = new ArrayList<FieldDefn>();
+        for (int i = 0; i < fields_count; i++) {
+            field_def = def.GetFieldDefn(i);
+            String field_name = field_def.GetName();
+            int field_type = field_def.GetFieldType();
+            System.out.println("字段名称:" + field_name + ",字段类型:" + field_def.GetFieldTypeName(field_type));
+            fields.add(field_def);
+        }
+
+        ExcelRowData row = null;
+        List<ExcelCellData> cells = null;
+        ExcelCellData cell = null;
+        ExcelDefinition defi = null;
+        List<ExcelRowData> rows = new ArrayList<ExcelRowData>();
+        // 读取每个要素的属性信息
+        for (int i = first; i < lastrow; i++) {
+            Feature iFeature = extentLayer.GetFeature(i);
+            if (null == iFeature) {
+                continue;
+            }
+            row = new ExcelRowData();
+            cells = new ArrayList<ExcelCellData>();
+            if (!ignoreGeom) {
+                Geometry geom = iFeature.GetGeometryRef();
+                String str_json = geom.ExportToJson();
+                System.out.println(str_json);
+
+                cell = CreateShapeCell();
+                cell.setData(str_json);
+                cells.add(cell);
+            }
+            for (int j = 0; j < fields.size(); j++) {
+                field_def = (FieldDefn) fields.get(j);
+                int fType = field_def.GetFieldType();
+                String fieldName = field_def.GetName();
+                String fieldType = field_def.GetFieldTypeName(fType);
+
+                cell = new ExcelCellData();
+                defi = new ExcelDefinition();
+                defi.setColumn(fieldName);
+                defi.setTitle(fieldName);
+                defi.setDataType(DataTypeTransfer(fieldType));
+                cell.setDefinition(defi);
+
+                if (fieldType.equalsIgnoreCase("Integer")) {
+                    cell.setData(iFeature.GetFieldAsInteger(fieldName));
+                } else if (fieldType.equalsIgnoreCase("Real")) {
+                    cell.setData(iFeature.GetFieldAsDouble(fieldName));
+                } else if (fieldType.equalsIgnoreCase("String")) {
+                    cell.setData(iFeature.GetFieldAsString(fieldName));
+                } else if (fieldType.equalsIgnoreCase("Date")) {
+                    cell.setData(iFeature.GetFieldAsString(fieldName));
+                } else {
+                    cell.setData(iFeature.GetFieldAsString(fieldName));
+                }
+
+                cells.add(cell);
+            }
+            row.setCells(cells);
+            rows.add(row);
+        }
+        return rows;
+    }
+
+    public static ExcelDefinition CreateShapeDefinition() {
+        ExcelDefinition defi = new ExcelDefinition();
+        defi.setColumn("Shape");
+        defi.setTitle("Shape");
+        defi.setShpFlag(true);
+        defi.setDataType(SupportDataType.ShapeType);
+
+        return defi;
+    }
+
+    public static ExcelCellData CreateShapeCell() {
+        ExcelCellData cell = new ExcelCellData();
+        ExcelDefinition defi = CreateShapeDefinition();
+
+        cell.setDefinition(defi);
+
+        return cell;
+    }
+
+    public static SupportDataType DataTypeTransfer(String fieldType) {
+        if (fieldType.equalsIgnoreCase("Integer")) {
+            return SupportDataType.NumberType;
+        } else if (fieldType.equalsIgnoreCase("Real")) {
+            return SupportDataType.NumberType;
+        } else if (fieldType.equalsIgnoreCase("String")) {
+            return SupportDataType.StringType;
+        } else if (fieldType.equalsIgnoreCase("Date")) {
+            return SupportDataType.StringType;
+        } else {
+            return SupportDataType.StringType;
+        }
+    }
+
+    public List<ExcelDefinition> readShapeDefinitions(String file) {
+        List<ExcelDefinition> fields = new ArrayList<>();
+        ExcelDefinition defi = null;
+        Layer extentLayer = readLayerFromShp(file);
+        FeatureDefn def = extentLayer.GetLayerDefn();
+        int fields_count = def.GetFieldCount();
+        FieldDefn field_def = null;
+        // ArrayList<FieldDefn> fields = new ArrayList<FieldDefn>();
+        for (int i = 0; i < fields_count; i++) {
+            field_def = def.GetFieldDefn(i);
+            String fieldName = field_def.GetName();
+            int field_type = field_def.GetFieldType();
+            // System.out.println("字段名称:" + field_name + ",字段类型:" +
+            // field_def.GetFieldTypeName(field_type));
+            defi = new ExcelDefinition();
+            defi.setColumn(fieldName);
+            defi.setTitle(fieldName);
+            defi.setDataType(DataTypeTransfer(field_def.GetFieldTypeName(field_type)));
+
+            fields.add(defi);
+        }
+        fields.add(CreateShapeDefinition());
+
+        return fields;
+    }
+
+
+
+    public void readRD(String rasterFilePath) {
+        List<Map<String,Object>> dataList = new ArrayList<>();
+        try {
+            Dataset poSrcDS = (Dataset) gdal.Open(rasterFilePath, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null){
+                System.out.println("Open Failed...");
+                return;
+            }
+            Band raster_band = poSrcDS.GetRasterBand(1);
+            //ColorTable colorTable = raster_band.GetRasterColorTable();
+            List<Color> colorTable = readRasterColorTable(rasterFilePath);
+            int m_Width = poSrcDS.GetRasterXSize();
+            int m_Height = poSrcDS.GetRasterYSize();
+
+            /*int[] buffer = new int[m_Width * m_Height]; // 存储数据的缓冲区
+            int flag = raster_band.ReadRaster(0, 0, m_Width, m_Height, m_Width, m_Height,
+                    gdalconstConstants.GDT_UInt32, buffer, 0, 0);
+            if (flag != gdalconstConstants.CE_None) {
+                System.out.println("no...");
+                return;
+            }
+            System.out.println(JSONObject.toJSON(buffer));*/
+
+            double min_value = 0;
+            double max_value = 0;
+            double no_data_value = 0;
+
+            Double[] vals = new Double[1];
+            raster_band.GetMaximum(vals);
+            max_value = vals[0];
+            raster_band.GetMinimum(vals);
+            min_value = vals[0];
+            raster_band.GetNoDataValue(vals);
+            no_data_value = vals[0];
+
+            System.out.println("OverviewCount="+raster_band.GetOverviewCount());
+            if(m_Width > 3000 && raster_band.GetOverviewCount() > 0){
+
+                for(int i=0;i<raster_band.GetOverviewCount();i++) {
+                    System.out.println(JSONObject.toJSONString(raster_band.GetOverview(i)));
+                }
+
+                raster_band = raster_band.GetOverview(raster_band.GetOverviewCount()/2);
+                m_Width = raster_band.GetXSize();
+                m_Height = raster_band.GetYSize();
+            }
+
+            int[] buffer = new int[m_Width * m_Height]; // 存储数据的缓冲区
+            int flag = raster_band.ReadRaster(0, 0, m_Width, m_Height, m_Width, m_Height,gdalconstConstants.GDT_UInt32, buffer, 0, 0);
+            if (flag != gdalconstConstants.CE_None) {
+                System.out.println("no...");
+                return;
+            }
+            //System.out.println(JSONObject.toJSON(buffer));
+
+            int index = 0;
+            /*int type = BufferedImage.TYPE_INT_ARGB;
+            BufferedImage image = new BufferedImage(m_Width,m_Height, type);
+            for(int m=0;m<m_Height;m++){
+                for(int n=0;n<m_Width;n++){
+                    int value = buffer[index];
+                    index++;
+                    if(value == 0) continue;
+
+                    Color color = colorTable.get(value);
+                    image.setRGB(n,m,color.getRGB());
+                }
+                //System.out.println("row="+m);
+            }
+
+            ImageIO.write(image, "PNG", new File("f:/test.png"));
+
+
+            if(true) return;*/
+
+
+            int[] buffer2 = new int[m_Width * m_Height]; // 存储数据的缓冲区
+            int index_ = 0;
+            int perheight = 1000;
+            int pos = 0;
+            int[] buffer_ = null;
+            for(int m=0;m<m_Height;m++){
+                if(m % perheight == 0) {
+                    buffer_ = new int[m_Width*perheight];
+                    int sjheight = (m+perheight>m_Height?m_Height-m:perheight);
+                    raster_band.ReadRaster(0, m, m_Width, sjheight, m_Width, sjheight, gdalconstConstants.GDT_UInt32, buffer_, 0, 0);
+                    pos = 0;
+                }
+                for(int n=0;n<m_Width;n++){
+                    if(max_value < buffer_[pos]){
+                        buffer2[index_] = 0;
+                    }else {
+                        buffer2[index_] = buffer_[pos];
+                    }
+                    pos++;
+
+                    index_++;
+
+                }
+            }
+            //System.out.println(JSONObject.toJSON(buffer2));
+            System.out.println(JSONObject.toJSON(buffer2.length));
+
+
+
+
+            double[] adfGeoTransform = poSrcDS.GetGeoTransform();
+            //System.out.println(JSONObject.toJSON(adfGeoTransform));
+
+            index = 0;
+            //计算每个像素点的经纬度
+            for(int m=0;m<m_Height;m++){
+                List<double[]> rows = new ArrayList<>();
+                for(int n=0;n<m_Width;n++){
+                    double px = adfGeoTransform[0] + n * adfGeoTransform[1] + m * adfGeoTransform[2];
+                    double py = adfGeoTransform[3] + n * adfGeoTransform[4] + m * adfGeoTransform[5];
+                    Map<String,Object> data = new HashMap<>();
+                    //获取value值
+                    int value = 0;//buffer[index];
+
+                    index++;
+
+                    data.put("row",m+1);
+                    data.put("col",n+1);
+                    data.put("value",value);
+
+                    if(value != 0) {
+                        //获取Color
+                        Color color = colorTable.get(value);
+                        data.put("color",JSONObject.toJSON(color)+"");
+                    }else{
+                        data.put("color","");
+                    }
+                    /*
+                    Map geom = new HashMap();
+                    geom.put("type","Point");
+                    geom.put("coordinates",new double[]{px,py});
+                     */
+                    //data.put("Shape","POINT("+px+" "+py+")");
+                    data.put("lng",px);
+                    data.put("lat",py);
+                    dataList.add(data);
+                }
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        ShapeReader reader = ShapeReader.getIntance("UTF-8");
+        String file = "C:\\Users\\小小张丫\\Downloads\\ne_10m_admin_0_countries\\ne_10m_admin_0_countries.shp";
+        /*
+        String targetFile = "F:\\binguan\\宾馆.json";*/
+        Layer layer = reader.readLayerFromShp(file);
+        List<Map<String,Object>> ftlist = new ArrayList<>();
+        for(int i=0;i<layer.GetFeatureCount();i++){
+            Map<String,Object> feature = new HashMap<>();
+            ftlist.add(feature);
+            Feature iFeature = layer.GetFeature(i);
+            for(int j=0;j<iFeature.GetFieldCount();j++){
+                feature.put(iFeature.GetFieldDefnRef(j).GetName(),iFeature.GetFieldAsString(j));
+            }
+            feature.put("Shape:",iFeature.GetGeometryRef().ExportToJson());
+        }
+        System.out.println(ftlist);
+        //System.out.println(System.getenv("PATH"));
+        //reader.writeShpJson(file, targetFile);
+
+        //gdal栅格转矢量
+
+        //SpatialDataInfo sdi = reader.readSpatialDataInfo("F:\\LandUse\\landuse.tif");
+        //System.out.println(JSONObject.toJSON(sdi));
+
+        //List<Color> colorList = reader.readRasterColorTable("F:\\全球数据-开发\\Forests2000\\Forests2000.tif");
+        //System.out.println(JSONObject.toJSON(colorList));
+
+        reader.readRD("F:\\全球数据-开发\\DEM-Gtopo30\\gtopo30onekm.tif");
+
+        //List<Map<String,Object>> list = reader.readRasterDatas("F:\\全球数据-开发\\DEM-Gtopo30\\gtopo30onekm.tif",true);
+        //System.out.println(JSONObject.toJSON(list));
+        //System.out.println(list.size());
+
+        //reader.createRasterImage("F:\\全球数据-开发\\Forests2000\\Forests2000.tif","f:/Forests2000.png");
+
+
+        //int[] buffer = new int[43200*21600]; // 存储数据的缓冲区
+        //System.out.println(buffer.length);
+
+        //String data = reader.readRasterPixData("F:\\landuse\\landuse.tif");
+        //System.out.println(JSONObject.toJSON(data));
+
+        //reader.convertRasterToPicture("F:\\全球数据-开发\\Forests2000\\Forests2000.tif","F:\\dem\\dem.png");
+
+        //reader.convertRasterToPicture("F:\\LandUse\\landuse.tif","F:\\LandUse\\landuse.png");
+
+        //reader.getTransparencyImage();
+
+        //reader.createRasterImage(43200,21600,list,"f:/temp.png");
+
+
+        /*
+        BufferedImage image = new BufferedImage(43200,21600, BufferedImage.TYPE_INT_ARGB);
+        for(int i=0;i<43200;i++){
+            for(int j=0;j<21600;j++){
+                Color color = Color.red;
+                if(i % 2 == 0) color = Color.blue;
+                image.setRGB(i,j,color.getRGB());
+            }
+        }
+        ImageIO.write(image, "PNG", new File("f:/temp.png"));
+
+         */
+
+
+        System.out.println("Finish...");
+
+    }
+
+    /**
+     * 创建图像
+     * @param width
+     * @param height
+     * @param pngPath
+     */
+    public boolean createRasterImage(int width,int height,List<Map<String,Object>> list,String pngPath){
+        try{
+            File file = new File(pngPath);
+            //创建目录
+            if(!file.getParentFile().exists()) file.getParentFile().mkdirs();
+
+            int type = BufferedImage.TYPE_INT_ARGB;
+
+            BufferedImage image = new BufferedImage(width, height, type);
+
+            for(Map<String,Object> map:list){
+                int value = Integer.parseInt(map.get("value").toString());
+                if(value ==0) continue;
+                int row = Integer.parseInt(map.get("row").toString());
+                int col = Integer.parseInt(map.get("col").toString());
+                Color myWhite = JSONObject.parseObject(map.get("color").toString(),Color.class);
+                int color = myWhite.getRGB();
+                //System.out.println("row="+row+",col="+col+",color="+color);
+                image.setRGB(col-1,row-1,color);
+            }
+            ImageIO.write(image, "PNG", file);
+
+            return true;
+
+        }catch (Exception e){
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 读取栅格生成图片
+     * @param rasterFilePath
+     * @param pngPath
+     * @return
+     */
+    public boolean createRasterImage(String rasterFilePath,String pngPath){
+        try{
+            File file = new File(pngPath);
+            //创建目录
+            if(!file.getParentFile().exists()) file.getParentFile().mkdirs();
+            Dataset poSrcDS = (Dataset) gdal.Open(rasterFilePath, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null){
+                System.out.println("Open Failed...");
+                return false;
+            }
+            int m_Width = poSrcDS.GetRasterXSize();
+            int m_Height = poSrcDS.GetRasterYSize();
+
+            /*System.out.println("m_Width="+m_Width+",m_Height="+m_Height);
+
+            double[] gepTransform = poSrcDS.GetGeoTransform();
+            System.out.println(JSONObject.toJSON(gepTransform));
+            double[] extent = new double[4];
+            extent[0] = gepTransform[0];
+            extent[1] = gepTransform[3] + m_Height * gepTransform[5] + gepTransform[4];
+            extent[2] = gepTransform[0] + m_Width * gepTransform[1] + gepTransform[2];
+            extent[3] = gepTransform[3];
+            System.out.println(JSONObject.toJSON(extent));
+            String sr_info = "";
+            sr_info = poSrcDS.GetProjectionRef();
+            System.out.println(sr_info);*/
+
+
+            Band raster_band = poSrcDS.GetRasterBand(1);
+            List<Color> colorTable = readRasterColorTable(rasterFilePath);
+
+            int type = BufferedImage.TYPE_INT_ARGB;
+            BufferedImage image = new BufferedImage(m_Width, m_Height, type);
+
+            int perheight = 1000;
+            int pos = 0;
+            int[] buffer_ = null;
+            for(int m=0;m<m_Height;m++){
+                if(m % perheight == 0) {
+                    buffer_ = new int[m_Width*perheight];
+                    int sjheight = (m+perheight>m_Height?m_Height-m:perheight);
+                    raster_band.ReadRaster(0, m, m_Width, sjheight, m_Width, sjheight, gdalconstConstants.GDT_UInt32, buffer_, 0, 0);
+                    pos = 0;
+                }
+                for(int n=0;n<m_Width;n++){
+                    int value = buffer_[pos];
+                    pos++;
+                    if(value == 0) continue;
+
+                    Color color = colorTable.get(value);
+                    image.setRGB(n,m,color.getRGB());
+                }
+                //System.out.println("row="+m);
+            }
+
+            ImageIO.write(image, "PNG", file);
+
+            return true;
+
+        }catch (Exception e){
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 栅格根据颜色表生成图片
+     * @param rasterFilePath
+     * @param file
+     * @param colorTable
+     * @return
+     */
+    public boolean createRasterImage(String rasterFilePath,File file,List<Integer> colorTable){
+        try{
+            //创建目录
+            if(!file.getParentFile().exists()) file.getParentFile().mkdirs();
+            Dataset poSrcDS = (Dataset) gdal.Open(rasterFilePath, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null){
+                System.out.println("Open Failed...");
+                return false;
+            }
+            int m_Width = poSrcDS.GetRasterXSize();
+            int m_Height = poSrcDS.GetRasterYSize();
+
+
+            Band raster_band = poSrcDS.GetRasterBand(1);
+            int type = BufferedImage.TYPE_INT_ARGB;
+            BufferedImage image = new BufferedImage(m_Width, m_Height, type);
+
+            int perheight = 1000;
+            int pos = 0;
+            int[] buffer_ = null;
+            for(int m=0;m<m_Height;m++){
+                if(m % perheight == 0) {
+                    buffer_ = new int[m_Width*perheight];
+                    int sjheight = (m+perheight>m_Height?m_Height-m:perheight);
+                    raster_band.ReadRaster(0, m, m_Width, sjheight, m_Width, sjheight, gdalconstConstants.GDT_UInt32, buffer_, 0, 0);
+                    pos = 0;
+                }
+                for(int n=0;n<m_Width;n++){
+                    int value = buffer_[pos];
+                    pos++;
+                    if(value == 0) continue;
+
+                    image.setRGB(n,m,colorTable.get(value));
+                }
+                //System.out.println("row="+m);
+            }
+
+            ImageIO.write(image, "PNG", file);
+
+            return true;
+
+        }catch (Exception e){
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 创建透明的图片
+     *
+     * @param
+     * @throws IOException
+     */
+    public void getTransparencyImage() throws IOException {
+        //初始化基本数据
+        int width = 255, height = 255, ascent = 1, line = 1;
+
+        // 创建BufferedImage对象
+        BufferedImage image = new BufferedImage(width, (height+ascent)*line, BufferedImage.TYPE_INT_ARGB);
+        // 获取Graphics2D
+        Graphics2D g2d = image.createGraphics();
+
+        // ---------- 增加下面的代码使得背景透明 -----------------
+        image = g2d.getDeviceConfiguration().createCompatibleImage(width, (height+ascent)*line);
+        g2d.dispose();
+        g2d = image.createGraphics();
+        // ---------- 背景透明代码结束 -----------------
+
+        //抗锯齿 让图片看起来更清晰
+        RenderingHints rh = g2d.getRenderingHints();
+        rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        g2d.setRenderingHints(rh);
+
+        // 画图 Start
+        //获得字体颜色
+        int r = 255,
+                g = 0,
+                b = 0;
+        // 设置字体颜色
+        g2d.setColor(new Color(r, g, b));
+
+        g2d.drawLine(0, 100, 100, 100);
+
+        // 画图 End
+        // 释放对象
+        g2d.dispose();
+        // 保存文件
+        ImageIO.write(image, "PNG", new File("F:/temp.png"));
+    }
+
+    /** 通过指定参数写一个图片  */
+    public static boolean writeImage(BufferedImage bi, String picType, File file) {
+
+        Graphics g = bi.getGraphics();
+
+        g.setColor(new Color(12, 123, 88));
+        g.drawLine(0, 100, 100, 100);
+        g.dispose();
+        boolean val = false;
+        try {
+            val = ImageIO.write(bi, picType, file);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return val;
+    }
+
+    public int readTotalCnts(String file) {
+        int result = 0;
+        try {
+            Layer extentLayer = readLayerFromShp(file);
+            result = (int) extentLayer.GetFeatureCount();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    /**
+     * 读取Shapefile图层范围,顺序:xmin xmax ymin ymax
+     *
+     * @param file
+     * @return
+     */
+    public double[] readLayerExtent(String file) {
+        double[] result = null;
+        try {
+            Layer extentLayer = readLayerFromShp(file);
+            result = extentLayer.GetExtent();
+            double temp = result[1];
+            result[1] = result[2];
+            result[2] = temp;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    /**
+     * 读空间数据
+     * @param file
+     * @return
+     */
+    public SpatialDataInfo readSpatialDataInfo(String file) {
+
+        SpatialDataInfo result = null;
+        try {
+            result = new SpatialDataInfo();
+            String suffix = file.substring(file.lastIndexOf(".") + 1);
+            if (suffix.equalsIgnoreCase("shp")) {
+                Layer extentLayer = readLayerFromShp(file);
+                double[] extent = extentLayer.GetExtent();
+
+                double temp = extent[1];
+                extent[1] = extent[2];
+                extent[2] = temp;
+
+                result.setExtent(extent);
+                result.setSpatialReference(extentLayer.GetSpatialRef());
+            } else if (suffix.equalsIgnoreCase("img") || suffix.equalsIgnoreCase("tif")) {
+                Dataset poSrcDS = (Dataset) gdal.Open(file, gdalconstConstants.GA_ReadOnly);
+                if (poSrcDS == null)
+                    return null;
+
+                int band_count = poSrcDS.GetRasterCount();
+                result.setRasterBandCount(band_count);
+
+                int m_Width = poSrcDS.GetRasterXSize();
+                int m_Height = poSrcDS.GetRasterYSize();
+
+                byte[] buffer = new byte[m_Width * m_Height]; // 存储数据的缓冲区
+                Band raster_band = poSrcDS.GetRasterBand(1);
+                /**int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize,
+                 * int buf_type, byte[] regularArrayOut, int nPixelSpace, int nLineSpace*/
+                int flag = raster_band.ReadRaster(0, 0, m_Width, m_Height, m_Width, m_Height,
+                        gdalconstConstants.GDT_Byte, buffer, 0, 0);
+                if (flag != gdalconstConstants.CE_None) {
+                    System.out.println("no...");
+                }
+
+                /*
+                double[] adfGeoTransform = poSrcDS.GetGeoTransform();
+                System.out.println(JSONObject.toJSON(adfGeoTransform));
+                //计算每个像素点的经纬度
+                List<List<double[]>> allpix = new ArrayList<>();
+                for(int m=0;m<m_Height;m++){
+                    List<double[]> rows = new ArrayList<>();
+                    for(int n=0;n<m_Width;n++){
+                        double px = adfGeoTransform[0] + m * adfGeoTransform[1] + n * adfGeoTransform[2];
+                        double py = adfGeoTransform[3] + m * adfGeoTransform[4] + n * adfGeoTransform[5];
+                        rows.add(new double[]{px,py});
+                    }
+                    allpix.add(rows);
+                }
+                //System.out.println(JSONObject.toJSON(allpix));
+
+                ColorTable colorTable = raster_band.GetRasterColorTable();
+                for(int i=0;i<raster_band.GetDefaultRAT().GetColumnCount();i++) {
+                    System.out.print(raster_band.GetDefaultRAT().GetNameOfCol(i)+"\t");
+                }
+                System.out.println();
+                for(int j=0;j<raster_band.GetDefaultRAT().GetRowCount();j++){
+                    for(int i=0;i<raster_band.GetDefaultRAT().GetColumnCount();i++) {
+                        System.out.print(raster_band.GetDefaultRAT().GetValueAsString(j,i)+"\t");
+                        //获取颜色
+                        if(raster_band.GetDefaultRAT().GetNameOfCol(i).toLowerCase().equals("value")) {
+                            Color color = colorTable.GetColorEntry(raster_band.GetDefaultRAT().GetValueAsInt(j,i));
+                            System.out.println(JSONObject.toJSON(color));
+                        }
+                    }
+                    System.out.println();
+                }
+
+                double min_value = 0;
+                double max_value = 0;
+                double no_data_value = 0;
+
+                Double[] vals = new Double[10];
+                raster_band.GetMaximum(vals);
+                System.out.println(JSONObject.toJSON(vals));
+                max_value = vals[0];
+                raster_band.GetMinimum(vals);
+                System.out.println(JSONObject.toJSON(vals));
+                min_value = vals[0];
+                raster_band.GetNoDataValue(vals);
+                System.out.println(JSONObject.toJSON(vals));
+                no_data_value = vals[0];
+                System.out.println(JSONObject.toJSON(buffer));
+                 */
+
+
+                result.setRasterXSize(m_Width);
+                result.setRasterYSize(m_Height);
+
+
+                double nX = m_Width;
+                double nY = m_Height;
+                double[] gepTransform = poSrcDS.GetGeoTransform();
+                result.setGeotransform(gepTransform);
+				/*
+				 * m_pDataset->GetGeoTransform( m_AdfGeoTransform );
+				   m_AdfGeoTransform是一个含6个元素的数组,执行了这行代码后,我们就可以获取m_AdfGeoTransform数组的信息,
+				   m_AdfGeoTransform[0],m_AdfGeoTransform[3]是整个影像的坐下角坐标,
+				   m_AdfGeoTransform[1]是影像宽度上的分辨率,m_AdfGeoTransform[5]是影像高度上的分辨率,
+				   而对于m_AdfGeoTransform[2]和m_AdfGeoTransform[4]来说,如果影像是指北的,这两个参数的值为0。
+				   有了这几个参数,我们就能通过以下两行代码求出影像左下角和右上角的信息:
+				   XMin = m_AdfGeoTransform[0];
+				   YMin = m_AdfGeoTransform[3];
+					
+				   XMax = m_AdfGeoTransform[0] + nX * m_AdfGeoTransform[1] + m_AdfGeoTransform[2]; 
+				   YMax = m_AdfGeoTransform[3] + m_AdfGeoTransform[4] + nY * m_AdfGeoTransform[5];
+				 *
+				 * */
+                /*顺序:xmin ymin xmax ymax*/
+                double[] extent = new double[4];
+                extent[0] = gepTransform[0];
+                extent[1] = gepTransform[3] + nY * gepTransform[5] + gepTransform[4];
+                extent[2] = gepTransform[0] + nX * gepTransform[1] + gepTransform[2];
+                extent[3] = gepTransform[3];
+                result.setExtent(extent);
+                String sr_info = "";
+                sr_info = poSrcDS.GetProjectionRef();
+                //sr_info = poSrcDS.GetProjection();
+                //sr_info = poSrcDS.GetGCPProjection();
+                SpatialReference spatialReference = new SpatialReference(sr_info);
+//				System.out.println(spatialReference.ExportToWkt());
+//				System.out.println(spatialReference.GetAttrValue("PROJECTION"));
+//				System.out.println(spatialReference.GetAttrValue("PROJCS"));
+//				System.out.println(spatialReference.GetAttrValue("GEOGCS"));
+//				System.out.println(spatialReference.GetAttrValue("GEOGCS", 2));
+//				System.out.println(spatialReference.GetAttrValue("DATUM"));
+//				System.out.println(spatialReference.GetAttrValue("PARAMETER"));
+                result.setSpatialReference(spatialReference);
+            }
+        } catch (Exception e) {
+            result = null;
+        }
+
+        return result;
+    }
+
+    /**
+     * 读取栅格像素数据
+     * @param file
+     * @return
+     */
+    public String readRasterPixData(String file) {
+        try {
+            Dataset poSrcDS = (Dataset) gdal.Open(file, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null)
+                return null;
+
+            int m_Width = poSrcDS.GetRasterXSize();
+            int m_Height = poSrcDS.GetRasterYSize();
+            Band raster_band = poSrcDS.GetRasterBand(1);
+            int[] buffer = new int[m_Width * m_Height]; // 存储数据的缓冲区
+
+            double min_value = 0;
+            double max_value = 0;
+            double no_data_value = 0;
+
+            Double[] vals = new Double[1];
+            raster_band.GetMaximum(vals);
+            max_value = vals[0];
+            raster_band.GetMinimum(vals);
+            min_value = vals[0];
+            raster_band.GetNoDataValue(vals);
+            no_data_value = vals[0];
+
+
+            int perheight = 1000;
+            int index = 0;
+            int pos = 0;
+            int[] buffer_ = null;
+            //计算每个像素点的经纬度
+            for(int m=0;m<m_Height;m++){
+                //读取指定行数据
+                if(m % perheight == 0) {
+                    buffer_ = new int[m_Width*perheight];
+                    int sjheight = (m+perheight>m_Height?m_Height-m:perheight);
+                    raster_band.ReadRaster(0, m, m_Width, sjheight, m_Width, sjheight, gdalconstConstants.GDT_UInt32, buffer_, 0, 0);
+                    pos = 0;
+                }
+                for(int n=0;n<m_Width;n++){
+                    int value = buffer_[pos]>max_value?0:buffer_[pos];
+                    buffer[index] = value;
+                    pos++;
+                    index++;
+                }
+            }
+            return JSONObject.toJSON(buffer).toString();
+
+        } catch (Exception e) {
+            return "";
+        }
+    }
+
+    public int[] readRasterPixData2(String file) {
+        try {
+            Dataset poSrcDS = (Dataset) gdal.Open(file, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null)
+                return null;
+
+            int m_Width = poSrcDS.GetRasterXSize();
+            int m_Height = poSrcDS.GetRasterYSize();
+
+            int[] buffer = new int[m_Width * m_Height]; // 存储数据的缓冲区
+            Band raster_band = poSrcDS.GetRasterBand(1);
+            int flag = raster_band.ReadRaster(0, 0, m_Width, m_Height, m_Width, m_Height,
+                    gdalconstConstants.GDT_UInt32, buffer, 0, 0);
+            if (flag != gdalconstConstants.CE_None) {
+                System.out.println("no...");
+                return null;
+            }
+
+            return buffer;
+
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * 读取栅格颜色表
+     * @param file
+     * @return
+     */
+    public List<Color> readRasterColorTable(String file) {
+        try {
+            Dataset poSrcDS = (Dataset) gdal.Open(file, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null)
+                return null;
+            Band raster_band = poSrcDS.GetRasterBand(1);
+            System.out.println(JSONObject.toJSON(raster_band));
+            ColorTable colorTable = raster_band.GetRasterColorTable();
+            List<Color> colorList = new ArrayList<>();
+            if(colorTable != null){
+                for(int i=0;i<colorTable.GetCount();i++){
+                    Color color = colorTable.GetColorEntry(i);
+                    System.out.println(JSONObject.toJSON(color));
+                    colorList.add(color);
+                }
+            }else{
+                //生成颜色表
+                //最小值
+                double min_value = 0;
+                //最大值
+                double max_value = 0;
+                Double[] vals = new Double[10];
+                raster_band.GetMaximum(vals);
+                max_value = vals[0];
+                raster_band.GetMinimum(vals);
+                min_value = vals[0];
+                createColorTable(min_value,max_value,colorList);
+            }
+            return colorList;
+
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * 生成颜色表
+     * @param min_value
+     * @param max_value
+     * @param colorList
+     */
+    public void createColorTable(double min_value,double max_value,List<Color> colorList){
+        String[] breakArray = new String[8];
+        double dx_value = (max_value - min_value) / 8;
+        for(int i=0;i<8;i++){
+            breakArray[i] = (min_value+ i * dx_value)+"";
+        }
+        String colorStr = "[[0,0,0,255],[74,145,148,255],[77,141,124,255],[76,164,76,255],[161,135,63,255],[161,108,91,255],[151,75,144,255],[95,99,159,255]]";
+        JSONArray colorArr = JSONArray.parseArray(colorStr);
+        for(int i=0;i<min_value;i++){
+            colorList.add(new Color(0,0,0,255));
+        }
+        for(double j=min_value;j<=max_value;j++){
+            int[] clr = getlinearColor(j,colorArr,breakArray);
+            colorList.add(new Color(clr[0],clr[1],clr[2],clr[3]));
+        }
+    }
+
+    /**
+     * 根据颜色列表生成颜色值
+     * @param colorStr
+     * @param min_value
+     * @param max_value
+     * @return
+     */
+    public void createColorTable(String colorStr,double min_value,double max_value,List<Integer> colorList){
+        JSONArray colorArr = JSONArray.parseArray(colorStr);
+        String[] breakArray = new String[colorArr.size()];
+        double dx_value = (max_value - min_value) / colorArr.size();
+        for(int i=0;i<colorArr.size();i++){
+            breakArray[i] = (min_value+ i * dx_value)+"";
+        }
+        //String colorStr = "[[0,0,0,255],[74,145,148,255],[77,141,124,255],[76,164,76,255],[161,135,63,255],[161,108,91,255],[151,75,144,255],[95,99,159,255]]";
+
+        for(int i=0;i<min_value;i++){
+            colorList.add(new Color(0,0,0,0).getRGB());
+        }
+        for(double j=min_value;j<=max_value;j++){
+            int[] clr = getlinearColor(j,colorArr,breakArray);
+            colorList.add(new Color(clr[0],clr[1],clr[2],clr[3]).getRGB());
+        }
+    }
+
+    /**
+     * 读取栅格范围
+     * @param rasterFilePath
+     * @return
+     */
+    public double[] readRasterExtent(String rasterFilePath) {
+        double[] result = new double[4];
+        try {
+
+            Dataset poSrcDS = (Dataset) gdal.Open(rasterFilePath, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null)
+                return null;
+
+            double nX = poSrcDS.GetRasterXSize();
+            double nY = poSrcDS.GetRasterYSize();
+            double[] gepTransform = poSrcDS.GetGeoTransform();
+            result[0] = gepTransform[0];
+            result[1] = gepTransform[3] + nY * gepTransform[5] + gepTransform[4];
+            result[2] = gepTransform[0] + nX * gepTransform[1] + gepTransform[2];
+            result[3] = gepTransform[3];
+        } catch (Exception e) {
+            result = null;
+        }
+
+        return result;
+    }
+    /**
+     * 读取栅格数据总数
+     * @param rasterFilePath
+     * @return
+     */
+    public int readRasterTotalCnts(String rasterFilePath) {
+        return readRasterTotalCnts(rasterFilePath,false);
+    }
+    public int readRasterTotalCnts(String rasterFilePath,boolean filter) {
+        int result = 0;
+        try {
+            Dataset poSrcDS = (Dataset) gdal.Open(rasterFilePath, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null)
+                return 0;
+            Band raster_band = poSrcDS.GetRasterBand(1);
+            int m_Width = poSrcDS.GetRasterXSize();
+            int m_Height = poSrcDS.GetRasterYSize();
+
+            int[] buffer = new int[m_Width * m_Height]; // 存储数据的缓冲区
+            int flag = raster_band.ReadRaster(0, 0, m_Width, m_Height, m_Width, m_Height,
+                    gdalconstConstants.GDT_UInt32, buffer, 0, 0);
+            if (flag != gdalconstConstants.CE_None) {
+                System.out.println("no...");
+                return 0;
+            }
+            for(int i=0;i<buffer.length;i++){
+                if(filter)
+                    if(buffer[i] == 0) continue;
+                result++;
+            }
+
+            //result = raster_band.GetDefaultRAT().GetRowCount();
+
+        } catch (Exception e) {
+        }
+        return result;
+    }
+    /**
+     * 读取栅格属性
+     * @param rasterFilePath
+     * @return
+     */
+    public List<ExcelDefinition> readRasterDefinitions(String rasterFilePath) {
+        List<ExcelDefinition> fields = new ArrayList<>();
+        try {
+            //Dataset poSrcDS = (Dataset) gdal.Open(rasterFilePath, gdalconstConstants.GA_ReadOnly);
+            //if (poSrcDS == null)
+             //   return null;
+            ExcelDefinition rowdefi = new ExcelDefinition();
+            rowdefi.setColumn("row");
+            rowdefi.setTitle("row");
+            rowdefi.setDataType(SupportDataType.NumberType);
+            fields.add(rowdefi);
+
+            ExcelDefinition coldefi = new ExcelDefinition();
+            coldefi.setColumn("col");
+            coldefi.setTitle("col");
+            coldefi.setDataType(SupportDataType.NumberType);
+            fields.add(coldefi);
+
+            ExcelDefinition valuedefi = new ExcelDefinition();
+            valuedefi.setColumn("value");
+            valuedefi.setTitle("value");
+            valuedefi.setDataType(SupportDataType.NumberType);
+            fields.add(valuedefi);
+
+            ExcelDefinition colordefi = new ExcelDefinition();
+            colordefi.setColumn("color");
+            colordefi.setTitle("color");
+            colordefi.setDataType(SupportDataType.StringType);
+            fields.add(colordefi);
+
+            ExcelDefinition lngdefi = new ExcelDefinition();
+            lngdefi.setColumn("lng");
+            lngdefi.setTitle("lng");
+            lngdefi.setDataType(SupportDataType.NumberType);
+            fields.add(lngdefi);
+
+            ExcelDefinition latdefi = new ExcelDefinition();
+            latdefi.setColumn("lat");
+            latdefi.setTitle("lat");
+            latdefi.setDataType(SupportDataType.NumberType);
+            fields.add(latdefi);
+            //fields.add(CreateShapeDefinition());
+
+        } catch (Exception e) {
+
+        }
+        return fields;
+    }
+    public List<ExcelDefinition> readRasterDefinitions1(String rasterFilePath) {
+        List<ExcelDefinition> fields = new ArrayList<>();
+        try {
+            Dataset poSrcDS = (Dataset) gdal.Open(rasterFilePath, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null)
+                return null;
+
+            //只处理第1段
+            Band raster_band = poSrcDS.GetRasterBand(1);
+            ColorTable colorTable = raster_band.GetRasterColorTable();
+            for(int i=0;i<raster_band.GetDefaultRAT().GetColumnCount();i++) {
+                raster_band.GetDefaultRAT().GetUsageOfCol(i);
+                int coltype = raster_band.GetDefaultRAT().GetTypeOfCol(i);
+                //列是否引用
+                int colUsage = raster_band.GetDefaultRAT().GetUsageOfCol(i);
+                //判断是否是引用值,是代表是有颜色表引用
+                if(colUsage>0) continue;
+
+
+                String fieldName = raster_band.GetDefaultRAT().GetNameOfCol(i);
+                ExcelDefinition defi = new ExcelDefinition();
+                defi.setColumn(fieldName);
+                defi.setTitle(fieldName);
+                defi.setDataType(coltype==0?SupportDataType.NumberType:SupportDataType.StringType);
+                if(colorTable!=null) {
+                    if (raster_band.GetDefaultRAT().GetNameOfCol(i).toLowerCase().equals("value")) {
+                        ExcelDefinition colordefi = new ExcelDefinition();
+                        colordefi.setColumn("COLOR");
+                        colordefi.setTitle("COLOR");
+                        colordefi.setDataType(SupportDataType.StringType);
+                        fields.add(colordefi);
+                    }
+
+                }
+                fields.add(defi);
+            }
+
+        } catch (Exception e) {
+
+        }
+        return fields;
+    }
+    /**
+     * 计算线性渐变色
+     *
+     * @param value      value
+     * @param colorArr   颜色数组
+     * @param breakArray 颜色分级
+     * @return int[]
+     */
+    public static int[] getlinearColor(double value, JSONArray colorArr, String[] breakArray) {
+        for (int i = 0; i < breakArray.length; i++) {
+            double breakValue = Double.parseDouble(breakArray[i]);
+            JSONArray rgba = colorArr.getJSONArray(i);
+            if (value <= breakValue) {
+                if (i == 0) {
+                    return arrayToPixel(rgba);
+                } else {
+                    double lastBreak = Double.parseDouble(breakArray[i - 1]);
+                    JSONArray lastrgba = colorArr.getJSONArray(i - 1);
+                    int[] pixel = new int[4];
+                    //计算RGB的线性值
+                    pixel[0] = (int) linearInterpolation(value, lastBreak, breakValue, lastrgba.getFloat(0), rgba.getFloat(0));
+                    pixel[1] = (int) linearInterpolation(value, lastBreak, breakValue, lastrgba.getFloat(1), rgba.getFloat(1));
+                    pixel[2] = (int) linearInterpolation(value, lastBreak, breakValue, lastrgba.getFloat(2), rgba.getFloat(2));
+                    pixel[3] = (int) linearInterpolation(value, lastBreak, breakValue, lastrgba.getFloat(3), rgba.getFloat(3));
+                    return pixel;
+                }
+            }
+        }
+        return arrayToPixel(colorArr.getJSONArray(colorArr.size() - 1));
+    }
+
+    /**
+     * 线性插值
+     *
+     * @param x       插值点坐标
+     * @param x1      顶点坐标
+     * @param x2      顶点坐标
+     * @param x1value 顶点数值
+     * @param x2value 顶点数值
+     * @return 插值后的数值
+     */
+    static float linearInterpolation(double x, double x1, double x2, float x1value, float x2value) {
+        return (float) (((x2 - x) / (x2 - x1) * x1value) + ((x - x1) / (x2 - x1) * x2value));
+    }
+
+    /**
+     * array转int[] 获取像素点颜色
+     *
+     * @param rgba rgbaArray
+     * @return int[]
+     */
+    static int[] arrayToPixel(JSONArray rgba) {
+        int[] pixel = new int[4];
+        pixel[0] = rgba.getInteger(0);
+        pixel[1] = rgba.getInteger(1);
+        pixel[2] = rgba.getInteger(2);
+        pixel[3] = rgba.getInteger(3);
+        return pixel;
+    }
+
+    /**
+     * 读取栅格数据
+     * @param rasterFilePath
+     */
+    public List<Map<String,Object>> readRasterDatas(String rasterFilePath) {
+        return readRasterDatas(rasterFilePath,false);
+    }
+    public List<Map<String,Object>> readRasterDatas(String rasterFilePath,boolean filter) {
+        List<Map<String,Object>> dataList = new ArrayList<>();
+        try {
+            Dataset poSrcDS = (Dataset) gdal.Open(rasterFilePath, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null)
+                return dataList;
+            Band raster_band = poSrcDS.GetRasterBand(1);
+            List<Color> colorTable = readRasterColorTable(rasterFilePath);
+            int m_Width = poSrcDS.GetRasterXSize();
+            int m_Height = poSrcDS.GetRasterYSize();
+
+            double min_value = 0;
+            double max_value = 0;
+            double no_data_value = 0;
+
+            Double[] vals = new Double[1];
+            raster_band.GetMaximum(vals);
+            max_value = vals[0];
+            raster_band.GetMinimum(vals);
+            min_value = vals[0];
+            raster_band.GetNoDataValue(vals);
+            no_data_value = vals[0];
+
+
+            double[] adfGeoTransform = poSrcDS.GetGeoTransform();
+            int index = 0;
+            int perheight = 1000;
+            int pos = 0;
+            int[] buffer_ = null;
+            //计算每个像素点的经纬度
+            for(int m=0;m<m_Height;m++){
+                //读取指定行数据
+                if(m % perheight == 0) {
+                    buffer_ = new int[m_Width*perheight];
+                    int sjheight = (m+perheight>m_Height?m_Height-m:perheight);
+                    raster_band.ReadRaster(0, m, m_Width, sjheight, m_Width, sjheight, gdalconstConstants.GDT_UInt32, buffer_, 0, 0);
+                    pos = 0;
+                }
+
+                for(int n=0;n<m_Width;n++){
+                    double px = adfGeoTransform[0] + n * adfGeoTransform[1] + m * adfGeoTransform[2];
+                    double py = adfGeoTransform[3] + n * adfGeoTransform[4] + m * adfGeoTransform[5];
+                    Map<String,Object> data = new HashMap<>();
+
+                    int value = buffer_[pos]>max_value?0:buffer_[pos];//buffer[index];
+                    pos++;
+
+                    index++;
+
+                    /*if(index % 10000 == 0){
+                        System.out.println("row="+m+",col="+n+",value="+value);
+                    }*/
+
+                    if(filter)
+                        if(value == 0) continue;
+
+                    data.put("row",m+1);
+                    data.put("col",n+1);
+                    data.put("value",value);
+
+                    if(value != 0) {
+                        //获取Color
+                        Color color = colorTable.get(value == colorTable.size()?value-1:value);
+                        data.put("color",JSONObject.toJSON(color)+"");
+                    }else{
+                        data.put("color","");
+                    }
+                    /*
+                    Map geom = new HashMap();
+                    geom.put("type","Point");
+                    geom.put("coordinates",new double[]{px,py});
+                     */
+                    //data.put("Shape","POINT("+px+" "+py+")");
+                    data.put("lng",px);
+                    data.put("lat",py);
+
+                    dataList.add(data);
+                }
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return dataList;
+
+    }
+    public List<Map<String,Object>> readRasterDatas1(String rasterFilePath) {
+        List<Map<String,Object>> dataList = new ArrayList<>();
+        try {
+            Dataset poSrcDS = (Dataset) gdal.Open(rasterFilePath, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null)
+                return dataList;
+            Band raster_band = poSrcDS.GetRasterBand(1);
+            ColorTable colorTable = raster_band.GetRasterColorTable();
+            for(int j=0;j<raster_band.GetDefaultRAT().GetRowCount();j++){
+                Map<String,Object> map = new HashMap<>();
+                for(int i=0;i<raster_band.GetDefaultRAT().GetColumnCount();i++) {
+                    //类型
+                    int colType = raster_band.GetDefaultRAT().GetTypeOfCol(i);
+                    //列是否引用
+                    int colUsage = raster_band.GetDefaultRAT().GetUsageOfCol(i);
+                    //判断是否是引用值,是代表是有颜色表引用
+                    if(colUsage>0) continue;
+
+                    String colName = raster_band.GetDefaultRAT().GetNameOfCol(i);
+                    //值
+                    String colValue = raster_band.GetDefaultRAT().GetValueAsString(j,i);
+
+                    map.put(colName,colValue);
+
+                    if(colorTable!=null) {
+                        //获取实际颜色值
+                        if (raster_band.GetDefaultRAT().GetNameOfCol(i).toLowerCase().equals("value")) {
+                            Color color = colorTable.GetColorEntry(raster_band.GetDefaultRAT().GetValueAsInt(j,i));
+                            map.put("COLOR",JSONObject.toJSON(color).toString()+"");
+                        }
+                    }
+                }
+                dataList.add(map);
+            }
+
+        } catch (Exception e) {
+
+        }
+
+        return dataList;
+
+    }
+
+    public List<ExcelRowData> buildExcelRowsFromRaster(String rasterFilePath, int first, int lastrow) {
+        List<ExcelDefinition> fields = readRasterDefinitions(rasterFilePath);
+        List<Map<String,Object>> datas = readRasterDatas(rasterFilePath);
+
+        ExcelRowData row = null;
+        List<ExcelCellData> cells = null;
+        ExcelCellData cell = null;
+        ExcelDefinition defi = null;
+        List<ExcelRowData> rows = new ArrayList<ExcelRowData>();
+        // 读取每个要素的属性信息
+        for (int i = first; i < lastrow; i++) {
+            Map<String,Object> iFeature = datas.get(i);
+            if (null == iFeature) {
+                continue;
+            }
+            row = new ExcelRowData();
+            cells = new ArrayList<ExcelCellData>();
+            for (int j = 0; j < fields.size(); j++) {
+                ExcelDefinition field_def = (ExcelDefinition) fields.get(j);
+                String fieldName = field_def.getColumn();
+                String fieldType = field_def.getDataType().toString();
+
+                cell = new ExcelCellData();
+                defi = new ExcelDefinition();
+                defi.setColumn(fieldName);
+                defi.setTitle(fieldName);
+                defi.setDataType(DataTypeTransfer(fieldType));
+                cell.setDefinition(defi);
+
+                cell.setData(iFeature.get(fieldName));
+
+                cells.add(cell);
+            }
+            row.setCells(cells);
+            rows.add(row);
+        }
+        return rows;
+    }
+    public List<ExcelRowData> readRasterData(String filePath, Integer page, Integer limit) {
+        int lastRowNum = readRasterTotalCnts(filePath);
+        int startRow = 0;
+        int endRow = 0;
+
+        if (page == 0 && limit == 0) {
+            //读取所有数据
+            startRow = 0;
+            endRow = lastRowNum;
+        } else {
+            //按范围读取数据
+            if (page == 1) {
+                startRow = 0;
+                endRow = startRow + limit;
+                endRow = endRow > lastRowNum ? (lastRowNum + 1) : endRow;
+            } else {
+                startRow = (page - 1) * limit;
+                int tmp = startRow + limit;
+                endRow = tmp < lastRowNum ? tmp : lastRowNum;
+            }
+        }
+        return buildExcelRowsFromRaster(filePath, startRow, endRow);
+    }
+
+    public List<ExcelRowData> readShapeData(String filePath, Integer page, Integer limit, boolean ignoreGeom) {
+        int lastRowNum = readTotalCnts(filePath);
+        int startRow = 0;
+        int endRow = 0;
+
+        if (page == 0 && limit == 0) {
+            //读取所有数据
+            startRow = 0;
+            endRow = lastRowNum;
+        } else {
+            //按范围读取数据
+            if (page == 1) {
+                startRow = 0;
+                endRow = startRow + limit;
+                endRow = endRow > lastRowNum ? (lastRowNum + 1) : endRow;
+            } else {
+                startRow = (page - 1) * limit;
+                int tmp = startRow + limit;
+                endRow = tmp < lastRowNum ? tmp : lastRowNum;
+            }
+        }
+        Layer extentLayer = readLayerFromShp(filePath);
+        return buildExcelRowsFromLayer(extentLayer, startRow, endRow, ignoreGeom);
+    }
+
+
+    /**
+     * Shapefile生成JSON文件
+     *
+     * @param file
+     * @param targetJsonFile 待生成的目标JSON文件
+     * @return
+     * @throws Exception
+     */
+    public Boolean writeShpJson(String file, String targetJsonFile) throws Exception {
+        Boolean result = false;
+        try {
+            DataSource ds = ogr.Open(file, 0);
+            // 将要素转换为GeoJson格式
+            Driver dv = ogr.GetDriverByName("GeoJSON");
+            DataSource dataSource = dv.CopyDataSource(ds, targetJsonFile);
+            //String command = "ogr2ogr -f \"GeoJSON\" " + targetJsonFile + " " + file;
+            //Runtime.getRuntime().exec(command);
+            //result = execCommand(command);
+            //dataSource.CommitTransaction();
+            String data = readFileContent(targetJsonFile);
+            try {
+                JSONObject.parseObject(data);
+                return true;
+            } catch (Exception e) {
+                FileWriter fileWriter = new FileWriter(targetJsonFile, true);
+                BufferedWriter bw = new BufferedWriter(fileWriter);
+                bw.write("]");
+                bw.write("}");
+                bw.close();
+                fileWriter.close();
+                return true;
+            }
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    public boolean execCommand(String commnad) {
+        try {
+            Runtime rt = Runtime.getRuntime();
+            Process proc = rt.exec(commnad);
+            OutputProcessor error = new OutputProcessor(proc.getErrorStream());
+            OutputProcessor input = new OutputProcessor(proc.getInputStream());
+            error.start();
+            input.start();
+            int exitCode = proc.waitFor();
+            if (exitCode == 0) {
+                return true;
+            }
+            return false;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    public String getShpJson(String jsonFile) {
+        File file = new File(jsonFile);
+        StringBuilder result = new StringBuilder();
+        try {
+            BufferedReader br = new BufferedReader(new FileReader(file));
+            String s = null;
+            while ((s = br.readLine()) != null) {
+                result.append(System.lineSeparator() + s);
+            }
+            br.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return result.toString();
+    }
+
+    /**
+     * 将栅格数据转换成图片
+     * @param raster_path
+     * @param picture_path
+     * @return
+     */
+    public Boolean convertRasterToPicture(String raster_path, String picture_path) {
+        Boolean result = false;
+        try {
+
+            Dataset poSrcDS = (Dataset) gdal.Open(raster_path, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null) {
+                return null;
+            }
+
+            // 以创建复制的方式,生成图片文件
+            org.gdal.gdal.Driver hDriver= null;
+            String suffix = picture_path.substring(picture_path.lastIndexOf(".") + 1);
+            if (suffix.equalsIgnoreCase("jpg")) {
+                hDriver = gdal.GetDriverByName("JPEG");
+            } else if (suffix.equalsIgnoreCase("bmp")) {
+                hDriver = gdal.GetDriverByName("BMP");
+            } else if (suffix.equalsIgnoreCase("png")) {
+                hDriver = gdal.GetDriverByName("PNG");
+            } else {
+                hDriver = gdal.GetDriverByName("JPEG");// JPEG PNG BMP
+            }
+
+            Dataset picture = hDriver.CreateCopy(picture_path, poSrcDS);
+
+            if (picture != null) {
+                result = true;
+            } else {
+                System.out.println("********图片生成失败!********");
+            }
+            hDriver.delete();
+        } catch (Exception e) {
+            result = false;
+        }
+
+        return result;
+    }
+
+    public Boolean convertRasterToPicture2(String raster_path, String picture_path) {
+
+        Boolean result = false;
+        try {
+
+            Dataset poSrcDS = (Dataset) gdal.Open(raster_path, gdalconstConstants.GA_ReadOnly);
+            if (poSrcDS == null) {
+                return null;
+            }
+
+            // 获取图像的基本信息,并把数据读入缓冲区间
+            String result_path = picture_path;
+            int m_Width = poSrcDS.GetRasterXSize();
+            int m_Height = poSrcDS.GetRasterYSize();
+
+            /* 以下程序是生成JPG的过程,上面的程序只为获得创建过程中的一些参数,如:图像的高、宽及图像数据 */
+            // 把数据保存到临时文件MEM
+            org.gdal.gdal.Driver pDriverMEM = gdal.GetDriverByName("MEM");
+            Dataset pOutMEMDataset = pDriverMEM.Create("", m_Width, m_Height, 3);// ,gdalconstConstants.GDT_Byte
+
+            int band_count = poSrcDS.GetRasterCount();
+            Boolean flag = false;
+            for (int i = 1; i <= band_count; i++) {
+                flag = WriteRasterBand(poSrcDS, i, pOutMEMDataset);
+                if (!flag) {
+                    break;
+                }
+            }
+
+            String suffix = picture_path.substring(picture_path.lastIndexOf(".") + 1);
+            // 以创建复制的方式,生成jpg文件
+            org.gdal.gdal.Driver pDriverJPG = null;
+            if (suffix.equalsIgnoreCase("jpg")) {
+                pDriverJPG = gdal.GetDriverByName("JPEG");
+            } else if (suffix.equalsIgnoreCase("bmp")) {
+                pDriverJPG = gdal.GetDriverByName("BMP");
+            } else if (suffix.equalsIgnoreCase("png")) {
+                pDriverJPG = gdal.GetDriverByName("PNG");
+            } else {
+                gdal.GetDriverByName("JPEG");// JPEG PNG BMP
+            }
+            Dataset picture = pDriverJPG.CreateCopy(result_path, pOutMEMDataset); // 创建jpg文件
+            if (picture != null) {
+                result = true;
+            } else {
+                System.out.println("********图片生成失败!********");
+            }
+
+        } catch (Exception e) {
+            result = false;
+        }
+
+        return result;
+    }
+
+    private Boolean WriteRasterBand(Dataset tif_ds, int idx_band, Dataset mem_ds) {
+
+        Boolean result = true;
+        try {
+            int m_Width = tif_ds.GetRasterXSize();
+            int m_Height = tif_ds.GetRasterYSize();
+
+            byte[] buffer = new byte[m_Width * m_Height]; // 存储数据的缓冲区
+
+            org.gdal.gdal.Band raster_band = tif_ds.GetRasterBand(idx_band);
+            /**int xoff, int yoff, int xsize, int ysize, int buf_xsize, int buf_ysize,
+             * int buf_type, byte[] regularArrayOut, int nPixelSpace, int nLineSpace*/
+            int flag = raster_band.ReadRaster(0, 0, m_Width, m_Height, m_Width, m_Height,
+                    gdalconstConstants.GDT_Byte, buffer, 0, 0);
+            if (flag != gdalconstConstants.CE_None) {
+                return false;
+            }
+
+            double min_value = 0;
+            double max_value = 0;
+            double no_data_value = 0;
+
+            Double[] vals = new Double[10];
+            raster_band.GetMaximum(vals);
+            max_value = vals[0];
+            raster_band.GetMinimum(vals);
+            min_value = vals[0];
+            raster_band.GetNoDataValue(vals);
+            no_data_value = vals[0];
+
+            int posSrc = 0, posScan = 0;
+
+            for (int i = 0; i < m_Height; i++) //row
+            {
+                for (int j = 0; j < m_Width; j++) //col
+                {
+                    double item = buffer[posSrc++];
+                    if (item == no_data_value) {
+                        buffer[posScan++] = 0; //黑色
+                    } else {
+                        buffer[posScan++] = (byte) ((item - min_value) * 256 / (max_value - min_value));
+                    }
+                }
+            }
+
+            Band pOutMEMRasterBand = mem_ds.GetRasterBand(idx_band);
+            flag = pOutMEMRasterBand.WriteRaster(0, 0, m_Width, m_Height, m_Width, m_Height,
+                    gdalconstConstants.GDT_Byte, buffer, 0, 0);
+            if (flag != gdalconstConstants.CE_None) {
+                return false;
+            }
+        } catch (Exception e) {
+            result = false;
+        }
+
+        return result;
+    }
+
+
+    public String readFileContent(String filePath) {
+        String str_result = "";
+        try {
+            String encoding = "UTF-8";
+            File file = new File(filePath);
+            if (file.isFile() && file.exists()) {
+                // 判断文件是否存在
+                InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);// 考虑到编码格式
+                BufferedReader bufferedReader = new BufferedReader(read);
+                String lineTxt = null;
+                while ((lineTxt = bufferedReader.readLine()) != null) {
+                    str_result += lineTxt;
+                }
+                System.out.println("文本内容长度:" + str_result.length());
+                read.close();
+                bufferedReader.close();
+            } else {
+                System.out.println("找不到指定的文件");
+                return "";
+            }
+        } catch (Exception e) {
+            System.out.println("读取文件内容出错");
+            e.printStackTrace();
+        }
+
+        return str_result;
+    }
+}

+ 408 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/StringUtils.java

@@ -0,0 +1,408 @@
+package com.ztmap.common.utils;
+
+import java.util.Collection;
+import java.util.Map;
+import com.ztmap.common.utils.text.StrFormatter;
+
+/**
+ * 字符串工具类
+ * 
+ * @author ztmap
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+    /** 空字符串 */
+    private static final String NULLSTR = "";
+
+    /** 下划线 */
+    private static final char SEPARATOR = '_';
+
+    /**
+     * 获取参数不为空值
+     * 
+     * @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 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);
+    }
+
+    /**
+     * 格式化文本, {} 表示占位符<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);
+    }
+
+    /**
+     * 驼峰转下划线命名
+     */
+    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();
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T cast(Object obj)
+    {
+        return (T) obj;
+    }
+}

+ 99 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/Threads.java

@@ -0,0 +1,99 @@
+package com.ztmap.common.utils;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 线程相关工具类.
+ * 
+ * @author ztmap
+ */
+public class Threads
+{
+    private static final Logger logger = LoggerFactory.getLogger(Threads.class);
+
+    /**
+     * sleep等待,单位为毫秒
+     */
+    public static void sleep(long milliseconds)
+    {
+        try
+        {
+            Thread.sleep(milliseconds);
+        }
+        catch (InterruptedException e)
+        {
+            return;
+        }
+    }
+
+    /**
+     * 停止线程池
+     * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
+     * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
+     * 如果仍人超時,則強制退出.
+     * 另对在shutdown时线程本身被调用中断做了处理.
+     */
+    public static void shutdownAndAwaitTermination(ExecutorService pool)
+    {
+        if (pool != null && !pool.isShutdown())
+        {
+            pool.shutdown();
+            try
+            {
+                if (!pool.awaitTermination(120, TimeUnit.SECONDS))
+                {
+                    pool.shutdownNow();
+                    if (!pool.awaitTermination(120, TimeUnit.SECONDS))
+                    {
+                        logger.info("Pool did not terminate");
+                    }
+                }
+            }
+            catch (InterruptedException ie)
+            {
+                pool.shutdownNow();
+                Thread.currentThread().interrupt();
+            }
+        }
+    }
+    
+    /**
+     * 打印线程异常信息
+     */
+    public static void printException(Runnable r, Throwable t)
+    {
+        if (t == null && r instanceof Future<?>)
+        {
+            try
+            {
+                Future<?> future = (Future<?>) r;
+                if (future.isDone())
+                {
+                    future.get();
+                }
+            }
+            catch (CancellationException ce)
+            {
+                t = ce;
+            }
+            catch (ExecutionException ee)
+            {
+                t = ee.getCause();
+            }
+            catch (InterruptedException ie)
+            {
+                Thread.currentThread().interrupt();
+            }
+        }
+        if (t != null)
+        {
+            logger.error(t.getMessage(), t);
+        }
+    }
+}

+ 137 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/TreeUtils.java

@@ -0,0 +1,137 @@
+package com.ztmap.common.utils;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import com.ztmap.project.system.menu.domain.Menu;
+
+/**
+ * 权限数据处理
+ * 
+ * @author ztmap
+ */
+public class TreeUtils
+{
+    /**
+     * 根据父节点的ID获取所有子节点
+     * 
+     * @param list 分类表
+     * @param parentId 传入的父节点ID
+     * @return String
+     */
+    public static List<Menu> getChildPerms(List<Menu> list, int parentId)
+    {
+        List<Menu> returnList = new ArrayList<Menu>();
+        for (Iterator<Menu> iterator = list.iterator(); iterator.hasNext();)
+        {
+            Menu t = (Menu) iterator.next();
+            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
+            if (t.getParentId() == parentId)
+            {
+                recursionFn(list, t);
+                returnList.add(t);
+            }
+        }
+        return returnList;
+    }
+
+    /**
+     * 递归列表
+     * 
+     * @param list
+     * @param t
+     */
+    private static void recursionFn(List<Menu> list, Menu t)
+    {
+        // 得到子节点列表
+        List<Menu> childList = getChildList(list, t);
+        t.setChildren(childList);
+        for (Menu tChild : childList)
+        {
+            if (hasChild(list, tChild))
+            {
+                recursionFn(list, tChild);
+            }
+        }
+    }
+
+    /**
+     * 得到子节点列表
+     */
+    private static List<Menu> getChildList(List<Menu> list, Menu t)
+    {
+
+        List<Menu> tlist = new ArrayList<Menu>();
+        Iterator<Menu> it = list.iterator();
+        while (it.hasNext())
+        {
+            Menu n = (Menu) it.next();
+            if (n.getParentId().longValue() == t.getMenuId().longValue())
+            {
+                tlist.add(n);
+            }
+        }
+        return tlist;
+    }
+
+    List<Menu> returnList = new ArrayList<Menu>();
+
+    /**
+     * 根据父节点的ID获取所有子节点
+     * 
+     * @param list 分类表
+     * @param typeId 传入的父节点ID
+     * @param prefix 子节点前缀
+     */
+    public List<Menu> getChildPerms(List<Menu> list, int typeId, String prefix)
+    {
+        if (list == null)
+        {
+            return null;
+        }
+        for (Iterator<Menu> iterator = list.iterator(); iterator.hasNext();)
+        {
+            Menu node = (Menu) iterator.next();
+            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
+            if (node.getParentId() == typeId)
+            {
+                recursionFn(list, node, prefix);
+            }
+            // 二、遍历所有的父节点下的所有子节点
+            /*
+             * if (node.getParentId()==0) { recursionFn(list, node); }
+             */
+        }
+        return returnList;
+    }
+
+    private void recursionFn(List<Menu> list, Menu node, String p)
+    {
+        // 得到子节点列表
+        List<Menu> childList = getChildList(list, node);
+        if (hasChild(list, node))
+        {
+            // 判断是否有子节点
+            returnList.add(node);
+            Iterator<Menu> it = childList.iterator();
+            while (it.hasNext())
+            {
+                Menu n = (Menu) it.next();
+                n.setMenuName(p + n.getMenuName());
+                recursionFn(list, n, p + p);
+            }
+        }
+        else
+        {
+            returnList.add(node);
+        }
+    }
+
+    /**
+     * 判断是否有子节点
+     */
+    private static boolean hasChild(List<Menu> list, Menu t)
+    {
+        return getChildList(list, t).size() > 0 ? true : false;
+    }
+}

+ 110 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/bean/BeanUtils.java

@@ -0,0 +1,110 @@
+package com.ztmap.common.utils.bean;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Bean 工具类
+ * 
+ * @author ztmap
+ */
+public class BeanUtils extends org.springframework.beans.BeanUtils
+{
+    /** Bean方法名中属性名开始的下标 */
+    private static final int BEAN_METHOD_PROP_INDEX = 3;
+
+    /** * 匹配getter方法的正则表达式 */
+    private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)");
+
+    /** * 匹配setter方法的正则表达式 */
+    private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)");
+
+    /**
+     * Bean属性复制工具方法。
+     * 
+     * @param dest 目标对象
+     * @param src 源对象
+     */
+    public static void copyBeanProp(Object dest, Object src)
+    {
+        try
+        {
+            copyProperties(src, dest);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 获取对象的setter方法。
+     * 
+     * @param obj 对象
+     * @return 对象的setter方法列表
+     */
+    public static List<Method> getSetterMethods(Object obj)
+    {
+        // setter方法列表
+        List<Method> setterMethods = new ArrayList<Method>();
+
+        // 获取所有方法
+        Method[] methods = obj.getClass().getMethods();
+
+        // 查找setter方法
+
+        for (Method method : methods)
+        {
+            Matcher m = SET_PATTERN.matcher(method.getName());
+            if (m.matches() && (method.getParameterTypes().length == 1))
+            {
+                setterMethods.add(method);
+            }
+        }
+        // 返回setter方法列表
+        return setterMethods;
+    }
+
+    /**
+     * 获取对象的getter方法。
+     * 
+     * @param obj 对象
+     * @return 对象的getter方法列表
+     */
+
+    public static List<Method> getGetterMethods(Object obj)
+    {
+        // getter方法列表
+        List<Method> getterMethods = new ArrayList<Method>();
+        // 获取所有方法
+        Method[] methods = obj.getClass().getMethods();
+        // 查找getter方法
+        for (Method method : methods)
+        {
+            Matcher m = GET_PATTERN.matcher(method.getName());
+            if (m.matches() && (method.getParameterTypes().length == 0))
+            {
+                getterMethods.add(method);
+            }
+        }
+        // 返回getter方法列表
+        return getterMethods;
+    }
+
+    /**
+     * 检查Bean方法名中的属性名是否相等。<br>
+     * 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。
+     * 
+     * @param m1 方法名1
+     * @param m2 方法名2
+     * @return 属性名一样返回true,否则返回false
+     */
+
+    public static boolean isMethodPropEquals(String m1, String m2)
+    {
+        return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
+    }
+}

+ 19 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/domain/ExcelCellData.java

@@ -0,0 +1,19 @@
+package com.ztmap.common.utils.domain;
+
+public class ExcelCellData {
+
+	private ExcelDefinition definition;
+	private Object data;
+	public ExcelDefinition getDefinition() {
+		return definition;
+	}
+	public void setDefinition(ExcelDefinition definition) {
+		this.definition = definition;
+	}
+	public Object getData() {
+		return data;
+	}
+	public void setData(Object data) {
+		this.data = data;
+	}
+}

+ 35 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/domain/ExcelDefinition.java

@@ -0,0 +1,35 @@
+package com.ztmap.common.utils.domain;
+
+
+import com.ztmap.common.constant.SupportDataType;
+
+public class ExcelDefinition {
+	private String title;
+	private String column;
+	private boolean shpFlag = false;
+	private SupportDataType dataType;
+	public String getTitle() {
+		return title;
+	}
+	public void setTitle(String title) {
+		this.title = title;
+	}
+	public SupportDataType getDataType() {
+		return dataType;
+	}
+	public void setDataType(SupportDataType dataType) {
+		this.dataType = dataType;
+	}
+	public String getColumn() {
+		return column;
+	}
+	public void setColumn(String column) {
+		this.column = column;
+	}
+	public boolean getShpFlag() {
+		return shpFlag;
+	}
+	public void setShpFlag(boolean shpFlag) {
+		this.shpFlag = shpFlag;
+	}
+}

+ 26 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/domain/ExcelRowData.java

@@ -0,0 +1,26 @@
+package com.ztmap.common.utils.domain;
+
+import java.util.List;
+
+public class ExcelRowData {
+
+	private List<ExcelCellData> cells;
+	
+	private List<ExcelDefinition> defs;
+
+	public List<ExcelCellData> getCells() {
+		return cells;
+	}
+
+	public void setCells(List<ExcelCellData> cells) {
+		this.cells = cells;
+	}
+
+	public List<ExcelDefinition> getDefs() {
+		return defs;
+	}
+
+	public void setDefs(List<ExcelDefinition> defs) {
+		this.defs = defs;
+	}
+}

+ 73 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/domain/SpatialDataInfo.java

@@ -0,0 +1,73 @@
+package com.ztmap.common.utils.domain;
+
+import org.gdal.osr.SpatialReference;
+
+public class SpatialDataInfo {
+
+	private double[] extent;
+	private SpatialReference spatialReference;
+
+	private int RasterBandCount;
+	
+	private int RasterXSize;
+	
+	private int RasterYSize;
+
+	private double[] geotransform;
+
+	public double[] getGeotransform() {
+		return geotransform;
+	}
+
+	public void setGeotransform(double[] geotransform) {
+		this.geotransform = geotransform;
+	}
+
+	/**图层范围*/
+	public double[] getExtent() {
+		return extent;
+	}
+	/**图层范围*/
+	public void setExtent(double[] extent) {
+		this.extent = extent;
+	}
+
+	/**坐标参考*/
+	public SpatialReference getSpatialReference() {
+		return spatialReference;
+	}
+	/**坐标参考*/
+	public void setSpatialReference(SpatialReference spatialReference) {
+		this.spatialReference = spatialReference;
+	}
+	/**获取坐标参考描述*/
+	public String getSpatialReferenceDesc() {
+		String result = "";
+		if(spatialReference != null) {
+			String geo_gcs = spatialReference.GetAttrValue("GEOGCS");
+			String projection = spatialReference.GetAttrValue("PROJECTION");
+			result = "GEOGCS:" + geo_gcs + "; PROJECTION:" + projection;
+		}
+		
+		return result;
+	}
+	
+	public int getRasterBandCount() {
+		return RasterBandCount;
+	}
+	public void setRasterBandCount(int rasterBandCount) {
+		RasterBandCount = rasterBandCount;
+	}
+	public int getRasterXSize() {
+		return RasterXSize;
+	}
+	public void setRasterXSize(int rasterXSize) {
+		RasterXSize = rasterXSize;
+	}
+	public int getRasterYSize() {
+		return RasterYSize;
+	}
+	public void setRasterYSize(int rasterYSize) {
+		RasterYSize = rasterYSize;
+	}
+}

+ 76 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/file/FileTypeUtils.java

@@ -0,0 +1,76 @@
+package com.ztmap.common.utils.file;
+
+import java.io.File;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 文件类型工具类
+ *
+ * @author ztmap
+ */
+public class FileTypeUtils
+{
+    /**
+     * 获取文件类型
+     * <p>
+     * 例如: ztmap.txt, 返回: txt
+     * 
+     * @param file 文件名
+     * @return 后缀(不含".")
+     */
+    public static String getFileType(File file)
+    {
+        if (null == file)
+        {
+            return StringUtils.EMPTY;
+        }
+        return getFileType(file.getName());
+    }
+
+    /**
+     * 获取文件类型
+     * <p>
+     * 例如: ztmap.txt, 返回: txt
+     *
+     * @param fileName 文件名
+     * @return 后缀(不含".")
+     */
+    public static String getFileType(String fileName)
+    {
+        int separatorIndex = fileName.lastIndexOf(".");
+        if (separatorIndex < 0)
+        {
+            return "";
+        }
+        return fileName.substring(separatorIndex + 1).toLowerCase();
+    }
+
+    /**
+     * 获取文件类型
+     * 
+     * @param photoByte 文件字节码
+     * @return 后缀(不含".")
+     */
+    public static String getFileExtendName(byte[] photoByte)
+    {
+        String strFileExtendName = "JPG";
+        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
+                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
+        {
+            strFileExtendName = "GIF";
+        }
+        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
+        {
+            strFileExtendName = "JPG";
+        }
+        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
+        {
+            strFileExtendName = "BMP";
+        }
+        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
+        {
+            strFileExtendName = "PNG";
+        }
+        return strFileExtendName;
+    }
+}

+ 240 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/file/FileUploadUtils.java

@@ -0,0 +1,240 @@
+package com.ztmap.common.utils.file;
+
+import java.io.File;
+import java.io.IOException;
+import org.apache.commons.io.FilenameUtils;
+import org.springframework.web.multipart.MultipartFile;
+import com.ztmap.common.constant.Constants;
+import com.ztmap.common.exception.file.FileNameLengthLimitExceededException;
+import com.ztmap.common.exception.file.FileSizeLimitExceededException;
+import com.ztmap.common.exception.file.InvalidExtensionException;
+import com.ztmap.common.utils.DateUtils;
+import com.ztmap.common.utils.StringUtils;
+import com.ztmap.common.utils.uuid.IdUtils;
+import com.ztmap.framework.config.ZTMapConfig;
+
+/**
+ * 文件上传工具类
+ * 
+ * @author ztmap
+ */
+public class FileUploadUtils
+{
+    /**
+     * 默认大小 50M
+     */
+    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
+
+    /**
+     * 默认的文件名最大长度 100
+     */
+    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
+
+    /**
+     * 默认文件类型jpg
+     */
+    public static final String IMAGE_JPG_EXTENSION = ".jpg";
+
+    /**
+     * 默认上传的地址
+     */
+    private static String defaultBaseDir = ZTMapConfig.getProfile();
+
+    public static void setDefaultBaseDir(String defaultBaseDir)
+    {
+        FileUploadUtils.defaultBaseDir = defaultBaseDir;
+    }
+
+    public static String getDefaultBaseDir()
+    {
+        return defaultBaseDir;
+    }
+
+    /**
+     * 以默认配置进行文件上传
+     *
+     * @param file 上传的文件
+     * @return 文件名称
+     * @throws Exception
+     */
+    public static final String upload(MultipartFile file) throws IOException
+    {
+        try
+        {
+            return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+        }
+        catch (Exception e)
+        {
+            throw new IOException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 根据文件路径上传
+     *
+     * @param baseDir 相对应用的基目录
+     * @param file 上传的文件
+     * @return 文件名称
+     * @throws IOException
+     */
+    public static final String upload(String baseDir, MultipartFile file) throws IOException
+    {
+        try
+        {
+            return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+        }
+        catch (Exception e)
+        {
+            throw new IOException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 文件上传
+     *
+     * @param baseDir 相对应用的基目录
+     * @param file 上传的文件
+     * @param allowedExtension 上传文件类型
+     * @return 返回上传成功的文件名
+     * @throws FileSizeLimitExceededException 如果超出最大大小
+     * @throws FileNameLengthLimitExceededException 文件名太长
+     * @throws IOException 比如读写文件出错时
+     * @throws InvalidExtensionException 文件校验异常
+     */
+    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
+            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
+            InvalidExtensionException
+    {
+        int fileNamelength = file.getOriginalFilename().length();
+        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
+        {
+            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
+        }
+
+        assertAllowed(file, allowedExtension);
+
+        String fileName = extractFilename(file);
+
+        File desc = getAbsoluteFile(baseDir, fileName);
+        file.transferTo(desc);
+        String pathFileName = getPathFileName(baseDir, fileName);
+        return pathFileName;
+    }
+
+    /**
+     * 编码文件名
+     */
+    public static final String extractFilename(MultipartFile file)
+    {
+        String fileName = file.getOriginalFilename();
+        String extension = getExtension(file);
+        fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
+        return fileName;
+    }
+
+    private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
+    {
+        File desc = new File(uploadDir + File.separator + fileName);
+
+        if (!desc.exists())
+        {
+            if (!desc.getParentFile().exists())
+            {
+                desc.getParentFile().mkdirs();
+            }
+        }
+        return desc;
+    }
+
+    private static final String getPathFileName(String uploadDir, String fileName) throws IOException
+    {
+        int dirLastIndex = ZTMapConfig.getProfile().length() + 1;
+        String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
+        String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
+        return pathFileName;
+    }
+
+    /**
+     * 文件大小校验
+     *
+     * @param file 上传的文件
+     * @return
+     * @throws FileSizeLimitExceededException 如果超出最大大小
+     * @throws InvalidExtensionException
+     */
+    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
+            throws FileSizeLimitExceededException, InvalidExtensionException
+    {
+        long size = file.getSize();
+        if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE)
+        {
+            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
+        }
+
+        String fileName = file.getOriginalFilename();
+        String extension = getExtension(file);
+        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
+        {
+            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
+            {
+                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
+                        fileName);
+            }
+            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
+            {
+                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
+                        fileName);
+            }
+            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
+            {
+                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
+                        fileName);
+            }
+            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
+            {
+                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
+                        fileName);
+            }
+            else
+            {
+                throw new InvalidExtensionException(allowedExtension, extension, fileName);
+            }
+        }
+
+    }
+
+    /**
+     * 判断MIME类型是否是允许的MIME类型
+     *
+     * @param extension
+     * @param allowedExtension
+     * @return
+     */
+    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
+    {
+        for (String str : allowedExtension)
+        {
+            if (str.equalsIgnoreCase(extension))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 获取文件名的后缀
+     * 
+     * @param file 表单文件
+     * @return 后缀名
+     */
+    public static final String getExtension(MultipartFile file)
+    {
+        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
+        if (StringUtils.isEmpty(extension))
+        {
+            extension = MimeTypeUtils.getExtension(file.getContentType());
+        }
+        return extension;
+    }
+}

+ 203 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/file/FileUtils.java

@@ -0,0 +1,203 @@
+package com.ztmap.common.utils.file;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.ArrayUtils;
+import com.ztmap.common.utils.StringUtils;
+
+/**
+ * 文件处理工具类
+ * 
+ * @author ztmap
+ */
+public class FileUtils extends org.apache.commons.io.FileUtils
+{
+    public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
+
+    /**
+     * 输出指定文件的byte数组
+     * 
+     * @param filePath 文件路径
+     * @param os 输出流
+     * @return
+     */
+    public static void writeBytes(String filePath, OutputStream os) throws IOException
+    {
+        FileInputStream fis = null;
+        try
+        {
+            File file = new File(filePath);
+            if (!file.exists())
+            {
+                throw new FileNotFoundException(filePath);
+            }
+            fis = new FileInputStream(file);
+            byte[] b = new byte[1024];
+            int length;
+            while ((length = fis.read(b)) > 0)
+            {
+                os.write(b, 0, length);
+            }
+        }
+        catch (IOException e)
+        {
+            throw e;
+        }
+        finally
+        {
+            if (os != null)
+            {
+                try
+                {
+                    os.close();
+                }
+                catch (IOException e1)
+                {
+                    e1.printStackTrace();
+                }
+            }
+            if (fis != null)
+            {
+                try
+                {
+                    fis.close();
+                }
+                catch (IOException e1)
+                {
+                    e1.printStackTrace();
+                }
+            }
+        }
+    }
+
+    /**
+     * 删除文件
+     * 
+     * @param filePath 文件
+     * @return
+     */
+    public static boolean deleteFile(String filePath)
+    {
+        boolean flag = false;
+        File file = new File(filePath);
+        // 路径为文件且不为空则进行删除
+        if (file.isFile() && file.exists())
+        {
+            file.delete();
+            flag = true;
+        }
+        return flag;
+    }
+
+    /**
+     * 文件名称验证
+     * 
+     * @param filename 文件名称
+     * @return true 正常 false 非法
+     */
+    public static boolean isValidFilename(String filename)
+    {
+        return filename.matches(FILENAME_PATTERN);
+    }
+
+    /**
+     * 检查文件是否可下载
+     * 
+     * @param resource 需要下载的文件
+     * @return true 正常 false 非法
+     */
+    public static boolean checkAllowDownload(String resource)
+    {
+        // 禁止目录上跳级别
+        if (StringUtils.contains(resource, ".."))
+        {
+            return false;
+        }
+
+        // 检查允许下载的文件规则
+        if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
+        {
+            return true;
+        }
+
+        // 不在允许下载的文件规则
+        return false;
+    }
+
+    /**
+     * 下载文件名重新编码
+     * 
+     * @param request 请求对象
+     * @param fileName 文件名
+     * @return 编码后的文件名
+     */
+    public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
+    {
+        final String agent = request.getHeader("USER-AGENT");
+        String filename = fileName;
+        if (agent.contains("MSIE"))
+        {
+            // IE浏览器
+            filename = URLEncoder.encode(filename, "utf-8");
+            filename = filename.replace("+", " ");
+        }
+        else if (agent.contains("Firefox"))
+        {
+            // 火狐浏览器
+            filename = new String(fileName.getBytes(), "ISO8859-1");
+        }
+        else if (agent.contains("Chrome"))
+        {
+            // google浏览器
+            filename = URLEncoder.encode(filename, "utf-8");
+        }
+        else
+        {
+            // 其它浏览器
+            filename = URLEncoder.encode(filename, "utf-8");
+        }
+        return filename;
+    }
+
+    /**
+     * 下载文件名重新编码
+     *
+     * @param response 响应对象
+     * @param realFileName 真实文件名
+     * @return
+     */
+    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
+    {
+        String percentEncodedFileName = percentEncode(realFileName);
+
+        StringBuilder contentDispositionValue = new StringBuilder();
+        contentDispositionValue.append("attachment; filename=")
+                .append(percentEncodedFileName)
+                .append(";")
+                .append("filename*=")
+                .append("utf-8''")
+                .append(percentEncodedFileName);
+
+        response.setHeader("Content-disposition", contentDispositionValue.toString());
+    }
+
+    /**
+     * 百分号编码工具方法
+     *
+     * @param s 需要百分号编码的字符串
+     * @return 百分号编码后的字符串
+     */
+    public static String percentEncode(String s) throws UnsupportedEncodingException
+    {
+        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
+        return encode.replaceAll("\\+", "%20");
+    }
+}

+ 100 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/file/ImageUtils.java

@@ -0,0 +1,100 @@
+package com.ztmap.common.utils.file;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Arrays;
+import org.apache.poi.util.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ztmap.common.constant.Constants;
+import com.ztmap.common.utils.StringUtils;
+import com.ztmap.framework.config.ZTMapConfig;
+
+/**
+ * 图片处理工具类
+ *
+ * @author ruoyi
+ */
+public class ImageUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
+
+    public static byte[] getImage(String imagePath)
+    {
+        InputStream is = getFile(imagePath);
+        try
+        {
+            return IOUtils.toByteArray(is);
+        }
+        catch (Exception e)
+        {
+            log.error("图片加载异常 {}", e);
+            return null;
+        }
+        finally
+        {
+            IOUtils.closeQuietly(is);
+        }
+    }
+
+    public static InputStream getFile(String imagePath)
+    {
+        try
+        {
+            byte[] result = readFile(imagePath);
+            result = Arrays.copyOf(result, result.length);
+            return new ByteArrayInputStream(result);
+        }
+        catch (Exception e)
+        {
+            log.error("获取图片异常 {}", e);
+        }
+        return null;
+    }
+
+    /**
+     * 读取文件为字节数据
+     * 
+     * @param url 地址
+     * @return 字节数据
+     */
+    public static byte[] readFile(String url)
+    {
+        InputStream in = null;
+        ByteArrayOutputStream baos = null;
+        try
+        {
+            if (url.startsWith("http"))
+            {
+                // 网络地址
+                URL urlObj = new URL(url);
+                URLConnection urlConnection = urlObj.openConnection();
+                urlConnection.setConnectTimeout(30 * 1000);
+                urlConnection.setReadTimeout(60 * 1000);
+                urlConnection.setDoInput(true);
+                in = urlConnection.getInputStream();
+            }
+            else
+            {
+                // 本机地址
+                String localPath = ZTMapConfig.getProfile();
+                String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
+                in = new FileInputStream(downloadPath);
+            }
+            return IOUtils.toByteArray(in);
+        }
+        catch (Exception e)
+        {
+            log.error("获取文件路径异常 {}", e);
+            return null;
+        }
+        finally
+        {
+            IOUtils.closeQuietly(baos);
+        }
+    }
+}

+ 59 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/file/MimeTypeUtils.java

@@ -0,0 +1,59 @@
+package com.ztmap.common.utils.file;
+
+/**
+ * 媒体类型工具类
+ * 
+ * @author ztmap
+ */
+public class MimeTypeUtils
+{
+    public static final String IMAGE_PNG = "image/png";
+
+    public static final String IMAGE_JPG = "image/jpg";
+
+    public static final String IMAGE_JPEG = "image/jpeg";
+
+    public static final String IMAGE_BMP = "image/bmp";
+
+    public static final String IMAGE_GIF = "image/gif";
+
+    public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
+
+    public static final String[] FLASH_EXTENSION = { "swf", "flv" };
+
+    public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
+            "asf", "rm", "rmvb" };
+
+    public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
+
+    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
+            // 图片
+            "bmp", "gif", "jpg", "jpeg", "png",
+            // word excel powerpoint
+            "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
+            // 压缩文件
+            "rar", "zip", "gz", "bz2",
+            // 视频格式
+            "mp4", "avi", "rmvb",
+            // pdf
+            "pdf" };
+
+    public static String getExtension(String prefix)
+    {
+        switch (prefix)
+        {
+            case IMAGE_PNG:
+                return "png";
+            case IMAGE_JPG:
+                return "jpg";
+            case IMAGE_JPEG:
+                return "jpeg";
+            case IMAGE_BMP:
+                return "bmp";
+            case IMAGE_GIF:
+                return "gif";
+            default:
+                return "";
+        }
+    }
+}

+ 155 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/html/EscapeUtil.java

@@ -0,0 +1,155 @@
+package com.ztmap.common.utils.html;
+
+import com.ztmap.common.utils.StringUtils;
+
+/**
+ * 转义和反转义工具类
+ * 
+ * @author ruoyi
+ */
+public class EscapeUtil
+{
+    public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
+
+    private static final char[][] TEXT = new char[64][];
+
+    static
+    {
+        for (int i = 0; i < 64; i++)
+        {
+            TEXT[i] = new char[] { (char) i };
+        }
+
+        // special HTML characters
+        TEXT['\''] = "&#039;".toCharArray(); // 单引号
+        TEXT['"'] = "&#34;".toCharArray(); // 双引号
+        TEXT['&'] = "&#38;".toCharArray(); // &符
+        TEXT['<'] = "&#60;".toCharArray(); // 小于号
+        TEXT['>'] = "&#62;".toCharArray(); // 大于号
+    }
+
+    /**
+     * 转义文本中的HTML字符为安全的字符
+     * 
+     * @param text 被转义的文本
+     * @return 转义后的文本
+     */
+    public static String escape(String text)
+    {
+        return encode(text);
+    }
+
+    /**
+     * 还原被转义的HTML特殊字符
+     * 
+     * @param content 包含转义符的HTML内容
+     * @return 转换后的字符串
+     */
+    public static String unescape(String content)
+    {
+        return decode(content);
+    }
+
+    /**
+     * 清除所有HTML标签,但是不删除标签内的内容
+     * 
+     * @param content 文本
+     * @return 清除标签后的文本
+     */
+    public static String clean(String content)
+    {
+        return new HTMLFilter().filter(content);
+    }
+
+    /**
+     * Escape编码
+     * 
+     * @param text 被编码的文本
+     * @return 编码后的字符
+     */
+    private static String encode(String text)
+    {
+        int len;
+        if ((text == null) || ((len = text.length()) == 0))
+        {
+            return StringUtils.EMPTY;
+        }
+        StringBuilder buffer = new StringBuilder(len + (len >> 2));
+        char c;
+        for (int i = 0; i < len; i++)
+        {
+            c = text.charAt(i);
+            if (c < 64)
+            {
+                buffer.append(TEXT[c]);
+            }
+            else
+            {
+                buffer.append(c);
+            }
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Escape解码
+     * 
+     * @param content 被转义的内容
+     * @return 解码后的字符串
+     */
+    public static String decode(String content)
+    {
+        if (StringUtils.isEmpty(content))
+        {
+            return content;
+        }
+
+        StringBuilder tmp = new StringBuilder(content.length());
+        int lastPos = 0, pos = 0;
+        char ch;
+        while (lastPos < content.length())
+        {
+            pos = content.indexOf("%", lastPos);
+            if (pos == lastPos)
+            {
+                if (content.charAt(pos + 1) == 'u')
+                {
+                    ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
+                    tmp.append(ch);
+                    lastPos = pos + 6;
+                }
+                else
+                {
+                    ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
+                    tmp.append(ch);
+                    lastPos = pos + 3;
+                }
+            }
+            else
+            {
+                if (pos == -1)
+                {
+                    tmp.append(content.substring(lastPos));
+                    lastPos = content.length();
+                }
+                else
+                {
+                    tmp.append(content.substring(lastPos, pos));
+                    lastPos = pos;
+                }
+            }
+        }
+        return tmp.toString();
+    }
+
+    public static void main(String[] args)
+    {
+        String html = "<script>alert(1);</script>";
+        // String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
+        // String html = "<123";
+        // String html = "123>";
+        System.out.println(EscapeUtil.clean(html));
+        System.out.println(EscapeUtil.escape(html));
+        System.out.println(EscapeUtil.unescape(html));
+    }
+}

+ 570 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/html/HTMLFilter.java

@@ -0,0 +1,570 @@
+package com.ztmap.common.utils.html;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * HTML过滤器,用于去除XSS漏洞隐患。
+ *
+ * @author ztmap
+ */
+public final class HTMLFilter
+{
+    /**
+     * regex flag union representing /si modifiers in php
+     **/
+    private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
+    private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
+    private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
+    private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
+    private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
+    private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
+    private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
+    private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
+    private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
+    private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
+    private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
+    private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
+    private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
+    private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
+    private static final Pattern P_END_ARROW = Pattern.compile("^>");
+    private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
+    private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
+    private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
+    private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
+    private static final Pattern P_AMP = Pattern.compile("&");
+    private static final Pattern P_QUOTE = Pattern.compile("\"");
+    private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
+    private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
+    private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
+
+    // @xxx could grow large... maybe use sesat's ReferenceMap
+    private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>();
+    private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>();
+
+    /**
+     * set of allowed html elements, along with allowed attributes for each element
+     **/
+    private final Map<String, List<String>> vAllowed;
+    /**
+     * counts of open tags for each (allowable) html element
+     **/
+    private final Map<String, Integer> vTagCounts = new HashMap<>();
+
+    /**
+     * html elements which must always be self-closing (e.g. "<img />")
+     **/
+    private final String[] vSelfClosingTags;
+    /**
+     * html elements which must always have separate opening and closing tags (e.g. "<b></b>")
+     **/
+    private final String[] vNeedClosingTags;
+    /**
+     * set of disallowed html elements
+     **/
+    private final String[] vDisallowed;
+    /**
+     * attributes which should be checked for valid protocols
+     **/
+    private final String[] vProtocolAtts;
+    /**
+     * allowed protocols
+     **/
+    private final String[] vAllowedProtocols;
+    /**
+     * tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />")
+     **/
+    private final String[] vRemoveBlanks;
+    /**
+     * entities allowed within html markup
+     **/
+    private final String[] vAllowedEntities;
+    /**
+     * flag determining whether comments are allowed in input String.
+     */
+    private final boolean stripComment;
+    private final boolean encodeQuotes;
+    /**
+     * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>"
+     * becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped.
+     */
+    private final boolean alwaysMakeTags;
+
+    /**
+     * Default constructor.
+     */
+    public HTMLFilter()
+    {
+        vAllowed = new HashMap<>();
+
+        final ArrayList<String> a_atts = new ArrayList<>();
+        a_atts.add("href");
+        a_atts.add("target");
+        vAllowed.put("a", a_atts);
+
+        final ArrayList<String> img_atts = new ArrayList<>();
+        img_atts.add("src");
+        img_atts.add("width");
+        img_atts.add("height");
+        img_atts.add("alt");
+        vAllowed.put("img", img_atts);
+
+        final ArrayList<String> no_atts = new ArrayList<>();
+        vAllowed.put("b", no_atts);
+        vAllowed.put("strong", no_atts);
+        vAllowed.put("i", no_atts);
+        vAllowed.put("em", no_atts);
+
+        vSelfClosingTags = new String[] { "img" };
+        vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" };
+        vDisallowed = new String[] {};
+        vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp.
+        vProtocolAtts = new String[] { "src", "href" };
+        vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" };
+        vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" };
+        stripComment = true;
+        encodeQuotes = true;
+        alwaysMakeTags = false;
+    }
+
+    /**
+     * Map-parameter configurable constructor.
+     *
+     * @param conf map containing configuration. keys match field names.
+     */
+    @SuppressWarnings("unchecked")
+    public HTMLFilter(final Map<String, Object> conf)
+    {
+
+        assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
+        assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
+        assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
+        assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
+        assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
+        assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
+        assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
+        assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
+
+        vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
+        vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
+        vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
+        vDisallowed = (String[]) conf.get("vDisallowed");
+        vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
+        vProtocolAtts = (String[]) conf.get("vProtocolAtts");
+        vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
+        vAllowedEntities = (String[]) conf.get("vAllowedEntities");
+        stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
+        encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
+        alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
+    }
+
+    private void reset()
+    {
+        vTagCounts.clear();
+    }
+
+    // ---------------------------------------------------------------
+    // my versions of some PHP library functions
+    public static String chr(final int decimal)
+    {
+        return String.valueOf((char) decimal);
+    }
+
+    public static String htmlSpecialChars(final String s)
+    {
+        String result = s;
+        result = regexReplace(P_AMP, "&amp;", result);
+        result = regexReplace(P_QUOTE, "&quot;", result);
+        result = regexReplace(P_LEFT_ARROW, "&lt;", result);
+        result = regexReplace(P_RIGHT_ARROW, "&gt;", result);
+        return result;
+    }
+
+    // ---------------------------------------------------------------
+
+    /**
+     * given a user submitted input String, filter out any invalid or restricted html.
+     *
+     * @param input text (i.e. submitted by a user) than may contain html
+     * @return "clean" version of input, with only valid, whitelisted html elements allowed
+     */
+    public String filter(final String input)
+    {
+        reset();
+        String s = input;
+
+        s = escapeComments(s);
+
+        s = balanceHTML(s);
+
+        s = checkTags(s);
+
+        s = processRemoveBlanks(s);
+
+        // s = validateEntities(s);
+
+        return s;
+    }
+
+    public boolean isAlwaysMakeTags()
+    {
+        return alwaysMakeTags;
+    }
+
+    public boolean isStripComments()
+    {
+        return stripComment;
+    }
+
+    private String escapeComments(final String s)
+    {
+        final Matcher m = P_COMMENTS.matcher(s);
+        final StringBuffer buf = new StringBuffer();
+        if (m.find())
+        {
+            final String match = m.group(1); // (.*?)
+            m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
+        }
+        m.appendTail(buf);
+
+        return buf.toString();
+    }
+
+    private String balanceHTML(String s)
+    {
+        if (alwaysMakeTags)
+        {
+            //
+            // try and form html
+            //
+            s = regexReplace(P_END_ARROW, "", s);
+            // 不追加结束标签
+            s = regexReplace(P_BODY_TO_END, "<$1>", s);
+            s = regexReplace(P_XML_CONTENT, "$1<$2", s);
+
+        }
+        else
+        {
+            //
+            // escape stray brackets
+            //
+            s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);
+            s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);
+
+            //
+            // the last regexp causes '<>' entities to appear
+            // (we need to do a lookahead assertion so that the last bracket can
+            // be used in the next pass of the regexp)
+            //
+            s = regexReplace(P_BOTH_ARROWS, "", s);
+        }
+
+        return s;
+    }
+
+    private String checkTags(String s)
+    {
+        Matcher m = P_TAGS.matcher(s);
+
+        final StringBuffer buf = new StringBuffer();
+        while (m.find())
+        {
+            String replaceStr = m.group(1);
+            replaceStr = processTag(replaceStr);
+            m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
+        }
+        m.appendTail(buf);
+
+        // these get tallied in processTag
+        // (remember to reset before subsequent calls to filter method)
+        final StringBuilder sBuilder = new StringBuilder(buf.toString());
+        for (String key : vTagCounts.keySet())
+        {
+            for (int ii = 0; ii < vTagCounts.get(key); ii++)
+            {
+                sBuilder.append("</").append(key).append(">");
+            }
+        }
+        s = sBuilder.toString();
+
+        return s;
+    }
+
+    private String processRemoveBlanks(final String s)
+    {
+        String result = s;
+        for (String tag : vRemoveBlanks)
+        {
+            if (!P_REMOVE_PAIR_BLANKS.containsKey(tag))
+            {
+                P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
+            }
+            result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
+            if (!P_REMOVE_SELF_BLANKS.containsKey(tag))
+            {
+                P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
+            }
+            result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
+        }
+
+        return result;
+    }
+
+    private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s)
+    {
+        Matcher m = regex_pattern.matcher(s);
+        return m.replaceAll(replacement);
+    }
+
+    private String processTag(final String s)
+    {
+        // ending tags
+        Matcher m = P_END_TAG.matcher(s);
+        if (m.find())
+        {
+            final String name = m.group(1).toLowerCase();
+            if (allowed(name))
+            {
+                if (false == inArray(name, vSelfClosingTags))
+                {
+                    if (vTagCounts.containsKey(name))
+                    {
+                        vTagCounts.put(name, vTagCounts.get(name) - 1);
+                        return "</" + name + ">";
+                    }
+                }
+            }
+        }
+
+        // starting tags
+        m = P_START_TAG.matcher(s);
+        if (m.find())
+        {
+            final String name = m.group(1).toLowerCase();
+            final String body = m.group(2);
+            String ending = m.group(3);
+
+            // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
+            if (allowed(name))
+            {
+                final StringBuilder params = new StringBuilder();
+
+                final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
+                final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
+                final List<String> paramNames = new ArrayList<>();
+                final List<String> paramValues = new ArrayList<>();
+                while (m2.find())
+                {
+                    paramNames.add(m2.group(1)); // ([a-z0-9]+)
+                    paramValues.add(m2.group(3)); // (.*?)
+                }
+                while (m3.find())
+                {
+                    paramNames.add(m3.group(1)); // ([a-z0-9]+)
+                    paramValues.add(m3.group(3)); // ([^\"\\s']+)
+                }
+
+                String paramName, paramValue;
+                for (int ii = 0; ii < paramNames.size(); ii++)
+                {
+                    paramName = paramNames.get(ii).toLowerCase();
+                    paramValue = paramValues.get(ii);
+
+                    // debug( "paramName='" + paramName + "'" );
+                    // debug( "paramValue='" + paramValue + "'" );
+                    // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
+
+                    if (allowedAttribute(name, paramName))
+                    {
+                        if (inArray(paramName, vProtocolAtts))
+                        {
+                            paramValue = processParamProtocol(paramValue);
+                        }
+                        params.append(' ').append(paramName).append("=\"").append(paramValue).append("\"");
+                    }
+                }
+
+                if (inArray(name, vSelfClosingTags))
+                {
+                    ending = " /";
+                }
+
+                if (inArray(name, vNeedClosingTags))
+                {
+                    ending = "";
+                }
+
+                if (ending == null || ending.length() < 1)
+                {
+                    if (vTagCounts.containsKey(name))
+                    {
+                        vTagCounts.put(name, vTagCounts.get(name) + 1);
+                    }
+                    else
+                    {
+                        vTagCounts.put(name, 1);
+                    }
+                }
+                else
+                {
+                    ending = " /";
+                }
+                return "<" + name + params + ending + ">";
+            }
+            else
+            {
+                return "";
+            }
+        }
+
+        // comments
+        m = P_COMMENT.matcher(s);
+        if (!stripComment && m.find())
+        {
+            return "<" + m.group() + ">";
+        }
+
+        return "";
+    }
+
+    private String processParamProtocol(String s)
+    {
+        s = decodeEntities(s);
+        final Matcher m = P_PROTOCOL.matcher(s);
+        if (m.find())
+        {
+            final String protocol = m.group(1);
+            if (!inArray(protocol, vAllowedProtocols))
+            {
+                // bad protocol, turn into local anchor link instead
+                s = "#" + s.substring(protocol.length() + 1);
+                if (s.startsWith("#//"))
+                {
+                    s = "#" + s.substring(3);
+                }
+            }
+        }
+
+        return s;
+    }
+
+    private String decodeEntities(String s)
+    {
+        StringBuffer buf = new StringBuffer();
+
+        Matcher m = P_ENTITY.matcher(s);
+        while (m.find())
+        {
+            final String match = m.group(1);
+            final int decimal = Integer.decode(match).intValue();
+            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+        }
+        m.appendTail(buf);
+        s = buf.toString();
+
+        buf = new StringBuffer();
+        m = P_ENTITY_UNICODE.matcher(s);
+        while (m.find())
+        {
+            final String match = m.group(1);
+            final int decimal = Integer.valueOf(match, 16).intValue();
+            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+        }
+        m.appendTail(buf);
+        s = buf.toString();
+
+        buf = new StringBuffer();
+        m = P_ENCODE.matcher(s);
+        while (m.find())
+        {
+            final String match = m.group(1);
+            final int decimal = Integer.valueOf(match, 16).intValue();
+            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+        }
+        m.appendTail(buf);
+        s = buf.toString();
+
+        s = validateEntities(s);
+        return s;
+    }
+
+    private String validateEntities(final String s)
+    {
+        StringBuffer buf = new StringBuffer();
+
+        // validate entities throughout the string
+        Matcher m = P_VALID_ENTITIES.matcher(s);
+        while (m.find())
+        {
+            final String one = m.group(1); // ([^&;]*)
+            final String two = m.group(2); // (?=(;|&|$))
+            m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
+        }
+        m.appendTail(buf);
+
+        return encodeQuotes(buf.toString());
+    }
+
+    private String encodeQuotes(final String s)
+    {
+        if (encodeQuotes)
+        {
+            StringBuffer buf = new StringBuffer();
+            Matcher m = P_VALID_QUOTES.matcher(s);
+            while (m.find())
+            {
+                final String one = m.group(1); // (>|^)
+                final String two = m.group(2); // ([^<]+?)
+                final String three = m.group(3); // (<|$)
+                // 不替换双引号为&quot;,防止json格式无效 regexReplace(P_QUOTE, "&quot;", two)
+                m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three));
+            }
+            m.appendTail(buf);
+            return buf.toString();
+        }
+        else
+        {
+            return s;
+        }
+    }
+
+    private String checkEntity(final String preamble, final String term)
+    {
+
+        return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&amp;" + preamble;
+    }
+
+    private boolean isValidEntity(final String entity)
+    {
+        return inArray(entity, vAllowedEntities);
+    }
+
+    private static boolean inArray(final String s, final String[] array)
+    {
+        for (String item : array)
+        {
+            if (item != null && item.equals(s))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean allowed(final String name)
+    {
+        return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
+    }
+
+    private boolean allowedAttribute(final String name, final String paramName)
+    {
+        return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
+    }
+}

+ 262 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/http/HttpUtils.java

@@ -0,0 +1,262 @@
+package com.ztmap.common.utils.http;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ztmap.common.constant.Constants;
+
+/**
+ * 通用http发送方法
+ * 
+ * @author ztmap
+ */
+public class HttpUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
+
+    /**
+     * 向指定 URL 发送GET方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendGet(String url, String param)
+    {
+        return sendGet(url, param, Constants.UTF8);
+    }
+
+    /**
+     * 向指定 URL 发送GET方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @param contentType 编码类型
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendGet(String url, String param, String contentType)
+    {
+        StringBuilder result = new StringBuilder();
+        BufferedReader in = null;
+        try
+        {
+            String urlNameString = url + "?" + param;
+//            log.info("sendGet - {}", urlNameString);
+            URL realUrl = new URL(urlNameString);
+            URLConnection connection = realUrl.openConnection();
+            connection.setRequestProperty("accept", "*/*");
+            connection.setRequestProperty("connection", "Keep-Alive");
+            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            connection.connect();
+            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
+            String line;
+            while ((line = in.readLine()) != null)
+            {
+                result.append(line);
+            }
+//            log.info("recv - {}", result);
+        }
+        catch (ConnectException e)
+        {
+            log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
+        }
+        finally
+        {
+            try
+            {
+                if (in != null)
+                {
+                    in.close();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
+            }
+        }
+        return result.toString();
+    }
+
+    /**
+     * 向指定 URL 发送POST方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendPost(String url, String param)
+    {
+        PrintWriter out = null;
+        BufferedReader in = null;
+        StringBuilder result = new StringBuilder();
+        try
+        {
+            String urlNameString = url;
+            log.info("sendPost - {}", urlNameString);
+            URL realUrl = new URL(urlNameString);
+            URLConnection conn = realUrl.openConnection();
+            conn.setRequestProperty("accept", "*/*");
+            conn.setRequestProperty("connection", "Keep-Alive");
+            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            conn.setRequestProperty("Accept-Charset", "utf-8");
+            conn.setRequestProperty("contentType", "utf-8");
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            out = new PrintWriter(conn.getOutputStream());
+            out.print(param);
+            out.flush();
+            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
+            String line;
+            while ((line = in.readLine()) != null)
+            {
+                result.append(line);
+            }
+            log.info("recv - {}", result);
+        }
+        catch (ConnectException e)
+        {
+            log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
+        }
+        finally
+        {
+            try
+            {
+                if (out != null)
+                {
+                    out.close();
+                }
+                if (in != null)
+                {
+                    in.close();
+                }
+            }
+            catch (IOException ex)
+            {
+                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
+            }
+        }
+        return result.toString();
+    }
+
+    public static String sendSSLPost(String url, String param)
+    {
+        StringBuilder result = new StringBuilder();
+        String urlNameString = url + "?" + param;
+        try
+        {
+            log.info("sendSSLPost - {}", urlNameString);
+            SSLContext sc = SSLContext.getInstance("SSL");
+            sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
+            URL console = new URL(urlNameString);
+            HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
+            conn.setRequestProperty("accept", "*/*");
+            conn.setRequestProperty("connection", "Keep-Alive");
+            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            conn.setRequestProperty("Accept-Charset", "utf-8");
+            conn.setRequestProperty("contentType", "utf-8");
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+
+            conn.setSSLSocketFactory(sc.getSocketFactory());
+            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
+            conn.connect();
+            InputStream is = conn.getInputStream();
+            BufferedReader br = new BufferedReader(new InputStreamReader(is));
+            String ret = "";
+            while ((ret = br.readLine()) != null)
+            {
+                if (ret != null && !ret.trim().equals(""))
+                {
+                    result.append(new String(ret.getBytes("ISO-8859-1"), "utf-8"));
+                }
+            }
+            log.info("recv - {}", result);
+            conn.disconnect();
+            br.close();
+        }
+        catch (ConnectException e)
+        {
+            log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
+        }
+        return result.toString();
+    }
+
+    private static class TrustAnyTrustManager implements X509TrustManager
+    {
+        @Override
+        public void checkClientTrusted(X509Certificate[] chain, String authType)
+        {
+        }
+
+        @Override
+        public void checkServerTrusted(X509Certificate[] chain, String authType)
+        {
+        }
+
+        @Override
+        public X509Certificate[] getAcceptedIssuers()
+        {
+            return new X509Certificate[] {};
+        }
+    }
+
+    private static class TrustAnyHostnameVerifier implements HostnameVerifier
+    {
+        @Override
+        public boolean verify(String hostname, SSLSession session)
+        {
+            return true;
+        }
+    }
+}

+ 210 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/modbus/ModbusMasterTCP.java

@@ -0,0 +1,210 @@
+package com.ztmap.common.utils.modbus;
+
+import com.digitalpetri.modbus.codec.Modbus;
+import com.digitalpetri.modbus.master.ModbusTcpMaster;
+import com.digitalpetri.modbus.master.ModbusTcpMasterConfig;
+import com.digitalpetri.modbus.requests.ReadCoilsRequest;
+import com.digitalpetri.modbus.requests.ReadDiscreteInputsRequest;
+import com.digitalpetri.modbus.requests.ReadHoldingRegistersRequest;
+import com.digitalpetri.modbus.requests.ReadInputRegistersRequest;
+import com.digitalpetri.modbus.responses.ReadCoilsResponse;
+import com.digitalpetri.modbus.responses.ReadDiscreteInputsResponse;
+import com.digitalpetri.modbus.responses.ReadHoldingRegistersResponse;
+import com.digitalpetri.modbus.responses.ReadInputRegistersResponse;
+import io.netty.buffer.ByteBuf;
+import io.netty.util.ReferenceCountUtil;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+public class ModbusMasterTCP {
+     ModbusTcpMaster master;
+
+    /**
+     * 获取TCP协议的Master
+     *
+     * @return
+     */
+    public  void initModbusTcpMaster(String ip) {
+        if (master == null) {
+            // 创建配置
+            ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder(ip).setPort(502).build();
+            master = new ModbusTcpMaster(config);
+        }
+    }
+
+    /***
+     * 释放资源
+     */
+    public  void release() {
+        if (master != null) {
+            master.disconnect();
+        }
+        Modbus.releaseSharedResources();
+    }
+
+
+
+
+    /**
+     * 读取Coils开关量
+     *
+     * @param address
+     *            寄存器开始地址
+     * @param quantity
+     *            数量
+     * @param unitId
+     *            ID
+     * @return 读取值
+     * @throws InterruptedException
+     *             异常
+     * @throws ExecutionException
+     *             异常
+     */
+    public  Boolean readCoils(int address, int quantity, int unitId)
+            throws InterruptedException, ExecutionException {
+        Boolean result = null;
+        CompletableFuture<ReadCoilsResponse> future = master.sendRequest(new ReadCoilsRequest(address, quantity),
+                unitId);
+        ReadCoilsResponse readCoilsResponse = future.get();// 工具类做的同步返回.实际使用推荐结合业务进行异步处理
+        if (readCoilsResponse != null) {
+            ByteBuf buf = readCoilsResponse.getCoilStatus();
+            result = buf.readBoolean();
+            ReferenceCountUtil.release(readCoilsResponse);
+        }
+        return result;
+    }
+
+    /**
+     * 读取readDiscreteInputs开关量
+     *
+     * @param address
+     *            寄存器开始地址
+     * @param quantity
+     *            数量
+     * @param unitId
+     *            ID
+     * @return 读取值
+     * @throws InterruptedException
+     *             异常
+     * @throws ExecutionException
+     *             异常
+     */
+    public  Boolean readDiscreteInputs(int address, int quantity, int unitId)
+            throws InterruptedException, ExecutionException {
+        Boolean result = null;
+        CompletableFuture<ReadDiscreteInputsResponse> future = master
+                .sendRequest(new ReadDiscreteInputsRequest(address, quantity), unitId);
+        ReadDiscreteInputsResponse discreteInputsResponse = future.get();// 工具类做的同步返回.实际使用推荐结合业务进行异步处理
+        if (discreteInputsResponse != null) {
+            ByteBuf buf = discreteInputsResponse.getInputStatus();
+            result = buf.readBoolean();
+            ReferenceCountUtil.release(discreteInputsResponse);
+        }
+        return result;
+    }
+
+    /**
+     * 读取HoldingRegister数据
+     *
+     * @param address
+     *            寄存器地址
+     * @param quantity
+     *            寄存器数量
+     * @param unitId
+     *            id
+     * @return 读取结果
+     * @throws InterruptedException
+     *             异常
+     * @throws ExecutionException
+     *             异常
+     */
+    public  Number readHoldingRegisters(int address, int quantity, int unitId)
+            throws InterruptedException, ExecutionException {
+        Number result = null;
+        CompletableFuture<ReadHoldingRegistersResponse> future = master
+                .sendRequest(new ReadHoldingRegistersRequest(address, quantity), unitId);
+        ReadHoldingRegistersResponse readHoldingRegistersResponse = future.get();// 工具类做的同步返回.实际使用推荐结合业务进行异步处理
+        if (readHoldingRegistersResponse != null) {
+            ByteBuf buf = readHoldingRegistersResponse.getRegisters();
+            result = buf.readFloat();
+            ReferenceCountUtil.release(readHoldingRegistersResponse);
+        }
+        return result;
+    }
+
+    /**
+     * 读取InputRegisters模拟量数据
+     *
+     * @param address
+     *            寄存器开始地址
+     * @param quantity
+     *            数量
+     * @param unitId
+     *            ID
+     * @return 读取值
+     * @throws InterruptedException
+     *             异常
+     * @throws ExecutionException
+     *             异常
+     */
+    public  Number readInputRegisters(int address, int quantity, int unitId)
+            throws InterruptedException, ExecutionException {
+        Number result = null;
+        CompletableFuture<ReadInputRegistersResponse> future = master
+                .sendRequest(new ReadInputRegistersRequest(address, quantity), unitId);
+        ReadInputRegistersResponse readInputRegistersResponse = future.get();// 工具类做的同步返回.实际使用推荐结合业务进行异步处理
+        if (readInputRegistersResponse != null) {
+            ByteBuf buf = readInputRegistersResponse.getRegisters();
+            result = buf.readDouble();
+            ReferenceCountUtil.release(readInputRegistersResponse);
+        }
+        return result;
+    }
+
+    /**
+     * 读取[03 Holding Register类型 2x]模拟量数据
+     * @param master ModbusMaster对象
+     * @param slaveId
+     *            slave Id  设备ID
+     * @param offset
+     *            偏移截止位置
+     * @param dataType
+     *            数据类型,来自com.serotonin.modbus4j.code.DataType
+     * @return
+     * @throws ModbusTransportException
+     *             异常
+     * @throws ErrorResponseException
+     *             异常
+     * @throws ModbusInitException
+     *             异常
+     */
+//    public static Number readHoldingRegister(ModbusMaster master, int slaveId, int offset, int dataType)
+//            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
+//        // 03 Holding Register类型数据读取
+//        BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
+//        System.out.println("loc:"+loc);
+//        Number value =master.getValue(loc);
+//        System.out.println();
+//        return value;
+//    }
+
+    public static void main(String[] args) {
+        try {
+            // 初始化资源
+            ModbusMasterTCP modbusMasterTCP = new ModbusMasterTCP();
+            modbusMasterTCP.initModbusTcpMaster("192.168.1.200");
+
+            // 执行操作
+
+
+            // 读取模拟量
+           // System.out.println(modbusMasterTCP.readHoldingRegisters(1001, 2, 1));
+
+            // 释放资源
+            modbusMasterTCP.release();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 1125 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/poi/ExcelUtil.java

@@ -0,0 +1,1125 @@
+package com.ztmap.common.utils.poi;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.DataValidation;
+import org.apache.poi.ss.usermodel.DataValidationConstraint;
+import org.apache.poi.ss.usermodel.DataValidationHelper;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.util.CellRangeAddressList;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDataValidation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ztmap.common.exception.BusinessException;
+import com.ztmap.common.utils.DateUtils;
+import com.ztmap.common.utils.StringUtils;
+import com.ztmap.common.utils.file.FileTypeUtils;
+import com.ztmap.common.utils.file.ImageUtils;
+import com.ztmap.common.utils.reflect.ReflectUtils;
+import com.ztmap.common.utils.text.Convert;
+import com.ztmap.framework.aspectj.lang.annotation.Excel;
+import com.ztmap.framework.aspectj.lang.annotation.Excel.ColumnType;
+import com.ztmap.framework.aspectj.lang.annotation.Excel.Type;
+import com.ztmap.framework.aspectj.lang.annotation.Excels;
+import com.ztmap.framework.config.ZTMapConfig;
+import com.ztmap.framework.web.domain.AjaxResult;
+import com.ztmap.project.system.dict.utils.DictUtils;
+
+/**
+ * Excel相关处理
+ * 
+ * @author ruoyi
+ */
+public class ExcelUtil<T>
+{
+    private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
+
+    /**
+     * Excel sheet最大行数,默认65536
+     */
+    public static final int sheetSize = 65536;
+
+    /**
+     * 工作表名称
+     */
+    private String sheetName;
+
+    /**
+     * 导出类型(EXPORT:导出数据;IMPORT:导入模板)
+     */
+    private Type type;
+
+    /**
+     * 工作薄对象
+     */
+    private Workbook wb;
+
+    /**
+     * 工作表对象
+     */
+    private Sheet sheet;
+
+    /**
+     * 样式列表
+     */
+    private Map<String, CellStyle> styles;
+
+    /**
+     * 导入导出数据列表
+     */
+    private List<T> list;
+
+    /**
+     * 注解列表
+     */
+    private List<Object[]> fields;
+
+    /**
+     * 最大高度
+     */
+    private short maxHeight;
+
+    /**
+     * 统计列表
+     */
+    private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
+    
+    /**
+     * 数字格式
+     */
+    private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
+    
+    /**
+     * 实体对象
+     */
+    public Class<T> clazz;
+
+    public ExcelUtil(Class<T> clazz)
+    {
+        this.clazz = clazz;
+    }
+
+    public void init(List<T> list, String sheetName, Type type)
+    {
+        if (list == null)
+        {
+            list = new ArrayList<T>();
+        }
+        this.list = list;
+        this.sheetName = sheetName;
+        this.type = type;
+        createExcelField();
+        createWorkbook();
+    }
+
+    /**
+     * 对excel表单默认第一个索引名转换成list
+     * 
+     * @param is 输入流
+     * @return 转换后集合
+     */
+    public List<T> importExcel(InputStream is) throws Exception
+    {
+        return importExcel(StringUtils.EMPTY, is);
+    }
+
+    /**
+     * 对excel表单指定表格索引名转换成list
+     * 
+     * @param sheetName 表格索引名
+     * @param is 输入流
+     * @return 转换后集合
+     */
+    public List<T> importExcel(String sheetName, InputStream is) throws Exception
+    {
+        this.type = Type.IMPORT;
+        this.wb = WorkbookFactory.create(is);
+        List<T> list = new ArrayList<T>();
+        Sheet sheet = null;
+        if (StringUtils.isNotEmpty(sheetName))
+        {
+            // 如果指定sheet名,则取指定sheet中的内容.
+            sheet = wb.getSheet(sheetName);
+        }
+        else
+        {
+            // 如果传入的sheet名不存在则默认指向第1个sheet.
+            sheet = wb.getSheetAt(0);
+        }
+
+        if (sheet == null)
+        {
+            throw new IOException("文件sheet不存在");
+        }
+
+        // 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1
+        int rows = sheet.getLastRowNum();
+
+        if (rows > 0)
+        {
+            // 定义一个map用于存放excel列的序号和field.
+            Map<String, Integer> cellMap = new HashMap<String, Integer>();
+            // 获取表头
+            Row heard = sheet.getRow(0);
+            for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++)
+            {
+                Cell cell = heard.getCell(i);
+                if (StringUtils.isNotNull(cell))
+                {
+                    String value = this.getCellValue(heard, i).toString();
+                    cellMap.put(value, i);
+                }
+                else
+                {
+                    cellMap.put(null, i);
+                }
+            }
+            // 有数据时才处理 得到类的所有field.
+            Field[] allFields = clazz.getDeclaredFields();
+            // 定义一个map用于存放列的序号和field.
+            Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>();
+            for (int col = 0; col < allFields.length; col++)
+            {
+                Field field = allFields[col];
+                Excel attr = field.getAnnotation(Excel.class);
+                if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
+                {
+                    // 设置类的私有字段属性可访问.
+                    field.setAccessible(true);
+                    Integer column = cellMap.get(attr.name());
+                    if (column != null)
+                    {
+                        fieldsMap.put(column, field);
+                    }
+                }
+            }
+            for (int i = 1; i <= rows; i++)
+            {
+                // 从第2行开始取数据,默认第一行是表头.
+                Row row = sheet.getRow(i);
+                // 判断当前行是否是空行
+                if (isRowEmpty(row))
+                {
+                    continue;
+                }
+                T entity = null;
+                for (Map.Entry<Integer, Field> entry : fieldsMap.entrySet())
+                {
+                    Object val = this.getCellValue(row, entry.getKey());
+
+                    // 如果不存在实例则新建.
+                    entity = (entity == null ? clazz.newInstance() : entity);
+                    // 从map中得到对应列的field.
+                    Field field = fieldsMap.get(entry.getKey());
+                    // 取得类型,并根据对象类型设置值.
+                    Class<?> fieldType = field.getType();
+                    if (String.class == fieldType)
+                    {
+                        String s = Convert.toStr(val);
+                        if (StringUtils.endsWith(s, ".0"))
+                        {
+                            val = StringUtils.substringBefore(s, ".0");
+                        }
+                        else
+                        {
+                            String dateFormat = field.getAnnotation(Excel.class).dateFormat();
+                            if (StringUtils.isNotEmpty(dateFormat))
+                            {
+                                val = DateUtils.parseDateToStr(dateFormat, (Date) val);
+                            }
+                            else
+                            {
+                                val = Convert.toStr(val);
+                            }
+                        }
+                    }
+                    else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
+                    {
+                        val = Convert.toInt(val);
+                    }
+                    else if (Long.TYPE == fieldType || Long.class == fieldType)
+                    {
+                        val = Convert.toLong(val);
+                    }
+                    else if (Double.TYPE == fieldType || Double.class == fieldType)
+                    {
+                        val = Convert.toDouble(val);
+                    }
+                    else if (Float.TYPE == fieldType || Float.class == fieldType)
+                    {
+                        val = Convert.toFloat(val);
+                    }
+                    else if (BigDecimal.class == fieldType)
+                    {
+                        val = Convert.toBigDecimal(val);
+                    }
+                    else if (Date.class == fieldType)
+                    {
+                        if (val instanceof String)
+                        {
+                            val = DateUtils.parseDate(val);
+                        }
+                        else if (val instanceof Double)
+                        {
+                            val = DateUtil.getJavaDate((Double) val);
+                        }
+                    }
+                    else if (Boolean.TYPE == fieldType || Boolean.class == fieldType)
+                    {
+                        val = Convert.toBool(val, false);
+                    }
+                    if (StringUtils.isNotNull(fieldType))
+                    {
+                        Excel attr = field.getAnnotation(Excel.class);
+                        String propertyName = field.getName();
+                        if (StringUtils.isNotEmpty(attr.targetAttr()))
+                        {
+                            propertyName = field.getName() + "." + attr.targetAttr();
+                        }
+                        else if (StringUtils.isNotEmpty(attr.readConverterExp()))
+                        {
+                            val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
+                        }
+                        else if (StringUtils.isNotEmpty(attr.dictType()))
+                        {
+                            val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
+                        }
+                        ReflectUtils.invokeSetter(entity, propertyName, val);
+                    }
+                }
+                list.add(entity);
+            }
+        }
+        return list;
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @param list 导出数据集合
+     * @param sheetName 工作表的名称
+     * @return 结果
+     */
+    public AjaxResult exportExcel(List<T> list, String sheetName)
+    {
+        this.init(list, sheetName, Type.EXPORT);
+        return exportExcel();
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @param sheetName 工作表的名称
+     * @return 结果
+     */
+    public AjaxResult importTemplateExcel(String sheetName)
+    {
+        this.init(null, sheetName, Type.IMPORT);
+        return exportExcel();
+    }
+
+    /**
+     * 对list数据源将其里面的数据导入到excel表单
+     * 
+     * @return 结果
+     */
+    public AjaxResult exportExcel()
+    {
+        OutputStream out = null;
+        try
+        {
+            // 取出一共有多少个sheet.
+            double sheetNo = Math.ceil(list.size() / sheetSize);
+            for (int index = 0; index <= sheetNo; index++)
+            {
+                createSheet(sheetNo, index);
+
+                // 产生一行
+                Row row = sheet.createRow(0);
+                int column = 0;
+                // 写入各个字段的列头名称
+                for (Object[] os : fields)
+                {
+                    Excel excel = (Excel) os[1];
+                    this.createCell(excel, row, column++);
+                }
+                if (Type.EXPORT.equals(type))
+                {
+                    fillExcelData(index, row);
+                    addStatisticsRow();
+                }
+            }
+            String filename = encodingFilename(sheetName);
+            out = new FileOutputStream(getAbsoluteFile(filename));
+            wb.write(out);
+            return AjaxResult.success(filename);
+        }
+        catch (Exception e)
+        {
+            log.error("导出Excel异常{}", e.getMessage());
+            throw new BusinessException("导出Excel失败,请联系网站管理员!");
+        }
+        finally
+        {
+            if (wb != null)
+            {
+                try
+                {
+                    wb.close();
+                }
+                catch (IOException e1)
+                {
+                    e1.printStackTrace();
+                }
+            }
+            if (out != null)
+            {
+                try
+                {
+                    out.close();
+                }
+                catch (IOException e1)
+                {
+                    e1.printStackTrace();
+                }
+            }
+        }
+    }
+
+    /**
+     * 填充excel数据
+     * 
+     * @param index 序号
+     * @param row 单元格行
+     */
+    public void fillExcelData(int index, Row row)
+    {
+        int startNo = index * sheetSize;
+        int endNo = Math.min(startNo + sheetSize, list.size());
+        for (int i = startNo; i < endNo; i++)
+        {
+            row = sheet.createRow(i + 1 - startNo);
+            // 得到导出对象.
+            T vo = (T) list.get(i);
+            int column = 0;
+            for (Object[] os : fields)
+            {
+                Field field = (Field) os[0];
+                Excel excel = (Excel) os[1];
+                // 设置实体类私有属性可访问
+                field.setAccessible(true);
+                this.addCell(excel, row, vo, field, column++);
+            }
+        }
+    }
+
+    /**
+     * 创建表格样式
+     * 
+     * @param wb 工作薄对象
+     * @return 样式列表
+     */
+    private Map<String, CellStyle> createStyles(Workbook wb)
+    {
+        // 写入各条记录,每条记录对应excel表中的一行
+        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
+        CellStyle style = wb.createCellStyle();
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setBorderRight(BorderStyle.THIN);
+        style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderTop(BorderStyle.THIN);
+        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        Font dataFont = wb.createFont();
+        dataFont.setFontName("Arial");
+        dataFont.setFontHeightInPoints((short) 10);
+        style.setFont(dataFont);
+        styles.put("data", style);
+
+        style = wb.createCellStyle();
+        style.cloneStyleFrom(styles.get("data"));
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
+        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        Font headerFont = wb.createFont();
+        headerFont.setFontName("Arial");
+        headerFont.setFontHeightInPoints((short) 10);
+        headerFont.setBold(true);
+        headerFont.setColor(IndexedColors.WHITE.getIndex());
+        style.setFont(headerFont);
+        styles.put("header", style);
+        
+        style = wb.createCellStyle();
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        Font totalFont = wb.createFont();
+        totalFont.setFontName("Arial");
+        totalFont.setFontHeightInPoints((short) 10);
+        style.setFont(totalFont);
+        styles.put("total", style);
+
+        style = wb.createCellStyle();
+        style.cloneStyleFrom(styles.get("data"));
+        style.setAlignment(HorizontalAlignment.LEFT);
+        styles.put("data1", style);
+
+        style = wb.createCellStyle();
+        style.cloneStyleFrom(styles.get("data"));
+        style.setAlignment(HorizontalAlignment.CENTER);
+        styles.put("data2", style);
+
+        style = wb.createCellStyle();
+        style.cloneStyleFrom(styles.get("data"));
+        style.setAlignment(HorizontalAlignment.RIGHT);
+        styles.put("data3", style);
+
+        return styles;
+    }
+
+    /**
+     * 创建单元格
+     */
+    public Cell createCell(Excel attr, Row row, int column)
+    {
+        // 创建列
+        Cell cell = row.createCell(column);
+        // 写入列信息
+        cell.setCellValue(attr.name());
+        setDataValidation(attr, row, column);
+        cell.setCellStyle(styles.get("header"));
+        return cell;
+    }
+
+    /**
+     * 设置单元格信息
+     * 
+     * @param value 单元格值
+     * @param attr 注解相关
+     * @param cell 单元格信息
+     */
+    public void setCellVo(Object value, Excel attr, Cell cell)
+    {
+        if (ColumnType.STRING == attr.cellType())
+        {
+            cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix());
+        }
+        else if (ColumnType.NUMERIC == attr.cellType())
+        {
+            if (StringUtils.isNotNull(value))
+            {
+                cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
+            }
+        }
+        else if (ColumnType.IMAGE == attr.cellType())
+        {
+            ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1),
+                    cell.getRow().getRowNum() + 1);
+            String imagePath = Convert.toStr(value);
+            if (StringUtils.isNotEmpty(imagePath))
+            {
+                byte[] data = ImageUtils.getImage(imagePath);
+                getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
+                        cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
+            }
+        }
+    }
+    
+    /**
+     * 获取画布
+     */
+    public static Drawing<?> getDrawingPatriarch(Sheet sheet)
+    {
+        if (sheet.getDrawingPatriarch() == null)
+        {
+            sheet.createDrawingPatriarch();
+        }
+        return sheet.getDrawingPatriarch();
+    }
+
+    /**
+     * 获取图片类型,设置图片插入类型
+     */
+    public int getImageType(byte[] value)
+    {
+        String type = FileTypeUtils.getFileExtendName(value);
+        if ("JPG".equalsIgnoreCase(type))
+        {
+            return Workbook.PICTURE_TYPE_JPEG;
+        }
+        else if ("PNG".equalsIgnoreCase(type))
+        {
+            return Workbook.PICTURE_TYPE_PNG;
+        }
+        return Workbook.PICTURE_TYPE_JPEG;
+    }
+
+    /**
+     * 创建表格样式
+     */
+    public void setDataValidation(Excel attr, Row row, int column)
+    {
+        if (attr.name().indexOf("注:") >= 0)
+        {
+            sheet.setColumnWidth(column, 6000);
+        }
+        else
+        {
+            // 设置列宽
+            sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
+        }
+        // 如果设置了提示信息则鼠标放上去提示.
+        if (StringUtils.isNotEmpty(attr.prompt()))
+        {
+            // 这里默认设了2-101列提示.
+            setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column);
+        }
+        // 如果设置了combo属性则本列只能选择不能输入
+        if (attr.combo().length > 0)
+        {
+            // 这里默认设了2-101列只能选择不能输入.
+            setXSSFValidation(sheet, attr.combo(), 1, 100, column, column);
+        }
+    }
+
+    /**
+     * 添加单元格
+     */
+    public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
+    {
+        Cell cell = null;
+        try
+        {
+            // 设置行高
+            row.setHeight(maxHeight);
+            // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
+            if (attr.isExport())
+            {
+                // 创建cell
+                cell = row.createCell(column);
+                int align = attr.align().value();
+                cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : "")));
+
+                // 用于读取对象中的属性
+                Object value = getTargetValue(vo, field, attr);
+                String dateFormat = attr.dateFormat();
+                String readConverterExp = attr.readConverterExp();
+                String separator = attr.separator();
+                String dictType = attr.dictType();
+                if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
+                {
+                    cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value));
+                }
+                else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
+                {
+                    cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
+                }
+                else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
+                {
+                    cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator));
+                }
+                else if (value instanceof BigDecimal && -1 != attr.scale())
+                {
+                    cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString());
+                }
+                else
+                {
+                    // 设置列类型
+                    setCellVo(value, attr, cell);
+                }
+                addStatisticsData(column, Convert.toStr(value), attr);
+            }
+        }
+        catch (Exception e)
+        {
+            log.error("导出Excel失败{}", e);
+        }
+        return cell;
+    }
+
+    /**
+     * 设置 POI XSSFSheet 单元格提示
+     * 
+     * @param sheet 表单
+     * @param promptTitle 提示标题
+     * @param promptContent 提示内容
+     * @param firstRow 开始行
+     * @param endRow 结束行
+     * @param firstCol 开始列
+     * @param endCol 结束列
+     */
+    public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow,
+            int firstCol, int endCol)
+    {
+        DataValidationHelper helper = sheet.getDataValidationHelper();
+        DataValidationConstraint constraint = helper.createCustomConstraint("DD1");
+        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
+        DataValidation dataValidation = helper.createValidation(constraint, regions);
+        dataValidation.createPromptBox(promptTitle, promptContent);
+        dataValidation.setShowPromptBox(true);
+        sheet.addValidationData(dataValidation);
+    }
+
+    /**
+     * 设置某些列的值只能输入预制的数据,显示下拉框.
+     * 
+     * @param sheet 要设置的sheet.
+     * @param textlist 下拉框显示的内容
+     * @param firstRow 开始行
+     * @param endRow 结束行
+     * @param firstCol 开始列
+     * @param endCol 结束列
+     * @return 设置好的sheet.
+     */
+    public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol)
+    {
+        DataValidationHelper helper = sheet.getDataValidationHelper();
+        // 加载下拉列表内容
+        DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist);
+        // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
+        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
+        // 数据有效性对象
+        DataValidation dataValidation = helper.createValidation(constraint, regions);
+        // 处理Excel兼容性问题
+        if (dataValidation instanceof XSSFDataValidation)
+        {
+            dataValidation.setSuppressDropDownArrow(true);
+            dataValidation.setShowErrorBox(true);
+        }
+        else
+        {
+            dataValidation.setSuppressDropDownArrow(false);
+        }
+
+        sheet.addValidationData(dataValidation);
+    }
+
+    /**
+     * 解析导出值 0=男,1=女,2=未知
+     * 
+     * @param propertyValue 参数值
+     * @param converterExp 翻译注解
+     * @param separator 分隔符
+     * @return 解析后值
+     */
+    public static String convertByExp(String propertyValue, String converterExp, String separator)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        String[] convertSource = converterExp.split(",");
+        for (String item : convertSource)
+        {
+            String[] itemArray = item.split("=");
+            if (StringUtils.containsAny(separator, propertyValue))
+            {
+                for (String value : propertyValue.split(separator))
+                {
+                    if (itemArray[0].equals(value))
+                    {
+                        propertyString.append(itemArray[1] + separator);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                if (itemArray[0].equals(propertyValue))
+                {
+                    return itemArray[1];
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 反向解析值 男=0,女=1,未知=2
+     * 
+     * @param propertyValue 参数值
+     * @param converterExp 翻译注解
+     * @param separator 分隔符
+     * @return 解析后值
+     */
+    public static String reverseByExp(String propertyValue, String converterExp, String separator)
+    {
+        StringBuilder propertyString = new StringBuilder();
+        String[] convertSource = converterExp.split(",");
+        for (String item : convertSource)
+        {
+            String[] itemArray = item.split("=");
+            if (StringUtils.containsAny(separator, propertyValue))
+            {
+                for (String value : propertyValue.split(separator))
+                {
+                    if (itemArray[1].equals(value))
+                    {
+                        propertyString.append(itemArray[0] + separator);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                if (itemArray[1].equals(propertyValue))
+                {
+                    return itemArray[0];
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+    
+    /**
+     * 解析字典值
+     * 
+     * @param dictValue 字典值
+     * @param dictType 字典类型
+     * @param separator 分隔符
+     * @return 字典标签
+     */
+    public static String convertDictByExp(String dictValue, String dictType, String separator)
+    {
+        return DictUtils.getDictLabel(dictType, dictValue, separator);
+    }
+
+    /**
+     * 反向解析值字典值
+     * 
+     * @param dictLabel 字典标签
+     * @param dictType 字典类型
+     * @param separator 分隔符
+     * @return 字典值
+     */
+    public static String reverseDictByExp(String dictLabel, String dictType, String separator)
+    {
+        return DictUtils.getDictValue(dictType, dictLabel, separator);
+    }
+    
+    /**
+     * 合计统计信息
+     */
+    private void addStatisticsData(Integer index, String text, Excel entity)
+    {
+        if (entity != null && entity.isStatistics())
+        {
+            Double temp = 0D;
+            if (!statistics.containsKey(index))
+            {
+                statistics.put(index, temp);
+            }
+            try
+            {
+                temp = Double.valueOf(text);
+            }
+            catch (NumberFormatException e)
+            {
+            }
+            statistics.put(index, statistics.get(index) + temp);
+        }
+    }
+
+    /**
+     * 创建统计行
+     */
+    public void addStatisticsRow()
+    {
+        if (statistics.size() > 0)
+        {
+            Cell cell = null;
+            Row row = sheet.createRow(sheet.getLastRowNum() + 1);
+            Set<Integer> keys = statistics.keySet();
+            cell = row.createCell(0);
+            cell.setCellStyle(styles.get("total"));
+            cell.setCellValue("合计");
+            
+            for (Integer key : keys)
+            {
+                cell = row.createCell(key);
+                cell.setCellStyle(styles.get("total"));
+                cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
+            }
+            statistics.clear();
+        }
+    }
+
+    /**
+     * 编码文件名
+     */
+    public String encodingFilename(String filename)
+    {
+        filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx";
+        return filename;
+    }
+
+    /**
+     * 获取下载路径
+     * 
+     * @param filename 文件名称
+     */
+    public String getAbsoluteFile(String filename)
+    {
+        String downloadPath = ZTMapConfig.getDownloadPath() + filename;
+        File desc = new File(downloadPath);
+        if (!desc.getParentFile().exists())
+        {
+            desc.getParentFile().mkdirs();
+        }
+        return downloadPath;
+    }
+
+    /**
+     * 获取bean中的属性值
+     * 
+     * @param vo 实体对象
+     * @param field 字段
+     * @param excel 注解
+     * @return 最终的属性值
+     * @throws Exception
+     */
+    private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
+    {
+        Object o = field.get(vo);
+        if (StringUtils.isNotEmpty(excel.targetAttr()))
+        {
+            String target = excel.targetAttr();
+            if (target.indexOf(".") > -1)
+            {
+                String[] targets = target.split("[.]");
+                for (String name : targets)
+                {
+                    o = getValue(o, name);
+                }
+            }
+            else
+            {
+                o = getValue(o, target);
+            }
+        }
+        return o;
+    }
+
+    /**
+     * 以类的属性的get方法方法形式获取值
+     * 
+     * @param o
+     * @param name
+     * @return value
+     * @throws Exception
+     */
+    private Object getValue(Object o, String name) throws Exception
+    {
+        if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name))
+        {
+            Class<?> clazz = o.getClass();
+            Field field = clazz.getDeclaredField(name);
+            field.setAccessible(true);
+            o = field.get(o);
+        }
+        return o;
+    }
+
+    /**
+     * 得到所有定义字段
+     */
+    private void createExcelField()
+    {
+        this.fields = new ArrayList<Object[]>();
+        List<Field> tempFields = new ArrayList<>();
+        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
+        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
+        for (Field field : tempFields)
+        {
+            // 单注解
+            if (field.isAnnotationPresent(Excel.class))
+            {
+                putToField(field, field.getAnnotation(Excel.class));
+            }
+
+            // 多注解
+            if (field.isAnnotationPresent(Excels.class))
+            {
+                Excels attrs = field.getAnnotation(Excels.class);
+                Excel[] excels = attrs.value();
+                for (Excel excel : excels)
+                {
+                    putToField(field, excel);
+                }
+            }
+        }
+        this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
+        this.maxHeight = getRowHeight();
+    }
+    
+    /**
+     * 根据注解获取最大行高
+     */
+    public short getRowHeight()
+    {
+        double maxHeight = 0;
+        for (Object[] os : this.fields)
+        {
+            Excel excel = (Excel) os[1];
+            maxHeight = maxHeight > excel.height() ? maxHeight : excel.height();
+        }
+        return (short) (maxHeight * 20);
+    }
+
+    /**
+     * 放到字段集合中
+     */
+    private void putToField(Field field, Excel attr)
+    {
+        if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
+        {
+            this.fields.add(new Object[] { field, attr });
+        }
+    }
+
+    /**
+     * 创建一个工作簿
+     */
+    public void createWorkbook()
+    {
+        this.wb = new SXSSFWorkbook(500);
+    }
+
+    /**
+     * 创建工作表
+     * 
+     * @param sheetNo sheet数量
+     * @param index 序号
+     */
+    public void createSheet(double sheetNo, int index)
+    {
+        this.sheet = wb.createSheet();
+        this.styles = createStyles(wb);
+        // 设置工作表的名称.
+        if (sheetNo == 0)
+        {
+            wb.setSheetName(index, sheetName);
+        }
+        else
+        {
+            wb.setSheetName(index, sheetName + index);
+        }
+    }
+
+    /**
+     * 获取单元格值
+     * 
+     * @param row 获取的行
+     * @param column 获取单元格列号
+     * @return 单元格值
+     */
+    public Object getCellValue(Row row, int column)
+    {
+        if (row == null)
+        {
+            return row;
+        }
+        Object val = "";
+        try
+        {
+            Cell cell = row.getCell(column);
+            if (StringUtils.isNotNull(cell))
+            {
+                if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA)
+                {
+                    val = cell.getNumericCellValue();
+                    if (DateUtil.isCellDateFormatted(cell))
+                    {
+                        val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换
+                    }
+                    else
+                    {
+                        if ((Double) val % 1 != 0)
+                        {
+                            val = new BigDecimal(val.toString());
+                        }
+                        else
+                        {
+                            val = new DecimalFormat("0").format(val);
+                        }
+                    }
+                }
+                else if (cell.getCellType() == CellType.STRING)
+                {
+                    val = cell.getStringCellValue();
+                }
+                else if (cell.getCellType() == CellType.BOOLEAN)
+                {
+                    val = cell.getBooleanCellValue();
+                }
+                else if (cell.getCellType() == CellType.ERROR)
+                {
+                    val = cell.getErrorCellValue();
+                }
+
+            }
+        }
+        catch (Exception e)
+        {
+            return val;
+        }
+        return val;
+    }
+
+    /**
+     * 判断是否是空行
+     * 
+     * @param row 判断的行
+     * @return
+     */
+    private boolean isRowEmpty(Row row)
+    {
+        if (row == null)
+        {
+            return true;
+        }
+        for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++)
+        {
+            Cell cell = row.getCell(i);
+            if (cell != null && cell.getCellType() != CellType.BLANK)
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+}

+ 410 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/reflect/ReflectUtils.java

@@ -0,0 +1,410 @@
+package com.ztmap.common.utils.reflect;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Date;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ztmap.common.utils.DateUtils;
+import com.ztmap.common.utils.text.Convert;
+
+/**
+ * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
+ * 
+ * @author ztmap
+ */
+@SuppressWarnings("rawtypes")
+public class ReflectUtils
+{
+    private static final String SETTER_PREFIX = "set";
+
+    private static final String GETTER_PREFIX = "get";
+
+    private static final String CGLIB_CLASS_SEPARATOR = "$$";
+
+    private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);
+
+    /**
+     * 调用Getter方法.
+     * 支持多级,如:对象名.对象名.方法
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeGetter(Object obj, String propertyName)
+    {
+        Object object = obj;
+        for (String name : StringUtils.split(propertyName, "."))
+        {
+            String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
+            object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
+        }
+        return (E) object;
+    }
+
+    /**
+     * 调用Setter方法, 仅匹配方法名。
+     * 支持多级,如:对象名.对象名.方法
+     */
+    public static <E> void invokeSetter(Object obj, String propertyName, E value)
+    {
+        Object object = obj;
+        String[] names = StringUtils.split(propertyName, ".");
+        for (int i = 0; i < names.length; i++)
+        {
+            if (i < names.length - 1)
+            {
+                String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
+                object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
+            }
+            else
+            {
+                String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
+                invokeMethodByName(object, setterMethodName, new Object[] { value });
+            }
+        }
+    }
+
+    /**
+     * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E getFieldValue(final Object obj, final String fieldName)
+    {
+        Field field = getAccessibleField(obj, fieldName);
+        if (field == null)
+        {
+            logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
+            return null;
+        }
+        E result = null;
+        try
+        {
+            result = (E) field.get(obj);
+        }
+        catch (IllegalAccessException e)
+        {
+            logger.error("不可能抛出的异常{}", e.getMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
+     */
+    public static <E> void setFieldValue(final Object obj, final String fieldName, final E value)
+    {
+        Field field = getAccessibleField(obj, fieldName);
+        if (field == null)
+        {
+            // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
+            logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
+            return;
+        }
+        try
+        {
+            field.set(obj, value);
+        }
+        catch (IllegalAccessException e)
+        {
+            logger.error("不可能抛出的异常: {}", e.getMessage());
+        }
+    }
+
+    /**
+     * 直接调用对象方法, 无视private/protected修饰符.
+     * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
+     * 同时匹配方法名+参数类型,
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
+            final Object[] args)
+    {
+        if (obj == null || methodName == null)
+        {
+            return null;
+        }
+        Method method = getAccessibleMethod(obj, methodName, parameterTypes);
+        if (method == null)
+        {
+            logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
+            return null;
+        }
+        try
+        {
+            return (E) method.invoke(obj, args);
+        }
+        catch (Exception e)
+        {
+            String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
+            throw convertReflectionExceptionToUnchecked(msg, e);
+        }
+    }
+
+    /**
+     * 直接调用对象方法, 无视private/protected修饰符,
+     * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
+     * 只匹配函数名,如果有多个同名函数调用第一个。
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args)
+    {
+        Method method = getAccessibleMethodByName(obj, methodName, args.length);
+        if (method == null)
+        {
+            // 如果为空不报错,直接返回空。
+            logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
+            return null;
+        }
+        try
+        {
+            // 类型转换(将参数数据类型转换为目标方法参数类型)
+            Class<?>[] cs = method.getParameterTypes();
+            for (int i = 0; i < cs.length; i++)
+            {
+                if (args[i] != null && !args[i].getClass().equals(cs[i]))
+                {
+                    if (cs[i] == String.class)
+                    {
+                        args[i] = Convert.toStr(args[i]);
+                        if (StringUtils.endsWith((String) args[i], ".0"))
+                        {
+                            args[i] = StringUtils.substringBefore((String) args[i], ".0");
+                        }
+                    }
+                    else if (cs[i] == Integer.class)
+                    {
+                        args[i] = Convert.toInt(args[i]);
+                    }
+                    else if (cs[i] == Long.class)
+                    {
+                        args[i] = Convert.toLong(args[i]);
+                    }
+                    else if (cs[i] == Double.class)
+                    {
+                        args[i] = Convert.toDouble(args[i]);
+                    }
+                    else if (cs[i] == Float.class)
+                    {
+                        args[i] = Convert.toFloat(args[i]);
+                    }
+                    else if (cs[i] == Date.class)
+                    {
+                        if (args[i] instanceof String)
+                        {
+                            args[i] = DateUtils.parseDate(args[i]);
+                        }
+                        else
+                        {
+                            args[i] = DateUtil.getJavaDate((Double) args[i]);
+                        }
+                    }
+                    else if (cs[i] == boolean.class || cs[i] == Boolean.class)
+                    {
+                        args[i] = Convert.toBool(args[i]);
+                    }
+                }
+            }
+            return (E) method.invoke(obj, args);
+        }
+        catch (Exception e)
+        {
+            String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
+            throw convertReflectionExceptionToUnchecked(msg, e);
+        }
+    }
+
+    /**
+     * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
+     * 如向上转型到Object仍无法找到, 返回null.
+     */
+    public static Field getAccessibleField(final Object obj, final String fieldName)
+    {
+        // 为空不报错。直接返回 null
+        if (obj == null)
+        {
+            return null;
+        }
+        Validate.notBlank(fieldName, "fieldName can't be blank");
+        for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
+        {
+            try
+            {
+                Field field = superClass.getDeclaredField(fieldName);
+                makeAccessible(field);
+                return field;
+            }
+            catch (NoSuchFieldException e)
+            {
+                continue;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
+     * 如向上转型到Object仍无法找到, 返回null.
+     * 匹配函数名+参数类型。
+     * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
+     */
+    public static Method getAccessibleMethod(final Object obj, final String methodName,
+            final Class<?>... parameterTypes)
+    {
+        // 为空不报错。直接返回 null
+        if (obj == null)
+        {
+            return null;
+        }
+        Validate.notBlank(methodName, "methodName can't be blank");
+        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
+        {
+            try
+            {
+                Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
+                makeAccessible(method);
+                return method;
+            }
+            catch (NoSuchMethodException e)
+            {
+                continue;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
+     * 如向上转型到Object仍无法找到, 返回null.
+     * 只匹配函数名。
+     * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
+     */
+    public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum)
+    {
+        // 为空不报错。直接返回 null
+        if (obj == null)
+        {
+            return null;
+        }
+        Validate.notBlank(methodName, "methodName can't be blank");
+        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
+        {
+            Method[] methods = searchType.getDeclaredMethods();
+            for (Method method : methods)
+            {
+                if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum)
+                {
+                    makeAccessible(method);
+                    return method;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
+     */
+    public static void makeAccessible(Method method)
+    {
+        if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
+                && !method.isAccessible())
+        {
+            method.setAccessible(true);
+        }
+    }
+
+    /**
+     * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
+     */
+    public static void makeAccessible(Field field)
+    {
+        if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
+                || Modifier.isFinal(field.getModifiers())) && !field.isAccessible())
+        {
+            field.setAccessible(true);
+        }
+    }
+
+    /**
+     * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
+     * 如无法找到, 返回Object.class.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Class<T> getClassGenricType(final Class clazz)
+    {
+        return getClassGenricType(clazz, 0);
+    }
+
+    /**
+     * 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
+     * 如无法找到, 返回Object.class.
+     */
+    public static Class getClassGenricType(final Class clazz, final int index)
+    {
+        Type genType = clazz.getGenericSuperclass();
+
+        if (!(genType instanceof ParameterizedType))
+        {
+            logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType");
+            return Object.class;
+        }
+
+        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
+
+        if (index >= params.length || index < 0)
+        {
+            logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+                    + params.length);
+            return Object.class;
+        }
+        if (!(params[index] instanceof Class))
+        {
+            logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
+            return Object.class;
+        }
+
+        return (Class) params[index];
+    }
+
+    public static Class<?> getUserClass(Object instance)
+    {
+        if (instance == null)
+        {
+            throw new RuntimeException("Instance must not be null");
+        }
+        Class clazz = instance.getClass();
+        if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR))
+        {
+            Class<?> superClass = clazz.getSuperclass();
+            if (superClass != null && !Object.class.equals(superClass))
+            {
+                return superClass;
+            }
+        }
+        return clazz;
+
+    }
+
+    /**
+     * 将反射时的checked exception转换为unchecked exception.
+     */
+    public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e)
+    {
+        if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
+                || e instanceof NoSuchMethodException)
+        {
+            return new IllegalArgumentException(msg, e);
+        }
+        else if (e instanceof InvocationTargetException)
+        {
+            return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());
+        }
+        return new RuntimeException(msg, e);
+    }
+}

+ 30 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/security/AuthorizationUtils.java

@@ -0,0 +1,30 @@
+package com.ztmap.common.utils.security;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.mgt.RealmSecurityManager;
+import com.ztmap.framework.shiro.realm.UserRealm;
+
+/**
+ * 用户授权信息
+ * 
+ * @author ztmap
+ */
+public class AuthorizationUtils
+{
+    /**
+     * 清理所有用户授权信息缓存
+     */
+    public static void clearAllCachedAuthorizationInfo()
+    {
+        getUserRealm().clearAllCachedAuthorizationInfo();
+    }
+
+    /**
+     * 获取自定义Realm
+     */
+    public static UserRealm getUserRealm()
+    {
+        RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
+        return (UserRealm) rsm.getRealms().iterator().next();
+    }
+}

+ 36 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/security/CipherUtils.java

@@ -0,0 +1,36 @@
+package com.ztmap.common.utils.security;
+
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import javax.crypto.KeyGenerator;
+
+/**
+ * 对称密钥密码算法工具类
+ *
+ * @author ztmap
+ */
+public class CipherUtils
+{
+    /**
+     * 生成随机秘钥
+     *
+     * @param keyBitSize 字节大小
+     * @param algorithmName 算法名称
+     * @return 创建密匙
+     */
+    public static Key generateNewKey(int keyBitSize, String algorithmName)
+    {
+        KeyGenerator kg;
+        try
+        {
+            kg = KeyGenerator.getInstance(algorithmName);
+        }
+        catch (NoSuchAlgorithmException e)
+        {
+            String msg = "Unable to acquire " + algorithmName + " algorithm.  This is required to function.";
+            throw new IllegalStateException(msg, e);
+        }
+        kg.init(keyBitSize);
+        return kg.generateKey();
+    }
+}

+ 77 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/security/PermissionUtils.java

@@ -0,0 +1,77 @@
+package com.ztmap.common.utils.security;
+
+import org.apache.commons.lang3.StringUtils;
+import com.ztmap.common.constant.PermissionConstants;
+import com.ztmap.common.utils.MessageUtils;
+
+/**
+ * permission 工具类
+ * 
+ * @author ztmap
+ */
+public class PermissionUtils
+{
+    /**
+     * 查看数据的权限
+     */
+    public static final String VIEW_PERMISSION = "no.view.permission";
+
+    /**
+     * 创建数据的权限
+     */
+    public static final String CREATE_PERMISSION = "no.create.permission";
+
+    /**
+     * 修改数据的权限
+     */
+    public static final String UPDATE_PERMISSION = "no.update.permission";
+
+    /**
+     * 删除数据的权限
+     */
+    public static final String DELETE_PERMISSION = "no.delete.permission";
+
+    /**
+     * 导出数据的权限
+     */
+    public static final String EXPORT_PERMISSION = "no.export.permission";
+
+    /**
+     * 其他数据的权限
+     */
+    public static final String PERMISSION = "no.permission";
+
+    /**
+     * 权限错误消息提醒
+     * 
+     * @param permissionsStr 错误信息
+     * @return 提示信息
+     */
+    public static String getMsg(String permissionsStr)
+    {
+        String permission = StringUtils.substringBetween(permissionsStr, "[", "]");
+        String msg = MessageUtils.message(PERMISSION, permission);
+        if (StringUtils.endsWithIgnoreCase(permission, PermissionConstants.ADD_PERMISSION))
+        {
+            msg = MessageUtils.message(CREATE_PERMISSION, permission);
+        }
+        else if (StringUtils.endsWithIgnoreCase(permission, PermissionConstants.EDIT_PERMISSION))
+        {
+            msg = MessageUtils.message(UPDATE_PERMISSION, permission);
+        }
+        else if (StringUtils.endsWithIgnoreCase(permission, PermissionConstants.REMOVE_PERMISSION))
+        {
+            msg = MessageUtils.message(DELETE_PERMISSION, permission);
+        }
+        else if (StringUtils.endsWithIgnoreCase(permission, PermissionConstants.EXPORT_PERMISSION))
+        {
+            msg = MessageUtils.message(EXPORT_PERMISSION, permission);
+        }
+        else if (StringUtils.endsWithAny(permission,
+                new String[] { PermissionConstants.VIEW_PERMISSION, PermissionConstants.LIST_PERMISSION }))
+        {
+            msg = MessageUtils.message(VIEW_PERMISSION, permission);
+        }
+        return msg;
+    }
+}

+ 75 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/security/ShiroUtils.java

@@ -0,0 +1,75 @@
+package com.ztmap.common.utils.security;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.shiro.subject.SimplePrincipalCollection;
+import com.ztmap.common.utils.StringUtils;
+import com.ztmap.common.utils.bean.BeanUtils;
+import com.ztmap.project.system.user.domain.User;
+
+/**
+ * shiro 工具类
+ * 
+ * @author ztmap
+ */
+public class ShiroUtils
+{
+    public static Subject getSubject()
+    {
+        return SecurityUtils.getSubject();
+    }
+
+    public static Session getSession()
+    {
+        return SecurityUtils.getSubject().getSession();
+    }
+
+    public static void logout()
+    {
+        getSubject().logout();
+    }
+
+    public static User getSysUser()
+    {
+        User user = null;
+        Object obj = getSubject().getPrincipal();
+        if (StringUtils.isNotNull(obj))
+        {
+            user = new User();
+            BeanUtils.copyBeanProp(user, obj);
+        }
+        return user;
+    }
+
+    public static void setSysUser(User user)
+    {
+        Subject subject = getSubject();
+        PrincipalCollection principalCollection = subject.getPrincipals();
+        String realmName = principalCollection.getRealmNames().iterator().next();
+        PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(user, realmName);
+        // 重新加载Principal
+        subject.runAs(newPrincipalCollection);
+    }
+
+    public static Long getUserId()
+    {
+        return getSysUser().getUserId().longValue();
+    }
+
+    public static String getLoginName()
+    {
+        return getSysUser() == null?"":getSysUser().getLoginName();
+    }
+
+    public static String getIp()
+    {
+        return getSubject().getSession().getHost();
+    }
+
+    public static String getSessionId()
+    {
+        return String.valueOf(getSubject().getSession().getId());
+    }
+}

+ 146 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/spring/SpringUtils.java

@@ -0,0 +1,146 @@
+package com.ztmap.common.utils.spring;
+
+import org.springframework.aop.framework.AopContext;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+import com.ztmap.common.utils.StringUtils;
+
+/**
+ * spring工具类 方便在非spring管理环境中获取bean
+ * 
+ * @author ztmap
+ */
+@Component
+public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
+{
+    /** Spring应用上下文环境 */
+    private static ConfigurableListableBeanFactory beanFactory;
+
+    private static ApplicationContext applicationContext;
+
+    @Override
+    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
+    {
+        SpringUtils.beanFactory = beanFactory;
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
+    {
+        SpringUtils.applicationContext = applicationContext;
+    }
+
+    /**
+     * 获取对象
+     *
+     * @param name
+     * @return Object 一个以所给名字注册的bean的实例
+     * @throws org.springframework.beans.BeansException
+     *
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String name) throws BeansException
+    {
+        return (T) beanFactory.getBean(name);
+    }
+
+    /**
+     * 获取类型为requiredType的对象
+     *
+     * @param clz
+     * @return
+     * @throws org.springframework.beans.BeansException
+     *
+     */
+    public static <T> T getBean(Class<T> clz) throws BeansException
+    {
+        T result = (T) beanFactory.getBean(clz);
+        return result;
+    }
+
+    /**
+     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
+     *
+     * @param name
+     * @return boolean
+     */
+    public static boolean containsBean(String name)
+    {
+        return beanFactory.containsBean(name);
+    }
+
+    /**
+     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
+     *
+     * @param name
+     * @return boolean
+     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+     *
+     */
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.isSingleton(name);
+    }
+
+    /**
+     * @param name
+     * @return Class 注册对象的类型
+     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+     *
+     */
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getType(name);
+    }
+
+    /**
+     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
+     *
+     * @param name
+     * @return
+     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+     *
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getAliases(name);
+    }
+
+    /**
+     * 获取aop代理对象
+     * 
+     * @param invoker
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getAopProxy(T invoker)
+    {
+        return (T) AopContext.currentProxy();
+    }
+
+    /**
+     * 获取当前的环境配置,无配置返回null
+     *
+     * @return 当前的环境配置
+     */
+    public static String[] getActiveProfiles()
+    {
+        return applicationContext.getEnvironment().getActiveProfiles();
+    }
+
+    /**
+     * 获取当前的环境配置,当有多个环境配置时,只获取第一个
+     *
+     * @return 当前的环境配置
+     */
+    public static String getActiveProfile()
+    {
+        final String[] activeProfiles = getActiveProfiles();
+        return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
+    }
+}

+ 37 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/sql/SqlUtil.java

@@ -0,0 +1,37 @@
+package com.ztmap.common.utils.sql;
+
+import com.ztmap.common.exception.base.BaseException;
+import com.ztmap.common.utils.StringUtils;
+
+/**
+ * sql操作工具类
+ * 
+ * @author ztmap
+ */
+public class SqlUtil
+{
+    /**
+     * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)
+     */
+    public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
+
+    /**
+     * 检查字符,防止注入绕过
+     */
+    public static String escapeOrderBySql(String value)
+    {
+        if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
+        {
+            throw new BaseException("参数不符合规范,不能进行查询");
+        }
+        return value;
+    }
+
+    /**
+     * 验证 order by 语法是否符合规范
+     */
+    public static boolean isValidOrderBySql(String value)
+    {
+        return value.matches(SQL_PATTERN);
+    }
+}

+ 87 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/text/CharsetKit.java

@@ -0,0 +1,87 @@
+package com.ztmap.common.utils.text;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import com.ztmap.common.utils.StringUtils;
+
+/**
+ * 字符集工具类
+ * 
+ * @author ztmap
+ *
+ */
+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();
+    }
+}

+ 1013 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/text/Convert.java

@@ -0,0 +1,1013 @@
+package com.ztmap.common.utils.text;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import com.ztmap.common.utils.StringUtils;
+
+/**
+ * 类型转换器
+ * 
+ * @author ztmap
+ */
+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);
+    }
+
+    /**
+     * 转换为List<String>数组<br>
+     *
+     * @param split 被转换的值
+     * @return 结果
+     */
+    public static List<String> toListStrArray(String str){
+        String[] stringArray= toStrArray(str);
+        List<String> stringB = Arrays.asList(stringArray);
+        return stringB;
+    }
+
+    /**
+     * 转换为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)
+    {
+        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":
+                return true;
+            case "false":
+                return false;
+            case "yes":
+                return true;
+            case "ok":
+                return true;
+            case "no":
+                return false;
+            case "1":
+                return true;
+            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 new BigDecimal((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[] || obj instanceof Byte[])
+        {
+            return str((Byte[]) obj, 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++)
+        {
+            s += (digit[(int) (Math.floor(n * 10 * 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("^整$", "零元整");
+    }
+}

+ 93 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/text/StrFormatter.java

@@ -0,0 +1,93 @@
+package com.ztmap.common.utils.text;
+
+import com.ztmap.common.utils.StringUtils;
+
+/**
+ * 字符串格式化
+ * 
+ * @author ztmap
+ */
+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;
+                }
+            }
+        }
+        // append the characters following the last {} pair.
+        // 加入最后一个占位符后所有的字符
+        sbuf.append(strPattern, handledPosition, strPattern.length());
+
+        return sbuf.toString();
+    }
+}

+ 49 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/uuid/IdUtils.java

@@ -0,0 +1,49 @@
+package com.ztmap.common.utils.uuid;
+
+/**
+ * ID生成器工具类
+ * 
+ * @author ztmap
+ */
+public class IdUtils
+{
+    /**
+     * 获取随机UUID
+     * 
+     * @return 随机UUID
+     */
+    public static String randomUUID()
+    {
+        return UUID.randomUUID().toString();
+    }
+
+    /**
+     * 简化的UUID,去掉了横线
+     * 
+     * @return 简化的UUID,去掉了横线
+     */
+    public static String simpleUUID()
+    {
+        return UUID.randomUUID().toString(true);
+    }
+
+    /**
+     * 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID
+     * 
+     * @return 随机UUID
+     */
+    public static String fastUUID()
+    {
+        return UUID.fastUUID().toString();
+    }
+
+    /**
+     * 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID
+     * 
+     * @return 简化的UUID,去掉了横线
+     */
+    public static String fastSimpleUUID()
+    {
+        return UUID.fastUUID().toString(true);
+    }
+}

+ 484 - 0
zhny_admin/src/main/java/com/ztmap/common/utils/uuid/UUID.java

@@ -0,0 +1,484 @@
+package com.ztmap.common.utils.uuid;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+import com.ztmap.common.exception.UtilException;
+
+/**
+ * 提供通用唯一识别码(universally unique identifier)(UUID)实现
+ *
+ * @author ztmap
+ */
+public final class UUID implements java.io.Serializable, Comparable<UUID>
+{
+    private static final long serialVersionUID = -1185015143654744140L;
+
+    /**
+     * SecureRandom 的单例
+     *
+     */
+    private static class Holder
+    {
+        static final SecureRandom numberGenerator = getSecureRandom();
+    }
+
+    /** 此UUID的最高64有效位 */
+    private final long mostSigBits;
+
+    /** 此UUID的最低64有效位 */
+    private final long leastSigBits;
+
+    /**
+     * 私有构造
+     * 
+     * @param data 数据
+     */
+    private UUID(byte[] data)
+    {
+        long msb = 0;
+        long lsb = 0;
+        assert data.length == 16 : "data must be 16 bytes in length";
+        for (int i = 0; i < 8; i++)
+        {
+            msb = (msb << 8) | (data[i] & 0xff);
+        }
+        for (int i = 8; i < 16; i++)
+        {
+            lsb = (lsb << 8) | (data[i] & 0xff);
+        }
+        this.mostSigBits = msb;
+        this.leastSigBits = lsb;
+    }
+
+    /**
+     * 使用指定的数据构造新的 UUID。
+     *
+     * @param mostSigBits 用于 {@code UUID} 的最高有效 64 位
+     * @param leastSigBits 用于 {@code UUID} 的最低有效 64 位
+     */
+    public UUID(long mostSigBits, long leastSigBits)
+    {
+        this.mostSigBits = mostSigBits;
+        this.leastSigBits = leastSigBits;
+    }
+
+    /**
+     * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。
+     * 
+     * @return 随机生成的 {@code UUID}
+     */
+    public static UUID fastUUID()
+    {
+        return randomUUID(false);
+    }
+
+    /**
+     * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
+     * 
+     * @return 随机生成的 {@code UUID}
+     */
+    public static UUID randomUUID()
+    {
+        return randomUUID(true);
+    }
+
+    /**
+     * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
+     * 
+     * @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能
+     * @return 随机生成的 {@code UUID}
+     */
+    public static UUID randomUUID(boolean isSecure)
+    {
+        final Random ng = isSecure ? Holder.numberGenerator : getRandom();
+
+        byte[] randomBytes = new byte[16];
+        ng.nextBytes(randomBytes);
+        randomBytes[6] &= 0x0f; /* clear version */
+        randomBytes[6] |= 0x40; /* set to version 4 */
+        randomBytes[8] &= 0x3f; /* clear variant */
+        randomBytes[8] |= 0x80; /* set to IETF variant */
+        return new UUID(randomBytes);
+    }
+
+    /**
+     * 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。
+     *
+     * @param name 用于构造 UUID 的字节数组。
+     *
+     * @return 根据指定数组生成的 {@code UUID}
+     */
+    public static UUID nameUUIDFromBytes(byte[] name)
+    {
+        MessageDigest md;
+        try
+        {
+            md = MessageDigest.getInstance("MD5");
+        }
+        catch (NoSuchAlgorithmException nsae)
+        {
+            throw new InternalError("MD5 not supported");
+        }
+        byte[] md5Bytes = md.digest(name);
+        md5Bytes[6] &= 0x0f; /* clear version */
+        md5Bytes[6] |= 0x30; /* set to version 3 */
+        md5Bytes[8] &= 0x3f; /* clear variant */
+        md5Bytes[8] |= 0x80; /* set to IETF variant */
+        return new UUID(md5Bytes);
+    }
+
+    /**
+     * 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。
+     *
+     * @param name 指定 {@code UUID} 字符串
+     * @return 具有指定值的 {@code UUID}
+     * @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常
+     *
+     */
+    public static UUID fromString(String name)
+    {
+        String[] components = name.split("-");
+        if (components.length != 5)
+        {
+            throw new IllegalArgumentException("Invalid UUID string: " + name);
+        }
+        for (int i = 0; i < 5; i++)
+        {
+            components[i] = "0x" + components[i];
+        }
+
+        long mostSigBits = Long.decode(components[0]).longValue();
+        mostSigBits <<= 16;
+        mostSigBits |= Long.decode(components[1]).longValue();
+        mostSigBits <<= 16;
+        mostSigBits |= Long.decode(components[2]).longValue();
+
+        long leastSigBits = Long.decode(components[3]).longValue();
+        leastSigBits <<= 48;
+        leastSigBits |= Long.decode(components[4]).longValue();
+
+        return new UUID(mostSigBits, leastSigBits);
+    }
+
+    /**
+     * 返回此 UUID 的 128 位值中的最低有效 64 位。
+     *
+     * @return 此 UUID 的 128 位值中的最低有效 64 位。
+     */
+    public long getLeastSignificantBits()
+    {
+        return leastSigBits;
+    }
+
+    /**
+     * 返回此 UUID 的 128 位值中的最高有效 64 位。
+     *
+     * @return 此 UUID 的 128 位值中最高有效 64 位。
+     */
+    public long getMostSignificantBits()
+    {
+        return mostSigBits;
+    }
+
+    /**
+     * 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。
+     * <p>
+     * 版本号具有以下含意:
+     * <ul>
+     * <li>1 基于时间的 UUID
+     * <li>2 DCE 安全 UUID
+     * <li>3 基于名称的 UUID
+     * <li>4 随机生成的 UUID
+     * </ul>
+     *
+     * @return 此 {@code UUID} 的版本号
+     */
+    public int version()
+    {
+        // Version is bits masked by 0x000000000000F000 in MS long
+        return (int) ((mostSigBits >> 12) & 0x0f);
+    }
+
+    /**
+     * 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。
+     * <p>
+     * 变体号具有以下含意:
+     * <ul>
+     * <li>0 为 NCS 向后兼容保留
+     * <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF&nbsp;RFC&nbsp;4122</a>(Leach-Salz), 用于此类
+     * <li>6 保留,微软向后兼容
+     * <li>7 保留供以后定义使用
+     * </ul>
+     *
+     * @return 此 {@code UUID} 相关联的变体号
+     */
+    public int variant()
+    {
+        // This field is composed of a varying number of bits.
+        // 0 - - Reserved for NCS backward compatibility
+        // 1 0 - The IETF aka Leach-Salz variant (used by this class)
+        // 1 1 0 Reserved, Microsoft backward compatibility
+        // 1 1 1 Reserved for future definition.
+        return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
+    }
+
+    /**
+     * 与此 UUID 相关联的时间戳值。
+     *
+     * <p>
+     * 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。<br>
+     * 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。
+     *
+     * <p>
+     * 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
+     * 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
+     *
+     * @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。
+     */
+    public long timestamp() throws UnsupportedOperationException
+    {
+        checkTimeBase();
+        return (mostSigBits & 0x0FFFL) << 48//
+                | ((mostSigBits >> 16) & 0x0FFFFL) << 32//
+                | mostSigBits >>> 32;
+    }
+
+    /**
+     * 与此 UUID 相关联的时钟序列值。
+     *
+     * <p>
+     * 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。
+     * <p>
+     * {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出
+     * UnsupportedOperationException。
+     *
+     * @return 此 {@code UUID} 的时钟序列
+     *
+     * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
+     */
+    public int clockSequence() throws UnsupportedOperationException
+    {
+        checkTimeBase();
+        return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
+    }
+
+    /**
+     * 与此 UUID 相关的节点值。
+     *
+     * <p>
+     * 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。
+     * <p>
+     * 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
+     * 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
+     *
+     * @return 此 {@code UUID} 的节点值
+     *
+     * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
+     */
+    public long node() throws UnsupportedOperationException
+    {
+        checkTimeBase();
+        return leastSigBits & 0x0000FFFFFFFFFFFFL;
+    }
+
+    /**
+     * 返回此{@code UUID} 的字符串表现形式。
+     *
+     * <p>
+     * UUID 的字符串表示形式由此 BNF 描述:
+     * 
+     * <pre>
+     * {@code
+     * UUID                   = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
+     * time_low               = 4*<hexOctet>
+     * time_mid               = 2*<hexOctet>
+     * time_high_and_version  = 2*<hexOctet>
+     * variant_and_sequence   = 2*<hexOctet>
+     * node                   = 6*<hexOctet>
+     * hexOctet               = <hexDigit><hexDigit>
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * </pre>
+     * 
+     * </blockquote>
+     *
+     * @return 此{@code UUID} 的字符串表现形式
+     * @see #toString(boolean)
+     */
+    @Override
+    public String toString()
+    {
+        return toString(false);
+    }
+
+    /**
+     * 返回此{@code UUID} 的字符串表现形式。
+     *
+     * <p>
+     * UUID 的字符串表示形式由此 BNF 描述:
+     * 
+     * <pre>
+     * {@code
+     * UUID                   = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
+     * time_low               = 4*<hexOctet>
+     * time_mid               = 2*<hexOctet>
+     * time_high_and_version  = 2*<hexOctet>
+     * variant_and_sequence   = 2*<hexOctet>
+     * node                   = 6*<hexOctet>
+     * hexOctet               = <hexDigit><hexDigit>
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * </pre>
+     * 
+     * </blockquote>
+     *
+     * @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串
+     * @return 此{@code UUID} 的字符串表现形式
+     */
+    public String toString(boolean isSimple)
+    {
+        final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
+        // time_low
+        builder.append(digits(mostSigBits >> 32, 8));
+        if (false == isSimple)
+        {
+            builder.append('-');
+        }
+        // time_mid
+        builder.append(digits(mostSigBits >> 16, 4));
+        if (false == isSimple)
+        {
+            builder.append('-');
+        }
+        // time_high_and_version
+        builder.append(digits(mostSigBits, 4));
+        if (false == isSimple)
+        {
+            builder.append('-');
+        }
+        // variant_and_sequence
+        builder.append(digits(leastSigBits >> 48, 4));
+        if (false == isSimple)
+        {
+            builder.append('-');
+        }
+        // node
+        builder.append(digits(leastSigBits, 12));
+
+        return builder.toString();
+    }
+
+    /**
+     * 返回此 UUID 的哈希码。
+     *
+     * @return UUID 的哈希码值。
+     */
+    @Override
+    public int hashCode()
+    {
+        long hilo = mostSigBits ^ leastSigBits;
+        return ((int) (hilo >> 32)) ^ (int) hilo;
+    }
+
+    /**
+     * 将此对象与指定对象比较。
+     * <p>
+     * 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。
+     *
+     * @param obj 要与之比较的对象
+     *
+     * @return 如果对象相同,则返回 {@code true};否则返回 {@code false}
+     */
+    @Override
+    public boolean equals(Object obj)
+    {
+        if ((null == obj) || (obj.getClass() != UUID.class))
+        {
+            return false;
+        }
+        UUID id = (UUID) obj;
+        return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
+    }
+
+    // Comparison Operations
+
+    /**
+     * 将此 UUID 与指定的 UUID 比较。
+     *
+     * <p>
+     * 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。
+     *
+     * @param val 与此 UUID 比较的 UUID
+     *
+     * @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。
+     *
+     */
+    @Override
+    public int compareTo(UUID val)
+    {
+        // The ordering is intentionally set up so that the UUIDs
+        // can simply be numerically compared as two numbers
+        return (this.mostSigBits < val.mostSigBits ? -1 : //
+                (this.mostSigBits > val.mostSigBits ? 1 : //
+                        (this.leastSigBits < val.leastSigBits ? -1 : //
+                                (this.leastSigBits > val.leastSigBits ? 1 : //
+                                        0))));
+    }
+
+    // -------------------------------------------------------------------------------------------------------------------
+    // Private method start
+    /**
+     * 返回指定数字对应的hex值
+     * 
+     * @param val 值
+     * @param digits 位
+     * @return 值
+     */
+    private static String digits(long val, int digits)
+    {
+        long hi = 1L << (digits * 4);
+        return Long.toHexString(hi | (val & (hi - 1))).substring(1);
+    }
+
+    /**
+     * 检查是否为time-based版本UUID
+     */
+    private void checkTimeBase()
+    {
+        if (version() != 1)
+        {
+            throw new UnsupportedOperationException("Not a time-based UUID");
+        }
+    }
+
+    /**
+     * 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG)
+     * 
+     * @return {@link SecureRandom}
+     */
+    public static SecureRandom getSecureRandom()
+    {
+        try
+        {
+            return SecureRandom.getInstance("SHA1PRNG");
+        }
+        catch (NoSuchAlgorithmException e)
+        {
+            throw new UtilException(e);
+        }
+    }
+
+    /**
+     * 获取随机数生成器对象<br>
+     * ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。
+     * 
+     * @return {@link ThreadLocalRandom}
+     */
+    public static ThreadLocalRandom getRandom()
+    {
+        return ThreadLocalRandom.current();
+    }
+}

+ 97 - 0
zhny_admin/src/main/java/com/ztmap/common/xss/XssFilter.java

@@ -0,0 +1,97 @@
+package com.ztmap.common.xss;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import com.ztmap.common.utils.StringUtils;
+
+/**
+ * 防止XSS攻击的过滤器
+ * 
+ * @author ztmap
+ */
+public class XssFilter implements Filter
+{
+    /**
+     * 排除链接
+     */
+    public List<String> excludes = new ArrayList<>();
+
+    /**
+     * xss过滤开关
+     */
+    public boolean enabled = false;
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException
+    {
+        String tempExcludes = filterConfig.getInitParameter("excludes");
+        String tempEnabled = filterConfig.getInitParameter("enabled");
+        if (StringUtils.isNotEmpty(tempExcludes))
+        {
+            String[] url = tempExcludes.split(",");
+            for (int i = 0; url != null && i < url.length; i++)
+            {
+                excludes.add(url[i]);
+            }
+        }
+        if (StringUtils.isNotEmpty(tempEnabled))
+        {
+            enabled = Boolean.valueOf(tempEnabled);
+        }
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+            throws IOException, ServletException
+    {
+        HttpServletRequest req = (HttpServletRequest) request;
+        HttpServletResponse resp = (HttpServletResponse) response;
+        if (handleExcludeURL(req, resp))
+        {
+            chain.doFilter(request, response);
+            return;
+        }
+        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
+        chain.doFilter(xssRequest, response);
+    }
+
+    private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
+    {
+        if (!enabled)
+        {
+            return true;
+        }
+        if (excludes == null || excludes.isEmpty())
+        {
+            return false;
+        }
+        String url = request.getServletPath();
+        for (String pattern : excludes)
+        {
+            Pattern p = Pattern.compile("^" + pattern);
+            Matcher m = p.matcher(url);
+            if (m.find())
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void destroy()
+    {
+
+    }
+}

+ 39 - 0
zhny_admin/src/main/java/com/ztmap/common/xss/XssHttpServletRequestWrapper.java

@@ -0,0 +1,39 @@
+package com.ztmap.common.xss;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import com.ztmap.common.utils.html.EscapeUtil;
+
+/**
+ * XSS过滤处理
+ * 
+ * @author ztmap
+ */
+public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
+{
+    /**
+     * @param request
+     */
+    public XssHttpServletRequestWrapper(HttpServletRequest request)
+    {
+        super(request);
+    }
+
+    @Override
+    public String[] getParameterValues(String name)
+    {
+        String[] values = super.getParameterValues(name);
+        if (values != null)
+        {
+            int length = values.length;
+            String[] escapseValues = new String[length];
+            for (int i = 0; i < length; i++)
+            {
+                // 防xss攻击和过滤前后空格
+                escapseValues[i] = EscapeUtil.clean(values[i]).trim();
+            }
+            return escapseValues;
+        }
+        return super.getParameterValues(name);
+    }
+}

+ 166 - 0
zhny_admin/src/main/java/com/ztmap/framework/aspectj/DataScopeAspect.java

@@ -0,0 +1,166 @@
+package com.ztmap.framework.aspectj;
+
+import java.lang.reflect.Method;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.Signature;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.stereotype.Component;
+import com.ztmap.common.utils.StringUtils;
+import com.ztmap.common.utils.security.ShiroUtils;
+import com.ztmap.framework.aspectj.lang.annotation.DataScope;
+import com.ztmap.framework.web.domain.BaseEntity;
+import com.ztmap.project.system.role.domain.Role;
+import com.ztmap.project.system.user.domain.User;
+
+/**
+ * 数据过滤处理
+ * 
+ * @author ztmap
+ */
+@Aspect
+@Component
+public class DataScopeAspect
+{
+    /**
+     * 全部数据权限
+     */
+    public static final String DATA_SCOPE_ALL = "1";
+
+    /**
+     * 自定数据权限
+     */
+    public static final String DATA_SCOPE_CUSTOM = "2";
+
+    /**
+     * 部门数据权限
+     */
+    public static final String DATA_SCOPE_DEPT = "3";
+
+    /**
+     * 部门及以下数据权限
+     */
+    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
+
+    /**
+     * 仅本人数据权限
+     */
+    public static final String DATA_SCOPE_SELF = "5";
+
+    /**
+     * 数据权限过滤关键字
+     */
+    public static final String DATA_SCOPE = "dataScope";
+
+    // 配置织入点
+    @Pointcut("@annotation(com.ztmap.framework.aspectj.lang.annotation.DataScope)")
+    public void dataScopePointCut()
+    {
+    }
+
+    @Before("dataScopePointCut()")
+    public void doBefore(JoinPoint point) throws Throwable
+    {
+        handleDataScope(point);
+    }
+
+    protected void handleDataScope(final JoinPoint joinPoint)
+    {
+        // 获得注解
+        DataScope controllerDataScope = getAnnotationLog(joinPoint);
+        if (controllerDataScope == null)
+        {
+            return;
+        }
+        // 获取当前的用户
+        User currentUser = ShiroUtils.getSysUser();
+        if (currentUser != null)
+        {
+            // 如果是超级管理员,则不过滤数据
+            if (!currentUser.isAdmin())
+            {
+                dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
+                        controllerDataScope.userAlias());
+            }
+        }
+    }
+
+    /**
+     * 数据范围过滤
+     * 
+     * @param joinPoint 切点
+     * @param user 用户
+     * @param deptAlias 部门别名
+     * @param userAlias 用户别名
+     */
+    public static void dataScopeFilter(JoinPoint joinPoint, User user, String deptAlias, String userAlias)
+    {
+        StringBuilder sqlString = new StringBuilder();
+
+        for (Role role : user.getRoles())
+        {
+            String dataScope = role.getDataScope();
+            if (DATA_SCOPE_ALL.equals(dataScope))
+            {
+                sqlString = new StringBuilder();
+                break;
+            }
+            else if (DATA_SCOPE_CUSTOM.equals(dataScope))
+            {
+                sqlString.append(StringUtils.format(
+                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
+                        role.getRoleId()));
+            }
+            else if (DATA_SCOPE_DEPT.equals(dataScope))
+            {
+                sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
+            }
+            else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
+            {
+                sqlString.append(StringUtils.format(
+                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
+                        deptAlias, user.getDeptId(), user.getDeptId()));
+            }
+            else if (DATA_SCOPE_SELF.equals(dataScope))
+            {
+                if (StringUtils.isNotBlank(userAlias))
+                {
+                    sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
+                }
+                else
+                {
+                    // 数据权限为仅本人且没有userAlias别名不查询任何数据
+                    sqlString.append(" OR 1=0 ");
+                }
+            }
+        }
+
+        if (StringUtils.isNotBlank(sqlString.toString()))
+        {
+            Object params = joinPoint.getArgs()[0];
+            if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
+            {
+                BaseEntity baseEntity = (BaseEntity) params;
+                baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
+            }
+        }
+    }
+
+    /**
+     * 是否存在注解,如果存在就获取
+     */
+    private DataScope getAnnotationLog(JoinPoint joinPoint)
+    {
+        Signature signature = joinPoint.getSignature();
+        MethodSignature methodSignature = (MethodSignature) signature;
+        Method method = methodSignature.getMethod();
+
+        if (method != null)
+        {
+            return method.getAnnotation(DataScope.class);
+        }
+        return null;
+    }
+}

+ 72 - 0
zhny_admin/src/main/java/com/ztmap/framework/aspectj/DataSourceAspect.java

@@ -0,0 +1,72 @@
+package com.ztmap.framework.aspectj;
+
+import java.util.Objects;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+import com.ztmap.common.utils.StringUtils;
+import com.ztmap.framework.aspectj.lang.annotation.DataSource;
+import com.ztmap.framework.datasource.DynamicDataSourceContextHolder;
+
+/**
+ * 多数据源处理
+ * 
+ * @author ztmap
+ */
+@Aspect
+@Order(1)
+@Component
+public class DataSourceAspect
+{
+    protected Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Pointcut("@annotation(com.ztmap.framework.aspectj.lang.annotation.DataSource)"
+            + "|| @within(com.ztmap.framework.aspectj.lang.annotation.DataSource)")
+    public void dsPointCut()
+    {
+
+    }
+
+    @Around("dsPointCut()")
+    public Object around(ProceedingJoinPoint point) throws Throwable
+    {
+        DataSource dataSource = getDataSource(point);
+
+        if (StringUtils.isNotNull(dataSource))
+        {
+            DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
+        }
+
+        try
+        {
+            return point.proceed();
+        }
+        finally
+        {
+            // 销毁数据源 在执行方法之后
+            DynamicDataSourceContextHolder.clearDataSourceType();
+        }
+    }
+
+    /**
+     * 获取需要切换的数据源
+     */
+    public DataSource getDataSource(ProceedingJoinPoint point)
+    {
+        MethodSignature signature = (MethodSignature) point.getSignature();
+        DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
+        if (Objects.nonNull(dataSource))
+        {
+            return dataSource;
+        }
+
+        return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
+    }
+}

+ 264 - 0
zhny_admin/src/main/java/com/ztmap/framework/aspectj/LogAspect.java

@@ -0,0 +1,264 @@
+package com.ztmap.framework.aspectj;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.Signature;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.multipart.MultipartFile;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.support.spring.PropertyPreFilters;
+import com.ztmap.common.utils.ServletUtils;
+import com.ztmap.common.utils.StringUtils;
+import com.ztmap.common.utils.security.ShiroUtils;
+import com.ztmap.framework.aspectj.lang.annotation.Log;
+import com.ztmap.framework.aspectj.lang.enums.BusinessStatus;
+import com.ztmap.framework.manager.AsyncManager;
+import com.ztmap.framework.manager.factory.AsyncFactory;
+import com.ztmap.project.monitor.operlog.domain.OperLog;
+import com.ztmap.project.system.user.domain.User;
+
+/**
+ * 操作日志记录处理
+ * 
+ * @author ztmap
+ */
+@Aspect
+@Component
+public class LogAspect
+{
+    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
+    
+    /** 排除敏感属性字段 */
+    public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
+
+    // 配置织入点
+    @Pointcut("@annotation(com.ztmap.framework.aspectj.lang.annotation.Log)")
+    public void logPointCut()
+    {
+    }
+
+    /**
+     * 处理完请求后执行
+     *
+     * @param joinPoint 切点
+     */
+    @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
+    public void doAfterReturning(JoinPoint joinPoint, Object jsonResult)
+    {
+        handleLog(joinPoint, null, jsonResult);
+    }
+
+    /**
+     * 拦截异常操作
+     * 
+     * @param joinPoint 切点
+     * @param e 异常
+     */
+    @AfterThrowing(value = "logPointCut()", throwing = "e")
+    public void doAfterThrowing(JoinPoint joinPoint, Exception e)
+    {
+        handleLog(joinPoint, e, null);
+    }
+
+    protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult)
+    {
+        try
+        {
+            // 获得注解
+            Log controllerLog = getAnnotationLog(joinPoint);
+            if (controllerLog == null)
+            {
+                return;
+            }
+
+            // 获取当前的用户
+            User currentUser = ShiroUtils.getSysUser();
+
+            // *========数据库日志=========*//
+            OperLog operLog = new OperLog();
+            operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
+            // 请求的地址
+            String ip = ShiroUtils.getIp();
+            operLog.setOperIp(ip);
+            // 返回参数
+            if (StringUtils.isNotNull(jsonResult))
+            {
+                operLog.setJsonResult(StringUtils.substring(JSONObject.toJSONString(jsonResult), 0, 2000));
+            }
+
+            operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
+            if (currentUser != null)
+            {
+                operLog.setOperName(currentUser.getLoginName());
+                if (StringUtils.isNotNull(currentUser.getDept())
+                        && StringUtils.isNotEmpty(currentUser.getDept().getDeptName()))
+                {
+                    operLog.setDeptName(currentUser.getDept().getDeptName());
+                }
+            }
+
+            if (e != null)
+            {
+                operLog.setStatus(BusinessStatus.FAIL.ordinal());
+                operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
+            }
+            // 设置方法名称
+            String className = joinPoint.getTarget().getClass().getName();
+            String methodName = joinPoint.getSignature().getName();
+            operLog.setMethod(className + "." + methodName + "()");
+            // 设置请求方式
+            operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
+            // 处理设置注解上的参数
+            getControllerMethodDescription(joinPoint, controllerLog, operLog);
+            // 保存数据库
+            AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
+        }
+        catch (Exception exp)
+        {
+            // 记录本地异常日志
+            log.error("==前置通知异常==");
+            log.error("异常信息:{}", exp.getMessage());
+            exp.printStackTrace();
+        }
+    }
+
+    /**
+     * 获取注解中对方法的描述信息 用于Controller层注解
+     * 
+     * @param log 日志
+     * @param operLog 操作日志
+     * @throws Exception
+     */
+    public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLog operLog) throws Exception
+    {
+        // 设置action动作
+        operLog.setBusinessType(log.businessType().ordinal());
+        // 设置标题
+        operLog.setTitle(log.title());
+        // 设置操作人类别
+        operLog.setOperatorType(log.operatorType().ordinal());
+        // 是否需要保存request,参数和值
+        if (log.isSaveRequestData())
+        {
+            // 获取参数的信息,传入到数据库中。
+            setRequestValue(joinPoint, operLog);
+        }
+    }
+
+    /**
+     * 获取请求的参数,放到log中
+     * 
+     * @param operLog
+     * @param request
+     */
+    private void setRequestValue(JoinPoint joinPoint, OperLog operLog)
+    {
+        Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
+        if (StringUtils.isNotEmpty(map))
+        {
+            String params = JSONObject.toJSONString(map, excludePropertyPreFilter());
+            operLog.setOperParam(StringUtils.substring(params, 0, 2000));
+        }
+        else
+        {
+            Object args = joinPoint.getArgs();
+            if (StringUtils.isNotNull(args))
+            {
+                String params = argsArrayToString(joinPoint.getArgs());
+                operLog.setOperParam(StringUtils.substring(params, 0, 2000));
+            }
+        }
+    }
+
+    /**
+     * 是否存在注解,如果存在就获取
+     */
+    private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
+    {
+        Signature signature = joinPoint.getSignature();
+        MethodSignature methodSignature = (MethodSignature) signature;
+        Method method = methodSignature.getMethod();
+
+        if (method != null)
+        {
+            return method.getAnnotation(Log.class);
+        }
+        return null;
+    }
+    
+    /**
+     * 忽略敏感属性
+     */
+    public PropertyPreFilters.MySimplePropertyPreFilter excludePropertyPreFilter()
+    {
+        return new PropertyPreFilters().addFilter().addExcludes(EXCLUDE_PROPERTIES);
+    }
+
+    /**
+     * 参数拼装
+     */
+    private String argsArrayToString(Object[] paramsArray)
+    {
+        String params = "";
+        if (paramsArray != null && paramsArray.length > 0)
+        {
+            for (int i = 0; i < paramsArray.length; i++)
+            {
+                if (!isFilterObject(paramsArray[i]))
+                {
+                    Object jsonObj = JSONObject.toJSONString(paramsArray[i], excludePropertyPreFilter());
+                    params += jsonObj.toString() + " ";
+                }
+            }
+        }
+        return params.trim();
+    }
+
+    /**
+     * 判断是否需要过滤的对象。
+     * 
+     * @param o 对象信息。
+     * @return 如果是需要过滤的对象,则返回true;否则返回false。
+     */
+    @SuppressWarnings("rawtypes")
+    public boolean isFilterObject(final Object o)
+    {
+        Class<?> clazz = o.getClass();
+        if (clazz.isArray())
+        {
+            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
+        }
+        else if (Collection.class.isAssignableFrom(clazz))
+        {
+            Collection collection = (Collection) o;
+            for (Iterator iter = collection.iterator(); iter.hasNext();)
+            {
+                return iter.next() instanceof MultipartFile;
+            }
+        }
+        else if (Map.class.isAssignableFrom(clazz))
+        {
+            Map map = (Map) o;
+            for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
+            {
+                Map.Entry entry = (Map.Entry) iter.next();
+                return entry.getValue() instanceof MultipartFile;
+            }
+        }
+        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
+                || o instanceof BindingResult;
+    }
+}

+ 28 - 0
zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/annotation/DataScope.java

@@ -0,0 +1,28 @@
+package com.ztmap.framework.aspectj.lang.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 数据权限过滤注解
+ * 
+ * @author ztmap
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataScope
+{
+    /**
+     * 部门表的别名
+     */
+    public String deptAlias() default "";
+
+    /**
+     * 用户表的别名
+     */
+    public String userAlias() default "";
+}

+ 28 - 0
zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/annotation/DataSource.java

@@ -0,0 +1,28 @@
+package com.ztmap.framework.aspectj.lang.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import com.ztmap.framework.aspectj.lang.enums.DataSourceType;
+
+/**
+ * 自定义多数据源切换注解
+ *
+ * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
+ *
+ * @author ztmap
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface DataSource
+{
+    /**
+     * 切换数据源名称
+     */
+    public DataSourceType value() default DataSourceType.MASTER;
+}

+ 165 - 0
zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/annotation/Excel.java

@@ -0,0 +1,165 @@
+package com.ztmap.framework.aspectj.lang.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.math.BigDecimal;
+
+/**
+ * 自定义导出Excel数据注解
+ * 
+ * @author ztmap
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Excel
+{
+    /**
+     * 导出时在excel中排序
+     */
+    public int sort() default Integer.MAX_VALUE;
+
+    /**
+     * 导出到Excel中的名字.
+     */
+    public String name() default "";
+
+    /**
+     * 日期格式, 如: yyyy-MM-dd
+     */
+    public String dateFormat() default "";
+
+    /**
+     * 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
+     */
+    public String dictType() default "";
+
+    /**
+     * 读取内容转表达式 (如: 0=男,1=女,2=未知)
+     */
+    public String readConverterExp() default "";
+
+    /**
+     * 分隔符,读取字符串组内容
+     */
+    public String separator() default ",";
+
+    /**
+     * BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
+     */
+    public int scale() default -1;
+
+    /**
+     * BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
+     */
+    public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
+
+    /**
+     * 导出类型(0数字 1字符串)
+     */
+    public ColumnType cellType() default ColumnType.STRING;
+
+    /**
+     * 导出时在excel中每个列的高度 单位为字符
+     */
+    public double height() default 14;
+
+    /**
+     * 导出时在excel中每个列的宽 单位为字符
+     */
+    public double width() default 16;
+
+    /**
+     * 文字后缀,如% 90 变成90%
+     */
+    public String suffix() default "";
+
+    /**
+     * 当值为空时,字段的默认值
+     */
+    public String defaultValue() default "";
+
+    /**
+     * 提示信息
+     */
+    public String prompt() default "";
+
+    /**
+     * 设置只能选择不能输入的列内容.
+     */
+    public String[] combo() default {};
+
+    /**
+     * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
+     */
+    public boolean isExport() default true;
+
+    /**
+     * 另一个类中的属性名称,支持多级获取,以小数点隔开
+     */
+    public String targetAttr() default "";
+
+    /**
+     * 是否自动统计数据,在最后追加一行统计数据总和
+     */
+    public boolean isStatistics() default false;
+
+    /**
+     * 导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右)
+     */
+    Align align() default Align.AUTO;
+
+    public enum Align
+    {
+        AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
+        private final int value;
+
+        Align(int value)
+        {
+            this.value = value;
+        }
+
+        public int value()
+        {
+            return this.value;
+        }
+    }
+
+    /**
+     * 字段类型(0:导出导入;1:仅导出;2:仅导入)
+     */
+    Type type() default Type.ALL;
+
+    public enum Type
+    {
+        ALL(0), EXPORT(1), IMPORT(2);
+        private final int value;
+
+        Type(int value)
+        {
+            this.value = value;
+        }
+
+        public int value()
+        {
+            return this.value;
+        }
+    }
+
+    public enum ColumnType
+    {
+        NUMERIC(0), STRING(1), IMAGE(2);
+        private final int value;
+
+        ColumnType(int value)
+        {
+            this.value = value;
+        }
+
+        public int value()
+        {
+            return this.value;
+        }
+    }
+}

+ 18 - 0
zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/annotation/Excels.java

@@ -0,0 +1,18 @@
+package com.ztmap.framework.aspectj.lang.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Excel注解集
+ * 
+ * @author ztmap
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Excels
+{
+    Excel[] value();
+}

+ 41 - 0
zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/annotation/Log.java

@@ -0,0 +1,41 @@
+package com.ztmap.framework.aspectj.lang.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import com.ztmap.framework.aspectj.lang.enums.BusinessType;
+import com.ztmap.framework.aspectj.lang.enums.OperatorType;
+
+/**
+ * 自定义操作日志记录注解
+ * 
+ * @author ztmap
+ *
+ */
+@Target({ ElementType.PARAMETER, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Log
+{
+    /**
+     * 模块 
+     */
+    public String title() default "";
+
+    /**
+     * 功能
+     */
+    public BusinessType businessType() default BusinessType.OTHER;
+
+    /**
+     * 操作人类别
+     */
+    public OperatorType operatorType() default OperatorType.MANAGE;
+
+    /**
+     * 是否保存请求的参数
+     */
+    public boolean isSaveRequestData() default true;
+}

+ 20 - 0
zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/enums/BusinessStatus.java

@@ -0,0 +1,20 @@
+package com.ztmap.framework.aspectj.lang.enums;
+
+/**
+ * 操作状态
+ * 
+ * @author ztmap
+ *
+ */
+public enum BusinessStatus
+{
+    /**
+     * 成功
+     */
+    SUCCESS,
+
+    /**
+     * 失败
+     */
+    FAIL,
+}

+ 60 - 0
zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/enums/BusinessType.java

@@ -0,0 +1,60 @@
+package com.ztmap.framework.aspectj.lang.enums;
+
+/**
+ * 业务操作类型
+ * 
+ * @author ztmap
+ *
+ */
+public enum BusinessType
+{
+    /**
+     * 其它
+     */
+    OTHER,
+
+    /**
+     * 新增
+     */
+    INSERT,
+
+    /**
+     * 修改
+     */
+    UPDATE,
+
+    /**
+     * 删除
+     */
+    DELETE,
+
+    /**
+     * 授权
+     */
+    GRANT,
+
+    /**
+     * 导出
+     */
+    EXPORT,
+
+    /**
+     * 导入
+     */
+    IMPORT,
+
+    /**
+     * 强退
+     */
+    FORCE,
+
+    /**
+     * 生成代码
+     */
+    GENCODE,
+    
+    /**
+     * 清空数据
+     */
+    CLEAN,
+}

+ 19 - 0
zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/enums/DataSourceType.java

@@ -0,0 +1,19 @@
+package com.ztmap.framework.aspectj.lang.enums;
+
+/**
+ * 数据源
+ * 
+ * @author ztmap
+ */
+public enum DataSourceType
+{
+    /**
+     * 主库
+     */
+    MASTER,
+
+    /**
+     * 从库
+     */
+    SLAVE
+}

+ 25 - 0
zhny_admin/src/main/java/com/ztmap/framework/aspectj/lang/enums/OperatorType.java

@@ -0,0 +1,25 @@
+package com.ztmap.framework.aspectj.lang.enums;
+
+/**
+ * 操作人类别
+ * 
+ * @author ztmap
+ *
+ */
+public enum OperatorType
+{
+    /**
+     * 其它
+     */
+    OTHER,
+
+    /**
+     * 后台用户
+     */
+    MANAGE,
+
+    /**
+     * 手机端用户
+     */
+    MOBILE
+}

+ 20 - 0
zhny_admin/src/main/java/com/ztmap/framework/config/ApplicationConfig.java

@@ -0,0 +1,20 @@
+package com.ztmap.framework.config;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+/**
+ * 程序注解配置
+ *
+ * @author ztmap
+ */
+@Configuration
+// 表示通过aop框架暴露该代理对象,AopContext能够访问
+@EnableAspectJAutoProxy(exposeProxy = true)
+// 指定要扫描的Mapper类的包的路径
+@MapperScan("com.ztmap.project.**.mapper")
+public class ApplicationConfig
+{
+
+}

+ 83 - 0
zhny_admin/src/main/java/com/ztmap/framework/config/CaptchaConfig.java

@@ -0,0 +1,83 @@
+package com.ztmap.framework.config;
+
+import java.util.Properties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.google.code.kaptcha.impl.DefaultKaptcha;
+import com.google.code.kaptcha.util.Config;
+import static com.google.code.kaptcha.Constants.*;
+
+/**
+ * 验证码配置
+ * 
+ * @author ztmap
+ */
+@Configuration
+public class CaptchaConfig
+{
+    @Bean(name = "captchaProducer")
+    public DefaultKaptcha getKaptchaBean()
+    {
+        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+        Properties properties = new Properties();
+        // 是否有边框 默认为true 我们可以自己设置yes,no
+        properties.setProperty(KAPTCHA_BORDER, "yes");
+        // 验证码文本字符颜色 默认为Color.BLACK
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
+        // 验证码图片宽度 默认为200
+        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
+        // 验证码图片高度 默认为50
+        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
+        // 验证码文本字符大小 默认为40
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
+        // KAPTCHA_SESSION_KEY
+        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
+        // 验证码文本字符长度 默认为5
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
+        // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
+        // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
+        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
+        Config config = new Config(properties);
+        defaultKaptcha.setConfig(config);
+        return defaultKaptcha;
+    }
+
+    @Bean(name = "captchaProducerMath")
+    public DefaultKaptcha getKaptchaBeanMath()
+    {
+        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+        Properties properties = new Properties();
+        // 是否有边框 默认为true 我们可以自己设置yes,no
+        properties.setProperty(KAPTCHA_BORDER, "yes");
+        // 边框颜色 默认为Color.BLACK
+        properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
+        // 验证码文本字符颜色 默认为Color.BLACK
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
+        // 验证码图片宽度 默认为200
+        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
+        // 验证码图片高度 默认为50
+        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
+        // 验证码文本字符大小 默认为40
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
+        // KAPTCHA_SESSION_KEY
+        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
+        // 验证码文本生成器
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ztmap.framework.config.KaptchaTextCreator");
+        // 验证码文本字符间距 默认为2
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
+        // 验证码文本字符长度 默认为5
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
+        // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
+        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
+        // 验证码噪点颜色 默认为Color.BLACK
+        properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
+        // 干扰实现类
+        properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
+        // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
+        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
+        Config config = new Config(properties);
+        defaultKaptcha.setConfig(config);
+        return defaultKaptcha;
+    }
+}

+ 128 - 0
zhny_admin/src/main/java/com/ztmap/framework/config/DruidConfig.java

@@ -0,0 +1,128 @@
+package com.ztmap.framework.config;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.sql.DataSource;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
+import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
+import com.alibaba.druid.util.Utils;
+import com.ztmap.common.utils.spring.SpringUtils;
+import com.ztmap.framework.aspectj.lang.enums.DataSourceType;
+import com.ztmap.framework.config.properties.DruidProperties;
+import com.ztmap.framework.datasource.DynamicDataSource;
+
+/**
+ * druid 配置多数据源
+ * 
+ * @author ztmap
+ */
+@Configuration
+public class DruidConfig
+{
+    @Bean
+    @ConfigurationProperties("spring.datasource.druid.master")
+    public DataSource masterDataSource(DruidProperties druidProperties)
+    {
+        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+        return druidProperties.dataSource(dataSource);
+    }
+
+    @Bean
+    @ConfigurationProperties("spring.datasource.druid.slave")
+    @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
+    public DataSource slaveDataSource(DruidProperties druidProperties)
+    {
+        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+        return druidProperties.dataSource(dataSource);
+    }
+
+    @Bean(name = "dynamicDataSource")
+    @Primary
+    public DynamicDataSource dataSource(DataSource masterDataSource)
+    {
+        Map<Object, Object> targetDataSources = new HashMap<>();
+        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
+        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
+        return new DynamicDataSource(masterDataSource, targetDataSources);
+    }
+
+    /**
+     * 设置数据源
+     * 
+     * @param targetDataSources 备选数据源集合
+     * @param sourceName 数据源名称
+     * @param beanName bean名称
+     */
+    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
+    {
+        try
+        {
+            DataSource dataSource = SpringUtils.getBean(beanName);
+            targetDataSources.put(sourceName, dataSource);
+        }
+        catch (Exception e)
+        {
+        }
+    }
+
+    /**
+     * 去除监控页面底部的广告
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Bean
+    @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
+    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
+    {
+        // 获取web监控页面的参数
+        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
+        // 提取common.js的配置路径
+        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
+        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
+        final String filePath = "support/http/resources/js/common.js";
+        // 创建filter进行过滤
+        Filter filter = new Filter()
+        {
+            @Override
+            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
+            {
+            }
+
+            @Override
+            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+                    throws IOException, ServletException
+            {
+                chain.doFilter(request, response);
+                // 重置缓冲区,响应头不会被重置
+                response.resetBuffer();
+                // 获取common.js
+                String text = Utils.readFromResource(filePath);
+                // 正则替换banner, 除去底部的广告信息
+                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
+                text = text.replaceAll("powered.*?shrek.wang</a>", "");
+                response.getWriter().write(text);
+            }
+
+            @Override
+            public void destroy()
+            {
+            }
+        };
+        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
+        registrationBean.setFilter(filter);
+        registrationBean.addUrlPatterns(commonJsPattern);
+        return registrationBean;
+    }
+}

+ 46 - 0
zhny_admin/src/main/java/com/ztmap/framework/config/FilterConfig.java

@@ -0,0 +1,46 @@
+package com.ztmap.framework.config;
+
+import java.util.Map;
+import javax.servlet.DispatcherType;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.google.common.collect.Maps;
+import com.ztmap.common.utils.StringUtils;
+import com.ztmap.common.xss.XssFilter;
+
+/**
+ * Filter配置
+ *
+ * @author ztmap
+ */
+@Configuration
+public class FilterConfig
+{
+    @Value("${xss.enabled}")
+    private String enabled;
+
+    @Value("${xss.excludes}")
+    private String excludes;
+
+    @Value("${xss.urlPatterns}")
+    private String urlPatterns;
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Bean
+    public FilterRegistrationBean xssFilterRegistration()
+    {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setDispatcherTypes(DispatcherType.REQUEST);
+        registration.setFilter(new XssFilter());
+        registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
+        registration.setName("xssFilter");
+        registration.setOrder(Integer.MAX_VALUE);
+        Map<String, String> initParameters = Maps.newHashMap();
+        initParameters.put("excludes", excludes);
+        initParameters.put("enabled", enabled);
+        registration.setInitParameters(initParameters);
+        return registration;
+    }
+}

+ 66 - 0
zhny_admin/src/main/java/com/ztmap/framework/config/GenConfig.java

@@ -0,0 +1,66 @@
+package com.ztmap.framework.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 读取代码生成相关配置
+ * 
+ * @author ztmap
+ */
+@Component
+@ConfigurationProperties(prefix = "gen")
+public class GenConfig
+{
+    /** 作者 */
+    public static String author;
+
+    /** 生成包路径 */
+    public static String packageName;
+
+    /** 自动去除表前缀,默认是true */
+    public static boolean autoRemovePre;
+
+    /** 表前缀(类名不会包含表前缀) */
+    public static String tablePrefix;
+
+    public static String getAuthor()
+    {
+        return author;
+    }
+
+    public void setAuthor(String author)
+    {
+        GenConfig.author = author;
+    }
+
+    public static String getPackageName()
+    {
+        return packageName;
+    }
+
+    public void setPackageName(String packageName)
+    {
+        GenConfig.packageName = packageName;
+    }
+
+    public static boolean getAutoRemovePre()
+    {
+        return autoRemovePre;
+    }
+
+    public void setAutoRemovePre(boolean autoRemovePre)
+    {
+        GenConfig.autoRemovePre = autoRemovePre;
+    }
+
+    public static String getTablePrefix()
+    {
+        return tablePrefix;
+    }
+
+    public void setTablePrefix(String tablePrefix)
+    {
+        GenConfig.tablePrefix = tablePrefix;
+    }
+}

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно