Browse Source

first commit

hexiao 2 years ago
commit
f969a8da8c
100 changed files with 9560 additions and 0 deletions
  1. 8 0
      .idea/.gitignore
  2. 9 0
      .idea/DC-SERVER.iml
  3. 8 0
      .idea/modules.xml
  4. 6 0
      .idea/vcs.xml
  5. 31 0
      da/.classpath
  6. 4 0
      da/.gitignore
  7. 273 0
      da/pom.xml
  8. 28 0
      da/src/main/java/com/datau/da/DaApplication.java
  9. 21 0
      da/src/main/java/com/datau/da/config/DruidDataSourceConfiguration.java
  10. 47 0
      da/src/main/java/com/datau/da/config/SwaggerConfig.java
  11. 64 0
      da/src/main/java/com/datau/da/constant/Constant.java
  12. 272 0
      da/src/main/java/com/datau/da/constant/StatusCode.java
  13. 212 0
      da/src/main/java/com/datau/da/controller/DataQualityController.java
  14. 262 0
      da/src/main/java/com/datau/da/controller/TaskController.java
  15. 15 0
      da/src/main/java/com/datau/da/dao/DataQualityDao.java
  16. 56 0
      da/src/main/java/com/datau/da/dao/TaskDao.java
  17. 71 0
      da/src/main/java/com/datau/da/entity/PageParams.java
  18. 106 0
      da/src/main/java/com/datau/da/entity/ReturnData.java
  19. 48 0
      da/src/main/java/com/datau/da/entity/dataquality/ListDataDTO.java
  20. 35 0
      da/src/main/java/com/datau/da/entity/dataquality/QuerySqlDTO.java
  21. 69 0
      da/src/main/java/com/datau/da/entity/dataquality/UpdateDataDTO.java
  22. 85 0
      da/src/main/java/com/datau/da/entity/mail/ErrorJobInfo.java
  23. 99 0
      da/src/main/java/com/datau/da/entity/mail/MailBean.java
  24. 30 0
      da/src/main/java/com/datau/da/entity/model/JobParseEvent.java
  25. 29 0
      da/src/main/java/com/datau/da/entity/model/ScheduleRoundEvent.java
  26. 151 0
      da/src/main/java/com/datau/da/entity/remotedb/MdmCreateTableDTO.java
  27. 195 0
      da/src/main/java/com/datau/da/entity/remotedb/MdmInfoColumn.java
  28. 188 0
      da/src/main/java/com/datau/da/entity/remotedb/MdmInfoDatabase.java
  29. 156 0
      da/src/main/java/com/datau/da/entity/remotedb/MdmInfoTable.java
  30. 43 0
      da/src/main/java/com/datau/da/entity/task/JobOperateCmd.java
  31. 34 0
      da/src/main/java/com/datau/da/entity/task/JobScheduleTime.java
  32. 236 0
      da/src/main/java/com/datau/da/entity/task/Task.java
  33. 20 0
      da/src/main/java/com/datau/da/entity/token/Header.java
  34. 99 0
      da/src/main/java/com/datau/da/entity/token/Payload.java
  35. 38 0
      da/src/main/java/com/datau/da/entity/token/Token.java
  36. 75 0
      da/src/main/java/com/datau/da/feign/AccountApi.java
  37. 68 0
      da/src/main/java/com/datau/da/feign/DaMdmFeign.java
  38. 35 0
      da/src/main/java/com/datau/da/handler/ScheduleRoundEventHandler.java
  39. 51 0
      da/src/main/java/com/datau/da/handler/ScheduleRoundExceptionHandler.java
  40. 47 0
      da/src/main/java/com/datau/da/job/JobServer.java
  41. 67 0
      da/src/main/java/com/datau/da/job/TestDemo.java
  42. 34 0
      da/src/main/java/com/datau/da/job/TestHandler.java
  43. 89 0
      da/src/main/java/com/datau/da/service/DataQualityService.java
  44. 497 0
      da/src/main/java/com/datau/da/service/impl/DataQualityServiceImpl.java
  45. 19 0
      da/src/main/java/com/datau/da/service/job/JobPutService.java
  46. 11 0
      da/src/main/java/com/datau/da/service/job/JobService.java
  47. 13 0
      da/src/main/java/com/datau/da/service/job/ScheDisruptInitService.java
  48. 21 0
      da/src/main/java/com/datau/da/service/job/ScheduleJobContainerManagerService.java
  49. 57 0
      da/src/main/java/com/datau/da/service/job/TimeTriggerJobListener.java
  50. 103 0
      da/src/main/java/com/datau/da/service/job/impl/FrequencyTriggerJob.java
  51. 217 0
      da/src/main/java/com/datau/da/service/job/impl/JobPutServiceImpl.java
  52. 62 0
      da/src/main/java/com/datau/da/service/job/impl/JobServiceImpl.java
  53. 48 0
      da/src/main/java/com/datau/da/service/job/impl/ScheDisruptInitServiceImpl.java
  54. 52 0
      da/src/main/java/com/datau/da/service/job/impl/ScheduleJobContainerManagerServiceImpl.java
  55. 260 0
      da/src/main/java/com/datau/da/service/job/impl/SchedulerTimeTriggeJob.java
  56. 82 0
      da/src/main/java/com/datau/da/service/job/impl/TimeTriggerJob.java
  57. 653 0
      da/src/main/java/com/datau/da/service/job/impl/TriggerJob.java
  58. 43 0
      da/src/main/java/com/datau/da/service/task/TaskService.java
  59. 247 0
      da/src/main/java/com/datau/da/service/task/impl/TaskServiceImpl.java
  60. 99 0
      da/src/main/java/com/datau/da/utils/AesUtil.java
  61. 55 0
      da/src/main/java/com/datau/da/utils/CommonConfUtil.java
  62. 56 0
      da/src/main/java/com/datau/da/utils/ConnectionUtil.java
  63. 179 0
      da/src/main/java/com/datau/da/utils/CronExpresUtil.java
  64. 93 0
      da/src/main/java/com/datau/da/utils/DateUtil.java
  65. 18 0
      da/src/main/java/com/datau/da/utils/FileTool.java
  66. 389 0
      da/src/main/java/com/datau/da/utils/FtpUtils.java
  67. 20 0
      da/src/main/java/com/datau/da/utils/JsonUtil.java
  68. 406 0
      da/src/main/java/com/datau/da/utils/ParamUtil.java
  69. 187 0
      da/src/main/java/com/datau/da/utils/R.java
  70. 93 0
      da/src/main/java/com/datau/da/utils/ReturnUtil.java
  71. 84 0
      da/src/main/java/com/datau/da/utils/S.java
  72. 300 0
      da/src/main/java/com/datau/da/utils/ThreadPoolUtil.java
  73. 33 0
      da/src/main/java/com/datau/da/utils/TokenUtil.java
  74. 71 0
      da/src/main/java/com/datau/da/utils/ftp/FtpClientFactory.java
  75. 51 0
      da/src/main/java/com/datau/da/utils/ftp/FtpClientPool.java
  76. 108 0
      da/src/main/java/com/datau/da/utils/ftp/FtpConfiguration.java
  77. 48 0
      da/src/main/java/com/datau/da/utils/mail/MailUtil.java
  78. 96 0
      da/src/main/java/com/datau/da/utils/mail/SendMailUtil.java
  79. 27 0
      da/src/main/resources/CommonConfig.properties
  80. 88 0
      da/src/main/resources/application.yml
  81. 19 0
      da/src/main/resources/bootstrap.yml
  82. 42 0
      da/src/main/resources/logback-spring.xml
  83. 204 0
      da/src/main/resources/mapper/TaskMapper.xml
  84. 18 0
      da/src/main/resources/sql/数据采集出错信息统计功能提测.sql
  85. 84 0
      da/src/main/resources/sql/数据采集提测.sql
  86. 8 0
      dc-account/.idea/.gitignore
  87. 11 0
      dc-account/.idea/misc.xml
  88. 6 0
      dc-account/.idea/vcs.xml
  89. BIN
      dc-account/.mvn/wrapper/maven-wrapper.jar
  90. 1 0
      dc-account/.mvn/wrapper/maven-wrapper.properties
  91. 3 0
      dc-account/WebContent/META-INF/MANIFEST.MF
  92. 225 0
      dc-account/mvnw
  93. 143 0
      dc-account/mvnw.cmd
  94. 159 0
      dc-account/pom.xml
  95. 33 0
      dc-account/src/main/java/com/datau/account/AccountApplication.java
  96. 90 0
      dc-account/src/main/java/com/datau/account/api/AccountInfoAPI.java
  97. 20 0
      dc-account/src/main/java/com/datau/account/config/DruidDataSourceConfiguration.java
  98. 51 0
      dc-account/src/main/java/com/datau/account/config/KaptchaProducer.java
  99. 43 0
      dc-account/src/main/java/com/datau/account/config/SwaggerConfig.java
  100. 0 0
      dc-account/src/main/java/com/datau/account/controller/AccountInfoController.java

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/../../../../../:\workspace\报表系统src\DC-SERVER\.idea/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/

+ 9 - 0
.idea/DC-SERVER.iml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/DC-SERVER.iml" filepath="$PROJECT_DIR$/.idea/DC-SERVER.iml" />
+    </modules>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>

+ 31 - 0
da/.classpath

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk1.8.0_144">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

+ 4 - 0
da/.gitignore

@@ -0,0 +1,4 @@
+.idea/
+*.iml
+logs/
+target/

+ 273 - 0
da/pom.xml

@@ -0,0 +1,273 @@
+<?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.datau</groupId>
+	<artifactId>da</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
+	<packaging>jar</packaging>
+	<name>da</name>
+	<description>Demo project for Spring Boot</description>
+
+	<parent>
+		<groupId>org.springframework.boot</groupId>
+		<artifactId>spring-boot-starter-parent</artifactId>
+		<version>2.0.1.RELEASE</version>
+		<relativePath /> <!-- lookup parent from repository -->
+	</parent>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+		<java.version>1.8</java.version>
+		<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-actuator</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-redis</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
+		</dependency>
+		<!-- <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> 
+			</dependency> -->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-openfeign</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.mybatis.spring.boot</groupId>
+			<artifactId>mybatis-spring-boot-starter</artifactId>
+			<version>1.3.2</version>
+		</dependency>
+
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<scope>compile</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>druid</artifactId>
+			<version>1.1.9</version>
+		</dependency>
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>fastjson</artifactId>
+			<version>1.2.12</version>
+		</dependency>
+		<dependency>
+			<groupId>com.auth0</groupId>
+			<artifactId>java-jwt</artifactId>
+			<version>3.1.0</version>
+		</dependency>
+		<dependency>
+			<groupId>io.jsonwebtoken</groupId>
+			<artifactId>jjwt</artifactId>
+			<version>0.6.0</version>
+		</dependency>
+		<dependency>
+			<groupId>com.github.pagehelper</groupId>
+			<artifactId>pagehelper-spring-boot-starter</artifactId>
+			<version>1.2.5</version>
+		</dependency>
+		<dependency>
+			<groupId>io.springfox</groupId>
+			<artifactId>springfox-swagger2</artifactId>
+			<version>2.7.0</version>
+		</dependency>
+		<dependency>
+			<groupId>io.springfox</groupId>
+			<artifactId>springfox-swagger-ui</artifactId>
+			<version>2.7.0</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-pool2</artifactId>
+			<version>2.4.2</version>
+		</dependency>
+
+		<dependency>
+			<groupId>commons-net</groupId>
+			<artifactId>commons-net</artifactId>
+			<version>3.6</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi</artifactId>
+			<version>3.9</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi-ooxml-schemas</artifactId>
+			<version>3.9</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi-ooxml</artifactId>
+			<version>3.9</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi-scratchpad</artifactId>
+			<version>3.9</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-io</groupId>
+			<artifactId>commons-io</artifactId>
+			<version>2.6</version>
+		</dependency>
+		<dependency>
+			<groupId>com.jcraft</groupId>
+			<artifactId>jsch</artifactId>
+			<version>0.1.54</version>
+		</dependency>
+		<dependency>
+			<groupId>org.bouncycastle</groupId>
+			<artifactId>bcprov-jdk16</artifactId>
+			<version>1.46</version>
+		</dependency>
+		<!-- <dependency> -->
+		<!-- <groupId>org.apache.hive</groupId> -->
+		<!-- <artifactId>hive-jdbc</artifactId> -->
+		<!-- <version>1.2.0</version> -->
+		<!-- </dependency> -->
+		<!-- <dependency> -->
+		<!-- <groupId>org.apache.hadoop</groupId> -->
+		<!-- <artifactId>hadoop-client</artifactId> -->
+		<!-- <version>2.7.3</version> -->
+		<!-- </dependency> -->
+
+
+		<dependency>
+			<groupId>jdk.tools</groupId>
+			<artifactId>jdk.tools</artifactId>
+			<version>1.8</version>
+			<scope>system</scope>
+			<systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
+		</dependency>
+
+
+		<dependency>
+			<groupId>org.apache.hadoop</groupId>
+			<artifactId>hadoop-hdfs</artifactId>
+			<version>2.6.4</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.hadoop</groupId>
+			<artifactId>hadoop-common</artifactId>
+			<version>2.6.4</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.hive</groupId>
+			<artifactId>hive-exec</artifactId>
+			<version>1.1.0</version>
+			<exclusions>
+				<exclusion>
+					<artifactId>
+                        pentaho-aggdesigner-algorithm
+                    </artifactId>
+					<groupId>org.pentaho</groupId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.hive</groupId>
+			<artifactId>hive-jdbc</artifactId>
+			<version>1.1.0</version>
+		</dependency>
+		<!-- <dependency> <groupId>org.eclipse.jetty.aggregate</groupId> <artifactId>jetty-all</artifactId> 
+			<version>9.2.19.v20160908</version> </dependency> -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-configuration-processor</artifactId>
+			<optional>true</optional>
+		</dependency>
+
+		<dependency>
+			<groupId>org.quartz-scheduler</groupId>
+			<artifactId>quartz</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.quartz-scheduler</groupId>
+			<artifactId>quartz-jobs</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>com.lmax</groupId>
+			<artifactId>disruptor</artifactId>
+			<version>3.3.0</version>
+		</dependency>
+	</dependencies>
+
+	<dependencyManagement>
+		<dependencies>
+			<dependency>
+				<groupId>org.springframework.cloud</groupId>
+				<artifactId>spring-cloud-dependencies</artifactId>
+				<version>${spring-cloud.version}</version>
+				<type>pom</type>
+				<scope>import</scope>
+			</dependency>
+		</dependencies>
+	</dependencyManagement>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+			</plugin>
+			<!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> 
+				<configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> 
+				</plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> 
+				<executions> <execution> <id>make-a-jar</id> <phase>compile</phase> <goals> 
+				<goal>jar</goal> </goals> </execution> </executions> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> 
+				</configuration> </plugin> -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-surefire-plugin</artifactId>
+				<configuration>
+					<testFailureIgnore>true</testFailureIgnore>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+	<repositories>
+		<repository>
+			<id>spring-milestones</id>
+			<name>Spring Milestones</name>
+			<url>https://repo.spring.io/milestone</url>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+	</repositories>
+
+
+</project>

+ 28 - 0
da/src/main/java/com/datau/da/DaApplication.java

@@ -0,0 +1,28 @@
+package com.datau.da;
+
+import com.datau.da.job.JobServer;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.Bean;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@MapperScan("com.datau.da.dao")
+@EnableSwagger2
+@EnableEurekaClient
+@EnableFeignClients
+@SpringBootApplication
+public class DaApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(DaApplication.class, args);
+	}
+
+	@Bean
+	public JobServer jobServer(){//启动调度服务
+		return new JobServer();
+	}
+
+}

+ 21 - 0
da/src/main/java/com/datau/da/config/DruidDataSourceConfiguration.java

@@ -0,0 +1,21 @@
+package com.datau.da.config;
+
+import javax.sql.DataSource;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.alibaba.druid.pool.DruidDataSource;
+
+@Configuration  
+public class DruidDataSourceConfiguration {  
+  
+    @Bean  
+    @ConfigurationProperties(prefix = "spring.datasource")  
+    public DataSource ontDruidDataSource() {  
+        DruidDataSource druidDataSource = new DruidDataSource(); 
+        return druidDataSource;
+    }  
+    
+}  

+ 47 - 0
da/src/main/java/com/datau/da/config/SwaggerConfig.java

@@ -0,0 +1,47 @@
+package com.datau.da.config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.bind.annotation.RestController;
+
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.ParameterBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.schema.ModelRef;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Parameter;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+
+@Configuration
+public class SwaggerConfig {
+	@Bean
+	public Docket api() {
+		return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
+				// 自行修改为自己的包路径
+				.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class)).paths(PathSelectors.any())
+				.build().pathMapping("/").globalOperationParameters(setHeaderToken());
+	}
+
+	private ApiInfo apiInfo() {
+		return new ApiInfoBuilder().title("api文档").description("数据中心->任务调度接口")
+				// 服务条款网址
+				// .termsOfServiceUrl("http://blog.csdn.net/forezp")
+				.version("1.0")
+				// .contact(new Contact("帅呆了", "url", "email"))
+				.build();
+	}
+
+	private List<Parameter> setHeaderToken() {
+		ParameterBuilder tokenPar = new ParameterBuilder();
+		List<Parameter> pars = new ArrayList<>();
+		tokenPar.name("token").description("token").modelRef(new ModelRef("string")).parameterType("header")
+				.required(false).build();
+		pars.add(tokenPar.build());
+		return pars;
+	}
+}

+ 64 - 0
da/src/main/java/com/datau/da/constant/Constant.java

@@ -0,0 +1,64 @@
+package com.datau.da.constant;
+
+/**
+ * @author 许明
+ * on 2019/3/6.
+ * @version 2.0.0
+ * 常量类
+ */
+public class Constant {
+
+    /************* 返回结果值 ***************/
+    public final static int RETURN_FAILD = -1;
+    public final static int RETURN_OK = 0;
+
+    /******** job周期类型 **********/
+    public final static int JOB_PERIOD_CUSTOM  = 0;// 自定义
+    public final static int JOB_PERIOD_MONTH = 1;// 月
+    public final static int JOB_PERIOD_DAY = 2;// 日
+    public final static int JOB_PERIOD_HOUR = 3;// 时
+    public final static int JOB_PERIOD_MINUTE = 4;// 分
+    public final static int JOB_PERIOD_SECONDS = 5;// 秒
+    public final static int JOB_PERIOD_WEEK = 6;// 周
+
+
+    public final static int JOB_PERIOD_YEAR = 8;// 年
+
+    /************* 后台线程池名称 ***************/
+    public final static String MODULE_MANGER_RESIDENT = "MangerResidentPool";// 后台管理进程常驻任务线程池
+    public final static String MODULE_MANGER_TMP = "MangerTmpPool";// 后台管理进程临时任务线程池(执行完成退出)
+    public final static String MODULE_MANGER_TIMING = "MangerTimingPool";// 后台管理进程定时任务总线程池
+    public final static int MODULE_MANAGER_TIMMING_NUM = 2;// 后台管理进程定时任务总线程池执行个数*CPU
+    public final static String MODULE_SCHEDULE_TIMING = "ScheduleTimingPool";// 后台调度进程定时任务总线程池
+    public final static int MODULE_SCHEDULE_TIMING_NUM = 2;// 后台调度进程定时任务总线程池执行个数*CPU
+    public final static String MODULE_JOB_LOG_TO_HIS = "JobLogToHis";// 日志转移历史表
+
+    public final static int SCHEDU_JOBCONDITION_JUDGE_NUM = 4;// 调度轮询条件判断线程数
+    public final static int SCHEDU_JOBPARSE_NUM = 4;// 调度job解析线程数
+    public final static int SCHEDU_NODE_EXEJUDGE_NUM = 4;// job任务可执行判断线程数
+
+    public final static long THREAD_SCANJOB_INTERVAL = 24 * 3600000L;// 一天
+
+    /******* job不进入轮询原因 ***********/
+    public final static int JOB_LOOP_OVERTIME = 1;// job结束时间超过当前时间不进行轮询
+    public final static int JOB_CONF_ERROR = 2;// job信息配置错误
+    public final static int JOB_PERIOD_RUN = 3;// 周期类型的job正在执行
+    public final static int JOB_RUN_ERROR = 4;// job执行node出错
+
+    public final static String FORMAT_MONTH = "yyyyMM";
+    public final static String FORMAT_WEEK = "yyyyMMdd";
+    public final static String FORMAT_DAY = "yyyyMMdd";
+    public final static String FORMAT_HOUR = "yyyyMMddHH";
+    public final static String FORMAT_MINUTE = "yyyyMMddHHmm";
+    public final static String FORMAT_SECONDS = "yyyyMMddHHmmss";
+    public final static String FORMAT_DATE = "HHmmss";
+
+    public final static String RE_FORMAT_YEAR = "yyyy";
+    public final static String RE_FORMAT_MONTH = "yyyy-MM";
+    public final static String RE_FORMAT_WEEK = "yyyy-MM-dd";
+    public final static String RE_FORMAT_DAY = "yyyy-MM-dd";
+    public final static String RE_FORMAT_HOUR = "yyyy-MM-dd HH";
+    public final static String RE_FORMAT_MINUTE = "yyyy-MM-dd HH:mm";
+    public final static String RE_FORMAT_SECONDS = "yyyy-MM-dd HH:mm:ss";
+    public final static String RE_FORMAT_DATE = "HH:mm:ss";
+}

+ 272 - 0
da/src/main/java/com/datau/da/constant/StatusCode.java

@@ -0,0 +1,272 @@
+package com.datau.da.constant;
+
+import com.datau.da.entity.ReturnData;
+
+import java.util.HashMap;
+
+/**
+ * @author 许明
+ * @version 1.0.0 创建于 2019/3/5
+ **/
+public final class StatusCode {
+
+    /**
+     * 请求成功
+     */
+    public static final String SUCCESS = "1";
+    /**
+     * 请求失败
+     */
+    public static final String FAILURE = "-1";
+
+
+    ///////////////////////////////////////获取呼叫的录音状态码//////////////////////////////////////////
+    /*
+     0    录音地址尚未生成,查询不到                 ------>      100000
+    -1    传入参数不合法                           ------>      100001
+    -2    错误的企业ID                             ------>      100002
+    -3    错误的坐席工号                           ------>      100003
+    -4    错误的坐席密码                           ------>      100004
+    -5    没有查到适合条件的记录                    ------>      100005
+    -7    企业尚未配置RecordFTPServer配置项        ------>      100007
+    -8    查询录音文件地址异常                     ------>      100008
+     */
+    /**
+     * 录音地址尚未生成,查询不到
+     */
+    public static final String AUDIO_ADRESS_NOT_EXIST = "100000";
+    /**
+     * 传入参数不合法
+     */
+    public static final String AUDIO_PARAMS_ERROR = "100001";
+    /**
+     * 错误的企业ID
+     */
+    public static final String AUDIO_ENTID_ERROR = "100002";
+    /**
+     * 错误的坐席工号
+     */
+    public static final String AUDIO_AGENTID_ERROR = "100003";
+    /**
+     * 错误的坐席密码
+     */
+    public static final String AUDIO_PASSWD_ERROR = "100004";
+    /**
+     * 没有查到适合条件的记录
+     */
+    public static final String AUDIO_NO_DATA = "100005";
+    /**
+     * 企业尚未配置RecordFTPServer配置项
+     */
+    public static final String AUDIO_NO_FTP_CONFIG = "100007";
+    /**
+     * 查询录音文件地址异常
+     */
+    public static final String AUDIO_ADDRESS_ERROR = "100008";
+
+    /**
+     * 还未生成话单
+     */
+    public static final String BILL_NOT_EXIST = "100009";
+
+
+    /*
+     * 大有外呼平台权限相关的 100101~100121
+     */
+
+    /**
+     * 权限不允许
+     */
+    public static final String NO_AUTH = "100101";
+    /**
+     * 令牌异常
+     */
+    public static final String TOKEN_ERROR = "100102";
+    /**
+     * 令牌配置异常
+     */
+    public static final String TOKEN_EXPIRE_TIME_NULL = "100103";
+    /**
+     * 令牌超时
+     */
+    public static final String TOKEN_EXPIRE_TIMEOUT = "100104";
+    /**
+     * 令牌被篡改
+     */
+    public static final String TOKEN_ALTERED = "100105";
+
+    /*
+     * 校验错误码 100200~100400
+     */
+    /**
+     * 用户名、密码或企业编号错误.
+     */
+    public static final String USER_PASSWD_ENTNO_ERROR = "100200";
+    /**
+     * 用户不存在
+     */
+    public static final String USER_NOT_EXIST = "100201";
+    /**
+     * 用户已登录
+     */
+    public static final String USER_ONLINE = "100207";
+    /**
+     * 用户所属企业失效
+     */
+    public static final String USER_ENT_CLOSE = "100208";
+
+
+    /**
+     * 获取编码信息错误
+     */
+    public static final String GET_CODE_ERROR = "100202";
+    /**
+     * 获取任务详情错误
+     */
+    public static final String GET_TASK_DETAIL_ERROR = "100203";
+
+    /**
+     * 登录信息异常
+     */
+    public static final String USER_INFO_ERROR = "100204";
+    /**
+     * 请求参数错误
+     */
+    public static final String PARAMS_ERROR = "100205";
+    /**
+     * 操作失败,分配的流水号数大于可分配的流水号
+     */
+    public static final String FLOWNO_OVERFLOW_ERROR = "100206";
+    /**
+     * 操作失败,分配的流水号数大于可分配的流水号
+     */
+    public static final String NOT_SORT = "100250";
+
+
+    /**
+     * 企业id已存在
+     */
+    public static final String ENTERPRISE_NO_EXIST = "100251";
+    /**
+     * 部门编号已存在
+     */
+    public static final String DEPT_NO_EXIST = "100252";
+    /**
+     * 用户已存在
+     */
+    public static final String USER_EXIST = "100253";
+    /**
+     * 部门修改冲突
+     */
+    public static final String DEPT_EDIT_COMFLICT = "100254";
+
+    /**
+     * 华云科技认证失败
+     */
+    public static final String HUA_YUN_AUTH_FAILURE = "100255";
+    /**
+     * 坐席信息错误(华云登录信息为空)
+     */
+    public static final String HUA_YUN_LOGIN_INFO_IS_NULL = "100256";
+
+    /**
+     * 流水号错误
+     * (华云md5加密手机号没有对应的真实手机号)
+     */
+    public static final String HUA_YUN_FLOWNO_ERROR = "100257";
+
+
+    /**
+     *
+     */
+    private static final HashMap<String, String> codeMsg = new HashMap<String, String>() {
+        {
+            put(SUCCESS, "请求成功.");
+            put(FAILURE, "请求失败.");
+
+            //获取呼叫的录音状态码
+            put(AUDIO_ADRESS_NOT_EXIST, "录音地址尚未生成,查询不到.");
+            put(AUDIO_PARAMS_ERROR, "传入参数不合法.");
+            put(AUDIO_ENTID_ERROR, "错误的企业ID.");
+            put(AUDIO_AGENTID_ERROR, "错误的坐席工号.");
+            put(AUDIO_PASSWD_ERROR, "错误的坐席密码.");
+            put(AUDIO_NO_DATA, "没有查到适合条件的记录.");
+            put(AUDIO_NO_FTP_CONFIG, "企业尚未配置RecordFTPServer配置项.");
+            put(AUDIO_ADDRESS_ERROR, "查询录音文件地址异常.");
+            /**
+             * 话单
+             */
+            put(BILL_NOT_EXIST, "还未生成话单.");
+            /**
+             * 权限系统状态码
+             */
+            put(NO_AUTH, "权限不允许.");
+            put(TOKEN_ERROR, "令牌异常.");
+            put(TOKEN_EXPIRE_TIME_NULL, "令牌配置异常.");
+            put(TOKEN_EXPIRE_TIMEOUT, "令牌超时.");
+            put(TOKEN_ALTERED, "令牌被篡改.");
+            put(USER_ONLINE, "用户已登录.");
+            put(USER_ENT_CLOSE, "用户所属企业失效.");
+
+            /*
+             * 校验错误码
+             */
+            put(USER_PASSWD_ENTNO_ERROR, "用户名、密码或企业编号错误.");
+            put(USER_NOT_EXIST, "用户不存在.");
+            put(GET_CODE_ERROR, "获取编码信息错误.");
+            put(GET_TASK_DETAIL_ERROR, "获取任务详情错误.");
+            put(USER_INFO_ERROR, "登录信息异常.");
+            put(PARAMS_ERROR, "请求参数错误.");
+            put(FLOWNO_OVERFLOW_ERROR, "操作失败,分配的流水号数大于可分配的流水号.");
+            put(NOT_SORT, "非排序字段");
+            put(ENTERPRISE_NO_EXIST, "企业id已存在");
+            put(DEPT_NO_EXIST, "企业id已存在");
+            put(USER_EXIST, "用户已存在");
+            put(DEPT_EDIT_COMFLICT, "部门修改冲突");
+            /**
+             * 华云科技错误码
+             */
+            put(HUA_YUN_AUTH_FAILURE, "华云科技认证失败");
+            put(HUA_YUN_LOGIN_INFO_IS_NULL, "坐席信息错误");
+            put(HUA_YUN_FLOWNO_ERROR, "流水号错误");
+        }
+
+    };
+
+    public static ReturnData audioApiErrorCode(String code) {
+        switch (code) {
+            case "0":
+                return new ReturnData(AUDIO_ADRESS_NOT_EXIST, getMsg(AUDIO_ADRESS_NOT_EXIST));
+            case "-1":
+                return new ReturnData(AUDIO_PARAMS_ERROR, getMsg(AUDIO_PARAMS_ERROR));
+            case "-2":
+                return new ReturnData(AUDIO_ENTID_ERROR, getMsg(AUDIO_ENTID_ERROR));
+            case "-3":
+                return new ReturnData(AUDIO_AGENTID_ERROR, getMsg(AUDIO_AGENTID_ERROR));
+            case "-4":
+                return new ReturnData(AUDIO_PASSWD_ERROR, getMsg(AUDIO_PASSWD_ERROR));
+            case "-5":
+                return new ReturnData(AUDIO_NO_DATA, getMsg(AUDIO_NO_DATA));
+            case "-7":
+                return new ReturnData(AUDIO_NO_FTP_CONFIG, getMsg(AUDIO_NO_FTP_CONFIG));
+            case "-8":
+                return new ReturnData(AUDIO_ADDRESS_ERROR, getMsg(AUDIO_ADDRESS_ERROR));
+            default:
+                return new ReturnData(FAILURE, getMsg(FAILURE));
+
+        }
+    }
+
+
+    /**
+     * 根据状态码获取提示信息.
+     *
+     * @param code 状态吗
+     * @return 返回状态码对应的提示信息
+     */
+    public static String getMsg(String code) {
+        return codeMsg.get(code);
+    }
+
+
+}

+ 212 - 0
da/src/main/java/com/datau/da/controller/DataQualityController.java

@@ -0,0 +1,212 @@
+package com.datau.da.controller;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.poi.util.IOUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.datau.da.entity.dataquality.ListDataDTO;
+import com.datau.da.entity.dataquality.QuerySqlDTO;
+import com.datau.da.entity.dataquality.UpdateDataDTO;
+import com.datau.da.entity.remotedb.MdmInfoDatabase;
+import com.datau.da.entity.remotedb.MdmInfoTable;
+import com.datau.da.service.DataQualityService;
+import com.datau.da.utils.R;
+import com.datau.da.utils.S;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * @ClassName: DataQualityController
+ * @Description:数据质量相关接口
+ * @author: Zhao You Kai
+ * @date: Apr 3, 2019 2:05:29 PM
+ */
+@Api(value = "数据质量相关接口")
+@RestController
+public class DataQualityController {
+
+	private static final Logger log = LogManager.getLogger(DataQualityController.class);
+
+	@Autowired
+	private DataQualityService dataQualityService;
+
+	// @Autowireod
+	// private AccountApi accountApi;
+
+	@ApiOperation("获取数据库列表--非原始库")
+	@ApiImplicitParams({
+			@ApiImplicitParam(name = "resourceName", value = "数据资源名称(模糊搜索)", required = false, paramType = "query", dataType = "String") })
+	@GetMapping("/da/dataQuality/listDatabase")
+	public R<List<MdmInfoDatabase>> listDatabase(
+			@RequestParam(name = "resourceName", required = false) String resourceName) {
+		try {
+			return dataQualityService.listDatabase(resourceName);
+		} catch (Exception e) {
+			log.error(e.getMessage());
+			e.printStackTrace();
+			return new R<>(S.ERROR);
+		}
+	}
+
+	@ApiOperation("通过数据库ID获取表数据列表")
+	@ApiImplicitParams({
+			@ApiImplicitParam(name = "databaseId", value = "数据库ID", required = true, paramType = "query", dataType = "String") })
+	@GetMapping("/da/dataQuality/listTableByDatabaseId")
+	public R<List<MdmInfoTable>> listTableByDatabaseId(
+			@RequestParam(name = "databaseId", required = true) String databaseId) {
+		try {
+			return dataQualityService.listTableByDatabaseId(databaseId);
+		} catch (Exception e) {
+			log.error(e.getMessage());
+			e.printStackTrace();
+			return new R<>(S.ERROR);
+		}
+	}
+
+	@ApiOperation("通过表ID获取字段信息列表")
+	@ApiImplicitParams({
+			@ApiImplicitParam(name = "tableId", value = "表ID", required = false, paramType = "query", dataType = "String") })
+	@GetMapping("/da/dataQuality/getQuerySql")
+	public R<QuerySqlDTO> getQuerySql(@RequestParam(name = "tableId", required = true) String tableId) {
+		try {
+			return dataQualityService.getQuerySql(tableId);
+		} catch (Exception e) {
+			log.error(e.getMessage());
+			e.printStackTrace();
+			return new R<>(S.ERROR);
+		}
+	}
+
+	@ApiOperation("获取表中数据接口")
+	@ApiImplicitParams({
+			@ApiImplicitParam(name = "tableId", value = "数据表ID", required = true, paramType = "query", dataType = "String"),
+			@ApiImplicitParam(name = "primarySql", value = "主键部分sql", required = true, paramType = "query", dataType = "String"),
+			@ApiImplicitParam(name = "qureySql", value = "查询部分sql", required = true, paramType = "query", dataType = "String"),
+			@ApiImplicitParam(name = "page", value = "当前页数", required = false, paramType = "query", dataType = "Integer"),
+			@ApiImplicitParam(name = "pageSize", value = "每页条数", required = false, paramType = "query", dataType = "Integer") })
+	@GetMapping("/da/dataQuality/listData")
+	public R<ListDataDTO> listData(@RequestParam(name = "tableId", required = true) String tableId,
+			@RequestParam(name = "primarySql", required = true) String primarySql,
+			@RequestParam(name = "qureySql", required = true) String qureySql,
+			@RequestParam(required = false, defaultValue = "1") Integer page,
+			@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
+		try {
+			return dataQualityService.listData(tableId, primarySql + qureySql, page, pageSize);
+		} catch (Exception e) {
+			log.error(e.getMessage());
+			e.printStackTrace();
+			return new R<>(S.ERROR);
+		}
+	}
+
+	@ApiOperation("修改表中数据接口")
+	@PostMapping("/da/dataQuality/updateData")
+	public R<String> updateData(@RequestBody UpdateDataDTO updateData) {
+		try {
+			return dataQualityService.updateData(updateData);
+		} catch (Exception e) {
+			log.error(e.getMessage());
+			e.printStackTrace();
+			return new R<>(S.ERROR);
+		}
+	}
+
+	@ApiOperation("删除表中数据接口")
+	@PostMapping("/da/dataQuality/deleteData")
+	public R<String> deleteData(@RequestBody UpdateDataDTO updateData) {
+		try {
+			return dataQualityService.deleteData(updateData);
+		} catch (Exception e) {
+			log.error(e.getMessage());
+			e.printStackTrace();
+			return new R<>(S.ERROR);
+		}
+	}
+
+	@ApiOperation("下载模板")
+	@ApiImplicitParams({
+			@ApiImplicitParam(name = "tableId", value = "数据表ID", required = true, paramType = "query", dataType = "String"),
+			@ApiImplicitParam(name = "primarySql", value = "主键部分sql", required = true, paramType = "query", dataType = "String"),
+			@ApiImplicitParam(name = "qureySql", value = "查询部分sql", required = true, paramType = "query", dataType = "String"), })
+	@GetMapping("/da/dataQuality/downloadTemplateData")
+	public void downloadTemplateColums(@RequestParam(name = "tableId", required = true) String tableId,
+			@RequestParam(name = "primarySql", required = true) String primarySql,
+			@RequestParam(name = "qureySql", required = true) String qureySql, HttpServletResponse response)
+			throws Exception {
+		InputStream inputStream = null;
+		ServletOutputStream servletOutputStream = null;
+		File f = null;
+		try {
+			// 文件名
+			String fileName = "template-data.xlsx";
+			String filePath = dataQualityService.downloadTemplateData(fileName.substring(0, fileName.lastIndexOf(".")),
+					tableId, primarySql + qureySql);
+			response.setContentType("application/vnd.ms-excel");
+			response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
+			response.addHeader("charset", "utf-8");
+			response.addHeader("Pragma", "no-cache");
+			String encodeName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
+			response.setHeader("Content-Disposition",
+					"attachment; filename=\"" + encodeName + "\"; filename*=utf-8''" + encodeName);
+			f = new File(filePath);
+			inputStream = new FileInputStream(f);
+			servletOutputStream = response.getOutputStream();
+			IOUtils.copy(inputStream, servletOutputStream);
+			response.flushBuffer();
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			try {
+				if (servletOutputStream != null) {
+					servletOutputStream.close();
+					servletOutputStream = null;
+				}
+				if (inputStream != null) {
+					inputStream.close();
+					f.delete();
+					inputStream = null;
+				}
+				// 召唤jvm的垃圾回收器
+				System.gc();
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	@ApiOperation(value = "字段模板上传")
+	@ApiImplicitParams({
+			@ApiImplicitParam(name = "tableId", value = "表Id", required = true, paramType = "form", dataType = "String"),
+			@ApiImplicitParam(name = "file", value = "报表文件", required = true, paramType = "form", dataType = "__file") })
+	@PostMapping(value = "/da/dataQuality/uploadTemplateData", consumes = "multipart/*", headers = "content-type=multipart/form-data")
+	public R<String> loadTemplateData(@RequestParam("file") MultipartFile file,
+			@RequestParam("tableId") String tableId) {
+		try {
+			return dataQualityService.loadTemplateData(tableId, file);
+		} catch (Exception e) {
+			e.printStackTrace();
+			return new R<>(S.ERROR);
+		}
+	}
+
+}

+ 262 - 0
da/src/main/java/com/datau/da/controller/TaskController.java

@@ -0,0 +1,262 @@
+package com.datau.da.controller;
+
+import com.datau.da.entity.PageParams;
+import com.datau.da.entity.ReturnData;
+import com.datau.da.entity.remotedb.MdmInfoColumn;
+import com.datau.da.entity.remotedb.MdmInfoDatabase;
+import com.datau.da.entity.remotedb.MdmInfoTable;
+import com.datau.da.entity.task.JobOperateCmd;
+import com.datau.da.entity.task.Task;
+import com.datau.da.feign.AccountApi;
+import com.datau.da.service.task.TaskService;
+import com.datau.da.utils.ReturnUtil;
+import com.github.pagehelper.Page;
+import io.swagger.annotations.*;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+@Api(value = "任务管理相关接口", description = "任务管理相关接口")
+@RestController
+public class TaskController {
+
+    private static final Logger logger = LogManager.getLogger(TaskController.class);
+
+    @Autowired
+    private TaskService taskService;
+
+    @Autowired
+    private AccountApi accountApi;
+
+    @ApiOperation(value = "数据中心-->数据采集-->新增采集任务", notes = "数据中心-->数据采集-->新增采集任务")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "token", value = "放在请求头中的令牌", dataType = "String", paramType = "header", required = true),
+    })
+    @PostMapping(value = "/task/add", produces = "application/json;charset=UTF-8", consumes = "application/json;charset=UTF-8")
+    public ReturnData addTask(@RequestHeader(name = "token", required = true) String token,
+                              @RequestBody @ApiParam Task task) {
+        ReturnData returnData = new ReturnData();
+        String userId = "";
+        try {
+            userId = accountApi.parseTokenId(token);
+        } catch (Exception e) {
+            logger.error("解析令牌错误:" + e.getMessage());
+            return ReturnUtil.createExceptionReturn(e);
+        }
+        try {
+            task.setUserId(userId);
+            taskService.addTask(task);
+            returnData.setMsg("新增成功");
+            return returnData;
+        } catch (Exception e) {
+            logger.error("新增任务失败,信息为:" + e.getMessage());
+            returnData.setCode("-1");
+            returnData.setMsg(e.getMessage());
+            return returnData;
+        }
+    }
+
+    @ApiOperation(value = "数据中心-->数据采集-->获取当前任务列表", notes = "数据中心-->数据采集-->获取当前任务列表")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "taskName", value = "任务名称", dataType = "String", paramType = "query", required = false),
+    })
+    @GetMapping(value = "/task/list", produces = "application/json;charset=UTF-8")
+    public ReturnData<List<Task>> listTask(@RequestParam(name = "taskName", required = false) String taskName,
+                                           @RequestParam(name = "page", required = false, defaultValue = "1") Integer page,
+                                           @RequestParam(name = "pageSize", required = false, defaultValue = "10") Integer pageSize,
+                                           @RequestParam(name = "sort", required = false, defaultValue = "createTime") String sort,
+                                           @RequestParam(name = "order", required = false, defaultValue = "desc") String order) {
+        try {
+            PageParams<Task> pageParams = new PageParams<>();
+            Task task = new Task();
+            task.setTaskName(taskName);
+            pageParams.setData(task);
+            pageParams.setPage(page);
+            pageParams.setPageSize(pageSize);
+            pageParams.setSort(sort);
+            pageParams.setOrder(order);
+            Page<Task> pageResult = taskService.listTask(pageParams);
+            return ReturnUtil.assemblyReturnData(pageResult);
+        } catch (Exception e) {
+            return ReturnUtil.createExceptionReturn(e);
+        }
+    }
+
+    @ApiOperation(value = "数据中心-->数据采集-->获取指定任务信息(回显)", notes = "数据中心-->数据采集-->获取指定任务信息(回显)")
+    @GetMapping(value = "/task/toEdit/{id}", produces = "application/json;charset=UTF-8")
+    public ReturnData<Task> getTaskById(@PathVariable(name = "id") String id) {
+        ReturnData<Task> returnData = new ReturnData();
+        try {
+            Task task = taskService.getTaskInfoById(id);
+            returnData.setData(task);
+            return returnData;
+        } catch (Exception e) {
+            logger.error("获取指定任务信息失败,信息为:" + e.getMessage());
+            returnData.setCode("-1");
+            returnData.setMsg(e.getMessage());
+            return returnData;
+        }
+    }
+
+    @ApiOperation(value = "数据中心-->数据采集-->更新任务", notes = "数据中心-->数据采集-->更新任务")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "token", value = "放在请求头中的令牌", dataType = "String", paramType = "header", required = true),
+    })
+    @PutMapping(value = "/task/update/{id}", produces = "application/json;charset=UTF-8", consumes = "application/json;charset=UTF-8")
+    public ReturnData addTask(@RequestHeader(name = "token", required = true) String token,
+                              @PathVariable(name = "id") String id,
+                              @RequestBody @ApiParam Task task) {
+        ReturnData returnData = new ReturnData();
+        String userId = "";
+        try {
+        	userId = accountApi.parseTokenId(token);
+        } catch (Exception e) {
+            logger.error("解析令牌异常!");
+            return ReturnUtil.createExceptionReturn(e);
+        }
+        try {
+            task.setUserId(userId);
+            taskService.updateTaskById(task);
+            returnData.setMsg("更新成功");
+            return returnData;
+        } catch (Exception e) {
+            logger.error("更新任务失败,信息为:" + e.getMessage());
+            returnData.setCode("-1");
+            returnData.setMsg(e.getMessage());
+            return returnData;
+        }
+    }
+    
+    @ApiOperation(value = "数据中心-->数据采集-->删除指定任务信息", notes = "数据中心-->数据采集-->删除指定任务信息")
+    @DeleteMapping(value = "/task/toDel/{id}", produces = "application/json;charset=UTF-8")
+    public ReturnData deleteTaskById(@PathVariable(name = "id") String id) {
+        ReturnData returnData = new ReturnData();
+        try {
+            taskService.deleteTaskById(id);
+            returnData.setMsg("删除成功");
+            return returnData;
+        } catch (Exception e) {
+            logger.error("删除指定任务信息失败,信息为:" + e.getMessage());
+            returnData.setCode("-1");
+            returnData.setMsg(e.getMessage());
+            return returnData;
+        }
+    }
+
+    @ApiOperation(value = "数据中心-->数据采集-->启停任务,立即执行任务", notes = "数据中心-->数据采集-->启停任务,立即执行任务")
+    @PutMapping(value = "/task/operate/{id}", produces = "application/json;charset=UTF-8", consumes = "application/json;charset=UTF-8")
+    public ReturnData operateTask(@PathVariable(name = "id") String id,
+                                  @RequestBody @ApiParam JobOperateCmd jobOperateCmd) {
+        ReturnData returnData = new ReturnData();
+        try {
+            returnData = taskService.operateTask(jobOperateCmd);
+            return returnData;
+        } catch (Exception e) {
+            logger.error("操作失败,信息为:" + e.getMessage());
+            returnData.setCode("-1");
+            returnData.setMsg(e.getMessage());
+            return returnData;
+        }
+    }
+
+    @ApiOperation(value = "数据中心-->数据采集-->获取当前数据库连接信息", notes = "数据中心-->数据采集-->获取当前库数据库连接信息")
+    @GetMapping(value = "/task/list/database/{id}", produces = "application/json;charset=UTF-8")
+    public ReturnData<MdmInfoDatabase> database(@PathVariable(name = "id", required = true) String id) {
+        ReturnData<MdmInfoDatabase> returnData = new ReturnData();
+        try {
+            MdmInfoDatabase mdmInfoDatabase = taskService.database(id);
+            returnData.setData(mdmInfoDatabase);
+            return returnData;
+        } catch (Exception e) {
+            logger.error("获取当前数据库连接信息异常,信息为:" + e.getMessage());
+            returnData.setCode("-1");
+            returnData.setMsg(e.getMessage());
+            return returnData;
+        }
+    }
+
+    @ApiOperation(value = "数据中心-->数据采集-->获取当前数据库中所有表", notes = "数据中心-->数据采集-->获取当前数据库中所有表")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "databaseId", value = "数据库id", dataType = "String", paramType = "query", required = true),
+    })
+    @GetMapping(value = "/task/list/listTableByDatabaseId", produces = "application/json;charset=UTF-8")
+    public ReturnData<List<MdmInfoTable>> listTableByDatabaseId(@RequestParam(name = "databaseId", required = true) String databaseId) {
+        ReturnData<List<MdmInfoTable>> returnData = new ReturnData();
+        try {
+            List<MdmInfoTable> mdmInfoTableList = taskService.listTableByDatabaseId(databaseId);
+            returnData.setData(mdmInfoTableList);
+            return returnData;
+        } catch (Exception e) {
+            logger.error("获取当前数据库中所有表异常,信息为:" + e.getMessage());
+            returnData.setCode("-1");
+            returnData.setMsg(e.getMessage());
+            return returnData;
+        }
+    }
+
+    @ApiOperation(value = "数据中心-->数据采集-->获取源库数据库列表", notes = "数据中心-->数据采集-->获取源库数据库列表")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "resourceName", value = "数据库id", dataType = "String", paramType = "query", required = false),
+    })
+    @GetMapping(value = "/task/list/listOriginal", produces = "application/json;charset=UTF-8")
+    public ReturnData<List<MdmInfoDatabase>> listOriginal(@RequestParam(name = "resourceName", required = false) String resourceName) {
+        ReturnData<List<MdmInfoDatabase>> returnData = new ReturnData();
+        try {
+            List<MdmInfoDatabase> mdmInfoDatabaseList = taskService.listOriginal(resourceName);
+            returnData.setData(mdmInfoDatabaseList);
+            return returnData;
+        } catch (Exception e) {
+            logger.error("获取源库数据库列表异常,信息为:" + e.getMessage());
+            returnData.setCode("-1");
+            returnData.setMsg(e.getMessage());
+            return returnData;
+        }
+    }
+
+    @ApiOperation(value = "数据中心-->数据采集-->获取目标库数据库列表", notes = "数据中心-->数据采集-->获取目标库数据库列表")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "resourceName", value = "数据库id", dataType = "String", paramType = "query", required = false),
+    })
+    @GetMapping(value = "/task/list/listDatabase", produces = "application/json;charset=UTF-8")
+    public ReturnData<List<MdmInfoDatabase>> listDatabase(@RequestParam(name = "resourceName", required = false) String resourceName) {
+        ReturnData<List<MdmInfoDatabase>> returnData = new ReturnData();
+        try {
+            List<MdmInfoDatabase> mdmInfoDatabaseList = taskService.listDatabase(resourceName);
+            returnData.setData(mdmInfoDatabaseList);
+            return returnData;
+        } catch (Exception e) {
+            logger.error("获取目标库数据库列表异常,信息为:" + e.getMessage());
+            returnData.setCode("-1");
+            returnData.setMsg(e.getMessage());
+            return returnData;
+        }
+    }
+
+    @ApiOperation(value = "数据中心-->数据采集-->获取当前库当前表的所有字段信息", notes = "数据中心-->数据采集-->获取当前库当前表的所有字段信息")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "tableId", value = "数据库id", dataType = "String", paramType = "query", required = false),
+    })
+    @GetMapping(value = "/task/list/listColumnByTableId", produces = "application/json;charset=UTF-8")
+    public ReturnData<List<MdmInfoColumn>> listColumnByTableId(@RequestParam(name = "tableId", required = false) String tableId) {
+        ReturnData<List<MdmInfoColumn>> returnData = new ReturnData();
+        try {
+            List<MdmInfoColumn> mdmInfoColumnList = taskService.listColumnByTableId(tableId);
+            returnData.setData(mdmInfoColumnList);
+            return returnData;
+        } catch (Exception e) {
+            logger.error("获取当前库当前表的所有字段信息异常,信息为:" + e.getMessage());
+            returnData.setCode("-1");
+            returnData.setMsg(e.getMessage());
+            return returnData;
+        }
+    }
+
+}

+ 15 - 0
da/src/main/java/com/datau/da/dao/DataQualityDao.java

@@ -0,0 +1,15 @@
+package com.datau.da.dao;
+
+import org.springframework.stereotype.Repository;
+
+/**
+ * 
+ * @ClassName: DataQualityDao
+ * @Description:
+ * @author: Zhao You Kai
+ * @date: Apr 3, 2019 2:32:21 PM
+ */
+@Repository
+public interface DataQualityDao {
+
+}

+ 56 - 0
da/src/main/java/com/datau/da/dao/TaskDao.java

@@ -0,0 +1,56 @@
+package com.datau.da.dao;
+
+import com.datau.da.entity.PageParams;
+import com.datau.da.entity.mail.ErrorJobInfo;
+import com.datau.da.entity.task.Task;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+@Repository
+public interface TaskDao {
+
+    void addTask(Task task);
+
+    void deleteTaskById(@Param("taskId") String taskId);
+
+    Task getTaskInfoById(@Param("taskId") String taskId);
+
+    int updateTaskById(Task task);
+
+    int updateTaskStatusById(@Param("id") String id, @Param("taskStatus") String taskStatus, @Param("nextRunDate") String nextRunDate);
+
+    int updateTaskRunStatusById(@Param("id") String id, @Param("runStatus") String taskStatus, @Param("nextRunDate") String nextRunDate);
+
+    List<Task> listTask(PageParams<Task> pageParams);
+
+    List<Task> getAllInitJob();
+
+    void deleteTaskErrorInfo(@Param("taskId") String taskId);
+
+    void insertTaskErrorInfo(ErrorJobInfo errorJobInfo);
+
+    /**
+     * 获取任务报错信息
+     * @param taskId
+     * @return
+     */
+    ErrorJobInfo getErrorJobInfoById(@Param("taskId") String taskId);
+
+    /**
+     * 更新任务邮件发送标识
+     * @param id
+     * @param sendStatus
+     */
+    void updateSendedStatusById(@Param("id") String id, @Param("sendStatus") String sendStatus);
+
+    String getTaskSendStatusById(@Param("taskId") String taskId);
+
+    List<String> getSendMailsConfig();
+}

+ 71 - 0
da/src/main/java/com/datau/da/entity/PageParams.java

@@ -0,0 +1,71 @@
+package com.datau.da.entity;
+
+/**
+ * @author 宋显哲
+ * @version 1.0.0 创建于 2018/7/4
+ **/
+public class PageParams<T> {
+    private String startTime;
+    private String endTime;
+    private String sort;
+    private String order;
+    private int page;
+    private int pageSize;
+    private T data;
+
+    public String getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(String startTime) {
+        this.startTime = startTime;
+    }
+
+    public String getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(String endTime) {
+        this.endTime = endTime;
+    }
+
+    public String getSort() {
+        return sort;
+    }
+
+    public void setSort(String sort) {
+        this.sort = sort;
+    }
+
+    public String getOrder() {
+        return order;
+    }
+
+    public void setOrder(String order) {
+        this.order = order;
+    }
+
+    public int getPage() {
+        return page;
+    }
+
+    public void setPage(int page) {
+        this.page = page;
+    }
+
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(int pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+}

+ 106 - 0
da/src/main/java/com/datau/da/entity/ReturnData.java

@@ -0,0 +1,106 @@
+package com.datau.da.entity;
+
+import com.datau.da.constant.StatusCode;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @author 宋显哲
+ * @version 1.0.0 创建于 2017/12/27
+ **/
+@ApiModel(description = "请求返回实体类", value = "返回值")
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ReturnData<T> {
+    @ApiModelProperty(dataType = "int", name = "code", value = "请求返回状态码")
+    private String code = StatusCode.SUCCESS;
+    @ApiModelProperty(dataType = "String", name = "msg", value = "请求返回描述信息")
+    private String msg = "请求成功.";
+    @ApiModelProperty(dataType = "T", name = "data", value = "返回数据")
+    T data;
+    private Integer page;
+    private Integer pageSize;
+    private Integer totalNumber;
+    private Integer totalPageCount;
+
+    public ReturnData() {
+    }
+
+    public ReturnData(T data) {
+        this.data = data;
+    }
+
+    public ReturnData(String code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public ReturnData(String code, String msg, T data) {
+        this.code = code;
+        this.msg = msg;
+        this.data = data;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public ReturnData<T> setData(T data) {
+        this.data = data;
+        return this;
+    }
+
+    public ReturnData<T> retStatus(String code) {
+        this.setCode(code);
+        this.setMsg(StatusCode.getMsg(code));
+        return this;
+    }
+
+    public Integer getPage() {
+        return page;
+    }
+
+    public void setPage(Integer page) {
+        this.page = page;
+    }
+
+    public Integer getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(Integer pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    public Integer getTotalNumber() {
+        return totalNumber;
+    }
+
+    public void setTotalNumber(Integer totalNumber) {
+        this.totalNumber = totalNumber;
+    }
+
+    public Integer getTotalPageCount() {
+        return totalPageCount;
+    }
+
+    public void setTotalPageCount(Integer totalPageCount) {
+        this.totalPageCount = totalPageCount;
+    }
+}

+ 48 - 0
da/src/main/java/com/datau/da/entity/dataquality/ListDataDTO.java

@@ -0,0 +1,48 @@
+package com.datau.da.entity.dataquality;
+
+import java.util.List;
+import java.util.Map;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * 
+ * @ClassName: ListDataDTO
+ * @Description:数据质量管理获取表中数据实体类
+ * @author: Zhao You Kai
+ * @date: Apr 3, 2019 4:14:03 PM
+ */
+public class ListDataDTO {
+
+	@ApiModelProperty("主键字段")
+	private List<String> primaryColumns;
+	@ApiModelProperty("字段展示列表")
+	private List<String> listColumn;
+	@ApiModelProperty("数据列表")
+	private List<Map<String, Object>> listData;
+
+	public List<String> getListColumn() {
+		return listColumn;
+	}
+
+	public void setListColumn(List<String> listColumn) {
+		this.listColumn = listColumn;
+	}
+
+	public List<String> getPrimaryColumns() {
+		return primaryColumns;
+	}
+
+	public void setPrimaryColumns(List<String> primaryColumns) {
+		this.primaryColumns = primaryColumns;
+	}
+
+	public List<Map<String, Object>> getListData() {
+		return listData;
+	}
+
+	public void setListData(List<Map<String, Object>> listData) {
+		this.listData = listData;
+	}
+
+}

+ 35 - 0
da/src/main/java/com/datau/da/entity/dataquality/QuerySqlDTO.java

@@ -0,0 +1,35 @@
+package com.datau.da.entity.dataquality;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * 
+ * @ClassName: QuerySqlDTO
+ * @Description:查询sql实体类
+ * @author: Zhao You Kai
+ * @date: Apr 3, 2019 3:48:32 PM
+ */
+
+public class QuerySqlDTO {
+	@ApiModelProperty("主键部分sql,包括 select 主键1,主键2...(不可修改)")
+	private String primarySql;
+	@ApiModelProperty("查询部分sql,主键部分后sql语句(可以修改)")
+	private String qureySql;
+
+	public String getPrimarySql() {
+		return primarySql;
+	}
+
+	public void setPrimarySql(String primarySql) {
+		this.primarySql = primarySql;
+	}
+
+	public String getQureySql() {
+		return qureySql;
+	}
+
+	public void setQureySql(String qureySql) {
+		this.qureySql = qureySql;
+	}
+
+}

+ 69 - 0
da/src/main/java/com/datau/da/entity/dataquality/UpdateDataDTO.java

@@ -0,0 +1,69 @@
+package com.datau.da.entity.dataquality;
+
+import java.util.List;
+import java.util.Map;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * 
+ * @ClassName: UpdateDataDTO
+ * @Description:修改数据参数实体类
+ * @author: Zhao You Kai
+ * @date: Apr 4, 2019 2:53:39 PM
+ */
+public class UpdateDataDTO {
+	@ApiModelProperty("表ID")
+	private String tableId;
+
+	@ApiModelProperty("表主键字段列表")
+	private List<String> primaryColumns;
+	@ApiModelProperty("表主键字段列表")
+	private Map<String, Object> primaryData;
+	@ApiModelProperty("修改数据字段")
+	private String updateColumn;
+	@ApiModelProperty("修改后数据")
+	private Map<String, Object> updateData;
+	
+
+	public String getTableId() {
+		return tableId;
+	}
+
+	public void setTableId(String tableId) {
+		this.tableId = tableId;
+	}
+
+	public List<String> getPrimaryColumns() {
+		return primaryColumns;
+	}
+
+	public void setPrimaryColumns(List<String> primaryColumns) {
+		this.primaryColumns = primaryColumns;
+	}
+
+	public Map<String, Object> getPrimaryData() {
+		return primaryData;
+	}
+
+	public void setPrimaryData(Map<String, Object> primaryData) {
+		this.primaryData = primaryData;
+	}
+
+	public String getUpdateColumn() {
+		return updateColumn;
+	}
+
+	public void setUpdateColumn(String updateColumn) {
+		this.updateColumn = updateColumn;
+	}
+
+	public Map<String, Object> getUpdateData() {
+		return updateData;
+	}
+
+	public void setUpdateData(Map<String, Object> updateData) {
+		this.updateData = updateData;
+	}
+
+}

+ 85 - 0
da/src/main/java/com/datau/da/entity/mail/ErrorJobInfo.java

@@ -0,0 +1,85 @@
+package com.datau.da.entity.mail;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @author 许明
+ * on 2019/5/9.
+ * @version 2.0.0
+ */
+@ApiModel(description = "出错任务实体类")
+public class ErrorJobInfo implements Serializable {
+    @ApiModelProperty(dataType = "String", name = "id", value = "主键id")
+    private String id;
+    @ApiModelProperty(dataType = "String", name = "taskId", value = "任务id")
+    private String taskId;
+    @ApiModelProperty(dataType = "String", name = "taskName", value = "任务名称")
+    private String taskName;
+    @ApiModelProperty(dataType = "String", name = "errorDesc", value = "错误描述")
+    private String errorDesc;
+    @ApiModelProperty(dataType = "String", name = "sendStatus", value = "邮件发送状态,0:未发送,1:已发送")
+    private String sendStatus;
+    @ApiModelProperty(dataType = "String", name = "createTime", value = "出错时间")
+    private String createTime;
+    @ApiModelProperty(dataType = "String", name = "updateTime", value = "更新时间")
+    private String updateTime;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getTaskName() {
+        return taskName;
+    }
+
+    public void setTaskName(String taskName) {
+        this.taskName = taskName;
+    }
+
+    public String getErrorDesc() {
+        return errorDesc;
+    }
+
+    public void setErrorDesc(String errorDesc) {
+        this.errorDesc = errorDesc;
+    }
+
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getTaskId() {
+        return taskId;
+    }
+
+    public void setTaskId(String taskId) {
+        this.taskId = taskId;
+    }
+
+    public String getSendStatus() {
+        return sendStatus;
+    }
+
+    public void setSendStatus(String sendStatus) {
+        this.sendStatus = sendStatus;
+    }
+
+    public String getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(String updateTime) {
+        this.updateTime = updateTime;
+    }
+}

+ 99 - 0
da/src/main/java/com/datau/da/entity/mail/MailBean.java

@@ -0,0 +1,99 @@
+package com.datau.da.entity.mail;
+
+import java.util.Vector;
+
+/**
+ * @author 许明
+ * on 2019/05/09.
+ * @version 2.0.0
+ */
+public class MailBean {
+    private String to; // 收件人
+    private String from; // 发件人
+    private String host; // SMTP主机
+    private String username; // 发件人的用户名
+    private String password; // 发件人的密码
+    private String subject; // 邮件主题
+    private String content; // 邮件正文
+    Vector<String> file; // 多个附件
+    private String filename; // 附件的文件名
+
+    public String getTo() {
+        return to;
+    }
+
+    public void setTo(String to) {
+        this.to = to;
+    }
+
+    public String getFrom() {
+        return from;
+    }
+
+    public void setFrom(String from) {
+        this.from = from;
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public Vector<String> getFile() {
+        return file;
+    }
+
+    public void setFile(Vector<String> file) {
+        this.file = file;
+    }
+
+    public String getFilename() {
+        return filename;
+    }
+
+    public void setFilename(String filename) {
+        this.filename = filename;
+    }
+
+    public void attachFile(String fileName) {
+        if (file == null) {
+            file = new Vector<String>();
+        }
+        file.addElement(fileName);
+    }
+}

+ 30 - 0
da/src/main/java/com/datau/da/entity/model/JobParseEvent.java

@@ -0,0 +1,30 @@
+package com.datau.da.entity.model;
+
+import com.datau.da.entity.task.Task;
+import com.lmax.disruptor.EventFactory;
+
+/**
+ * @author 许明
+ * on 2019/3/7.
+ * @version 2.0.0
+ */
+public class JobParseEvent {
+
+    private Task parseTask;// 待执行任务信息
+
+    public final static EventFactory<JobParseEvent> EVENT_FACTORY = new EventFactory<JobParseEvent>()
+    {
+        public JobParseEvent newInstance()
+        {
+            return new JobParseEvent();
+        }
+    };
+
+    public Task getParseTask() {
+        return parseTask;
+    }
+
+    public void setParseTask(Task parseTask) {
+        this.parseTask = parseTask;
+    }
+}

+ 29 - 0
da/src/main/java/com/datau/da/entity/model/ScheduleRoundEvent.java

@@ -0,0 +1,29 @@
+package com.datau.da.entity.model;
+
+import com.datau.da.entity.task.Task;
+import com.lmax.disruptor.EventFactory;
+
+/**
+ * @author 许明
+ * on 2019/3/6.
+ * @version 2.0.0
+ */
+public class ScheduleRoundEvent {
+    private Task task;
+
+    public final static EventFactory<ScheduleRoundEvent> EVENT_FACTORY = new EventFactory<ScheduleRoundEvent>()
+    {
+        public ScheduleRoundEvent newInstance()
+        {
+            return new ScheduleRoundEvent();
+        }
+    };
+
+    public Task getTask() {
+        return task;
+    }
+
+    public void setTask(Task task) {
+        this.task = task;
+    }
+}

+ 151 - 0
da/src/main/java/com/datau/da/entity/remotedb/MdmCreateTableDTO.java

@@ -0,0 +1,151 @@
+package com.datau.da.entity.remotedb;
+
+import java.util.List;
+
+import io.swagger.annotations.ApiModelProperty;
+
+public class MdmCreateTableDTO {
+	@ApiModelProperty("表Id")
+	private String tableId;
+	@ApiModelProperty("表名称")
+	private String tableName;
+	@ApiModelProperty("表注释(中文名)")
+	private String tableComment;
+	@ApiModelProperty("表描述")
+	private String tableDesc;
+	@ApiModelProperty("所属数据库ID")
+	private String databaseId;
+	@ApiModelProperty("字符集ID")
+	private Integer charsetId;
+	@ApiModelProperty("字符集名称")
+	private String charsetName;
+	@ApiModelProperty("hive建表行分割符")
+	private Integer hiveSeparatorRow;
+	@ApiModelProperty("hive建表列分割符")
+	private Integer hiveSeparatorColumn;
+	@ApiModelProperty("hive建表分区")
+	private String hivePartition;
+	@ApiModelProperty("最后更新人")
+	private String updateUserId;
+
+	@ApiModelProperty("DDL建表sql语句")
+	private String ddl;
+	@ApiModelProperty("扫描建表复制后表Id")
+	private String copyTableId;
+
+	public String getCopyTableId() {
+		return copyTableId;
+	}
+
+	public void setCopyTableId(String copyTableId) {
+		this.copyTableId = copyTableId;
+	}
+
+	public String getDdl() {
+		return ddl;
+	}
+
+	public void setDdl(String ddl) {
+		this.ddl = ddl;
+	}
+
+	public String getTableId() {
+		return tableId;
+	}
+
+	public void setTableId(String tableId) {
+		this.tableId = tableId;
+	}
+
+	@ApiModelProperty("表包含字段")
+	private List<MdmInfoColumn> columns;
+
+	public String getCharsetName() {
+		return charsetName;
+	}
+
+	public void setCharsetName(String charsetName) {
+		this.charsetName = charsetName;
+	}
+
+	public String getTableName() {
+		return tableName;
+	}
+
+	public void setTableName(String tableName) {
+		this.tableName = tableName;
+	}
+
+	public String getTableComment() {
+		return tableComment;
+	}
+
+	public void setTableComment(String tableComment) {
+		this.tableComment = tableComment;
+	}
+
+	public String getTableDesc() {
+		return tableDesc;
+	}
+
+	public void setTableDesc(String tableDesc) {
+		this.tableDesc = tableDesc;
+	}
+
+	public String getDatabaseId() {
+		return databaseId;
+	}
+
+	public void setDatabaseId(String databaseId) {
+		this.databaseId = databaseId;
+	}
+
+	public Integer getCharsetId() {
+		return charsetId;
+	}
+
+	public void setCharsetId(Integer charsetId) {
+		this.charsetId = charsetId;
+	}
+
+	public Integer getHiveSeparatorRow() {
+		return hiveSeparatorRow;
+	}
+
+	public void setHiveSeparatorRow(Integer hiveSeparatorRow) {
+		this.hiveSeparatorRow = hiveSeparatorRow;
+	}
+
+	public Integer getHiveSeparatorColumn() {
+		return hiveSeparatorColumn;
+	}
+
+	public void setHiveSeparatorColumn(Integer hiveSeparatorColumn) {
+		this.hiveSeparatorColumn = hiveSeparatorColumn;
+	}
+
+	public String getHivePartition() {
+		return hivePartition;
+	}
+
+	public void setHivePartition(String hivePartition) {
+		this.hivePartition = hivePartition;
+	}
+
+	public String getUpdateUserId() {
+		return updateUserId;
+	}
+
+	public void setUpdateUserId(String updateUserId) {
+		this.updateUserId = updateUserId;
+	}
+
+	public List<MdmInfoColumn> getColumns() {
+		return columns;
+	}
+
+	public void setColumns(List<MdmInfoColumn> columns) {
+		this.columns = columns;
+	}
+
+}

+ 195 - 0
da/src/main/java/com/datau/da/entity/remotedb/MdmInfoColumn.java

@@ -0,0 +1,195 @@
+package com.datau.da.entity.remotedb;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * 
+ * @ClassName: MdmInfoColumn
+ * @Description: 表字段信息表实体类
+ * @author: Zhao You Kai
+ * @date: Feb 19, 2019 4:20:55 PM
+ */
+public class MdmInfoColumn {
+	@ApiModelProperty("ID")
+	private String id;
+	@ApiModelProperty("字段名称")
+	private String columnName;
+	@ApiModelProperty("字段描述")
+	private String columnComment;
+	@ApiModelProperty("字段类型")
+	private Integer columnType;
+	@ApiModelProperty("字段长度")
+	private Integer length;
+	@ApiModelProperty("字段小数位数")
+	private Integer numericScale;
+	@ApiModelProperty("是否是主键")
+	private Integer ifPrimary;
+	@ApiModelProperty("是否可为空")
+	private Integer ifNull;
+	@ApiModelProperty("字段所属表ID")
+	private String tableId;
+	@ApiModelProperty("字段序列号")
+	private Integer columnCode;
+	@ApiModelProperty("创建人ID")
+	private String updateUserId;
+	@ApiModelProperty("更新时间")
+	private String updateTime;
+	@ApiModelProperty("字段类型名称")
+	private String columnTypeName;
+	@ApiModelProperty("是否浮点类型")
+	private Integer isFloatPoint;
+	@ApiModelProperty("是否时间类型")
+	private Integer isTime;
+	@ApiModelProperty("是否文本类型")
+	private Integer ifChar;
+	@ApiModelProperty("所属表名")
+	private String tableName;
+
+	@ApiModelProperty("所属数据库名")
+	private String databaseId;
+
+	public Integer getIsTime() {
+		return isTime;
+	}
+
+	public void setIsTime(Integer isTime) {
+		this.isTime = isTime;
+	}
+
+	public Integer getIfChar() {
+		return ifChar;
+	}
+
+	public void setIfChar(Integer ifChar) {
+		this.ifChar = ifChar;
+	}
+
+	public String getDatabaseId() {
+		return databaseId;
+	}
+
+	public void setDatabaseId(String databaseId) {
+		this.databaseId = databaseId;
+	}
+
+	public String getTableName() {
+		return tableName;
+	}
+
+	public void setTableName(String tableName) {
+		this.tableName = tableName;
+	}
+
+	public Integer getIsFloatPoint() {
+		return isFloatPoint;
+	}
+
+	public void setIsFloatPoint(Integer isFloatPoint) {
+		this.isFloatPoint = isFloatPoint;
+	}
+
+	public String getColumnTypeName() {
+		return columnTypeName;
+	}
+
+	public void setColumnTypeName(String columnTypeName) {
+		this.columnTypeName = columnTypeName;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public Integer getLength() {
+		return length;
+	}
+
+	public void setLength(Integer length) {
+		this.length = length;
+	}
+
+	public Integer getNumericScale() {
+		return numericScale;
+	}
+
+	public void setNumericScale(Integer numericScale) {
+		this.numericScale = numericScale;
+	}
+
+	public Integer getIfPrimary() {
+		return ifPrimary;
+	}
+
+	public void setIfPrimary(Integer ifPrimary) {
+		this.ifPrimary = ifPrimary;
+	}
+
+	public Integer getIfNull() {
+		return ifNull;
+	}
+
+	public void setIfNull(Integer ifNull) {
+		this.ifNull = ifNull;
+	}
+
+	public Integer getColumnCode() {
+		return columnCode;
+	}
+
+	public void setColumnCode(Integer columnCode) {
+		this.columnCode = columnCode;
+	}
+
+	public String getUpdateUserId() {
+		return updateUserId;
+	}
+
+	public void setUpdateUserId(String updateUserId) {
+		this.updateUserId = updateUserId;
+	}
+
+	public String getColumnName() {
+		return columnName;
+	}
+
+	public void setColumnName(String columnName) {
+		this.columnName = columnName;
+	}
+
+	public String getColumnComment() {
+		return columnComment;
+	}
+
+	public void setColumnComment(String columnComment) {
+		this.columnComment = columnComment;
+	}
+
+	public Integer getColumnType() {
+		return columnType;
+	}
+
+	public void setColumnType(Integer columnType) {
+		this.columnType = columnType;
+	}
+
+	public String getTableId() {
+		return tableId;
+	}
+
+	public void setTableId(String tableId) {
+		this.tableId = tableId;
+	}
+
+	public String getUpdateTime() {
+		return updateTime;
+	}
+
+	public void setUpdateTime(String updateTime) {
+		this.updateTime = updateTime;
+	}
+
+}

+ 188 - 0
da/src/main/java/com/datau/da/entity/remotedb/MdmInfoDatabase.java

@@ -0,0 +1,188 @@
+package com.datau.da.entity.remotedb;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * 
+ * @ClassName: MdmInfoDatabase
+ * @Description: 数据库信息表实体类
+ * @author: Zhao You Kai
+ * @date: Feb 19, 2019 2:20:42 PM
+ */
+public class MdmInfoDatabase {
+	@ApiModelProperty("ID")
+	private String id;
+	@ApiModelProperty("资源名称")
+	private String resourceName;
+	@ApiModelProperty("资源IP")
+	private String ip;
+	@ApiModelProperty("资源类型")
+	private Integer resourceType;
+	@ApiModelProperty("资源端口")
+	private String resourcePort;
+	@ApiModelProperty("连接用户名")
+	private String username;
+	@ApiModelProperty("连接密码")
+	private String password;
+	@ApiModelProperty("数据库名称")
+	private String databaseName;
+	@ApiModelProperty("数据仓库类型")
+	private Integer databaseType;
+	@ApiModelProperty("字符集")
+	private Integer charset;
+	@ApiModelProperty("最后更新人")
+	private String updateUserId;
+	@ApiModelProperty("最后更新人名")
+	private String updateUserName;
+	@ApiModelProperty("更新时间")
+	private String updateTime;
+
+	@ApiModelProperty("数据库类型名称")
+	private String databaseTypeName;
+	@ApiModelProperty("资源类型名称")
+	private String resourceTypeName;
+	@ApiModelProperty("编码集名称")
+	private String charsetName;
+
+	@ApiModelProperty("不同数据库JDBC加载驱动")
+	private String driverName;
+	@ApiModelProperty("不同数据库JDBC连接url")
+	private String url;
+
+	public String getDriverName() {
+		return driverName;
+	}
+
+	public void setDriverName(String driverName) {
+		this.driverName = driverName;
+	}
+
+	public String getUrl() {
+		return url;
+	}
+
+	public void setUrl(String url) {
+		this.url = url;
+	}
+
+	public String getDatabaseTypeName() {
+		return databaseTypeName;
+	}
+
+	public void setDatabaseTypeName(String databaseTypeName) {
+		this.databaseTypeName = databaseTypeName;
+	}
+
+	public String getResourceTypeName() {
+		return resourceTypeName;
+	}
+
+	public void setResourceTypeName(String resourceTypeName) {
+		this.resourceTypeName = resourceTypeName;
+	}
+
+	public String getCharsetName() {
+		return charsetName;
+	}
+
+	public void setCharsetName(String charsetName) {
+		this.charsetName = charsetName;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public String getIp() {
+		return ip;
+	}
+
+	public void setIp(String ip) {
+		this.ip = ip;
+	}
+
+	public String getUsername() {
+		return username;
+	}
+
+	public void setUsername(String username) {
+		this.username = username;
+	}
+
+	public String getPassword() {
+		return password;
+	}
+
+	public void setPassword(String password) {
+		this.password = password;
+	}
+
+	public String getUpdateUserId() {
+		return updateUserId;
+	}
+
+	public void setUpdateUserId(String updateUserId) {
+		this.updateUserId = updateUserId;
+	}
+
+	public String getResourceName() {
+		return resourceName;
+	}
+
+	public void setResourceName(String resourceName) {
+		this.resourceName = resourceName;
+	}
+
+	public Integer getResourceType() {
+		return resourceType;
+	}
+
+	public void setResourceType(Integer resourceType) {
+		this.resourceType = resourceType;
+	}
+
+	public String getResourcePort() {
+		return resourcePort;
+	}
+
+	public void setResourcePort(String resourcePort) {
+		this.resourcePort = resourcePort;
+	}
+
+	public String getDatabaseName() {
+		return databaseName;
+	}
+
+	public void setDatabaseName(String databaseName) {
+		this.databaseName = databaseName;
+	}
+
+	public Integer getDatabaseType() {
+		return databaseType;
+	}
+
+	public void setDatabaseType(Integer databaseType) {
+		this.databaseType = databaseType;
+	}
+
+	public Integer getCharset() {
+		return charset;
+	}
+
+	public void setCharset(Integer charset) {
+		this.charset = charset;
+	}
+
+	public String getUpdateTime() {
+		return updateTime;
+	}
+
+	public void setUpdateTime(String updateTime) {
+		this.updateTime = updateTime;
+	}
+
+}

+ 156 - 0
da/src/main/java/com/datau/da/entity/remotedb/MdmInfoTable.java

@@ -0,0 +1,156 @@
+package com.datau.da.entity.remotedb;
+
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * 
+ * @ClassName: MdmInfoTable
+ * @Description: 数据表信息表实体类
+ * @author: Zhao You Kai
+ * @date: Feb 19, 2019 4:20:22 PM
+ */
+public class MdmInfoTable {
+
+	@ApiModelProperty("ID")
+	private String id;
+
+	@ApiModelProperty("表名称")
+	private String tableName;
+	@ApiModelProperty("表注释(中文名)")
+	private String tableComment;
+	@ApiModelProperty("所属数据库ID")
+	private String databaseId;
+	@ApiModelProperty("创建人ID")
+	private String updateUserId;
+	@ApiModelProperty("创建人名称")
+	private String updateUserName;
+	@ApiModelProperty("更新时间")
+	private String updateTime;
+	@ApiModelProperty("编码")
+	private Integer charset;
+	@ApiModelProperty("hive建表行分割符")
+	private Integer hiveSeparatorRow;
+	@ApiModelProperty("hive建表列分割符")
+	private Integer hiveSeparatorColumn;
+	@ApiModelProperty("hive建表分区")
+	private String hivePartition;
+	@ApiModelProperty("表描述")
+	private String tableDesc;
+	@ApiModelProperty("所属库名")
+	private String databaseName;
+	@ApiModelProperty("所属库资源名")
+	private String resourceName;
+
+	public String getUpdateUserName() {
+		return updateUserName;
+	}
+
+	public void setUpdateUserName(String updateUserName) {
+		this.updateUserName = updateUserName;
+	}
+
+	public String getDatabaseName() {
+		return databaseName;
+	}
+
+	public void setDatabaseName(String databaseName) {
+		this.databaseName = databaseName;
+	}
+
+	public String getResourceName() {
+		return resourceName;
+	}
+
+	public void setResourceName(String resourceName) {
+		this.resourceName = resourceName;
+	}
+
+	public String getTableDesc() {
+		return tableDesc;
+	}
+
+	public void setTableDesc(String tableDesc) {
+		this.tableDesc = tableDesc;
+	}
+
+	public Integer getHiveSeparatorRow() {
+		return hiveSeparatorRow;
+	}
+
+	public void setHiveSeparatorRow(Integer hiveSeparatorRow) {
+		this.hiveSeparatorRow = hiveSeparatorRow;
+	}
+
+	public Integer getHiveSeparatorColumn() {
+		return hiveSeparatorColumn;
+	}
+
+	public void setHiveSeparatorColumn(Integer hiveSeparatorColumn) {
+		this.hiveSeparatorColumn = hiveSeparatorColumn;
+	}
+
+	public String getHivePartition() {
+		return hivePartition;
+	}
+
+	public void setHivePartition(String hivePartition) {
+		this.hivePartition = hivePartition;
+	}
+
+	public String getUpdateUserId() {
+		return updateUserId;
+	}
+
+	public void setUpdateUserId(String updateUserId) {
+		this.updateUserId = updateUserId;
+	}
+
+	public Integer getCharset() {
+		return charset;
+	}
+
+	public void setCharset(Integer charset) {
+		this.charset = charset;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public String getTableName() {
+		return tableName;
+	}
+
+	public void setTableName(String tableName) {
+		this.tableName = tableName;
+	}
+
+	public String getTableComment() {
+		return tableComment;
+	}
+
+	public void setTableComment(String tableComment) {
+		this.tableComment = tableComment;
+	}
+
+	public String getDatabaseId() {
+		return databaseId;
+	}
+
+	public void setDatabaseId(String databaseId) {
+		this.databaseId = databaseId;
+	}
+
+	public String getUpdateTime() {
+		return updateTime;
+	}
+
+	public void setUpdateTime(String updateTime) {
+		this.updateTime = updateTime;
+	}
+
+}

+ 43 - 0
da/src/main/java/com/datau/da/entity/task/JobOperateCmd.java

@@ -0,0 +1,43 @@
+package com.datau.da.entity.task;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @author 许明
+ * on 2019/3/7.
+ * @version 2.0.0
+ */
+@ApiModel(description = "任务操作类")
+public class JobOperateCmd {
+    @ApiModelProperty(dataType = "String", name = "jobId", value = "任务id")
+    private String jobId;
+    @ApiModelProperty(dataType = "String", name = "operateType", value = "操作类型,1:开始,2:结束,3:立即执行一次")
+    private String operateType;
+
+    public JobOperateCmd(){
+    }
+
+    public JobOperateCmd(String jobId, long time, String operateType)
+    {
+        this.jobId = jobId;
+        this.operateType = operateType;
+    }
+
+    public String getJobId() {
+        return jobId;
+    }
+
+    public void setJobId(String jobId) {
+        this.jobId = jobId;
+    }
+
+    public String getOperateType() {
+        return operateType;
+    }
+
+    public void setOperateType(String operateType) {
+        this.operateType = operateType;
+    }
+
+}

+ 34 - 0
da/src/main/java/com/datau/da/entity/task/JobScheduleTime.java

@@ -0,0 +1,34 @@
+package com.datau.da.entity.task;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @author 许明
+ * on 2019/3/7.
+ * @version 2.0.0
+ */
+@ApiModel(description = "调度时间实体类")
+public class JobScheduleTime {
+
+    @ApiModelProperty(dataType = "String", name = "id", value = "任务id")
+    private String id;
+    @ApiModelProperty(dataType = "String", name = "cronExpression", value = "cron表达式")
+    private String cronExpression;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getCronExpression() {
+        return cronExpression;
+    }
+
+    public void setCronExpression(String cronExpression) {
+        this.cronExpression = cronExpression;
+    }
+}

+ 236 - 0
da/src/main/java/com/datau/da/entity/task/Task.java

@@ -0,0 +1,236 @@
+package com.datau.da.entity.task;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+@ApiModel(description = "任务实体类")
+public class Task implements Serializable {
+
+    @ApiModelProperty(dataType = "String", name = "id", value = "任务id")
+    private String id;
+    @ApiModelProperty(dataType = "String", name = "taskName", value = "任务名称")
+    private String taskName;
+    @ApiModelProperty(dataType = "int", name = "periodType", value = "周期类型,0:自定义,1:月,2:日,3:时,4:分,5:秒")
+    private int periodType;
+    @ApiModelProperty(dataType = "String", name = "periodTypeDesc", value = "周期类型描述")
+    private String periodTypeDesc;
+    @ApiModelProperty(dataType = "int", name = "scheduleOffset", value = "调度偏移量,默认:-1")
+    private int scheduleOffset;
+    @ApiModelProperty(dataType = "String", name = "dataFormat", value = "数据日期类型")
+    private String dataFormat;
+    @ApiModelProperty(dataType = "String", name = "taskStatus", value = "任务状态,1:启用,2:停用,默认:2")
+    private String taskStatus;
+    @ApiModelProperty(dataType = "String", name = "runStatus", value = "任务运行状态,默认:0,0:未运行,1:等待运行,2:运行中,3:运行完成,4:运行失败")
+    private String runStatus;
+    @ApiModelProperty(dataType = "String", name = "taskStatusDesc", value = "任务状态描述")
+    private String taskStatusDesc;
+    @ApiModelProperty(dataType = "String", name = "taskCron", value = "任务定时cron")
+    private String taskCron;
+    @ApiModelProperty(dataType = "String", name = "ddlSql", value = "数据采集的DDL语句")
+    private String ddlSql;
+    @ApiModelProperty(dataType = "String", name = "sourceDatabaseId", value = "源库id")
+    private String sourceDatabaseId;
+    @ApiModelProperty(dataType = "String", name = "sourceTableId", value = "源表id")
+    private String sourceTableId;
+    @ApiModelProperty(dataType = "String", name = "sourceTableName", value = "源表名称")
+    private String sourceTableName;
+    @ApiModelProperty(dataType = "String", name = "targetDatabaseId", value = "目标库id")
+    private String targetDatabaseId;
+    @ApiModelProperty(dataType = "String", name = "targetTableId", value = "目标表id")
+    private String targetTableId;
+    @ApiModelProperty(dataType = "String", name = "targetTableName", value = "目标表名称")
+    private String targetTableName;
+    @ApiModelProperty(dataType = "String", name = "createTime", value = "创建时间")
+    private String createTime;
+    @ApiModelProperty(dataType = "String", name = "updateTime", value = "更新时间")
+    private String updateTime;
+    @ApiModelProperty(dataType = "String", name = "userId", value = "操作人id")
+    private String userId;
+    @ApiModelProperty(dataType = "String", name = "userName", value = "操作人名称")
+    private String userName;
+    @ApiModelProperty(dataType = "String", name = "nextRunDate", value = "下次运行时间")
+    private String nextRunDate;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getTaskName() {
+        return taskName;
+    }
+
+    public void setTaskName(String taskName) {
+        this.taskName = taskName;
+    }
+
+    public int getPeriodType() {
+        return periodType;
+    }
+
+    public void setPeriodType(int periodType) {
+        this.periodType = periodType;
+    }
+
+    public String getPeriodTypeDesc() {
+        return periodTypeDesc;
+    }
+
+    public void setPeriodTypeDesc(String periodTypeDesc) {
+        this.periodTypeDesc = periodTypeDesc;
+    }
+
+    public int getScheduleOffset() {
+        return scheduleOffset;
+    }
+
+    public void setScheduleOffset(int scheduleOffset) {
+        this.scheduleOffset = scheduleOffset;
+    }
+
+    public String getDataFormat() {
+        return dataFormat;
+    }
+
+    public void setDataFormat(String dataFormat) {
+        this.dataFormat = dataFormat;
+    }
+
+    public String getTaskStatus() {
+        return taskStatus;
+    }
+
+    public void setTaskStatus(String taskStatus) {
+        this.taskStatus = taskStatus;
+    }
+
+    public String getRunStatus() {
+        return runStatus;
+    }
+
+    public void setRunStatus(String runStatus) {
+        this.runStatus = runStatus;
+    }
+
+    public String getTaskStatusDesc() {
+        return taskStatusDesc;
+    }
+
+    public void setTaskStatusDesc(String taskStatusDesc) {
+        this.taskStatusDesc = taskStatusDesc;
+    }
+
+    public String getTaskCron() {
+        return taskCron;
+    }
+
+    public void setTaskCron(String taskCron) {
+        this.taskCron = taskCron;
+    }
+
+    public String getDdlSql() {
+        return ddlSql;
+    }
+
+    public void setDdlSql(String ddlSql) {
+        this.ddlSql = ddlSql;
+    }
+
+    public String getSourceDatabaseId() {
+        return sourceDatabaseId;
+    }
+
+    public void setSourceDatabaseId(String sourceDatabaseId) {
+        this.sourceDatabaseId = sourceDatabaseId;
+    }
+
+    public String getSourceTableId() {
+        return sourceTableId;
+    }
+
+    public void setSourceTableId(String sourceTableId) {
+        this.sourceTableId = sourceTableId;
+    }
+
+    public String getSourceTableName() {
+        return sourceTableName;
+    }
+
+    public void setSourceTableName(String sourceTableName) {
+        this.sourceTableName = sourceTableName;
+    }
+
+    public String getTargetDatabaseId() {
+        return targetDatabaseId;
+    }
+
+    public void setTargetDatabaseId(String targetDatabaseId) {
+        this.targetDatabaseId = targetDatabaseId;
+    }
+
+    public String getTargetTableId() {
+        return targetTableId;
+    }
+
+    public void setTargetTableId(String targetTableId) {
+        this.targetTableId = targetTableId;
+    }
+
+    public String getTargetTableName() {
+        return targetTableName;
+    }
+
+    public void setTargetTableName(String targetTableName) {
+        this.targetTableName = targetTableName;
+    }
+
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(String updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getNextRunDate() {
+        return nextRunDate;
+    }
+
+    public void setNextRunDate(String nextRunDate) {
+        this.nextRunDate = nextRunDate;
+    }
+}

+ 20 - 0
da/src/main/java/com/datau/da/entity/token/Header.java

@@ -0,0 +1,20 @@
+package com.datau.da.entity.token;
+
+import java.io.Serializable;
+
+/**
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+public class Header implements Serializable {
+    private long timestamp;
+
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+}

+ 99 - 0
da/src/main/java/com/datau/da/entity/token/Payload.java

@@ -0,0 +1,99 @@
+package com.datau.da.entity.token;
+
+import java.io.Serializable;
+
+/**
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+public class Payload implements Serializable {
+    private String id;
+    private String deptNo;
+    private String username;
+    private String enterpriseNo;
+    private String seatNumber;
+    private String roleCode;
+    //用户在线状态
+    private Integer online;
+    //企业状态
+    private String entStatus;
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getEnterpriseNo() {
+        return enterpriseNo;
+    }
+
+    public void setEnterpriseNo(String enterpriseNo) {
+        this.enterpriseNo = enterpriseNo;
+    }
+
+    public String getSeatNumber() {
+        return seatNumber;
+    }
+
+    public void setSeatNumber(String seatNumber) {
+        this.seatNumber = seatNumber;
+    }
+
+    public String getRoleCode() {
+        return roleCode;
+    }
+
+    public void setRoleCode(String roleCode) {
+        this.roleCode = roleCode;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getDeptNo() {
+        return deptNo;
+    }
+
+    public void setDeptNo(String deptNo) {
+        this.deptNo = deptNo;
+    }
+
+    public Integer getOnline() {
+        return online;
+    }
+
+    public void setOnline(Integer online) {
+        this.online = online;
+    }
+
+    public String getEntStatus() {
+        return entStatus;
+    }
+
+    public void setEntStatus(String entStatus) {
+        this.entStatus = entStatus;
+    }
+
+    @Override
+    public String toString() {
+        return "Payload{" +
+                "id='" + id + '\'' +
+                ", deptNo='" + deptNo + '\'' +
+                ", username='" + username + '\'' +
+                ", enterpriseNo='" + enterpriseNo + '\'' +
+                ", seatNumber='" + seatNumber + '\'' +
+                ", roleCode='" + roleCode + '\'' +
+                ", online=" + online +
+                ", entStatus='" + entStatus + '\'' +
+                '}';
+    }
+}

+ 38 - 0
da/src/main/java/com/datau/da/entity/token/Token.java

@@ -0,0 +1,38 @@
+package com.datau.da.entity.token;
+
+import java.io.Serializable;
+
+/**
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+public class Token implements Serializable {
+    private Header header;
+    private Payload payload;
+    private String sig;
+
+    public Header getHeader() {
+        return header;
+    }
+
+    public void setHeader(Header header) {
+        this.header = header;
+    }
+
+    public Payload getPayload() {
+        return payload;
+    }
+
+    public void setPayload(Payload payload) {
+        this.payload = payload;
+    }
+
+    public String getSig() {
+        return sig;
+    }
+
+    public void setSig(String sig) {
+        this.sig = sig;
+    }
+}

+ 75 - 0
da/src/main/java/com/datau/da/feign/AccountApi.java

@@ -0,0 +1,75 @@
+package com.datau.da.feign;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * 
+ * @ClassName: AccountApi   
+ * @Description:  
+ * @author: Zhao You Kai
+ * @date: Mar 6, 2019 10:35:33 AM
+ */
+@FeignClient(value = "account")
+public interface AccountApi {
+
+	/**
+	 * 通过token解析userId
+	 * 
+	 * @param jwt
+	 * @return
+	 */
+	@GetMapping("/account/parseTokenId")
+	public String parseTokenId(@RequestParam("jwt") String jwt);
+
+	/**
+	 * 通过token解析第二参数,预留
+	 * 
+	 * @param jwt
+	 * @return
+	 */
+	@GetMapping("/account/parseTokenSubject")
+	public String parseTokenSubject(@RequestParam("jwt") String jwt);
+
+	/**
+	 * 保存token
+	 * 
+	 * @param id
+	 * @param token
+	 * @param minute
+	 * @return
+	 */
+	@GetMapping("/account/saveToken")
+	public String saveToken(@RequestParam("id") String id, @RequestParam("token") String token,
+                            @RequestParam("minute") int minute);
+
+	/**
+	 * 删除token
+	 * 
+	 * @param id
+	 * @return
+	 */
+	@GetMapping("/account/deleteToken")
+	public String deleteToken(@RequestParam("id") String id);
+
+	/**
+	 * 根据userId获取token
+	 * 
+	 * @param accountId
+	 * @return
+	 */
+	@GetMapping("/account/getTokenByAccountId")
+	public String getTokenByAccountId(@RequestParam(value = "accountId", required = true) String accountId);
+
+	/**
+	 * 刷新token
+	 * 
+	 * @param accountId
+	 * @param minute
+	 * @return
+	 */
+	@GetMapping("/account/refreshToken")
+	public String refreshToken(@RequestParam(value = "accountId", required = true) String accountId,
+                               @RequestParam(value = "minute", required = true) int minute);
+}

+ 68 - 0
da/src/main/java/com/datau/da/feign/DaMdmFeign.java

@@ -0,0 +1,68 @@
+package com.datau.da.feign;
+
+import com.datau.da.entity.remotedb.MdmCreateTableDTO;
+import com.datau.da.entity.remotedb.MdmInfoColumn;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import com.datau.da.entity.remotedb.MdmInfoDatabase;
+import com.datau.da.entity.remotedb.MdmInfoTable;
+import com.datau.da.utils.R;
+
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author 许明 on 2019/3/11.
+ * @version 2.0.0
+ */
+@FeignClient(name = "mdm")
+public interface DaMdmFeign {
+
+	@GetMapping(value = "/mdm/kpiManage/database/{id}")
+	MdmInfoDatabase database(@PathVariable(name = "id") String dbId);
+
+	@GetMapping(value = "/mdm/kpiManage/listTableByDatabaseId")
+	List<MdmInfoTable> listTableByDatabaseId(@RequestParam(name = "databaseId") String databaseId);
+
+	@GetMapping(value = "/mdm/kpiManage/listOriginal")
+	List<MdmInfoDatabase> listOriginal(@RequestParam(name = "resourceName") String resourceName);
+
+	@GetMapping(value = "/mdm/kpiManage/listDatabase")
+	List<MdmInfoDatabase> listDatabase(@RequestParam(name = "resourceName") String resourceName);
+
+	@GetMapping(value = "/mdm/kpiManage/listColumnByTableId")
+	List<MdmInfoColumn> listColumnByTableId(@RequestParam(name = "tableId") String tableId);
+
+	@GetMapping(value = "/mdm/storageManage/getTableInfoById/{tableId}")
+	R<MdmCreateTableDTO> getTableInfoById(@PathVariable(name = "tableId") String tableId);
+
+	/**
+	 * 执行sql获取查询数据
+	 * 
+	 * @param databaseId
+	 * @param sql
+	 * @return
+	 */
+	@PostMapping("/mdm/listData")
+	List<Map<String, Object>> listData(@RequestParam("databaseId") String databaseId,
+			@RequestBody Map<String, String> sql);
+
+	/**
+	 * 执行sql修改语句
+	 * 
+	 * @param databaseId
+	 * @param sql
+	 * @return
+	 */
+	@PostMapping("/mdm/executeSql")
+	Integer executeSql(@RequestParam("databaseId") String databaseId, @RequestBody Map<String, String> sql);
+}

+ 35 - 0
da/src/main/java/com/datau/da/handler/ScheduleRoundEventHandler.java

@@ -0,0 +1,35 @@
+package com.datau.da.handler;
+
+import com.datau.da.entity.model.ScheduleRoundEvent;
+import com.datau.da.service.job.JobPutService;
+import com.lmax.disruptor.WorkHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * @author 许明
+ * on 2019/3/7.
+ * @version 2.0.0
+ * 调度轮循事件处理
+ */
+@Component
+public class ScheduleRoundEventHandler implements WorkHandler<ScheduleRoundEvent> {
+
+	public static ScheduleRoundEventHandler scheduleRoundEventHandler;
+
+    @Autowired
+    private JobPutService jobPutService;
+
+    @PostConstruct
+    public void init() {
+        scheduleRoundEventHandler = this;
+    }
+
+    @Override
+    public void onEvent(ScheduleRoundEvent event) throws Exception {
+        //job运行条件判断
+        scheduleRoundEventHandler.jobPutService.jobRunConditionJudge(event.getTask());
+    }
+}

+ 51 - 0
da/src/main/java/com/datau/da/handler/ScheduleRoundExceptionHandler.java

@@ -0,0 +1,51 @@
+package com.datau.da.handler;
+
+import com.datau.da.entity.task.Task;
+import com.datau.da.entity.model.ScheduleRoundEvent;
+import com.lmax.disruptor.ExceptionHandler;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * @author 许明
+ * on 2019/3/7.
+ * @version 2.0.0
+ */
+public class ScheduleRoundExceptionHandler implements ExceptionHandler {
+
+    private static final Logger logger = LogManager.getLogger(ScheduleRoundExceptionHandler.class);
+
+    /**
+     * @see com.lmax.disruptor.ExceptionHandler#handleEventException(java.lang.Throwable,
+     *      long, java.lang.Object)
+     */
+    @Override
+    public void handleEventException(Throwable ex, long sequence, Object event)
+    {
+        Task task = ((ScheduleRoundEvent) event).getTask();
+        String errorMsg = "";
+        if (task != null)
+        {
+            errorMsg = "job配置错误  job id[" + ((ScheduleRoundEvent) event).getTask().getId() + "]将不进行轮询";
+        }
+        logger.error(errorMsg, ex);
+    }
+
+    /**
+     * @see com.lmax.disruptor.ExceptionHandler#handleOnStartException(java.lang.Throwable)
+     */
+    @Override
+    public void handleOnStartException(Throwable ex)
+    {
+        logger.error("Exception during onStart()", ex);
+    }
+
+    /**
+     * @see com.lmax.disruptor.ExceptionHandler#handleOnShutdownException(java.lang.Throwable)
+     */
+    @Override
+    public void handleOnShutdownException(Throwable ex)
+    {
+        logger.error("Exception during onShutdown()", ex);
+    }
+}

+ 47 - 0
da/src/main/java/com/datau/da/job/JobServer.java

@@ -0,0 +1,47 @@
+package com.datau.da.job;
+
+import com.datau.da.constant.Constant;
+import com.datau.da.entity.model.ScheduleRoundEvent;
+import com.datau.da.entity.remotedb.MdmInfoDatabase;
+import com.datau.da.entity.remotedb.MdmInfoTable;
+import com.datau.da.entity.task.Task;
+import com.datau.da.service.job.JobService;
+import com.lmax.disruptor.RingBuffer;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.core.annotation.Order;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author 许明
+ * on 2019/3/6.
+ * @version 2.0.0
+ */
+@Order(1)
+public class JobServer implements CommandLineRunner {
+
+    private static final Logger logger = LogManager.getLogger(JobServer.class);
+
+    public static RingBuffer<ScheduleRoundEvent> SCHEDULE_CONDITION_JUDGE_BUFFER;// 条件轮询判断队列(无锁队列)
+    public static ConcurrentHashMap<String, Task> MEM_JOB_CACHE = new ConcurrentHashMap<String, Task>();// 存放从数据库中查询出来的所有JOB
+    // 存放新增任务选中的数据源信息
+    public static ConcurrentHashMap<String, MdmInfoDatabase> SOURCE_AND_TARGET_DB_INFO_CACHE = new ConcurrentHashMap<String, MdmInfoDatabase>();
+
+    @Autowired
+    private JobService jobService;
+
+    @Override
+    public void run(String... args) throws Exception {
+        logger.info("初始化数据中心调度任务轮询线程池start ...........................");
+        int initResult = jobService.init();
+        if(Constant.RETURN_FAILD == initResult){
+            logger.info("退出系统");
+            System.exit(0);
+        }
+        logger.info("初始化数据中心调度任务轮询线程池end ...........................");
+
+    }
+}

+ 67 - 0
da/src/main/java/com/datau/da/job/TestDemo.java

@@ -0,0 +1,67 @@
+package com.datau.da.job;
+
+import com.datau.da.entity.model.ScheduleRoundEvent;
+import com.datau.da.entity.task.Task;
+import com.lmax.disruptor.*;
+import com.lmax.disruptor.dsl.Disruptor;
+import com.lmax.disruptor.dsl.ProducerType;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * @author 许明
+ * on 2019/3/6.
+ * @version 2.0.0
+ */
+public class TestDemo {
+
+    private static Disruptor<ScheduleRoundEvent> disruptor;
+
+    public static void main(String[] args) throws InterruptedException{
+        final int BUFFER_SIZE = 1024;
+        final int THREAD_NUMBERS = 4;
+        EventFactory<ScheduleRoundEvent> eventFactory = new EventFactory<ScheduleRoundEvent>() {
+            @Override
+            public ScheduleRoundEvent newInstance() {
+                return new ScheduleRoundEvent();
+            }
+        };
+
+//        ExecutorService executors = Executors.newFixedThreadPool(4);
+//        disruptor = new Disruptor<ScheduleRoundEvent>(eventFactory, 8 << 8, executors, ProducerType.MULTI, new BlockingWaitStrategy());
+//        TestHandler testHandler = new TestHandler();
+//        disruptor.handleEventsWith(testHandler);
+//        disruptor.start();
+
+        RingBuffer<ScheduleRoundEvent> ringBuffer = RingBuffer.createSingleProducer(eventFactory, BUFFER_SIZE);
+        SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();
+        ExecutorService executor = Executors.newFixedThreadPool(THREAD_NUMBERS);
+        TestHandler[] workHandlers = new TestHandler[3];
+        for (int i = 0; i < 3; i++) {
+            TestHandler workHandler = new TestHandler();
+            workHandlers[i] = workHandler;
+        }
+        WorkerPool<ScheduleRoundEvent> workerPool = new WorkerPool<ScheduleRoundEvent>(ringBuffer, sequenceBarrier, new IgnoreExceptionHandler(), workHandlers);
+        workerPool.start(executor);
+
+
+//        RingBuffer<ScheduleRoundEvent> ringBuffer1 = disruptor.getRingBuffer();
+        for (int i = 0; i < 100; i++) {
+            long seq = ringBuffer.next();
+            Task task = new Task();
+            task.setTaskName("测试任务名称"+ i);
+            ringBuffer.get(seq).setTask(task);
+            ringBuffer.publish(seq);
+//            if (i % 10 == 0) {
+//                System.out.println(((ThreadPoolExecutor) executor).getActiveCount() + "============================================");
+//            }
+        }
+//        Thread.sleep(1000);
+//        workerPool.halt();
+//        Thread.sleep(1);
+//        executor.shutdown();
+
+    }
+
+}

+ 34 - 0
da/src/main/java/com/datau/da/job/TestHandler.java

@@ -0,0 +1,34 @@
+package com.datau.da.job;
+
+import com.datau.da.entity.model.ScheduleRoundEvent;
+import com.datau.da.service.job.JobPutService;
+import com.lmax.disruptor.WorkHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @author 许明
+ * on 2019/3/6.
+ * @version 2.0.0
+ */
+public class TestHandler implements WorkHandler<ScheduleRoundEvent> {
+
+    @Autowired
+    private JobPutService jobPutService;
+
+
+    @Override
+    public void onEvent(ScheduleRoundEvent event) throws Exception {
+//        event.getTask().setTaskName("测试线程1111");
+        System.out.println(event.getTask() == null ? "sssss" : event.getTask().getTaskName() + "==================");
+//        if(jobPutService == null){
+//            System.out.println("spring 工厂没有初始化");
+//        }
+//        jobPutService.jobRunConditionJudge(event.getTask());
+    }
+//
+//    @Override
+//    public void onEvent(ScheduleRoundEvent event, long sequence, boolean endOfBatch) throws Exception {
+//        event.getTask().setTaskName("测试线程");
+//        System.out.println(event.getTask() == null ? "sssss" : event.getTask().getTaskName() + "==================");
+//    }
+}

+ 89 - 0
da/src/main/java/com/datau/da/service/DataQualityService.java

@@ -0,0 +1,89 @@
+package com.datau.da.service;
+
+import java.util.List;
+
+import org.springframework.web.multipart.MultipartFile;
+
+import com.datau.da.entity.dataquality.ListDataDTO;
+import com.datau.da.entity.dataquality.QuerySqlDTO;
+import com.datau.da.entity.dataquality.UpdateDataDTO;
+import com.datau.da.entity.remotedb.MdmInfoDatabase;
+import com.datau.da.entity.remotedb.MdmInfoTable;
+import com.datau.da.utils.R;
+
+/**
+ * 
+ * @ClassName: DataQualityService
+ * @Description:数据质量管理
+ * @author: Zhao You Kai
+ * @date: Apr 3, 2019 2:13:36 PM
+ */
+public interface DataQualityService {
+
+	/**
+	 * 获取表中数据
+	 * 
+	 * @param tableId
+	 * @param sql
+	 * @param page
+	 * @param pageSize
+	 * @return
+	 */
+	R<ListDataDTO> listData(String tableId, String sql, Integer page, Integer pageSize) throws Exception;
+
+	/**
+	 * 获取数据库列表--非原始库
+	 * 
+	 * @param resourceName
+	 * @return
+	 */
+	R<List<MdmInfoDatabase>> listDatabase(String resourceName) throws Exception;
+
+	/**
+	 * 通过数据库ID获取表数据列表
+	 * 
+	 * @param databaseId
+	 * @return
+	 */
+	R<List<MdmInfoTable>> listTableByDatabaseId(String databaseId) throws Exception;
+
+	R<QuerySqlDTO> getQuerySql(String tableId) throws Exception;
+
+	/**
+	 * 修改数据
+	 * 
+	 * @param updateData
+	 * @return
+	 */
+	R<String> updateData(UpdateDataDTO updateData) throws Exception;
+
+	/**
+	 * 删除数据
+	 * 
+	 * @param updateData
+	 * @return
+	 */
+	R<String> deleteData(UpdateDataDTO updateData) throws Exception;
+
+	/**
+	 * 下载数据模板
+	 * 
+	 * @param fileName
+	 * @param tableId
+	 * @param sql
+	 * @return
+	 * @throws Exception
+	 */
+	String downloadTemplateData(String fileName, String tableId, String sql) throws Exception;
+
+	/**
+	 * 上传数据
+	 * 
+	 * @param tableId
+	 * @param file
+	 * @return
+	 * @throws Exception
+	 */
+	R<String> loadTemplateData(String tableId, MultipartFile file) throws Exception;
+
+}

+ 497 - 0
da/src/main/java/com/datau/da/service/impl/DataQualityServiceImpl.java

@@ -0,0 +1,497 @@
+package com.datau.da.service.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFDataFormat;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.datau.da.entity.dataquality.ListDataDTO;
+import com.datau.da.entity.dataquality.QuerySqlDTO;
+import com.datau.da.entity.dataquality.UpdateDataDTO;
+import com.datau.da.entity.remotedb.MdmCreateTableDTO;
+import com.datau.da.entity.remotedb.MdmInfoColumn;
+import com.datau.da.entity.remotedb.MdmInfoDatabase;
+import com.datau.da.entity.remotedb.MdmInfoTable;
+import com.datau.da.feign.DaMdmFeign;
+import com.datau.da.service.DataQualityService;
+import com.datau.da.utils.FileTool;
+import com.datau.da.utils.R;
+
+/**
+ * 
+ * @ClassName: DataQualityService
+ * @Description:数据质量管理
+ * @author: Zhao You Kai
+ * @date: Apr 3, 2019 2:13:36 PM
+ */
+@Service
+public class DataQualityServiceImpl implements DataQualityService {
+	@Autowired
+	private DaMdmFeign daMdmFeign;
+
+	@Override
+	public R<ListDataDTO> listData(String tableId, String sql, Integer page, Integer pageSize) {
+		R<ListDataDTO> result = new R<>();
+		ListDataDTO resultData = new ListDataDTO();
+		Map<String, String> sqlMap = null;
+		// 主键字段名称
+		List<String> primaryColumns = new ArrayList<>();
+		// TODO chectSql() 检验sql是否符合查询规则
+		MdmCreateTableDTO table = daMdmFeign.getTableInfoById(tableId).getData();
+		List<MdmInfoColumn> columns = daMdmFeign.listColumnByTableId(tableId);
+		for (MdmInfoColumn column : columns) {
+			if (column.getIfPrimary() == 1) {
+				primaryColumns.add(column.getColumnName());
+			}
+		}
+		// 获取查询总数量
+		sqlMap = new HashMap<>();
+		sqlMap.put("sql", "select count(0) totalnumber from (" + sql + ") temp");
+		Integer totalNumber = null;
+		try {
+			totalNumber = (Integer) daMdmFeign.listData(table.getDatabaseId(), sqlMap).get(0).get("totalnumber");
+		} catch (Exception e) {
+			result.setCode("-1");
+			result.setMsg("sql执行异常");
+			return result;
+		}
+		// 总页数
+		Integer totalPageCount = (totalNumber - 1) / pageSize + 1;
+		// 执行查询sql,获取数据
+		sqlMap.put("sql", "select * from (" + sql + ") temp limit " + (pageSize * (page - 1)) + "," + pageSize);
+		List<Map<String, Object>> listData = daMdmFeign.listData(table.getDatabaseId(), sqlMap);
+		// 获取查询sql字段列表
+		resultData.setListColumn(getListColumnBySql(sql));
+		resultData.setListData(listData);
+		resultData.setPrimaryColumns(primaryColumns);
+		result.setData(resultData);
+		result.setTotalNumber(totalNumber);
+		result.setTotalPageCount(totalPageCount);
+		result.setPage(page);
+		result.setPageSize(pageSize);
+		return result;
+	}
+
+	/**
+	 * 获取查询sql字段列表
+	 * 
+	 * @param sql
+	 * @return
+	 */
+	private List<String> getListColumnBySql(String sql) {
+		// 去除所有空格
+		sql = sql.replace("\t", "");
+		sql = sql.replace(" ", "");
+		sql = sql.replace("`", "");
+		// 转小写
+		sql = sql.toLowerCase();
+		return Arrays.asList(sql.substring(sql.indexOf("select") + 6, sql.indexOf("from")).split(","));
+	}
+
+	@Override
+	public R<List<MdmInfoDatabase>> listDatabase(String resourceName) {
+		return new R<>(daMdmFeign.listDatabase(resourceName));
+	}
+
+	@Override
+	public R<List<MdmInfoTable>> listTableByDatabaseId(String databaseId) {
+		return new R<>(daMdmFeign.listTableByDatabaseId(databaseId));
+	}
+
+	@Override
+	public R<QuerySqlDTO> getQuerySql(String tableId) {
+		QuerySqlDTO result = new QuerySqlDTO();
+		// 主键部分sql,包括 select 主键1,主键2...
+		StringBuffer primarySql = new StringBuffer();
+		// 查询部分sql,主键部分后
+		StringBuffer qureySql = new StringBuffer();
+		primarySql.append("select ");
+		MdmCreateTableDTO table = daMdmFeign.getTableInfoById(tableId).getData();
+		List<MdmInfoColumn> columns = daMdmFeign.listColumnByTableId(tableId);
+		for (MdmInfoColumn column : columns) {
+			if (column.getIfPrimary() == 1) {
+				primarySql.append(column.getColumnName()).append(",");
+			} else {
+				qureySql.append(column.getColumnName()).append(",");
+			}
+		}
+		// 去掉最后一个逗号
+		if (qureySql.length() == 0) {
+			primarySql.deleteCharAt(primarySql.length() - 1);
+		}
+		// 如果只有主键字段
+		if (qureySql != null && qureySql.length() != 0) {
+			qureySql.deleteCharAt(qureySql.length() - 1);
+		}
+		qureySql.append(" from ").append(table.getTableName()).append(" where 1=1 ");
+		result.setPrimarySql(primarySql.toString());
+		result.setQureySql(qureySql.toString());
+		return new R<>(result);
+	}
+
+	@Override
+	public R<String> updateData(UpdateDataDTO updateData) {
+		R<String> r = new R<>();
+		MdmCreateTableDTO table = daMdmFeign.getTableInfoById(updateData.getTableId()).getData();
+
+		// 判断修改后主键是否重复
+		// StringBuffer checkSql = new StringBuffer();
+		// checkSql.append(" select count(0) count from
+		// ").append(table.getTableName());
+
+		StringBuffer updateSql = new StringBuffer();
+		// 主键部分sql
+		StringBuffer whereSql = new StringBuffer();
+		// 修改后值
+		String updateValue = null;
+		List<MdmInfoColumn> columns = daMdmFeign.listColumnByTableId(updateData.getTableId());
+		whereSql.append(" where 1=1");
+		for (String primaryColumn : updateData.getPrimaryColumns()) {
+			for (MdmInfoColumn column : columns) {
+				if (column.getColumnName().equals(primaryColumn)) {
+					// 判断是否是文本类型
+					if (column.getIfChar() == 1 || column.getIsTime() == 1) {
+						whereSql.append(" and ").append(primaryColumn).append("=").append("'")
+								.append(updateData.getPrimaryData().get(primaryColumn)).append("'");
+					} else {
+						whereSql.append(" and ").append(primaryColumn).append("=")
+								.append(updateData.getPrimaryData().get(primaryColumn));
+					}
+				}
+				// 修改后值判断字段类型
+				if (updateData.getUpdateColumn().equals(column.getColumnName())) {
+					// 判断是否是文本类型
+					if (column.getIfChar() == 1 || column.getIsTime() == 1) {
+						updateValue = "'" + (String) updateData.getUpdateData().get(updateData.getUpdateColumn()) + "'";
+					} else {
+						updateValue = updateData.getUpdateData().get(updateData.getUpdateColumn()).toString();
+					}
+				}
+			}
+		}
+		Map<String, String> sqlMap = null;
+		sqlMap = new HashMap<>();
+		updateSql.append("update ").append(table.getTableName()).append(" set ");
+		updateSql.append(updateData.getUpdateColumn()).append("=").append(updateValue);
+		Integer index = null;
+
+		// 判断update语句是否有where条件,避免全量修改
+		if (whereSql.toString().contains("and")) {
+			updateSql.append(whereSql.toString());
+			// 开始判断修改后主键
+			// checkSql.append(whereSql.toString());
+			// sqlMap.put("sql", checkSql.toString());
+			// Integer count = (Integer)
+			// daMdmFeign.listData(table.getDatabaseId(),
+			// sqlMap).get(0).get("count");
+
+			sqlMap.put("sql", updateSql.toString());
+			index = daMdmFeign.executeSql(table.getDatabaseId(), sqlMap);
+		}
+		if (index == null) {
+			r.setMsg("修改失败");
+			r.setCode("-1");
+			return r;
+		}
+		r.setMsg("修改成功");
+		r.setData(index.toString());
+		return r;
+	}
+
+	@Override
+	public R<String> deleteData(UpdateDataDTO updateData) {
+		R<String> r = new R<>();
+		StringBuffer deleteSql = new StringBuffer();
+		// 主键部分sql
+		StringBuffer whereSql = new StringBuffer();
+		List<MdmInfoColumn> columns = daMdmFeign.listColumnByTableId(updateData.getTableId());
+		whereSql.append(" where 1=1");
+		for (String primaryColumn : updateData.getPrimaryColumns()) {
+			for (MdmInfoColumn column : columns) {
+				if (column.getColumnName().equals(primaryColumn)) {
+					// 判断是否是文本类型
+					if (column.getIfChar() == 1 || column.getIsTime() == 1) {
+						whereSql.append(" and ").append(primaryColumn).append("=").append("'")
+								.append(updateData.getPrimaryData().get(primaryColumn)).append("'");
+					} else {
+						whereSql.append(" and ").append(primaryColumn).append("=")
+								.append(updateData.getPrimaryData().get(primaryColumn));
+					}
+				}
+			}
+		}
+		Map<String, String> sqlMap = null;
+		sqlMap = new HashMap<>();
+		MdmCreateTableDTO table = daMdmFeign.getTableInfoById(updateData.getTableId()).getData();
+		deleteSql.append("delete from ").append(table.getTableName());
+		Integer index = null;
+		// 判断update语句是否有where条件,避免全量修改
+		if (whereSql.toString().contains("and")) {
+			deleteSql.append(whereSql.toString());
+			sqlMap.put("sql", deleteSql.toString());
+			index = daMdmFeign.executeSql(table.getDatabaseId(), sqlMap);
+		}
+		if (index == null) {
+			r.setMsg("删除失败");
+			r.setCode("-1");
+			return r;
+		}
+		r.setMsg("删除成功");
+		r.setData(index.toString());
+		return r;
+	}
+
+	@Value("${log.file.path}")
+	protected String filePath;
+
+	@Override
+	public String downloadTemplateData(String sheetName, String tableId, String sql) throws Exception {
+		//
+		List<String> list = getListColumnBySql(sql);
+		// 第一步创建workbook
+		XSSFWorkbook wb = new XSSFWorkbook();
+		// 第二步创建sheet
+		XSSFSheet sheet = wb.createSheet(sheetName);
+		// 第三步创建行row:添加表头0行
+		XSSFCellStyle style = wb.createCellStyle();
+		XSSFDataFormat format = wb.createDataFormat();
+		style.setDataFormat(format.getFormat("@"));
+		style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
+		XSSFCell cell = null;
+		// 字段ID,标题
+		List<String> listColumn = getListColumnBySql(sql);
+		XSSFRow row = sheet.createRow(0);
+		for (int i = 0; i < list.size(); i++) {
+			cell = row.createCell(i);
+			cell.setCellValue(listColumn.get(i));
+			cell.setCellStyle(style);
+		}
+		// TODO checkSql() 检验sql是否符合查询规则
+		MdmCreateTableDTO table = daMdmFeign.getTableInfoById(tableId).getData();
+		Map<String, String> sqlMap = null;
+		sqlMap = new HashMap<>();
+		// 执行查询sql,获取数据
+		sqlMap.put("sql", sql);
+		List<Map<String, Object>> listData = daMdmFeign.listData(table.getDatabaseId(), sqlMap);
+		// 第四步创建单元格
+		for (int j = 0; j < listData.size(); j++) {
+			row = sheet.createRow(j + 1);
+			for (int i = 0; i < list.size(); i++) {
+				cell = row.createCell(i);
+				if (listData.get(j).get(listColumn.get(i)) == null
+						|| listData.get(j).get(listColumn.get(i)).equals("null")) {
+					cell.setCellValue("");
+				} else {
+					cell.setCellValue((String) "" + listData.get(j).get(listColumn.get(i)));
+				}
+				cell.setCellStyle(style);
+			}
+		}
+		// 第五步将生成excel文件保存到指定路径下
+		File downloanRootPath = new File(filePath + File.separator + "file");
+		if (!downloanRootPath.isDirectory()) {
+			downloanRootPath.mkdirs();
+		}
+		long fileName = System.currentTimeMillis();
+		String filePath = downloanRootPath.getAbsolutePath() + File.separator + fileName + ".xlsx";
+		FileOutputStream fout = new FileOutputStream(filePath);
+		wb.write(fout);
+		fout.flush();
+		fout.close();
+		return filePath;
+	}
+
+	/**
+	 * 上传数据
+	 * 
+	 * @throws Exception
+	 * @throws IOException
+	 */
+	@Override
+	public R<String> loadTemplateData(String tableId, MultipartFile multipartFile) throws Exception {
+		StringBuffer fileSb = new StringBuffer(multipartFile.getOriginalFilename());
+		fileSb.insert(fileSb.indexOf("."), "_" + System.currentTimeMillis());
+		FileTool.uploadFile(multipartFile.getBytes(), "", fileSb.toString());
+		File file = new File(fileSb.toString());
+		// 获取表信息
+		MdmCreateTableDTO table = daMdmFeign.getTableInfoById(tableId).getData();
+		// 获取字段信息
+		List<MdmInfoColumn> columns = daMdmFeign.listColumnByTableId(tableId);
+		// 获取文件数据
+		List<Map<String, Object>> dataList = xlsx(file);
+		StringBuffer sqlSb = new StringBuffer();
+		StringBuffer valuesSb = new StringBuffer();
+
+		sqlSb.append("insert into ").append(table.getTableName());
+		// 逗号隔开的字段
+		StringBuffer columnSb = new StringBuffer();
+		StringBuffer updateSb = new StringBuffer();
+
+		for (Map<String, Object> data : dataList) {
+			StringBuffer valueSb = new StringBuffer();
+			// 第一行,标题行
+			if (dataList.indexOf(data) == 0) {
+				for (String key : data.keySet()) {
+					columnSb.append(data.get(key)).append(",");
+					updateSb.append(key).append("=values(").append(key).append("),");
+				}
+				continue;
+			} else {
+				for (String key : data.keySet()) {
+					for (MdmInfoColumn c : columns) {
+						// 全部转为小写做匹配
+						if (c.getColumnName().toLowerCase().equals(key.toLowerCase())) {
+							// 如果是文本型字段
+							if (c.getIfChar() == 1 || c.getIsTime() == 1) {
+								valueSb.append("'").append(data.get(key)).append("'").append(",");
+							} else {
+								if (data.get(key) == null || data.get(key).equals("")) {
+									valueSb.append("null").append(",");
+								} else {
+									valueSb.append(data.get(key)).append(",");
+								}
+							}
+						}
+					}
+				}
+				// 去除最后一位逗号
+				valueSb.deleteCharAt(valueSb.length() - 1);
+				valuesSb.append(" (").append(valueSb.toString()).append("),");
+			}
+		}
+		columnSb.deleteCharAt(columnSb.length() - 1);
+		sqlSb.append(" (").append(columnSb.toString()).append(") ");
+		valuesSb.deleteCharAt(valuesSb.length() - 1);
+		updateSb.deleteCharAt(updateSb.length() - 1);
+		sqlSb.append(" values ").append(valuesSb.toString()).append(" ");
+		sqlSb.append(" ON DUPLICATE KEY UPDATE ").append(updateSb.toString());
+		// System.out.println("sqlSb:" + sqlSb);
+		// Log.info("sqlSb:" + sqlSb);
+		Map<String, String> sqlMap = null;
+		sqlMap = new HashMap<>();
+		// 执行查询sql,获取数据
+		sqlMap.put("sql", sqlSb.toString());
+		Integer value = daMdmFeign.executeSql(table.getDatabaseId(), sqlMap);
+		file.delete();
+		R<String> r = new R<>();
+		r.setMsg("上传成功");
+		r.setData(value.toString());
+		return r;
+	}
+
+	// 如果是xlsx,做什么操作
+	protected List<Map<String, Object>> xlsx(File file) throws Exception {
+		try {
+			XSSFWorkbook xssfWorkbook = new XSSFWorkbook(new FileInputStream(file));
+			return show(xssfWorkbook);
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		return null;
+
+	}
+
+	// 他们两者都有相同的父类,而且都是父类中的方法操作,那我干脆点直接将他们用父类的形式抽取出来,这样解决了代码的冗余问题
+	private List<Map<String, Object>> show(Workbook workbook) throws Exception {
+		Row xssfRow = null;
+		Cell data = null;
+		// 每列标题
+		String key = null;
+		List<Map<String, Object>> resultList = new ArrayList<>();
+		// 循环工作表Sheet
+		for (int numSheet = 0; numSheet < workbook.getNumberOfSheets(); numSheet++) {
+			Sheet xssfSheet = workbook.getSheetAt(numSheet);
+			// 这种主要是判断是否含空以免包空指针
+			if (xssfSheet == null) {
+				continue;
+			}
+			for (int i = 0; i > 0; i++) {
+				getValue(xssfSheet.getRow(0).getCell(i), workbook);
+			}
+			// 获取展示数据格式,先行,再列-防止无限循环,默认1000列循环
+			for (int rowNum = 0; rowNum <= xssfSheet.getLastRowNum(); rowNum++) {
+				Map<String, Object> rowDataMap = new HashMap<>();
+				for (int current = 0; current < 1000; current++) {
+					// 获取每列标题,判断标题为空时,停止文件扫描跳出循环
+					if (xssfSheet.getRow(0).getCell(current) == null) {
+						break;
+					}
+					key = getValue(xssfSheet.getRow(0).getCell(current), workbook);
+
+					xssfRow = xssfSheet.getRow(rowNum);
+					data = xssfRow.getCell(current);
+					if (data == null || getValue(data, workbook).equals("")) {
+						rowDataMap.put(key, "");
+						continue;
+					}
+					rowDataMap.put(key, getValue(data, workbook));
+				}
+				resultList.add(rowDataMap);
+			}
+		}
+		return resultList;
+	}
+
+	// 将他们两者的父类抽取出来,这样减少代码量,同时便于管理
+	private String getValue(Cell xssfCell, Workbook workbook) {
+		String value = "";
+		switch (xssfCell.getCellType()) {
+		case Cell.CELL_TYPE_STRING:
+			value = String.valueOf(xssfCell.getRichStringCellValue().getString());
+			break;
+		case Cell.CELL_TYPE_NUMERIC:
+			if (DateUtil.isCellDateFormatted(xssfCell)) {
+				value = String.valueOf(String.valueOf(xssfCell.getDateCellValue()));
+			} else {
+				value = String.valueOf(xssfCell.getNumericCellValue());
+				if (value.endsWith(".0")) {
+					value = value.replace(".0", "");
+				}
+			}
+			break;
+		case Cell.CELL_TYPE_BOOLEAN:
+			value = String.valueOf(xssfCell.getBooleanCellValue());
+			break;
+		// 公式,
+		case Cell.CELL_TYPE_FORMULA:
+			// 获取Excel中用公式获取到的值,//=SUM(P4-Q4-R4-S4)Excel用这种类似的公式计算出来的值用POI无法获取,要想获取的话,就必须一下操作
+			FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
+			evaluator.evaluateFormulaCell(xssfCell);
+			CellValue cellValue = evaluator.evaluate(xssfCell);
+			value = String.valueOf(cellValue.getNumberValue());
+			break;
+		case Cell.CELL_TYPE_ERROR:
+			value = String.valueOf(xssfCell.getErrorCellValue());
+			break;
+		default:
+		}
+		return value;
+	}
+
+}

+ 19 - 0
da/src/main/java/com/datau/da/service/job/JobPutService.java

@@ -0,0 +1,19 @@
+package com.datau.da.service.job;
+
+import com.datau.da.entity.task.Task;
+
+/**
+ * @author 许明
+ * on 2019/3/6.
+ * @version 2.0.0
+ */
+public interface JobPutService {
+
+    public boolean isRunnable(Task task);
+    /**
+     *
+     * @description job运行条件判断
+     * @param task
+     */
+    public void jobRunConditionJudge(Task task);
+}

+ 11 - 0
da/src/main/java/com/datau/da/service/job/JobService.java

@@ -0,0 +1,11 @@
+package com.datau.da.service.job;
+
+/**
+ * @author 许明
+ * on 2019/3/7.
+ * @version 2.0.0
+ */
+public interface JobService {
+
+    int init() throws Exception;
+}

+ 13 - 0
da/src/main/java/com/datau/da/service/job/ScheDisruptInitService.java

@@ -0,0 +1,13 @@
+package com.datau.da.service.job;
+
+/**
+ * @author 许明
+ * on 2019/3/7.
+ * @version 2.0.0
+ * 调度进程无锁队列初始化Service
+ */
+public interface ScheDisruptInitService {
+
+    public void initJobConJudgeDisruptor();
+
+}

+ 21 - 0
da/src/main/java/com/datau/da/service/job/ScheduleJobContainerManagerService.java

@@ -0,0 +1,21 @@
+package com.datau.da.service.job;
+
+import org.quartz.SchedulerException;
+
+import java.text.ParseException;
+
+/**
+ * @author 许明
+ * on 2019/3/13.
+ * @version 2.0.0
+ */
+public interface ScheduleJobContainerManagerService
+{
+    /**
+     *
+     * @description 初始化内存库job到进程内存
+     * @return
+     */
+    public int initMemJobToCache() throws ParseException, SchedulerException;
+
+}

+ 57 - 0
da/src/main/java/com/datau/da/service/job/TimeTriggerJobListener.java

@@ -0,0 +1,57 @@
+package com.datau.da.service.job;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.quartz.JobKey;
+import org.quartz.JobListener;
+
+/**
+ * @author 许明
+ * on 2019/3/7.
+ * @version 2.0.0
+ */
+public class TimeTriggerJobListener implements JobListener
+{
+    private static final Logger logger = LogManager.getLogger(TimeTriggerJobListener.class);
+
+    /**
+     * @see org.quartz.JobListener#getName()
+     */
+    public String getName()
+    {
+        return getClass().getSimpleName();
+    }
+
+    /**
+     * @see org.quartz.JobListener#jobExecutionVetoed(org.quartz.JobExecutionContext)
+     *      Scheduler 在 JobDetail 即将被执行,但又被 TriggerListener 否决了时调用这个方法。
+     */
+    public void jobExecutionVetoed(JobExecutionContext context)
+    {
+        JobKey jobName = context.getJobDetail().getKey();
+        logger.debug(jobName + " is about to be executed");
+    }
+
+    /**
+     * @see org.quartz.JobListener#jobToBeExecuted(org.quartz.JobExecutionContext)
+     *      Scheduler 在 JobDetail 将要被执行时调用这个方法。
+     */
+    public void jobToBeExecuted(JobExecutionContext context)
+    {
+        JobKey jobName = context.getJobDetail().getKey();
+        logger.debug("quartz任务:::" + jobName + ":::开始执行");
+    }
+
+    /**
+     * @see org.quartz.JobListener#jobWasExecuted(org.quartz.JobExecutionContext,
+     *      org.quartz.JobExecutionException) Scheduler 在 JobDetail 被执行之后调用这个方法。
+     */
+    public void jobWasExecuted(JobExecutionContext context, JobExecutionException exception)
+    {
+        JobKey jobName = context.getJobDetail().getKey();
+        logger.debug("quartz触发任务JOB_NAME[" + jobName + "]执行结束");
+    }
+
+}

+ 103 - 0
da/src/main/java/com/datau/da/service/job/impl/FrequencyTriggerJob.java

@@ -0,0 +1,103 @@
+package com.datau.da.service.job.impl;
+
+import com.datau.da.constant.Constant;
+import com.datau.da.entity.task.Task;
+import com.datau.da.job.JobServer;
+import com.datau.da.service.job.ScheDisruptInitService;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.BeanFactory;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author 许明
+ * on 2019/3/7.
+ * @version 2.0.0
+ * 频次触发调度
+ */
+public class FrequencyTriggerJob implements org.quartz.Job{
+
+    private static final Logger logger = LogManager.getLogger(FrequencyTriggerJob.class);
+
+    private static final String JOB_KEY = "jobid";
+
+    /**
+     * @see org.quartz.Job#execute(org.quartz.JobExecutionContext)
+     */
+    public void execute(JobExecutionContext context) throws JobExecutionException
+    {
+//        JobDetail jobDetail = context.getJobDetail();
+//        Date current = new Date();
+//        // 获取本次要执行的job信息,以及对应的时间出发表达式信息
+//        String jobid = (String) jobDetail.getJobDataMap().get(JOB_KEY);
+//        logger.debug("quartz任务JOBID[" + jobid + "]达到运行条件");
+//
+//        Task thisJob = JobServer.MEM_JOB_CACHE.get(jobid);
+//        SimpleDateFormat format = new SimpleDateFormat();
+//        format.applyPattern(thisJob.getDataFormat());
+//        if (Constant.JOB_RUN_SUSPEND == thisJob.getRunStatus() || Constant.JOB_RUN_HANG_UP == thisJob.getRunStatus()
+//                || Constant.JOB_RUN_LOCK == thisJob.getRunStatus())
+//        {
+//            logger.debug("job[" + jobid + "]处于暂停|挂起|锁定状态不进行触发");
+//        }
+//        else if ((thisJob.getTaskStatus() == Constant.JOB_RUN_WAIT || thisJob.getRunStatus() == Constant.JOB_RUN_START)
+//                && thisJob.getIsParallel() == Constant.CANNOT_PARALLEL)
+//        {
+//            // 写执行日志,当前时间未执行
+//            logger.warn("job[" + jobid + "]处于正在运行且不能并行,等待下次运行");
+//        }
+//        else
+//        {
+//            Date jobDataDate = getJobDataDate(thisJob, current);
+//            Task runJob = new Task();
+//            BeanUtils.copyProperties(thisJob, runJob);
+//            runJob.setJobDataDate(format.format(jobDataDate));
+//            runJob.setJobRunTriggerType(Constant.JOB_NORMAL_TRIGGER_TYPE);
+//            // 修改执行状态,当前丢入可执行队列,准备运行
+//            thisJob.setTaskStatus(Constant.JOB_RUN_WAIT);
+//            ScheDisruptInitService scheDisruptInitService = (ScheDisruptInitService) BeanFactory.getBean("scheDisruptInitServiceImpl");
+//            scheDisruptInitService.publishJobParseEvent(runJob);
+//            logger.debug("Job[JOB_ID=" + jobid + "]达到运行条件,放入可执行队列运行");
+//        }
+    }
+
+    private Date getJobDataDate(Task job, Date date)
+    {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        switch (job.getPeriodType())
+        {
+            case Constant.JOB_PERIOD_YEAR:
+                cal.add(Calendar.YEAR, -1);
+                break;
+            case Constant.JOB_PERIOD_WEEK:
+                cal.add(Calendar.WEEK_OF_YEAR, -1);
+                break;
+            case Constant.JOB_PERIOD_MONTH:
+                cal.add(Calendar.MONTH, -1);
+                break;
+            case Constant.JOB_PERIOD_DAY:
+                cal.add(Calendar.DAY_OF_YEAR, -1);
+                break;
+            case Constant.JOB_PERIOD_HOUR:
+                cal.add(Calendar.HOUR, -1);
+                break;
+            case Constant.JOB_PERIOD_MINUTE:
+                cal.add(Calendar.MINUTE, -1);
+                break;
+            case Constant.JOB_PERIOD_SECONDS:
+                cal.add(Calendar.SECOND, -1);
+                break;
+            default:
+                logger.error("JOB[" + job.getTaskName() + "]的周期类型错误");
+                break;
+        }
+        return cal.getTime();
+    }
+}

+ 217 - 0
da/src/main/java/com/datau/da/service/job/impl/JobPutServiceImpl.java

@@ -0,0 +1,217 @@
+package com.datau.da.service.job.impl;
+
+import com.datau.da.constant.Constant;
+import com.datau.da.entity.task.Task;
+import com.datau.da.service.job.JobPutService;
+import org.apache.commons.lang.time.DateUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.quartz.CronExpression;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author 许明
+ * on 2019/3/6.
+ * @version 2.0.0
+ */
+@Service
+@Transactional(rollbackFor = Exception.class)
+public class JobPutServiceImpl implements JobPutService {
+
+    private static final Logger logger = LogManager.getLogger(JobPutServiceImpl.class);
+
+    @Override
+    public void jobRunConditionJudge(Task task) {
+        logger.info("进入job执行条件判断Thread,job[" + task.getId() + "]");
+        boolean isRunnable = isRunnable(task);
+        //如果满足运行条件,则job放到quartz执行
+        if (isRunnable) {
+            SchedulerTimeTriggeJob.scheduler(task);
+        }
+        else{
+        	logger.info("JOB[" + task.getId() + "]不满足启用条件,无法启用!");
+        }
+        logger.info("thread end =======");
+    }
+
+    @Override
+    public boolean isRunnable(Task task) {
+        boolean flag = true;
+        try {
+        	if("2".equals(task.getRunStatus())){
+        		logger.info("JOB[" + task.getId() + "]未启用,启用后生效!");
+            	return false;
+        	}
+            //job处于等待运行或运行中状态,无法再次启用
+            if(!"0,3,4".contains(task.getRunStatus())){
+            	logger.info("JOB[" + task.getId() + "]处于等待运行或运行中状态,无法再次启用!");
+            	return false;
+            }
+            // TODO: 2019/3/8 如果后续有其他触发类型,再进行触发类型的判断
+//            flag = fixeTimeTrigger(task);
+        } catch (Exception e) {
+            logger.error("判断JOB[jobId=" + task.getId() + "]是否达到运行条件出错!", e);
+        }
+        return flag;
+    }
+
+
+    /**
+     * @param task 一个JOB任务
+     * @return true:满足运行条件,false:不满足运行条件
+     * @description 定时触发
+     */
+    private boolean fixeTimeTrigger(Task task) throws Exception {
+        try {
+            String taskCron = task.getTaskCron();
+            // 正常跑数据的流程判断 0,0,8,*,*,?
+            CronExpression cronExpression = new CronExpression(taskCron);
+            Date nextValidTime = cronExpression.getNextValidTimeAfter(getReference(task));
+            nextValidTime = filterNextValidTime(task, nextValidTime);
+            if (nextValidTime != null) {
+                Date date = new Date();
+                // 计算配置调度时间和当前时间时间间隔
+                long timeInterval = date.getTime() - nextValidTime.getTime();
+                return timeInterval >= -1000;
+            }
+        } catch (ParseException e) {
+            logger.error("JOB[jobId=" + task.getId() + "]的Cron表达式错误!", e);
+        }
+        return false;
+    }
+
+    /**
+     * @param job 一个JOB任务
+     * @return Date:按 不同周期类型格式化后的当前时间
+     * @description 获取当前JOB的下次运行时间的参照时间点
+     */
+    private Date getReference(Task job) {
+        Date current = null;
+        try {
+            job.setDataFormat(getDataFormatByPeriodType(job.getPeriodType()));
+            SimpleDateFormat format = new SimpleDateFormat(job.getDataFormat());
+            String current4format = format.format(new Date());
+            current = format.parse(current4format);
+        } catch (ParseException e) {
+            logger.error("JOB[" + job.getId() + "]数据日期和数据日期格式不匹配!", e);
+        }
+        return current;
+    }
+
+    private String getDataFormatByPeriodType(int periodType){
+        String dataFormat = "";
+        switch (periodType){
+            case 1:
+                dataFormat = "yyyyMM";
+                break;
+            case 2:
+                dataFormat = "yyyyMMdd";
+                break;
+            case 3:
+                dataFormat = "yyyyMMddHH";
+                break;
+            case 4:
+                dataFormat = "yyyyMMddHHmm";
+                break;
+            case 5:
+                dataFormat = "yyyyMMddHHmmss";
+                break;
+            default:
+                break;
+        }
+        return dataFormat;
+    }
+
+    private static Date filterNextValidTime(Task job, Date nextValidTime) {
+        Date date = nextValidTime;// 下次运行时间
+        if (null != job && null != nextValidTime) {
+            int offset = -1;
+            Calendar calendar = Calendar.getInstance();
+            calendar.setTime(date);
+            boolean isMillisZero = (calendar.get(Calendar.MILLISECOND) == 0);
+            boolean isSecondZero = (calendar.get(Calendar.SECOND) == 0);
+            boolean isMinuteZero = (calendar.get(Calendar.MINUTE) == 0 && isSecondZero);
+            boolean isHourZero = (calendar.get(Calendar.HOUR) == 0 && isMinuteZero);
+            switch (job.getPeriodType()) {
+                case Constant.JOB_PERIOD_YEAR:
+                    break;
+                case Constant.JOB_PERIOD_MONTH:
+                    Calendar nowCalendar = Calendar.getInstance();
+                    if (isHourZero) {
+                        if (calendar.get(Calendar.YEAR) > nowCalendar.get(Calendar.YEAR)
+                                || calendar.get(Calendar.MONTH) > nowCalendar.get(Calendar.MONTH)) {
+                            date = DateUtils.addMonths(nextValidTime, offset);
+                        }
+                    }
+                    break;
+                case Constant.JOB_PERIOD_WEEK:
+                    Calendar nowCalendar2 = Calendar.getInstance();
+                    if (isHourZero) {
+                        if (calendar.get(Calendar.DAY_OF_WEEK) <= nowCalendar2.get(Calendar.DAY_OF_WEEK)) {
+                            date = DateUtils.addWeeks(nextValidTime, offset);
+                        }
+                    } else {
+                        if (calendar.get(Calendar.DAY_OF_WEEK) < nowCalendar2.get(Calendar.DAY_OF_WEEK)) {
+                            date = DateUtils.addWeeks(nextValidTime, offset);
+                        }
+                    }
+                    break;
+                case Constant.JOB_PERIOD_DAY:
+                    if (isHourZero) {
+                        date = DateUtils.addDays(nextValidTime, offset);
+                    }
+                    break;
+                case Constant.JOB_PERIOD_HOUR:
+                    if (isMinuteZero) {
+                        date = DateUtils.addHours(nextValidTime, offset);
+                    }
+                    break;
+                case Constant.JOB_PERIOD_MINUTE:
+                    if (isSecondZero) {
+                        date = DateUtils.addMinutes(nextValidTime, offset);
+                    }
+                    break;
+                case Constant.JOB_PERIOD_SECONDS:
+                    if (isMillisZero) {
+                        date = DateUtils.addSeconds(nextValidTime, offset);
+                    }
+                    break;
+                default:
+                    logger.warn("JOB[jobId==" + job.getId() + "]的周期类型配置错误!");
+                    break;
+            }
+        }
+        return date;
+    }
+
+
+    public static void main(String[] args) throws Exception{
+        CronExpression cronExpression = new CronExpression("0 0 1 9 3 ? 2019");
+        Date current = null;
+        SimpleDateFormat format = new SimpleDateFormat("yyyMM");
+        SimpleDateFormat format1 = new SimpleDateFormat("yyyMM");
+        String current4format = format.format(new Date());
+        current = format.parse(current4format);
+        Date nextValidTime = cronExpression.getNextValidTimeAfter(current);
+
+        System.out.println(format1.format(nextValidTime) +"=============1");
+        Task task = new Task();
+        task.setPeriodType(1);
+        nextValidTime = filterNextValidTime(task, nextValidTime);
+
+        System.out.println(format1.format(nextValidTime) +"------2");
+        if (nextValidTime != null) {
+            Date date = new Date();
+            // 计算配置调度时间和当前时间时间间隔
+            long timeInterval = date.getTime() - nextValidTime.getTime();
+            System.out.println(timeInterval +"============");
+            System.out.println(timeInterval >= -1000);
+        }
+    }
+}

+ 62 - 0
da/src/main/java/com/datau/da/service/job/impl/JobServiceImpl.java

@@ -0,0 +1,62 @@
+package com.datau.da.service.job.impl;
+
+import com.datau.da.constant.Constant;
+import com.datau.da.service.job.JobService;
+import com.datau.da.service.job.ScheDisruptInitService;
+import com.datau.da.service.job.ScheduleJobContainerManagerService;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author 许明
+ * on 2019/3/7.
+ * @version 2.0.0
+ */
+@Service
+@Transactional(rollbackFor = Exception.class)
+public class JobServiceImpl implements JobService {
+
+    private static final Logger logger = LogManager.getLogger(JobServiceImpl.class);
+    private static boolean initFlag = false;
+
+    @Autowired
+    private ScheDisruptInitService scheDisruptInitService;
+    @Autowired
+    private ScheduleJobContainerManagerService scheduleJobContainerManagerService;
+
+    @Override
+    public int init() throws Exception {
+        if (!(initFlag)) {
+            logger.info("进入数据中心调度任务轮询初始化方法init ...........................");
+            initFlag = true;
+            try
+            {
+                if(Constant.RETURN_FAILD == SchedulerTimeTriggeJob.initScheduler()){
+                    logger.error("调度初始化Scheduler实例失败");
+                }
+                else{
+                    SchedulerTimeTriggeJob.start();
+                    SchedulerTimeTriggeJob.clear();
+                }
+            }
+            catch (SchedulerException e)
+            {
+                logger.error("启动Scheduler实例失败.........", e);
+                return Constant.RETURN_FAILD;
+            }
+            logger.info("初始化调度信息到内存.........");
+            if(Constant.RETURN_FAILD == scheduleJobContainerManagerService.initMemJobToCache()){
+                logger.error("初始化调度信息到内存失败.........");
+                return Constant.RETURN_FAILD;
+            }
+//            scheduleJobContainerManagerService.startJobContainerSchedule();
+            logger.info("初始化job运行条件判断线程.........");
+            scheDisruptInitService.initJobConJudgeDisruptor();
+        }
+        return Constant.RETURN_OK;
+    }
+}

+ 48 - 0
da/src/main/java/com/datau/da/service/job/impl/ScheDisruptInitServiceImpl.java

@@ -0,0 +1,48 @@
+package com.datau.da.service.job.impl;
+
+import com.datau.da.constant.Constant;
+import com.datau.da.handler.ScheduleRoundEventHandler;
+import com.datau.da.handler.ScheduleRoundExceptionHandler;
+import com.datau.da.job.JobServer;
+import com.datau.da.entity.model.ScheduleRoundEvent;
+import com.datau.da.service.job.ScheDisruptInitService;
+import com.lmax.disruptor.BlockingWaitStrategy;
+import com.lmax.disruptor.RingBuffer;
+import com.lmax.disruptor.Sequence;
+import com.lmax.disruptor.WorkerPool;
+import com.lmax.disruptor.dsl.ProducerType;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.concurrent.Executors;
+
+/**
+ * @author 许明
+ * on 2019/3/7.
+ * @version 2.0.0
+ */
+@Service
+@Transactional(rollbackFor = Exception.class)
+public class ScheDisruptInitServiceImpl implements ScheDisruptInitService {
+
+    private static final Logger logger = LogManager.getLogger(ScheDisruptInitServiceImpl.class);
+
+    @Override
+    public void initJobConJudgeDisruptor() {
+        JobServer.SCHEDULE_CONDITION_JUDGE_BUFFER = RingBuffer.create(ProducerType.SINGLE, ScheduleRoundEvent.EVENT_FACTORY, 64 * 1024,
+                new BlockingWaitStrategy());
+        ScheduleRoundEventHandler[] scheRoundEventHandler = new ScheduleRoundEventHandler[Constant.SCHEDU_JOBCONDITION_JUDGE_NUM];
+        for (int i = 0; i < Constant.SCHEDU_JOBCONDITION_JUDGE_NUM; i++)
+        {
+            scheRoundEventHandler[i] = new ScheduleRoundEventHandler();
+        }
+        WorkerPool<ScheduleRoundEvent> workerPool = new WorkerPool<ScheduleRoundEvent>(JobServer.SCHEDULE_CONDITION_JUDGE_BUFFER,
+                JobServer.SCHEDULE_CONDITION_JUDGE_BUFFER.newBarrier(), new ScheduleRoundExceptionHandler(), scheRoundEventHandler);
+        Sequence[] sequences = workerPool.getWorkerSequences();
+        JobServer.SCHEDULE_CONDITION_JUDGE_BUFFER.addGatingSequences(sequences);
+        workerPool.start(Executors.newFixedThreadPool(Constant.SCHEDU_JOBCONDITION_JUDGE_NUM));
+        logger.info("调度条件判断线程 处理个数[" + Constant.SCHEDU_JOBCONDITION_JUDGE_NUM + "]");
+    }
+}

+ 52 - 0
da/src/main/java/com/datau/da/service/job/impl/ScheduleJobContainerManagerServiceImpl.java

@@ -0,0 +1,52 @@
+package com.datau.da.service.job.impl;
+
+import com.datau.da.constant.Constant;
+import com.datau.da.dao.TaskDao;
+import com.datau.da.entity.task.Task;
+import com.datau.da.job.JobServer;
+import com.datau.da.service.job.ScheduleJobContainerManagerService;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.quartz.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.ParseException;
+import java.util.List;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * @author 许明
+ * on 2019/3/13.
+ * @version 2.0.0
+ */
+@Service
+public class ScheduleJobContainerManagerServiceImpl implements ScheduleJobContainerManagerService
+{
+	private static final Logger logger = LogManager.getLogger(ScheduleJobContainerManagerServiceImpl.class);
+
+	private static final ReentrantLock jobFlowStructLock = new ReentrantLock();
+
+	@Autowired
+	private TaskDao taskDao;
+
+	@Override
+	public int initMemJobToCache() throws ParseException, SchedulerException {
+		List<Task> taskList = taskDao.getAllInitJob();
+		if (taskList == null)
+		{
+			return Constant.RETURN_FAILD;
+		}
+		for (Task task : taskList)
+		{
+			JobServer.MEM_JOB_CACHE.put(task.getId(), task);
+		}
+		logger.info("job信息由数据库加载到内存成功..........");
+		logger.info("开始重新刷新所有调度的定时器....");
+        SchedulerTimeTriggeJob.putMemJobSchedule(taskList);
+		logger.info("重新刷新所有调度的定时器结束....");
+		taskList.clear();
+		return Constant.RETURN_OK;
+	}
+
+}

+ 260 - 0
da/src/main/java/com/datau/da/service/job/impl/SchedulerTimeTriggeJob.java

@@ -0,0 +1,260 @@
+package com.datau.da.service.job.impl;
+
+import com.datau.da.constant.Constant;
+import com.datau.da.entity.task.Task;
+import com.datau.da.service.job.TimeTriggerJobListener;
+import com.datau.da.utils.CronExpresUtil;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.quartz.*;
+import org.quartz.impl.StdSchedulerFactory;
+
+import java.text.ParseException;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author 许明
+ * on 2019/3/7.
+ * @version 2.0.0
+ * 时间触发调度
+ */
+public class SchedulerTimeTriggeJob {
+
+    private static final Logger logger = LogManager.getLogger(SchedulerTimeTriggeJob.class);
+
+    private static final String cronTriggers = "CRONTRIGGER";
+    private static final String JOB_KEY = "jobid";
+
+    public static Scheduler scheduler = null;
+
+    /**
+     * @return
+     * @description 非周期job初始化线程池
+     */
+    public static int initScheduler() {
+        synchronized (SchedulerTimeTriggeJob.class) {
+            try {
+                if (null == scheduler) {
+                    scheduler = StdSchedulerFactory.getDefaultScheduler();
+                    scheduler.getListenerManager().addJobListener(new TimeTriggerJobListener());
+                    logger.info("创建Scheduler实例成功.........");
+                }
+            } catch (Exception e) {
+                scheduler = null;
+                logger.error("创建Scheduler实例异常............", e);
+                return Constant.RETURN_FAILD;
+            }
+            return Constant.RETURN_OK;
+        }
+    }
+
+    public static void start() throws SchedulerException {
+        scheduler.start();
+    }
+
+    /**
+     * @throws SchedulerException
+     * @description TODO
+     */
+    public static void standby() throws SchedulerException {
+        scheduler.standby();
+    }
+
+    public static void clear() throws SchedulerException {
+        scheduler.clear();
+    }
+
+    public static void putMemJobSchedule(List<Task> taskList) throws SchedulerException, ParseException {
+        for(Task task : taskList){
+            scheduleFixedJob(scheduler, task, true);
+        }
+    }
+
+    /**
+     * @param scheduler
+     * @param timetriggerjob
+     * @param isReplaceIfExist 是否覆盖quartz中已经存在的同名job
+     * @throws SchedulerException
+     * @throws ParseException
+     * @description 装配时间触发调度事件
+     */
+    private static void scheduleFixedJob(Scheduler scheduler, Task timetriggerjob, boolean isReplaceIfExist)
+            throws SchedulerException, ParseException {
+        Date current = new Date();
+        // 配置Job
+        String jobid = timetriggerjob.getId();
+        JobKey jobKey = new JobKey(jobid);
+        JobDetail job = JobBuilder.newJob(TimeTriggerJob.class).withIdentity(jobKey).build();
+
+        job.getJobDataMap().put(JOB_KEY, timetriggerjob.getId());
+        // 配置时间触发器,可以为每个job配置多个触发器
+        Set<CronTrigger> triggers = new HashSet<CronTrigger>();
+        CronTrigger trigger = null;
+        String taskCron = timetriggerjob.getTaskCron();
+        //获取符合cron表达式的下次执行时间
+        Date nextFiredTime = getNextFiredDate(taskCron, current);
+        trigger = TriggerBuilder.newTrigger().withIdentity(jobid).withSchedule(CronScheduleBuilder.cronSchedule(taskCron)).startAt(nextFiredTime).build();
+        triggers.add(trigger);
+        if (CronExpresUtil.getNextFiredTime(triggers, current).getTime() - current.getTime() < Constant.THREAD_SCANJOB_INTERVAL) {
+            job.getJobDataMap().put(cronTriggers, triggers);
+            scheduler.scheduleJob(job, triggers, isReplaceIfExist);
+        }
+    }
+
+    /**
+     * @param task
+     * @description 时间触发调度,将job添加到quartz中去
+     */
+    public static void scheduler(Task task) {
+        String taskCron = task.getTaskCron();
+        String jobid = task.getId();
+        if (null == taskCron || taskCron.isEmpty()) {
+            logger.warn("quartz任务触发异常[" + jobid + "]对应CRON为空,JOB不执行");
+            return;
+        }
+        try {
+            scheduler(task, taskCron, true);
+        } catch (SchedulerException e) {
+            logger.error("quartz任务触发异常[" + jobid + "]", e);
+        } catch (ParseException e) {
+            logger.error("quartz任务触发异常[" + jobid + "]配置错误,解析异常", e);
+        }
+    }
+
+    /**
+     * @param job
+     * @param taskCron
+     * @throws SchedulerException
+     * @throws ParseException
+     * @description scheduler重载方法,提供job以及对应的cron表达式
+     */
+    public static void scheduler(Task job, String taskCron, boolean isReplaceIfExist) throws SchedulerException, ParseException {
+        String jobid = job.getId();
+        if (!taskCron.isEmpty()) {
+            // 如果job被修改,则quartz覆盖scheduler中已经存在的scheduler job
+            logger.info("quartz任务job key[" + jobid + "].........");
+            if (scheduler.getJobDetail(new JobKey(jobid)) == null || isReplaceIfExist) {
+                scheduleFixedJob(scheduler, job, taskCron, isReplaceIfExist);
+            }
+        }
+    }
+
+    /**
+     * @param scheduler
+     * @param timetriggerjob
+     * @param taskCron
+     * @param isReplaceIfExist 是否覆盖quartz中已经存在的同名job
+     * @throws SchedulerException
+     * @throws ParseException
+     * @description 装配时间触发调度事件
+     */
+    private static void scheduleFixedJob(Scheduler scheduler, Task timetriggerjob, String taskCron, boolean isReplaceIfExist)
+            throws SchedulerException, ParseException {
+        Date current = new Date();
+        // 配置Job
+        String jobid = timetriggerjob.getId();
+        JobKey jobKey = new JobKey(jobid);
+        JobDetail job = JobBuilder.newJob(TimeTriggerJob.class).withIdentity(jobKey).build();
+
+        job.getJobDataMap().put(JOB_KEY, timetriggerjob.getId());
+        // 配置时间触发器,可以为每个job配置多个触发器
+        Set<CronTrigger> triggers = new HashSet<CronTrigger>();
+        CronTrigger trigger = null;
+        //获取符合cron表达式的下次执行时间
+        Date nextFiredTime = getNextFiredDate(taskCron, current);
+        trigger = TriggerBuilder.newTrigger().withIdentity(jobid).withSchedule(CronScheduleBuilder.cronSchedule(taskCron)).startAt(nextFiredTime).build();
+        triggers.add(trigger);
+        if (CronExpresUtil.getNextFiredTime(triggers, current).getTime() - current.getTime() < Constant.THREAD_SCANJOB_INTERVAL) {
+            job.getJobDataMap().put(cronTriggers, triggers);
+            scheduler.scheduleJob(job, triggers, isReplaceIfExist);
+        }
+    }
+
+    public static Date getNextFiredDate(String taskCron, Date date) throws ParseException {
+        Date result = null;
+        Date nextFiretime = null;
+        CronExpression cron = new CronExpression(taskCron);
+        nextFiretime = cron.getTimeAfter(date);
+        if (null == nextFiretime) {
+            return result;
+        }
+        if (null != nextFiretime) {
+            result = (null == result ? nextFiretime : (nextFiretime.before(result) ? nextFiretime : result));
+        }
+        return result;
+    }
+
+    /**
+     *
+     * @description 根据job id 删除相应的job
+     * @param task
+     * @return
+     */
+    public static void deleteJobByJobId(Task task)
+    {
+        try
+        {
+            if (null != scheduler)
+            {
+                scheduler.deleteJob(new JobKey(task.getId()));
+            }
+        }
+        catch (SchedulerException e)
+        {
+            logger.error("删除JOB异常,JOB_ID[" + task.getId() + "]", e);
+        }
+    }
+
+    /**
+     * 停止job
+     * @param task
+     */
+    public static void shutDownJobByJobid(Task task)
+    {
+        try
+        {
+            scheduler.deleteJob(new JobKey(task.getId()));
+        }
+        catch (SchedulerException e)
+        {
+            logger.error("停止quartz中的job失败[" + task.getId() + "]", e);
+        }
+    }
+
+    /**
+     *
+     * @description 更新时间触发job相关配置信息
+     * @param timetriggerjob
+     *            job
+     * @param taskCcron
+     *            job对应cron表达式
+     * @return
+     */
+    public static void updateJobByJobid(Task timetriggerjob, String taskCcron)
+    {
+        try
+        {
+            if (scheduler.checkExists(new JobKey(timetriggerjob.getId())))
+            {
+                // 如果更新的Job存在
+                scheduler(timetriggerjob, taskCcron, true);
+            }
+            else
+            {
+                // 如果不存在
+                scheduler(timetriggerjob);
+            }
+        }
+        catch (SchedulerException e)
+        {
+            logger.error("Job__" + timetriggerjob.getId() + "__任务更新失败,SchedulerException happened ", e);
+        }
+        catch (ParseException e)
+        {
+            logger.error("Job__" + timetriggerjob.getId() + "__任务更新失败,ParseException happened ", e);
+        }
+    }
+}

+ 82 - 0
da/src/main/java/com/datau/da/service/job/impl/TimeTriggerJob.java

@@ -0,0 +1,82 @@
+package com.datau.da.service.job.impl;
+
+import com.datau.da.constant.Constant;
+import com.datau.da.entity.task.Task;
+import com.datau.da.job.JobServer;
+import com.datau.da.utils.CronExpresUtil;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.quartz.*;
+
+import java.util.Date;
+import java.util.Set;
+
+/**
+ * @author 许明
+ * on 2019/3/11.
+ * @version 2.0.0
+ */
+public class TimeTriggerJob implements org.quartz.Job {
+
+    private static final Logger logger = LogManager.getLogger(TimeTriggerJob.class);
+
+    // 存放在JobDataMap中的crontrigger的名称
+    private static final String cronTriggers = "CRONTRIGGER";
+
+    private static final String JOB_KEY = "jobid";
+
+    public static TimeTriggerJob timeTriggerJob;
+
+    /**
+     * @param context
+     * @return
+     * @description 达到job运行时间后执行的操作,将job加入到可执行队列中去
+     */
+    @SuppressWarnings("unchecked")
+    public void execute(JobExecutionContext context) throws JobExecutionException {
+        JobDetail jobDetail = context.getJobDetail();
+        // 获取本次要执行的job信息,以及对应的时间出发表达式信息
+        String jobid = (String) jobDetail.getJobDataMap().get(JOB_KEY);
+        logger.info("当前定时器中jobid为:" + jobid);
+        Set<CronTrigger> cronList = (Set<CronTrigger>) jobDetail.getJobDataMap().get(cronTriggers);
+        Date current = new Date();
+        Date nextFireTime = CronExpresUtil.getNextFiredTime(cronList, current);
+        logger.info("quartz任务JOBID[" + jobid + "]达到运行条件");
+        logger.info("job[" + jobid + "]nextFireTime[" + nextFireTime + "]");
+
+        Task thisJob = JobServer.MEM_JOB_CACHE.get(jobid);
+        //任务状态,1:启用,2:停用
+        if ("2".equals(thisJob.getTaskStatus())) {
+            logger.info("job[" + jobid + "]处于未启用状态不进行触发");
+        }
+        // 将job放入执行队列start,首先需要判断前次执行是否完毕,是否可以并行
+        // job在运行不允许并行
+        // 任务运行状态,0:未运行,1:等待运行,2:运行中,3:运行完成,4:运行失败
+        else if ("1,2".contains(thisJob.getRunStatus())) {
+            // 写执行日志,当前时间未执行
+            logger.info("job[" + jobid + "]处于等待运行或运行中状态,不进行并行触发");
+        } else {
+            logger.info("JOBID[" + jobid + "]开始进行数据采集任务");
+            TriggerJob triggerJob = new TriggerJob();
+            String result = "";
+            try {
+                result = triggerJob.execute(jobid, nextFireTime);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            if ("0".equals(result)) {
+                logger.info("JOBID[" + jobid + "]进行数据采集任务成功");
+            }
+            if ("-1".equals(result)) {
+                logger.info("JOBID[" + jobid + "]进行数据采集任务失败");
+            }
+        }
+        if (null == nextFireTime || (nextFireTime.getTime() - current.getTime()) > Constant.THREAD_SCANJOB_INTERVAL) {
+            try {// 下次执行时间为空,job执行完成,没有可运行trigger,删除该job
+                context.getScheduler().deleteJob(new JobKey(jobid));
+            } catch (SchedulerException e) {
+                logger.error("将job[" + jobid + "]从schedule删除异常", e);
+            }
+        }
+    }
+}

+ 653 - 0
da/src/main/java/com/datau/da/service/job/impl/TriggerJob.java

@@ -0,0 +1,653 @@
+package com.datau.da.service.job.impl;
+
+import com.datau.da.constant.Constant;
+import com.datau.da.dao.TaskDao;
+import com.datau.da.entity.mail.ErrorJobInfo;
+import com.datau.da.entity.remotedb.MdmInfoDatabase;
+import com.datau.da.entity.task.Task;
+import com.datau.da.feign.DaMdmFeign;
+import com.datau.da.job.JobServer;
+import com.datau.da.utils.CommonConfUtil;
+import com.datau.da.utils.ConnectionUtil;
+import com.datau.da.utils.mail.MailUtil;
+import org.apache.commons.lang.time.DateUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.PostConstruct;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.sql.*;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * @author 许明
+ * on 2019/3/11.
+ * @version 2.0.0
+ */
+@Component
+public class TriggerJob {
+
+    private static final Logger logger = LogManager.getLogger(TriggerJob.class);
+
+    private static final String TMP_FTP_FILE_PATH = CommonConfUtil.getConf("mysql.into.outfile.path");
+    private static final String TMP_FTP_FILE_SPLIT = CommonConfUtil.getConf("mysql.into.outfile.split");
+
+    public static TriggerJob triggerJob;
+
+    @Autowired
+    private TaskDao taskDao;
+    @Autowired
+    private DaMdmFeign daMdmFeign;
+
+    @PostConstruct
+    public void init() {
+        triggerJob = this;
+    }
+
+    /**
+     * 根据jobid执行任务
+     *
+     * @param jobId
+     * @return
+     */
+    public String execute(String jobId, Date nextFireTime) throws Exception {
+        Task thisJob = JobServer.MEM_JOB_CACHE.get(jobId);
+        String sendStatus = triggerJob.taskDao.getTaskSendStatusById(thisJob.getId());
+        if (thisJob == null) {
+            insertErrorInfoAndCheckSendStatus(thisJob, "未找到JOB[" + jobId + "]");
+            throw new Exception("未找到JOB[" + jobId + "]");
+        }
+        logger.info("JOB[" + jobId + "]开始进行数据采集任务");
+        //获取源库信息
+        MdmInfoDatabase sourceDatabase = packageMdmInfoDatabase(thisJob.getSourceDatabaseId());
+        MdmInfoDatabase targetDatabase = packageMdmInfoDatabase(thisJob.getTargetDatabaseId());
+        //源库数据库类型名称
+        String sResourceTypeName = sourceDatabase.getResourceTypeName();
+        //目标库数据库类型名称
+        String tResourceTypeName = targetDatabase.getResourceTypeName();
+        //开始执行装载任务
+
+        String result = "";
+        result = startGatherJob(sourceDatabase, targetDatabase, thisJob, sResourceTypeName, tResourceTypeName, nextFireTime);
+        return result;
+    }
+
+    private MdmInfoDatabase packageMdmInfoDatabase(String dbId) {
+        MdmInfoDatabase mdmInfoDatabase = triggerJob.daMdmFeign.database(dbId);
+        String resourceTypeName = mdmInfoDatabase.getResourceTypeName().toLowerCase();
+        String ip = mdmInfoDatabase.getIp();
+        String port = mdmInfoDatabase.getResourcePort();
+        String dbName = mdmInfoDatabase.getDatabaseName();
+        String url = "";
+        switch (resourceTypeName) {
+            case "mysql":
+                //jdbc:mysql://localhost:3306/sqltestdb
+                url = "jdbc:mysql://" + ip + ":" + port + "/" + dbName;
+                break;
+            case "hive":
+                //jdbc:hive2://192.168.31.243:10000/default
+                url = "jdbc:hive2://" + ip + ":" + port + "/" + dbName;
+                break;
+            default:
+                url = "jdbc:mysql://" + ip + ":" + port + "/" + dbName;
+                break;
+        }
+        mdmInfoDatabase.setUrl(url);
+        return mdmInfoDatabase;
+    }
+
+    /**
+     * 执行采集任务
+     * @param sourceDatabase
+     * @param targetDatabase
+     * @param thisJob
+     * @param sResourceTypeName
+     * @param tResourceTypeName
+     * @param nextFireTime
+     * @return
+     * @throws Exception
+     */
+    private String startGatherJob(MdmInfoDatabase sourceDatabase, MdmInfoDatabase targetDatabase, Task thisJob, String sResourceTypeName,
+                                  String tResourceTypeName, Date nextFireTime) throws Exception{
+        String fileName = "";
+        //获取源库数据库连接
+        Connection sourceConn = null;
+        Connection targetConn = null;
+        String result = "0";
+        String jobid = thisJob.getId();
+        String sql = thisJob.getDdlSql();
+        String targetTableName = thisJob.getTargetTableName();
+        String nextRunDate = formatNextRunDate(thisJob.getPeriodType(), nextFireTime);
+        String runStatus = "0";
+        try {
+            runStatus = "2";//运行中
+            triggerJob.taskDao.updateTaskRunStatusById(jobid, runStatus, nextRunDate);
+
+            sourceConn = ConnectionUtil.initConn(sourceDatabase);
+            // 创建statement类对象,用来执行SQL语句!!
+            Statement sourceStatement = sourceConn.createStatement();
+            if(sql.contains("'#(")){
+                String[] splitSql = sql.split("'#\\(");
+                for (int i = 0; i < splitSql.length; i++) {
+                    String date = "";
+                    if(i == 0){
+                        String tmp = sql.substring(splitSql[0].length() + 3);
+                        date = sql.substring(splitSql[0].length() + 3).substring(0, tmp.indexOf(")"));
+                    }
+                    else{
+                        if(sql.contains("'#(")){
+                            String aa = sql.substring(sql.indexOf("#") + 2);
+                            date = sql.substring(sql.indexOf("#") + 2).substring(0, aa.indexOf(")"));
+                        }
+                        else{
+                            break;
+                        }
+                    }
+//                    date = date.replaceAll("-", "").replaceAll(" ", "");
+                    sql = formatSql(thisJob, date, sql);
+                }
+            }
+            if(sql.contains("'#(")){
+                logger.error("DDL语句中日期通配符配置有问题,请检查!" + sql);
+                insertErrorInfoAndCheckSendStatus(thisJob, "DDL语句中日期通配符配置有问题,请检查!" + sql);
+                result = "-1";
+                throw new Exception("DDL语句中日期通配符配置有问题,请检查!");
+            }
+            logger.info("JOB[" + jobid + "]执行DDL语句为:" + sql);
+            ResultSet rs = sourceStatement.executeQuery(sql);
+
+            String tmpFilePath = System.getProperty("user.dir") + TMP_FTP_FILE_PATH;
+            if (StringUtils.isEmpty(tmpFilePath)) {
+                tmpFilePath = TMP_FTP_FILE_PATH + "/";
+            }
+            String outFileName = tmpFilePath + "/mysql_tmp_file_" + UUID.randomUUID() + ".txt";
+
+            // TODO: 2019/3/15 后续可以考虑自定义输出文件名及路径
+            logger.info("JOB[" + jobid + "]开始导出数据到本地" + outFileName + "文件.....");
+            //数据输出到本地文件
+            InputStream dataStream = writeToLocalFile(tmpFilePath, outFileName, rs);
+            logger.info("JOB[" + jobid + "]数据导出到本地" + outFileName + "文件结束.....");
+            sourceConn.close();
+
+            runStatus = "3";//运行完成
+            result = "0";
+            logger.info("获取目标库数据库连接...");
+            targetConn = ConnectionUtil.initConn(targetDatabase);
+
+            //拼接装载语句
+            String loadSql = formatDDLSql(tResourceTypeName.toLowerCase(), outFileName, sql, targetTableName);
+            PreparedStatement targetStatement = targetConn.prepareStatement(loadSql);
+
+//            Statement targetStatement = (com.mysql.jdbc.Statement)targetConn.createStatement();
+            if(dataStream != null){
+//        		((com.mysql.jdbc.Statement) targetStatement).setLocalInfileInputStream(dataStream);
+
+                logger.info("JOB[" + jobid + "]拼接装载语句[" + loadSql + "]");
+                File file = new File(outFileName);
+                fileName = outFileName;
+                if (file.exists()){
+                    logger.info("JOB[" + jobid + "]开始执行导入文本文件到目标库语句:[" + loadSql + "]");
+                    if (targetStatement.isWrapperFor(com.mysql.jdbc.Statement.class)) {
+                        com.mysql.jdbc.PreparedStatement mysqlStatement = targetStatement.unwrap(com.mysql.jdbc.PreparedStatement.class);
+                        mysqlStatement.setLocalInfileInputStream(dataStream);
+                        mysqlStatement.executeUpdate();
+                    }
+//                    targetStatement.exe();
+                    logger.info("JOB[" + jobid + "]执行导入文本文件到目标库语句:[" + loadSql + "] 结束");
+                    logger.info(outFileName + "数据文件装载成功");
+                    // 更新数据库中任务状态为运行完成
+                    runStatus = "3";//运行完成
+                    result = "0";
+
+                    // TODO: 2019/3/15 后续可能会添加是否删除文件的选项,需要进行判断
+                    file.delete();
+                } else {
+                    insertErrorInfoAndCheckSendStatus(thisJob, "JOB[" + jobid + "]未找到导出文件[" + outFileName + "],请检查!");
+                    logger.error("JOB[" + jobid + "]未找到导出文件[" + outFileName + "],请检查!");
+                    runStatus = "4";//运行失败
+                    result = "-1";
+                }
+            }
+
+            triggerJob.taskDao.updateTaskRunStatusById(jobid, runStatus, nextRunDate);
+            triggerJob.taskDao.updateSendedStatusById(jobid, "0");
+            targetConn.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+            runStatus = "4";//运行失败
+            result = "-1";
+            logger.info("执行调度异常,信息为:" + e.getMessage());
+            try {
+                insertErrorInfoAndCheckSendStatus(thisJob, e.getMessage());
+            } catch (Exception e1){
+                e1.getStackTrace();
+            }
+            triggerJob.taskDao.updateTaskRunStatusById(jobid, runStatus, nextRunDate);
+        } finally {
+            try {
+                if (sourceConn != null) {
+                    sourceConn.close();
+                }
+                if (targetConn != null) {
+                    targetConn.close();
+                }
+                // TODO: 2019/3/15 后续可能会添加是否删除文件的选项,需要进行判断
+                File file = new File(fileName);
+                if(file.exists()){
+                    file.delete();
+                }
+            } catch (SQLException e) {
+                e.printStackTrace();
+                try {
+                    insertErrorInfoAndCheckSendStatus(thisJob, e.getMessage());
+                } catch (Exception e1){
+                    e1.getStackTrace();
+                }
+                logger.info("关闭数据源连接或删除临时文件异常,信息为:" + e.getMessage());
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 数据输出到本地文件
+     * @param localFilePath
+     * @param rs
+     * @throws Exception
+     */
+    private static InputStream writeToLocalFile(String tmpFilePath, String localFilePath, ResultSet rs) throws Exception{
+        File file = new File(tmpFilePath);
+        if(!file.exists()){
+            logger.info("新增目录[" + tmpFilePath + "]");
+            file.mkdirs();
+        }
+        ResultSetMetaData data = rs.getMetaData();
+        FileWriter fw = new FileWriter(localFilePath);
+        StringBuilder builder = new StringBuilder();
+        while(rs.next()){
+            for (int i = 1; i <= data.getColumnCount(); i++) {
+                String columnClassName = data.getColumnClassName(i);
+                if(i == (data.getColumnCount())){
+                    if("java.lang.Integer".equals(columnClassName) || "java.lang.Double".equals(columnClassName)){
+                        if(rs.getString(i) == null || "null".equals(rs.getString(i)) || "".equals(rs.getString(i))){
+                            fw.write("\"" + "0" + "\"");
+                            builder.append("\"" + "0" + "\"");
+                        }
+                        else{
+                            fw.write("\"" + rs.getString(i) + "\"");
+                            builder.append("\"" + rs.getString(i) + "\"");
+                        }
+                    }
+                    else{
+                        fw.write("\"" + (rs.getString(i)==null ? "\\N" : rs.getString(i)) + "\"");
+                        builder.append("\"" + (rs.getString(i)==null ? "\\N" : rs.getString(i)) + "\"");
+                    }
+                    break;
+                }
+                if("java.lang.Integer".equals(columnClassName) || "java.lang.Double".equals(columnClassName)){
+                    if(rs.getString(i) == null || "null".equals(rs.getString(i)) || "".equals(rs.getString(i))){
+                        fw.write("\""+ "0" + "\"" + TMP_FTP_FILE_SPLIT);
+                        builder.append("\"" + "0" + "\"" + TMP_FTP_FILE_SPLIT);
+                    }
+                    else{
+                        fw.write("\"" + rs.getString(i) + "\"" + TMP_FTP_FILE_SPLIT);
+                        builder.append("\"" + rs.getString(i) + "\"" + TMP_FTP_FILE_SPLIT);
+                    }
+                }
+                else{
+                    fw.write("\"" + (rs.getString(i)==null ? "\\N" : rs.getString(i)) + "\"" + TMP_FTP_FILE_SPLIT);
+                    builder.append("\"" + (rs.getString(i)==null ? "\\N" : rs.getString(i)) + "\"" + TMP_FTP_FILE_SPLIT);
+                }
+            }
+            fw.write(System.lineSeparator());
+            builder.append(System.lineSeparator());
+        }
+        fw.close();
+        byte[] bytes = builder.toString().getBytes("GBK");
+        InputStream inputStream = null;
+        if(bytes.length != 0){
+            inputStream = new ByteArrayInputStream(bytes);
+        }
+        return inputStream;
+    }
+
+    /**
+     * 封装ddl语句用于数据导出和装载
+     *
+     * @param sourceTypeName
+     * @param fileName
+     * @param sql
+     * @return
+     */
+    private static String formatDDLSql(String sourceTypeName, String fileName, String sql, String targetTableName) {
+        String loadSql = "";
+        sql = sql.toLowerCase().trim();
+        String loadColumn = sql.substring(6, sql.indexOf("from")).replaceAll(" ", "");
+        //如果sql中查询字段为*,则装载时不指定字段,mysql顺序写入
+        //如果指定了字段,则需要添加具体入库字段,并忽略其他不入库的字段 @dummy
+        loadColumn = "*".equals(loadColumn) ? "" : "(" + loadColumn + ",@dummy)";
+        if ("mysql".equals(sourceTypeName.toLowerCase())) {
+            logger.info("当前数据库类型是mysql...");
+            loadSql = "LOAD DATA LOCAL INFILE '" + fileName
+                    + "' REPLACE INTO TABLE " + targetTableName + " character set gbk fields ENCLOSED BY '\"'" +
+                    " terminated by '" + TMP_FTP_FILE_SPLIT + "' LINES TERMINATED BY '"+ System.lineSeparator() +"' " + loadColumn;
+        }
+        if ("hive".equals(sourceTypeName.toLowerCase())) {
+            logger.info("当前数据库类型是hive...");
+        }
+        return loadSql;
+    }
+
+    /**
+     * 根据调度周期类型替换抽取sql的日期
+     * @return
+     */
+    private static String formatSql(Task task, String date, String sql) throws Exception{
+        int periodType = task.getPeriodType();
+        SimpleDateFormat format = new SimpleDateFormat();
+        int offset = task.getScheduleOffset();
+        int num = 0;
+        Date realDate = null;
+        String tmpFormat = "";
+        switch (periodType)
+        {
+            case Constant.JOB_PERIOD_CUSTOM:
+                String dataformat = getTaskDataFormat(task.getTaskCron());
+                format.applyPattern(dataformat);
+                String tmpformat = dataformat.toUpperCase().replaceAll("-", "").replaceAll(" ", "").replaceAll(":", "");
+                String period = tmpformat.substring(tmpformat.length() - 1);
+                num = getOffsetByPeriod(date, period);
+                realDate = getRealDateByDataFormat(tmpformat, offset + num);
+//                tmpFormat = getReplaceStrByPeriod(date, dataformat.toUpperCase(), num, period);
+//                tmpFormat = tmpFormat.replaceAll("-", "").replaceAll(" ", "").replaceAll(":", "");
+                break;
+            case Constant.JOB_PERIOD_MONTH:
+                format.applyPattern(Constant.RE_FORMAT_MONTH);
+                num = getOffsetByPeriod(date, "M");
+                realDate = DateUtils.addMonths(new Date(), offset + num);
+//                tmpFormat = getReplaceStrByPeriod(date, "YYYYMM", num, "M");
+                break;
+            case Constant.JOB_PERIOD_DAY:
+                format.applyPattern(Constant.RE_FORMAT_DAY);
+                num = getOffsetByPeriod(date, "D");
+                realDate = DateUtils.addDays(new Date(), offset + num);
+//                tmpFormat = getReplaceStrByPeriod(date, "YYYYMMDD", num, "D");
+                break;
+            case Constant.JOB_PERIOD_HOUR:
+                format.applyPattern(Constant.RE_FORMAT_HOUR);
+                num = getOffsetByPeriod(date, "H");
+                realDate = DateUtils.addHours(new Date(), offset + num);
+//                tmpFormat = getReplaceStrByPeriod(date, "YYYYMMDDHH", num, "H");
+                break;
+            case Constant.JOB_PERIOD_MINUTE:
+                format.applyPattern(Constant.RE_FORMAT_MINUTE);
+                num = getOffsetByPeriod(date, "M");
+                realDate = DateUtils.addMinutes(new Date(), offset + num);
+//                tmpFormat = getReplaceStrByPeriod(date, "YYYYMMDDHHMM", num, "M");
+                break;
+            case Constant.JOB_PERIOD_SECONDS:
+                format.applyPattern(Constant.RE_FORMAT_SECONDS);
+                num = getOffsetByPeriod(date, "S");
+                realDate = DateUtils.addSeconds(new Date(), offset + num);
+//                tmpFormat = getReplaceStrByPeriod(date, "YYYYMMDDHHMMSS", num, "S");
+                break;
+            default:
+                break;
+        }
+        return sql.replaceAll("#\\(" + date + "\\)", format.format(realDate));
+    }
+
+    /**
+     * @param job 一个JOB任务
+     * @return Date:按 不同周期类型格式化后的当前时间
+     * @description 获取当前JOB的下次运行时间的参照时间点
+     */
+    private static Date getReference(Task job) {
+        Date current = null;
+        try {
+            job.setDataFormat(getDataFormatByPeriodType(job.getPeriodType()));
+            SimpleDateFormat format = new SimpleDateFormat(job.getDataFormat());
+            String current4format = format.format(new Date());
+            current = format.parse(current4format);
+        } catch (ParseException e) {
+            try{
+                insertErrorInfoAndCheckSendStatus(job, "JOB[" + job.getId() + "]数据日期和数据日期格式不匹配!" + e.getMessage());
+            }catch (Exception e1){
+                e1.getStackTrace();
+            }
+            logger.error("JOB[" + job.getId() + "]数据日期和数据日期格式不匹配!", e);
+        }
+        return current;
+    }
+
+    private static String getDataFormatByPeriodType(int periodType){
+        String dataFormat = "";
+        switch (periodType){
+            case 1:
+                dataFormat = "yyyyMM";
+                break;
+            case 2:
+                dataFormat = "yyyyMMdd";
+                break;
+            case 3:
+                dataFormat = "yyyyMMddHH";
+                break;
+            case 4:
+                dataFormat = "yyyyMMddHHmm";
+                break;
+            case 5:
+                dataFormat = "yyyyMMddHHmmss";
+                break;
+            default:
+                dataFormat = "yyyyMMddHHmmss";
+                break;
+        }
+        return dataFormat;
+    }
+
+    /**
+     * 根据周期类型获取通配便宜值
+     * @param date
+     * @param period
+     * @return
+     */
+    private static int getOffsetByPeriod(String date, String period) throws Exception{
+        date = date.toUpperCase();
+        int num = 0;
+        try{
+            if (date.contains("_-")){
+                num = Integer.valueOf(date.substring(date.indexOf("_") + 2, date.lastIndexOf(period)));
+                return num;
+            }
+            else if(date.contains("_")){
+                num = Integer.valueOf(date.substring(date.indexOf("_") + 1, date.lastIndexOf(period)));
+                return 0 - num;
+            }
+        }
+        catch (Exception e){
+            logger.error("当前调度周期类型为:["+ period + "],通配符和当前周期类型不匹配!");
+            throw new Exception("当前调度周期类型为:["+ period + "],通配符和当前周期类型不匹配!");
+        }
+        return num;
+    }
+
+    /**
+     * 根据周期类型获取通配便宜值
+     * @param date
+     * @param period
+     * @return
+     */
+    private static String getReplaceStrByPeriod(String date, String dateFormat, int num, String period){
+        num = num < 0 ? Math.abs(num) : num;
+        date = date.toUpperCase();
+        if (date.contains("_-")){
+            dateFormat = dateFormat + "_-" + num + period;
+            return dateFormat;
+        }
+        if(date.contains("_")){
+            dateFormat = dateFormat + "_" + num + period;
+            return dateFormat;
+        }
+        return dateFormat;
+    }
+
+    /**
+     * 根据日期格式和调度偏移量,确认实际替换的日期
+     * @param dataformat
+     * @param offset
+     * @return
+     */
+    private static Date getRealDateByDataFormat(String dataformat, int offset){
+        Date realDate = null;
+        switch (dataformat){
+            case "YYYY":
+                realDate = DateUtils.addYears(new Date(), offset);
+                break;
+            case "YYYYMM":
+                realDate = DateUtils.addMonths(new Date(), offset);
+                break;
+            case "YYYYMMDD":
+                realDate = DateUtils.addDays(new Date(), offset);
+                break;
+            case "YYYYMMDDHH":
+                realDate = DateUtils.addHours(new Date(), offset);
+                break;
+            case "YYYYMMDDHHMM":
+                realDate = DateUtils.addMinutes(new Date(), offset);
+                break;
+            case "YYYYMMDDHHMMSS":
+                realDate = DateUtils.addSeconds(new Date(), offset);
+                break;
+            default:
+                realDate = DateUtils.addSeconds(new Date(), offset);
+                break;
+        }
+        return realDate;
+    }
+
+    public static String formatNextRunDate(int periodType, Date nextFireTime){
+        if(nextFireTime != null){
+            SimpleDateFormat format = new SimpleDateFormat();
+            switch (periodType)
+            {
+                case Constant.JOB_PERIOD_CUSTOM:
+                    format.applyPattern(Constant.RE_FORMAT_SECONDS);
+                    break;
+                case Constant.JOB_PERIOD_MONTH:
+                    format.applyPattern(Constant.RE_FORMAT_MONTH);
+                    break;
+                case Constant.JOB_PERIOD_DAY:
+                    format.applyPattern(Constant.RE_FORMAT_DAY);
+                    break;
+                case Constant.JOB_PERIOD_HOUR:
+                    format.applyPattern(Constant.RE_FORMAT_HOUR);
+                    break;
+                case Constant.JOB_PERIOD_MINUTE:
+                    format.applyPattern(Constant.RE_FORMAT_MINUTE);
+                    break;
+                case Constant.JOB_PERIOD_SECONDS:
+                    format.applyPattern(Constant.RE_FORMAT_SECONDS);
+                    break;
+                default:
+                    break;
+            }
+            return format.format(nextFireTime);
+        }
+        return "";
+    }
+
+    private static String getTaskDataFormat(String taskCron) throws Exception{
+        String[] crons = taskCron.split(" ");
+        int count = -1;
+        String dataFormat = "";
+        for (int i = 0; i < crons.length; i++) {
+            count ++;
+            if("*".equals(crons[i]) || crons[i].contains("*/")){
+                break;
+            }
+        }
+        switch (count){
+            case 1:
+                dataFormat = Constant.RE_FORMAT_MINUTE;
+                break;
+            case 2:
+                dataFormat = Constant.RE_FORMAT_HOUR;
+                break;
+            case 3:
+                dataFormat = Constant.RE_FORMAT_DAY;
+                break;
+            case 4:
+                dataFormat = Constant.RE_FORMAT_MONTH;
+                break;
+            case 5:
+                dataFormat = Constant.RE_FORMAT_YEAR;
+                break;
+            default:
+                dataFormat = Constant.RE_FORMAT_SECONDS;
+                break;
+        }
+        return dataFormat;
+    }
+
+    /**
+     * 获取出错任务信息
+     * @param taskId
+     * @return
+     */
+    public static ErrorJobInfo getErrorJobInfoById(String taskId){
+        return triggerJob.taskDao.getErrorJobInfoById(taskId);
+    }
+
+    /**
+     * 更新出错任务的邮件发送状态
+     * @param taskId
+     * @param sendStatus
+     */
+    public static void updateSendedStatusById(String taskId, String sendStatus){
+        triggerJob.taskDao.updateSendedStatusById(taskId, sendStatus);
+    }
+
+    /**
+     * 写入出错信息并校验是否需要发送邮件
+     * @param task
+     * @param errorInfo
+     */
+    private static void insertErrorInfoAndCheckSendStatus(Task task, String errorInfo) throws Exception{
+        String sendStatus = triggerJob.taskDao.getTaskSendStatusById(task.getId());
+        ErrorJobInfo errorJobInfo = new ErrorJobInfo();
+        errorJobInfo.setTaskId(task.getId());
+        errorJobInfo.setTaskName(task.getTaskName());
+        errorJobInfo.setErrorDesc(errorInfo);
+        errorJobInfo.setSendStatus(sendStatus);
+        triggerJob.taskDao.deleteTaskErrorInfo(task.getId());
+        triggerJob.taskDao.insertTaskErrorInfo(errorJobInfo);
+        if("0".equals(sendStatus)){
+            MailUtil.sendErrorTaskInfo(task.getId());
+        }
+    }
+
+    public static String getSendMailsConfig() throws Exception{
+        List<String> sendMails = triggerJob.taskDao.getSendMailsConfig();
+        if(sendMails.isEmpty()){
+            throw new Exception("错误信息需要发送的邮箱地址未配置!");
+        }
+        String mailTo = "";
+        for(String mail : sendMails){
+            if(mail.contains(";")){
+                throw new Exception("要发送的邮箱地址配置不正确!");
+            }
+            mailTo += mail + ";";
+        }
+        return mailTo;
+    }
+}

+ 43 - 0
da/src/main/java/com/datau/da/service/task/TaskService.java

@@ -0,0 +1,43 @@
+package com.datau.da.service.task;
+
+import com.datau.da.entity.PageParams;
+import com.datau.da.entity.ReturnData;
+import com.datau.da.entity.remotedb.MdmInfoColumn;
+import com.datau.da.entity.remotedb.MdmInfoDatabase;
+import com.datau.da.entity.remotedb.MdmInfoTable;
+import com.datau.da.entity.task.JobOperateCmd;
+import com.datau.da.entity.task.Task;
+import com.github.pagehelper.Page;
+
+import java.util.List;
+
+
+/**
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+public interface TaskService {
+
+    void addTask(Task task) throws Exception;
+    
+    void deleteTaskById(String taskId) throws Exception;
+
+    Task getTaskInfoById(String taskId) throws Exception;
+
+    int updateTaskById(Task task) throws Exception;
+
+    ReturnData operateTask(JobOperateCmd jobOperateCmd) throws Exception;
+
+    Page<Task> listTask(PageParams<Task> pageParams) throws Exception;
+    
+    MdmInfoDatabase database(String id) throws Exception;
+
+    List<MdmInfoTable> listTableByDatabaseId(String databaseId) throws Exception;
+
+    List<MdmInfoDatabase> listOriginal(String resourceName) throws Exception;
+
+    List<MdmInfoDatabase> listDatabase(String resourceName) throws Exception;
+
+    List<MdmInfoColumn> listColumnByTableId(String tableId) throws Exception;
+}

+ 247 - 0
da/src/main/java/com/datau/da/service/task/impl/TaskServiceImpl.java

@@ -0,0 +1,247 @@
+package com.datau.da.service.task.impl;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.datau.da.dao.TaskDao;
+import com.datau.da.entity.PageParams;
+import com.datau.da.entity.ReturnData;
+import com.datau.da.entity.remotedb.MdmCreateTableDTO;
+import com.datau.da.entity.remotedb.MdmInfoColumn;
+import com.datau.da.entity.remotedb.MdmInfoDatabase;
+import com.datau.da.entity.remotedb.MdmInfoTable;
+import com.datau.da.entity.task.JobOperateCmd;
+import com.datau.da.entity.task.Task;
+import com.datau.da.feign.DaMdmFeign;
+import com.datau.da.job.JobServer;
+import com.datau.da.service.job.impl.SchedulerTimeTriggeJob;
+import com.datau.da.service.job.impl.TriggerJob;
+import com.datau.da.service.task.TaskService;
+import com.datau.da.utils.CronExpresUtil;
+import com.datau.da.utils.R;
+import com.github.pagehelper.Page;
+import com.github.pagehelper.PageHelper;
+
+
+/**
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+@Service
+@Transactional(rollbackFor = Exception.class)
+public class TaskServiceImpl implements TaskService {
+
+    private static final Logger logger = LogManager.getLogger(TaskServiceImpl.class);
+
+    @Autowired
+    private TaskDao taskDao;
+
+    @Autowired
+    private DaMdmFeign daMdmFeign;
+
+    @Override
+    public void addTask(Task task) throws Exception {
+    	String taskCron = task.getTaskCron();
+        boolean isValidCron = CronExpresUtil.isValidExpress(taskCron);
+        if(!isValidCron){
+        	logger.error("Cron表达式[" + taskCron + "]不合法,请检查!");
+        	throw new Exception("Cron表达式不合法,请检查!");
+        }
+        //新增任务,默认新增到临时表
+        String taskId = UUID.randomUUID().toString();
+        task.setId(taskId);
+        task.setTaskStatus("2");
+        task.setRunStatus("0");
+        R<MdmCreateTableDTO> sourceTableDTO = daMdmFeign.getTableInfoById(task.getSourceTableId());
+        R<MdmCreateTableDTO> targetTableDTO = daMdmFeign.getTableInfoById(task.getTargetTableId());
+        String sourceTableName = sourceTableDTO.getData().getTableName();
+        String targetTableName = targetTableDTO.getData().getTableName();
+        logger.info("JOB[" + taskId + "]源表[" + sourceTableName + "][" + task.getSourceTableId() + "]");
+        logger.info("JOB[" + taskId + "]目标表[" + targetTableName + "][" + task.getTargetTableId() + "]");
+        task.setSourceTableName(sourceTableName);
+        task.setTargetTableName(targetTableName);
+        taskDao.addTask(task);
+        JobServer.MEM_JOB_CACHE.put(taskId, task);
+    }
+
+    @Override
+    public Task getTaskInfoById(String taskId) throws Exception {
+        return taskDao.getTaskInfoById(taskId);
+    }
+
+    @Override
+    public int updateTaskById(Task task) throws Exception {
+        String taskCron = task.getTaskCron();
+        boolean isValidCron = CronExpresUtil.isValidExpress(taskCron);
+        if(!isValidCron){
+            logger.error("Cron表达式[" + taskCron + "]不合法,请检查!");
+            throw new Exception("Cron表达式不合法,请检查!");
+        }
+    	R<MdmCreateTableDTO> sourceTableDTO = daMdmFeign.getTableInfoById(task.getSourceTableId());
+        R<MdmCreateTableDTO> targetTableDTO = daMdmFeign.getTableInfoById(task.getTargetTableId());
+        String sourceTableName = sourceTableDTO.getData().getTableName();
+        String targetTableName = targetTableDTO.getData().getTableName();
+        logger.info("JOB[" + task.getId() + "]源表[" + sourceTableName + "][" + task.getSourceTableId() + "]");
+        logger.info("JOB[" + task.getId() + "]目标表[" + targetTableName + "][" + task.getTargetTableId() + "]");
+        task.setSourceTableName(sourceTableName);
+        task.setTargetTableName(targetTableName);
+        int result = taskDao.updateTaskById(task);
+        Task task1 = taskDao.getTaskInfoById(task.getId());
+        
+        //根据id从正式表中获取要执行的任务信息,发布到队列,判断是否满足运行条件
+        long seq = JobServer.SCHEDULE_CONDITION_JUDGE_BUFFER.next();
+        JobServer.SCHEDULE_CONDITION_JUDGE_BUFFER.get(seq).setTask(task1);
+        JobServer.SCHEDULE_CONDITION_JUDGE_BUFFER.publish(seq);
+        JobServer.MEM_JOB_CACHE.put(task1.getId(), task1);
+        return result;
+    }
+
+    @Override
+    public ReturnData operateTask(JobOperateCmd jobOperateCmd) throws Exception {
+        ReturnData returnData = new ReturnData();
+        String operateType = jobOperateCmd.getOperateType();
+        String result = "";
+        switch (operateType) {
+            case "1":
+                logger.info("收到job[" + jobOperateCmd.getJobId() + "]开始运行命令");
+                result = startTask(jobOperateCmd.getJobId());
+                break;
+            case "2":
+                logger.info("收到job[" + jobOperateCmd.getJobId() + "]结束运行命令");
+                result = stopTask(jobOperateCmd.getJobId());
+                break;
+            case "3":
+                logger.info("收到job[" + jobOperateCmd.getJobId() + "]立即运行一次的命令");
+                result = startTaskNow(jobOperateCmd.getJobId());
+                break;
+            default:
+                logger.info("收到job[" + jobOperateCmd.getJobId() + "]开始运行命令");
+                result = startTask(jobOperateCmd.getJobId());
+                break;
+        }
+        if ("0".equals(result)) {
+            returnData.setMsg("操作成功");
+        }
+        if ("-1".equals(result)) {
+        	returnData.setCode("-1");
+            returnData.setMsg("操作失败");
+        }
+        if ("2".equals(result)) {
+        	returnData.setCode("-1");
+        	returnData.setMsg("调度未启用,不允许执行该操作!");
+        }
+        return returnData;
+    }
+
+    @Override
+    public Page<Task> listTask(PageParams<Task> pageParams) throws Exception {
+        String sortStr = pageParams.getSort() == null ? "createTime" : pageParams.getSort();
+        String orderByStr = sortStr + " " + pageParams.getOrder();
+        PageHelper.startPage(pageParams.getPage(), pageParams.getPageSize()).setOrderBy(orderByStr);
+        List<Task> resultList = taskDao.listTask(pageParams);
+        return (Page<Task>) resultList;
+    }
+
+    /**
+     * 根据id启动任务
+     *
+     * @param jobId
+     */
+    private String startTask(String jobId) throws Exception {
+        String result = "0";
+        //根据id从正式表中获取要执行的任务信息,发布到队列,判断是否满足运行条件
+        Task task = JobServer.MEM_JOB_CACHE.get(jobId);
+        task.setTaskStatus("1");
+        taskDao.updateTaskStatusById(jobId, "1", "");
+        long seq = JobServer.SCHEDULE_CONDITION_JUDGE_BUFFER.next();
+        JobServer.SCHEDULE_CONDITION_JUDGE_BUFFER.get(seq).setTask(task);
+        JobServer.SCHEDULE_CONDITION_JUDGE_BUFFER.publish(seq);
+        JobServer.MEM_JOB_CACHE.put(jobId, task);
+        return result;
+    }
+
+    /**
+     * 根据id停止任务
+     *
+     * @param jobId
+     */
+    private String stopTask(String jobId) throws Exception {
+    	Task task = JobServer.MEM_JOB_CACHE.get(jobId);
+    	task.setTaskStatus("2");
+        String result = "0";
+        taskDao.updateTaskStatusById(jobId, "2", "");
+        SchedulerTimeTriggeJob.deleteJobByJobId(task);
+        logger.info("停用job[" + jobId + "]成功");
+        JobServer.MEM_JOB_CACHE.put(jobId, task);
+        return result;
+    }
+
+    /**
+     * 根据id立即运行任务
+     *
+     * @param jobId
+     */
+    private String startTaskNow(String jobId) throws Exception {
+        String result = "";
+        TriggerJob triggerJob = new TriggerJob();
+        Task thisJob = JobServer.MEM_JOB_CACHE.get(jobId);
+        if("2".equals(thisJob.getTaskStatus())){
+        	result = "2";
+        	return result;
+    	}
+    	try {
+            result = triggerJob.execute(jobId, null);
+        } catch (Exception e){
+            result = "-1";
+        }
+        if ("0".equals(result)) {
+            logger.info("JOBID[" + jobId + "]进行数据采集任务成功");
+        }
+        if ("-1".equals(result)) {
+            logger.info("JOBID[" + jobId + "]进行数据采集任务失败");
+        }
+        return result;
+    }
+
+    @Override
+    public MdmInfoDatabase database(String id) throws Exception {
+        return daMdmFeign.database(id);
+    }
+
+    @Override
+    public List<MdmInfoTable> listTableByDatabaseId(String databaseId) {
+        return daMdmFeign.listTableByDatabaseId(databaseId);
+    }
+
+    @Override
+    public List<MdmInfoDatabase> listOriginal(String resourceName) throws Exception {
+        return daMdmFeign.listOriginal(resourceName);
+    }
+
+    @Override
+    public List<MdmInfoDatabase> listDatabase(String resourceName) throws Exception {
+        return daMdmFeign.listDatabase(resourceName);
+    }
+
+    @Override
+    public List<MdmInfoColumn> listColumnByTableId(String tableId) throws Exception {
+        return daMdmFeign.listColumnByTableId(tableId);
+    }
+
+	@Override
+	public void deleteTaskById(String taskId) throws Exception {
+		Task task = JobServer.MEM_JOB_CACHE.get(taskId);
+		if("1".equals(task.getTaskStatus())){
+			throw new Exception("启用状态的调度不允许删除!");
+		}
+		taskDao.deleteTaskById(taskId);
+		
+	}
+}

+ 99 - 0
da/src/main/java/com/datau/da/utils/AesUtil.java

@@ -0,0 +1,99 @@
+package com.datau.da.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.UnsupportedEncodingException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+
+/**
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+public final class AesUtil {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AesUtil.class);
+    private static final String UTF8 = "utf-8";
+    //key长16字节
+    private static final int KEY_LENGTH = 16;
+
+    /**
+     * 方法名称:AES 加密<br>
+     * 方法作用:对普通字符串进行AES加密
+     *
+     * @param content 等待加密的字符串
+     * @param key     加/解密 密钥
+     * @param iv      加/解密 初始化向量
+     * @return 返回加密后的字符串
+     * @throws Exception 异常信息
+     */
+    public static String encrypt(String content, String key, String iv) throws UnsupportedEncodingException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+        if (key == null) {
+            LOGGER.error("Key为空null");
+            return null;
+        }
+
+        // 判断Key是否为16位
+        if (key.getBytes(UTF8).length != KEY_LENGTH) {
+            LOGGER.error("Key长度不是16位");
+            return null;
+        }
+
+        byte[] raw = key.getBytes();
+        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+        //"算法/模式/补码方式"
+        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+        //使用CBC模式,需要一个向量iv,可增加加密算法的强度
+        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(iv.getBytes(UTF8)));
+        byte[] encrypted = cipher.doFinal(content.getBytes(UTF8));
+        //此处使用BAES64做转码功能。
+        return Base64.getEncoder().encodeToString(encrypted);
+    }
+
+    /**
+     * 方法名称:AES 解密<br>
+     * 方法作用:对经过Aes加密后的字符串进行解密,
+     *
+     * @param content 待解密内容字符串
+     * @param key     加/解密 密钥
+     * @param iv      加/解密 初始化向量
+     * @return 返回解密后的内容
+     * @throws Exception 异常
+     */
+    public static String decrypt(String content, String key, String iv) throws Exception {
+        try {
+            // 判断Key是否正确
+            if (key == null) {
+                LOGGER.error("Key为空null");
+                return null;
+            }
+
+            // 判断Key是否为16位
+            if (key.getBytes(UTF8).length != KEY_LENGTH) {
+                LOGGER.error("Key长度不是16位");
+                return null;
+            }
+
+            byte[] raw = key.getBytes(UTF8);
+            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+            cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(iv.getBytes(UTF8)));
+            byte[] encrypted1 = Base64.getDecoder().decode(content);
+            byte[] original = cipher.doFinal(encrypted1);
+            return new String(original);
+        } catch (Exception ex) {
+            LOGGER.error("AES解码异常,异常信息:" + ex.getMessage());
+            return null;
+        }
+    }
+}

+ 55 - 0
da/src/main/java/com/datau/da/utils/CommonConfUtil.java

@@ -0,0 +1,55 @@
+package com.datau.da.utils;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Properties;
+
+/**
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+public final class CommonConfUtil {
+    private static final Logger logger = LogManager.getLogger(CommonConfUtil.class);
+    private static HashMap<String, String> map = new HashMap<>();
+
+    static {
+        try {
+            Properties properties = new Properties();
+            properties.load(CommonConfUtil.class.getResourceAsStream("/CommonConfig.properties"));
+            properties.keySet().iterator().forEachRemaining(k -> map.put(String.valueOf(k), String.valueOf(properties.get(k))));
+        } catch (IOException e) {
+            logger.error("读取配置文件错误,错误信息:" + e.getMessage());
+        }
+    }
+
+    public static String getConf(String key) {
+        return map.get(key);
+    }
+
+    public static int getInteger(String key, int defaultValue) {
+        try {
+            return Integer.parseInt(map.get(key));
+        } catch (Exception e) {
+            return defaultValue;
+        }
+    }
+
+    public static long getLong(String key, long defaultValue) {
+        try {
+            return Long.parseLong(map.get(key));
+        } catch (Exception e) {
+            return defaultValue;
+        }
+    }
+    public static boolean getBool(String key, boolean defaultValue) {
+        try {
+            return Boolean.valueOf(map.get(key));
+        } catch (Exception e) {
+            return false;
+        }
+    }
+}

+ 56 - 0
da/src/main/java/com/datau/da/utils/ConnectionUtil.java

@@ -0,0 +1,56 @@
+package com.datau.da.utils;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import com.datau.da.entity.remotedb.MdmInfoDatabase;
+
+/**
+ * @author 许明
+ * on 2019/3/11.
+ * @version 2.0.0
+ */
+public class ConnectionUtil {
+
+    private static final Logger logger = LogManager.getLogger(ConnectionUtil.class);
+
+    public static Connection initConn(MdmInfoDatabase mdmInfoDatabase) {
+        //声明Connection对象
+        Connection conn = null;
+
+        //遍历查询结果集
+        try {
+        	//驱动程序名
+            String driver = mdmInfoDatabase.getDriverName();
+            //URL指向要访问的数据库名
+            String url = mdmInfoDatabase.getUrl();
+            //MySQL配置时的用户名
+            String user = mdmInfoDatabase.getUsername();
+            //MySQL配置时的密码
+            String password = mdmInfoDatabase.getPassword();
+            //加载驱动程序
+            Class.forName(driver);
+            //1.getConnection()方法,连接MySQL数据库!!
+            conn = DriverManager.getConnection(url, user, password);
+            if (!conn.isClosed()) {
+                System.out.println("Succeeded connecting to the Database!");
+            }
+        } catch (ClassNotFoundException e) {
+            //数据库驱动类异常处理
+            System.out.println("Sorry,can`t find the Driver!");
+            e.printStackTrace();
+        } catch (SQLException e) {
+            //数据库连接失败异常处理
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            System.out.println("数据库数据成功获取!!");
+        }
+        return conn;
+    }
+}

+ 179 - 0
da/src/main/java/com/datau/da/utils/CronExpresUtil.java

@@ -0,0 +1,179 @@
+/*
+ * 文件名:CronExpresUtil.java
+ * 版权:亚信联创版权所有
+ * 描述:TODO
+ * 修改人:xuwei3
+ * 修改时间:2013-12-30
+ * 修改内容:TODO
+ */
+package com.datau.da.utils;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import com.datau.da.constant.Constant;
+import org.quartz.CronExpression;
+import org.quartz.CronTrigger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @description TODO
+ * @author [xuwei3]
+ * @version [版本号,2013-12-30]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public class CronExpresUtil
+{
+	private static final Logger logger = LoggerFactory.getLogger(CronExpresUtil.class);
+	private static final List<Integer> JOB_PERIOD_TYPE = new ArrayList<Integer>();
+	static
+	{
+		JOB_PERIOD_TYPE.add(Constant.JOB_PERIOD_SECONDS);
+		JOB_PERIOD_TYPE.add(Constant.JOB_PERIOD_MINUTE);
+		JOB_PERIOD_TYPE.add(Constant.JOB_PERIOD_HOUR);
+		JOB_PERIOD_TYPE.add(Constant.JOB_PERIOD_DAY);
+		JOB_PERIOD_TYPE.add(Constant.JOB_PERIOD_MONTH);
+		JOB_PERIOD_TYPE.add(Constant.JOB_PERIOD_WEEK);
+		JOB_PERIOD_TYPE.add(Constant.JOB_PERIOD_YEAR);
+	}
+
+	/**
+	 * 
+	 * @description 获取job下一次运行时间
+	 * @param cronexpressions
+	 *            job对应cron表达式
+	 * @param date
+	 *            本次运行时间
+	 * @return
+	 */
+	public static Date getNextFiredTime(List<CronExpression> cronexpressions, Date date)
+	{
+		if (null == cronexpressions || cronexpressions.size() == 0)
+		{
+			logger.warn("Job对应的CRON表达式为空,请确认job配置正确");
+			return null;
+		}
+		Iterator<CronExpression> ite = cronexpressions.iterator();
+		Date result = null;
+		Date nextFiretime = null;
+		CronExpression cronExp = null;
+		while (ite.hasNext())
+		{
+			cronExp = ite.next();
+			nextFiretime = cronExp.getTimeAfter(date);
+			if (null != nextFiretime)
+			{
+				result = (null == result ? nextFiretime : (nextFiretime.before(result) ? nextFiretime : result));
+			}
+		}
+		return result;
+	}
+
+	public static Date getNextFiredTime(Set<CronTrigger> triggers, Date date)
+	{
+		if (triggers.size() == 0)
+		{
+			logger.warn("Job对应的CRON表达式为空,请确认job配置正确");
+			return null;
+		}
+		Iterator<CronTrigger> ite = triggers.iterator();
+		Date result = null;
+		Date nextFiretime = null;
+		CronTrigger trigger = null;
+		while (ite.hasNext())
+		{
+			trigger = ite.next();
+			nextFiretime = trigger.getFireTimeAfter(date);
+			if (null != nextFiretime)
+			{
+				result = (null == result ? nextFiretime : (nextFiretime.before(result) ? nextFiretime : result));
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * 
+	 * @description 判断给出的cron时候满足cron表达式规范
+	 * @param cronExpression
+	 *            需要判断的cron表达式
+	 * @return
+	 */
+	public static boolean isValidExpress(String cronExpression)
+	{
+		return CronExpression.isValidExpression(cronExpression);
+	}
+
+	/**
+	 * 
+	 * @description 判断给出的时间是否满足cron
+	 * @param cronexpressions
+	 *            cron表达式
+	 * @param compareDate
+	 *            判断时间,为空则默认是当前时间
+	 * @return
+	 */
+	public static boolean isSatisRunCondition(List<CronExpression> cronexpressions, Date compareDate)
+	{
+		if (cronexpressions.size() == 0)
+		{
+			logger.warn("Job对应的CRON表达式为空,请确认job配置正确");
+
+			return false;
+		}
+		if (null == compareDate)
+		{
+			compareDate = new Date();
+		}
+		for (CronExpression cronexp : cronexpressions)
+		{
+			if (cronexp.isSatisfiedBy(compareDate))
+			{
+				logger.info("给出的时间满足cron,达到运行时间::" + compareDate);
+				return true;
+			}
+		}
+		logger.info("给出的时间不满足cron,未达到运行条件");
+		return false;
+	}
+
+	public static int getPeriodType(String cronExp) throws ParseException
+	{
+		String[] periods = cronExp.split(" ");
+		if (periods.length != 7)
+		{
+			throw new ParseException("CRON表达式长度异常", -1);
+		}
+		for (int i = 0; i < 7; i++)
+		{
+			if (!"*".equals(periods[i]))
+			{
+				return JOB_PERIOD_TYPE.get(i);
+			}
+		}
+		return -1;
+	}
+
+	public static int getPeriodinterval(String cronExp) throws ParseException
+	{
+		String[] periods = cronExp.split(" ");
+		if (periods.length != 7)
+		{
+			throw new ParseException("CRON表达式长度异常", -1);
+		}
+		for (int i = 0; i < 7; i++)
+		{
+			if (!"*".equals(periods[i]))
+			{
+				return Integer.parseInt(periods[i]);
+			}
+		}
+		return -1;
+	}
+}

+ 93 - 0
da/src/main/java/com/datau/da/utils/DateUtil.java

@@ -0,0 +1,93 @@
+package com.datau.da.utils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * @author 宋显哲
+ * @version 1.0.0 创建于 2018/1/5
+ **/
+public final class DateUtil {
+
+    private DateUtil() {
+    }
+
+    private static final SimpleDateFormat yyyyMMddHHmmss = new SimpleDateFormat("yyyyMMddHHmmss");
+    private static final SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
+    private static final SimpleDateFormat yyyy_MM_dd_HH_mm_ss = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    private static final SimpleDateFormat yyyy_MM_dd = new SimpleDateFormat("yyyy-MM-dd");
+
+
+    /**
+     * 获取当时间并格式化为:yyyyMMddHHmmss格式
+     *
+     * @return 返回yyyyMMddHHmmss格式的时间字符串
+     * @throws Exception
+     */
+    public static String getCurrYyyyMMddHHmmssDate() throws Exception {
+        return yyyyMMddHHmmss.format(new Date());
+    }
+
+    /**
+     * 计算时间格式为:yyyyMMddHHmmss的时间差值
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @return 返回时间,单位秒
+     * @throws Exception
+     */
+    public static long compute_yyyyMMddHHmmssTime(String startTime, String endTime) throws Exception {
+        Date startDate = yyyyMMddHHmmss.parse(startTime);
+        Date endDate = yyyyMMddHHmmss.parse(endTime);
+        return (endDate.getTime() - startDate.getTime()) / 1000L;
+    }
+
+    /**
+     * 将时间从yyyyMMddHHmmss转换成:yyyy-MM-dd HH:mm:ss
+     *
+     * @param time
+     * @return
+     * @throws ParseException
+     */
+    public static String convertTime(String time) throws ParseException {
+        return yyyy_MM_dd_HH_mm_ss.format(yyyyMMddHHmmss.parse(time));
+    }
+
+    /**
+     * 将时间从yyyy-MM-dd HH:mm:ss转换成:yyyyMMddHHmmss
+     *
+     * @param time
+     * @return
+     * @throws ParseException
+     */
+    public static String yyyy_MM_dd_HH_mm_ss2yyyyMMddHHmmss(String time) throws ParseException {
+        return yyyyMMddHHmmss.format(yyyy_MM_dd_HH_mm_ss.parse(time));
+    }
+
+    public static String getCurrentyyyy_MM_dd_HH_mm_ss(){
+        return yyyy_MM_dd_HH_mm_ss.format(new Date());
+    }
+
+    /**
+     * 获取当前时间,时间格式为:yyyyMMdd
+     *
+     * @return 返回时间字符串
+     */
+    public static String getCurrYyyyMmDd() {
+        return yyyyMMdd.format(new Date());
+    }
+
+
+    public static String timestamp2yyyyMMddHHmmss(String timestamp) throws Exception {
+        return yyyyMMddHHmmss.format(new Date(Long.parseLong(timestamp) * 1000));
+    }
+
+    public static String getCurrYyyy_MM_dd() throws Exception {
+        return yyyy_MM_dd.format(new Date());
+    }
+    public static String formatDateToString(Date date) throws Exception {
+        return yyyy_MM_dd_HH_mm_ss.format(date);
+    }
+
+}

+ 18 - 0
da/src/main/java/com/datau/da/utils/FileTool.java

@@ -0,0 +1,18 @@
+package com.datau.da.utils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+
+public class FileTool {
+    public static void uploadFile(byte[] file, String filePath, String fileName) 
+            throws Exception { 
+        File targetFile = new File(filePath);  
+        if(!targetFile.exists()){    
+            targetFile.mkdirs();    
+        }       
+        FileOutputStream out = new FileOutputStream(filePath+fileName);
+        out.write(file);
+        out.flush();
+        out.close();
+    }
+}

+ 389 - 0
da/src/main/java/com/datau/da/utils/FtpUtils.java

@@ -0,0 +1,389 @@
+package com.datau.da.utils;
+
+import com.datau.da.utils.ftp.FtpClientPool;
+import com.datau.da.utils.ftp.FtpConfiguration;
+import org.apache.commons.net.ftp.FTPClient;
+import org.apache.commons.net.ftp.FTPFile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.util.StringTokenizer;
+
+/**
+ * @author 宋显哲
+ * @version 1.0.0 创建于 2018/8/16
+ **/
+public class FtpUtils {
+    private static final Logger LOGGER = LoggerFactory.getLogger(FtpUtils.class);
+    private volatile static FtpUtils instance = null;
+
+    private FtpClientPool ftpClientPool = null;
+
+    public FtpClientPool getFtpClientPool() {
+        return ftpClientPool;
+    }
+
+    private FtpUtils() {
+        FtpConfiguration configuration = new FtpConfiguration();
+        configuration.setHost(CommonConfUtil.getConf("mcd.ftp.host"));
+        configuration.setPort(CommonConfUtil.getInteger("mcd.ftp.port", 21));
+        configuration.setUsername(CommonConfUtil.getConf("mcd.ftp.username"));
+        configuration.setPassword(CommonConfUtil.getConf("mcd.ftp.password"));
+        configuration.setConnectTimeOut(CommonConfUtil.getInteger("mcd.ftp.timeout", 600));
+        configuration.setMaxTotal(CommonConfUtil.getInteger("mcd.ftp.maxTotal", 10));
+        configuration.setMaxIdle(CommonConfUtil.getInteger("mcd.ftp.maxIdle", 10));
+        configuration.setMinIdle(CommonConfUtil.getInteger("mcd.ftp.minIdle", 0));
+        configuration.setMaxWaitMillis(CommonConfUtil.getLong("mcd.ftp.maxWaitMillis", 600000));
+        configuration.setPassiveMode(CommonConfUtil.getBool("mcd.ftp.passiveMode", false));
+        ftpClientPool = new FtpClientPool(configuration);
+    }
+
+    private static FtpUtils getInstance() {
+        synchronized (FtpUtils.class) {
+            if (instance == null) {
+                instance = new FtpUtils();
+            }
+        }
+        return instance;
+    }
+
+    /**
+     * 判断 FTP 服务器上的文件是否存在
+     *
+     * @param filePath FTP服务器中的文件路径
+     * @return 文件存在则返回true,否则返回false
+     */
+    public static boolean fileIsExist(String filePath) {
+        FTPClient ftpClient = getInstance().getFtpClientPool().getFtpClient();
+        try {
+            if (filePath == null || "".equals(filePath)) {
+                LOGGER.error("filePath = {}", filePath);
+                return false;
+            }
+            String fileName = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.length());
+            FTPFile[] ftpFiles = ftpClient.listFiles(filePath, (ftpFile) -> fileName.equals(ftpFile.getName()));
+            if (ftpFiles == null || ftpFiles.length == 0) {
+                return false;
+            }
+            return ftpFiles[0].isFile();
+        } catch (IOException e) {
+            LOGGER.error("FTP操作异常,{}", e);
+            return false;
+        } finally {
+            getInstance().getFtpClientPool().returnFtpClient(ftpClient);
+        }
+    }
+
+    /**
+     * 判断 FTP 服务器上的文件夹是否存在
+     *
+     * @param path FTP服务器中的文件夹路径
+     * @return 文件存在则返回true,否则返回false
+     */
+    public static boolean dirIsExist(String path) {
+        FTPClient ftpClient = getInstance().getFtpClientPool().getFtpClient();
+        try {
+            if (path == null || "".equals(path)) {
+                LOGGER.error("path = {}", path);
+                return false;
+            }
+            String currDirName = path.substring(path.lastIndexOf("/") + 1, path.length());
+            String parentDir = path.substring(0, path.lastIndexOf("/"));
+            FTPFile[] ftpFiles = ftpClient.listDirectories(parentDir);
+            for (FTPFile ftpFile : ftpFiles) {
+                if (currDirName.equals(ftpFile.getName()) && ftpFile.isDirectory()) {
+                    return true;
+                }
+            }
+            return false;
+        } catch (Exception e) {
+            LOGGER.error("FTP操作异常,{}", e);
+            return false;
+        } finally {
+            getInstance().getFtpClientPool().returnFtpClient(ftpClient);
+        }
+    }
+
+    /**
+     * 创建在ftp服务器中创建文件夹
+     *
+     * @param path 文件夹路径,只支持创建以及目录
+     * @return 文件创建成功返回true,否则返回false
+     */
+    public static boolean createDir(String path) {
+        FTPClient ftpClient = getInstance().getFtpClientPool().getFtpClient();
+        try {
+            if (path == null || "".equals(path)) {
+                LOGGER.error("path = {}", path);
+                return false;
+            }
+            int i = ftpClient.mkd(path);
+            return i == 257;
+        } catch (Exception e) {
+            LOGGER.error("FTP操作异常,{}", e);
+            return false;
+        } finally {
+            getInstance().getFtpClientPool().returnFtpClient(ftpClient);
+        }
+    }
+
+    /**
+     * 创建在ftp服务器中创建多级文件夹
+     *
+     * @param path 文件夹路径,只支持创建以及目录
+     * @return 文件创建成功返回true,否则返回false
+     */
+    public static boolean createDirs(String path) {
+        try {
+            if (path == null || "".equals(path)) {
+                LOGGER.error("path = {}", path);
+                return false;
+            }
+            StringTokenizer stringTokenizer = new StringTokenizer(path, "/");
+            String createPath = "";
+            boolean b = false;
+            while (stringTokenizer.hasMoreElements()) {
+                createPath = createPath + "/" + (String) stringTokenizer.nextElement();
+                if (!dirIsExist(createPath)) {
+                    b = createDir(createPath);
+                }
+            }
+            return b;
+        } catch (Exception e) {
+            LOGGER.error("FTP操作异常,{}", e);
+            return false;
+        }
+    }
+
+
+    /**
+     * 将文件上传至FTP 服务器
+     *
+     * @param localFile  本地文件
+     * @param remotePath 文件上传至FTP服务器路径
+     * @return 上传成功返回true,否则返回false
+     */
+    public static boolean upload(String localFile, String remotePath) {
+        try {
+            if (localFile == null || "".equals(localFile)
+                    || remotePath == null || "".equals(remotePath)) {
+                LOGGER.error("localFile = {},remotePath = {}", localFile, remotePath);
+                return false;
+            }
+            return upload(localFile, remotePath, localFile.substring(localFile.lastIndexOf(File.separator) + 1, localFile.length()));
+        } catch (Exception e) {
+            LOGGER.error("FTP操作异常,{}", e);
+            return false;
+        }
+    }
+
+    /**
+     * 将文件上传至FTP 服务器
+     *
+     * @param localFile     本地文件
+     * @param remotePath    文件上传至FTP服务器路径
+     * @param storeFileName 存储在FTP服务器上的文件名
+     * @return 上传成功返回true,否则返回false
+     */
+    public static boolean upload(String localFile, String remotePath, String storeFileName) {
+        FTPClient ftpClient = getInstance().getFtpClientPool().getFtpClient();
+        try {
+            if (localFile == null || "".equals(localFile)
+                    || remotePath == null || "".equals(remotePath)) {
+                LOGGER.error("localFile = {},remotePath = {}", localFile, remotePath);
+                return false;
+            }
+            File file = new File(localFile);
+            if (!file.exists() || !file.isFile()) {
+                LOGGER.error("本地文件 {} 不存在!", localFile);
+                return false;
+            }
+            ftpClient.changeWorkingDirectory(remotePath);
+            return ftpClient.storeFile(storeFileName, new FileInputStream(file));
+        } catch (Exception e) {
+            LOGGER.error("FTP操作异常,{}", e);
+            return false;
+        } finally {
+            getInstance().getFtpClientPool().returnFtpClient(ftpClient);
+        }
+    }
+
+
+    /**
+     * 从FTP服务器中下载文件
+     *
+     * @param remoteFile    FTP中的文件路径
+     * @param localPath     下载到本地的文件路径
+     * @param localFileName 下载到本地的文件名
+     * @return 下载成功返回true,否则返回false
+     */
+    public static boolean load(String remoteFile, String localPath, String localFileName) {
+        FTPClient ftpClient = getInstance().getFtpClientPool().getFtpClient();
+        try {
+            if (localPath == null || "".equals(localPath)
+                    || remoteFile == null || "".equals(remoteFile)
+                    || localFileName == null || "".equals(localFileName)) {
+                LOGGER.error("remoteFile = {},localPath = {},localFileName={}", remoteFile, localPath, localFileName);
+                return false;
+            }
+
+            File localDir = new File(localPath);
+            if (!localDir.exists() || !localDir.isDirectory()) {
+                localDir.mkdirs();
+            }
+            return ftpClient.retrieveFile(remoteFile, new FileOutputStream(localPath + File.separator + localFileName));
+        } catch (Exception e) {
+            return false;
+        } finally {
+            getInstance().getFtpClientPool().returnFtpClient(ftpClient);
+        }
+    }
+
+    /**
+     * 从FTP服务器中下载文件
+     *
+     * @param remoteFile FTP中的文件路径
+     * @param localPath  下载到本地的文件路径
+     * @return 下载成功返回true,否则返回false
+     */
+    public static boolean load(String remoteFile, String localPath) {
+        FTPClient ftpClient = getInstance().getFtpClientPool().getFtpClient();
+        try {
+            if (localPath == null || "".equals(localPath)
+                    || remoteFile == null || "".equals(remoteFile)) {
+                LOGGER.error("remoteFile = {},localPath = {}", remoteFile, localPath);
+                return false;
+            }
+            File localDir = new File(localPath);
+            if (!localDir.exists() || !localDir.isDirectory()) {
+                localDir.mkdirs();
+            }
+            return ftpClient.retrieveFile(remoteFile, new FileOutputStream(localPath + File.separator + remoteFile.substring(remoteFile.lastIndexOf("/") + 1, remoteFile.length())));
+        } catch (Exception e) {
+            return false;
+        } finally {
+            getInstance().getFtpClientPool().returnFtpClient(ftpClient);
+        }
+    }
+
+    /**
+     * 删除FTP服务器上的文件夹
+     *
+     * @param remotePath FTP中的文件夹路径
+     * @return 删除成功返回true,否则返回false
+     */
+    public static boolean deleteDir(String remotePath) {
+        FTPClient ftpClient = getInstance().getFtpClientPool().getFtpClient();
+        try {
+            if (remotePath == null || "".equals(remotePath)) {
+                LOGGER.error("path = {}", remotePath);
+                return false;
+            }
+            return ftpClient.removeDirectory(remotePath);
+        } catch (Exception e) {
+            LOGGER.error("FTP操作异常,{}", e);
+            return false;
+        } finally {
+            getInstance().getFtpClientPool().returnFtpClient(ftpClient);
+        }
+    }
+
+    /**
+     * 删除FTP服务器上的文件
+     *
+     * @param remoteFile FTP中的文件路径
+     * @return 删除成功返回true,否则返回false
+     */
+    public static boolean deleteFile(String remoteFile) {
+        FTPClient ftpClient = getInstance().getFtpClientPool().getFtpClient();
+        try {
+            if (remoteFile == null || "".equals(remoteFile)) {
+                LOGGER.error("path = {}", remoteFile);
+                return false;
+            }
+            return ftpClient.deleteFile(remoteFile);
+        } catch (Exception e) {
+            LOGGER.error("FTP操作异常,{}", e);
+            return false;
+        } finally {
+            getInstance().getFtpClientPool().returnFtpClient(ftpClient);
+        }
+    }
+
+    /**
+     * 对FTP服务器中的文件重命名
+     *
+     * @param orgFileName    FTP中的文件原始名称(文件全路径)
+     * @param targetFileName FTP重命名后的文件名(文件全路径)
+     * @return 重命名成功返回true,否则返回false
+     */
+    public static boolean renameFile(String orgFileName, String targetFileName) {
+        FTPClient ftpClient = getInstance().getFtpClientPool().getFtpClient();
+        try {
+            if (orgFileName == null || "".equals(orgFileName)
+                    || targetFileName == null || "".equals(targetFileName)) {
+                LOGGER.error("orgFileName = {},localPath = {}", orgFileName, targetFileName);
+                return false;
+            }
+            ftpClient.rename(orgFileName, targetFileName);
+            return true;
+        } catch (Exception e) {
+            LOGGER.error("FTP操作异常,{}", e);
+            return false;
+        }finally {
+            getInstance().getFtpClientPool().returnFtpClient(ftpClient);
+        }
+    }
+
+    /**
+     * 将文件上传至FTP 服务器
+     *
+     * @param localFile     本地文件
+     * @param remotePath    文件上传至FTP服务器路径
+     * @param storeFileName 存储在FTP服务器上的文件名
+     * @return 上传成功返回true,否则返回false
+     */
+    public static boolean uploadAndDel(String localFile, String remotePath, String storeFileName) {
+        FTPClient ftpClient = getInstance().getFtpClientPool().getFtpClient();
+        FileInputStream in = null;
+        File file = null;
+        try {
+            if (localFile == null || "".equals(localFile)
+                    || remotePath == null || "".equals(remotePath)) {
+                LOGGER.error("localFile = {},remotePath = {}", localFile, remotePath);
+                return false;
+            }
+            file = new File(localFile);
+            if (!file.exists() || !file.isFile()) {
+                LOGGER.error("本地文件 {} 不存在!", localFile);
+                return false;
+            }
+            in = new FileInputStream(file);
+            ftpClient.changeWorkingDirectory(remotePath);
+            boolean uploadResult = ftpClient.storeFile(storeFileName, in);
+
+            return uploadResult;
+        } catch (Exception e) {
+            LOGGER.error("FTP操作异常,{}", e);
+            return false;
+        } finally {
+            getInstance().getFtpClientPool().returnFtpClient(ftpClient);
+            if(in != null){
+                try {
+                    in.close();
+                    file.delete();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    public static InputStream readFtpFile(String remoteFile) throws Exception {
+        FTPClient ftpClient = getInstance().getFtpClientPool().getFtpClient();
+        return ftpClient.retrieveFileStream(remoteFile);
+    }
+
+
+}

+ 20 - 0
da/src/main/java/com/datau/da/utils/JsonUtil.java

@@ -0,0 +1,20 @@
+package com.datau.da.utils;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+public final class JsonUtil {
+    private JsonUtil(){}
+    private static ObjectMapper objectMapper = new ObjectMapper();
+
+    public static String toJson(Object obj) throws Exception {
+        return objectMapper.writeValueAsString(obj);
+    }
+    public static <T> T fromJson(String jsonStr,Class<T> clazz) throws Exception {
+        return objectMapper.readValue(jsonStr,clazz);
+    }
+}

+ 406 - 0
da/src/main/java/com/datau/da/utils/ParamUtil.java

@@ -0,0 +1,406 @@
+package com.datau.da.utils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @ClassName: ParamUtil
+ * @Description: 接口参数转换类
+ * @author: IF
+ * @date: 2018年7月2日 下午3:25:59
+ */
+public class ParamUtil {
+
+	/**
+	 * @Title: getParamString
+	 * @Description: 用于模糊搜索
+	 * @param param
+	 * @return: String
+	 */
+	public static String getParamString(String param) {
+		String result = null;
+		if (param != null) {
+			result = param.replaceAll("%", "\\\\%").replaceAll("_", "\\\\_");
+		}
+		return result;
+	}
+
+	public static Boolean isFloat(String number) {
+		Boolean strResult = number.matches("-[0-9]+(.[0-9]+)?|[0-9]+(.[0-9]+)?");
+		return strResult;
+	}
+
+	public static boolean isValidDate(String str) {
+		boolean convertSuccess = true;
+		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+		try {
+			format.setLenient(false);
+			format.parse(str);
+		} catch (ParseException e) {
+			convertSuccess = false;
+		}
+		return convertSuccess;
+	}
+
+//	public static boolean isNumeric(String str) {
+//		try {
+//			Integer.parseInt(str);
+//			return true;
+//		} catch (NumberFormatException e) {
+//			return false;
+//		}
+//	}
+
+	public static boolean isNullString(String str) {
+		if (str == null || removeBlank(str).equals("")) {
+			return true;
+		}
+		return false;
+	}
+
+	public static String removeBlank(String str) {
+		String result = str.replaceAll("\\s*", "");
+		return result;
+	}
+
+	// 驼峰转下划线
+	public static final char UNDERLINE = '_';
+
+	public static String camelToUnderline(String param) {
+		if (param == null || "".equals(param.trim())) {
+			return "total";
+		}
+		int len = param.length();
+		StringBuilder sb = new StringBuilder(len);
+		for (int i = 0; i < len; i++) {
+			char c = param.charAt(i);
+			if (Character.isUpperCase(c)) {
+				sb.append(UNDERLINE);
+				sb.append(Character.toLowerCase(c));
+			} else {
+				sb.append(c);
+			}
+		}
+		return sb.toString();
+	}
+
+	private static Pattern linePattern = Pattern.compile("_(\\w)");
+
+	/** 下划线转驼峰 */
+	public static String lineToHump(String str) {
+		str = str.toLowerCase();
+		Matcher matcher = linePattern.matcher(str);
+		StringBuffer sb = new StringBuffer();
+		while (matcher.find()) {
+			matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
+		}
+		matcher.appendTail(sb);
+		return sb.toString();
+	}
+
+	public static String getDefaultOrder(String order) {
+		if (order == null || "".equals(order.trim())) {
+			return "asc";
+		}
+		return order;
+	}
+
+	public static String getDefaultEndTime(String endTime) {
+		if (endTime == null || endTime.equals("")) {
+			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+			// Calendar calendar = Calendar.getInstance();
+			Date todayDate = new Date();
+			String resultDay = df.format(todayDate);
+			// calendar.setTime(todayDate);
+			// calendar.add(Calendar.DAY_OF_MONTH, -1);
+			// Date resultDate = calendar.getTime();
+			// String resultDay = df.format(resultDate);
+			return resultDay;
+		} else {
+			return endTime;
+		}
+	}
+
+	/**
+	 * 
+	 * @Title: getDefaultCurrentTime
+	 * @Description:当前时间
+	 * @param endTime
+	 * @return
+	 * @return: String
+	 */
+	public static String getDefaultCurrentTime(String endTime) {
+		if (endTime == null || endTime.equals("")) {
+			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+			Date todayDate = new Date();
+			String today = df.format(todayDate);
+			return today;
+		} else {
+			return endTime;
+		}
+
+	}
+
+	public static String getDefaultBeginTime(String beginTime) {
+		// if (beginTime == null || beginTime.equals("")) {
+		// SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+		// Calendar calendar = Calendar.getInstance();
+		// Date todayDate = new Date();
+		// calendar.setTime(todayDate);
+		// calendar.add(Calendar.DAY_OF_MONTH, -1);
+		// Date resultDate = calendar.getTime();
+		// String resultDay = df.format(resultDate);
+		// return resultDay;
+		// } else {
+		return beginTime;
+		// }
+	}
+
+	// 输入一个月份,判断周数
+	public static void main(String args[]) throws Exception {
+		System.out.println(getDefaultDataMonth("2018-12", -1));
+
+	}
+
+	public static String getDefaultDataMonth(String dataMonth, Integer MonthNum) throws ParseException {
+		Date todayDate = null;
+		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM");
+		Calendar calendar = Calendar.getInstance();
+		if (MonthNum == null) {
+			MonthNum = 12;
+		}
+		if (dataMonth == null || dataMonth.equals("")) {
+			todayDate = new Date();
+			calendar.setTime(todayDate);
+			calendar.set(Calendar.MONDAY, calendar.get(Calendar.MONTH) - 1 - MonthNum);
+			Date resultDate = calendar.getTime();
+			String resultDay = df.format(resultDate);
+			return resultDay;
+		} else {
+			todayDate = df.parse(dataMonth);
+			calendar.setTime(todayDate);
+			calendar.set(Calendar.MONDAY, calendar.get(Calendar.MONTH) - 1 - MonthNum);
+			Date resultDate = calendar.getTime();
+			return df.format(resultDate);
+		}
+	}
+
+	public static String getDefaultBeginTime(String beginTime, Integer dayNum) throws ParseException {
+		Date todayDate = null;
+		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+		Calendar calendar = Calendar.getInstance();
+		if (dayNum == null) {
+			dayNum = 7;
+		}
+		if (beginTime == null || beginTime.equals("")) {
+			todayDate = new Date();
+			calendar.setTime(todayDate);
+			calendar.add(Calendar.DAY_OF_MONTH, -dayNum);
+			Date resultDate = calendar.getTime();
+			String resultDay = df.format(resultDate);
+			return resultDay;
+		} else {
+			todayDate = df.parse(beginTime);
+			calendar.setTime(todayDate);
+			calendar.add(Calendar.DAY_OF_MONTH, -dayNum);
+			Date resultDate = calendar.getTime();
+			return df.format(resultDate);
+		}
+	}
+
+	/**
+	 * 
+	 * @Title: getDaysOfMonth --废掉
+	 * @Description: 获取月天数
+	 * @param date
+	 * @return
+	 * @return: int
+	 */
+	public static int getDaysOfMonth(Date date) {
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
+	}
+
+	private static final String[] ONE_TO_TEN = { "一", "二", "三", "四", "五", "六", "七", "八", "九", "十" };
+
+	/**
+	 * 
+	 * @Title: getWeeks --废掉
+	 * @Description: 获取周列表
+	 * @param date
+	 * @return
+	 * @return: List<Map<String,String>>
+	 */
+	public static List<Map<String, String>> getWeeks(Date date) {
+		List<Map<String, String>> months = new ArrayList<>();
+		Map<String, String> week = new HashMap<>();
+
+		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		int month = calendar.get(Calendar.MONTH);
+		int count = 0;
+		while (calendar.get(Calendar.MONTH) == month) {
+			if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
+				week = new HashMap<>();
+				String time = format.format(calendar.getTime());
+				calendar.add(Calendar.DATE, 6);
+				String time2 = format.format(calendar.getTime());
+				week.put("value",
+						"第" + ONE_TO_TEN[count] + "周("
+								+ time.substring(time.length() - 5, time.length()).replace("-", "月") + "日-"
+								+ time2.substring(time2.length() - 5, time2.length()).replace("-", "月") + "日)");
+				week.put("key", time);
+				months.add(week);
+				count++;
+			}
+			calendar.add(Calendar.DATE, 1);
+		}
+		return months;
+	}
+
+	public static String getWeekEndTime(String weekBeginTime) throws Exception {
+		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+		Date weekBeginDate = format.parse(weekBeginTime);
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(weekBeginDate);
+		calendar.add(Calendar.DATE, 6);
+		String weekEndTime = format.format(calendar.getTime());
+		return weekEndTime;
+
+	}
+
+	/**
+	 * 
+	 * @Title: listWeeks
+	 * @Description: 获取数据最小时间到当前时间所有周信息
+	 * @param minDataTime
+	 *            一年内数据最小时间
+	 * @return
+	 * @throws Exception
+	 * @return: List<Map<String,String>>
+	 */
+	public static List<Map<String, String>> listWeeks(String minDataTime) throws Exception {
+		List<Map<String, String>> months = new ArrayList<>();
+		Map<String, String> week = new HashMap<>();
+		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+		Date date = format.parse(minDataTime);
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(date);
+		int count = 1;
+		boolean fristSunDay = false;
+		String startTime = null;
+		String endTime = null;
+		// 获取第一周第一天,即数据开始时间并赋值
+		startTime = format.format(calendar.getTime());
+		week.put("weekTime", startTime);
+		Date nowDate = new Date();
+		while (calendar.getTime().compareTo(nowDate) < 1) {
+			if (!fristSunDay && calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
+				fristSunDay = true;
+				endTime = format.format(calendar.getTime());
+				week.put("weekTime", startTime + "," + endTime);
+				week.put("value", "第" + count + "周(" + formatTime(startTime) + "-" + formatTime(endTime) + ")");
+				months.add(week);
+				count++;
+			}
+			if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
+				week = new HashMap<>();
+				startTime = format.format(calendar.getTime());
+				calendar.add(Calendar.DATE, 6);
+				endTime = format.format(calendar.getTime());
+				week.put("value", "第" + count + "周(" + formatTime(startTime) + "-" + formatTime(endTime) + ")");
+				week.put("weekTime", startTime + "," + endTime);
+
+				months.add(week);
+				count++;
+			}
+			calendar.add(Calendar.DATE, 1);
+		}
+		// 默认选中当前时间前一周
+		Map<String, String> map = months.get(months.size() - 2);
+		map.put("selected", "true");
+		months.set(months.size() - 2, map);
+		// 覆盖最后一周最后一天为当天
+		calendar.add(Calendar.DATE, -7);
+		months.get(months.size() - 1).put("value", "第" + (count - 1) + "周("
+				+ formatTime(format.format(calendar.getTime())) + "-" + formatTime(format.format(nowDate)) + ")");
+		months.get(months.size() - 1).put("weekTime", format.format(calendar.getTime()) + "," + format.format(nowDate));
+		Collections.reverse(months); // 倒序排列
+
+		return months;
+	}
+
+	/**
+	 * 
+	 * @Title: formatTime
+	 * @Description:格式化时间字符串 yyyy-MM-dd 为yyyy年MM月dd日
+	 * @param time
+	 * @return
+	 * @return: String
+	 */
+	public static String formatTime(String time) {
+		time = time.replaceFirst("-", "年");
+		time = time.replaceFirst("-", "月");
+		time = time + "日";
+		return time;
+	}
+
+	/**
+	 * 
+	 * @Title: getDefaultDate
+	 * @Description: 获取默认时间
+	 * @param week
+	 *            是否为周报
+	 * @return
+	 * @return: String
+	 * @throws Exception
+	 */
+	public static String getDefaultDate(Boolean week) throws Exception {
+		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+		String defaultDate = null;
+		Date date = null;
+		Calendar calendar = Calendar.getInstance();
+		date = new Date();
+		calendar.setTime(date);
+		if (week) {
+			String startDate = null;
+			String endDate = null;
+			while (week) {
+				if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
+					calendar.add(Calendar.DATE, -1);
+					endDate = format.format(calendar.getTime());
+					calendar.add(Calendar.DATE, -6);
+					startDate = format.format(calendar.getTime());
+					break;
+				}
+				calendar.add(Calendar.DATE, -1);
+			}
+			defaultDate = startDate + "," + endDate;
+		} else {
+
+			calendar.add(Calendar.DATE, -1);
+			defaultDate = format.format(calendar.getTime());
+		}
+		return defaultDate;
+	}
+
+	/**
+	 * 判断字符串是否为数字
+	 */
+	public static boolean isNumeric(String str) {
+		Pattern pattern = Pattern.compile("[0-9]*");
+		Matcher isNum = pattern.matcher(str);
+		return isNum.matches();
+	}
+}

+ 187 - 0
da/src/main/java/com/datau/da/utils/R.java

@@ -0,0 +1,187 @@
+package com.datau.da.utils;
+
+import java.util.List;
+
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+
+
+/**
+ * @author 宋显哲
+ * @version 1.0.0 创建于 2017/12/27
+ **/
+@Component
+@Scope("prototype")
+@ApiModel(description = "请求返回实体类", value = "返回值")
+public class R<T> {
+	@ApiModelProperty(dataType = "int", name = "code", value = "请求返回状态码")
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private String code = S.OK;
+	@ApiModelProperty(dataType = "String", name = "msg", value = "请求返回描述信息")
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private String msg = S.getMsg(S.OK);
+	@ApiModelProperty(dataType = "T", name = "data", value = "返回数据")
+	T data;
+	@ApiModelProperty(dataType = "Integer", name = "page", value = "当前页码")
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private Integer page;
+	@ApiModelProperty(dataType = "Integer", name = "pageSize", value = "每页行数")
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private Integer pageSize;
+	@ApiModelProperty(dataType = "Integer", name = "totalNumber", value = "数据总数")
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private Integer totalNumber;
+	@ApiModelProperty(dataType = "Integer", name = "totalPageCount", value = "总页数")
+	@JsonInclude(JsonInclude.Include.NON_EMPTY)
+	private Integer totalPageCount;
+
+	public R() {
+	}
+
+	public R(String code) {
+		this.code = code;
+		this.msg = S.getMsg(code);
+	}
+
+	public R(T data) {
+		this.data = data;
+	}
+
+	public R(String code, String msg) {
+		this.code = code;
+		this.msg = msg;
+	}
+
+	public R(String code, String msg, T data) {
+		this.code = code;
+		this.msg = msg;
+		this.data = data;
+	}
+
+	public String getCode() {
+		return code;
+	}
+
+	public void setCode(String code) {
+		this.code = code;
+	}
+
+	public String getMsg() {
+		return msg;
+	}
+
+	public void setMsg(String msg) {
+		this.msg = msg;
+	}
+
+	public T getData() {
+		return data;
+	}
+
+	public R<T> setData(T data) {
+		this.data = data;
+		return this;
+	}
+
+	public Integer getPage() {
+		return page;
+	}
+
+	public void setPage(Integer page) {
+		this.page = page;
+	}
+
+	public Integer getPageSize() {
+		return pageSize;
+	}
+
+	public void setPageSize(Integer pageSize) {
+		this.pageSize = pageSize;
+	}
+
+	public Integer getTotalNumber() {
+		return totalNumber;
+	}
+
+	public void setTotalNumber(Integer totalNumber) {
+		this.totalNumber = totalNumber;
+	}
+
+	public Integer getTotalPageCount() {
+		return totalPageCount;
+	}
+
+	public void setTotalPageCount(Integer totalPageCount) {
+		this.totalPageCount = totalPageCount;
+	}
+
+	@Override
+	public String toString() {
+		return "ReturnData [code=" + code + ", msg=" + msg + ", data=" + data + ", page=" + page + ", pageSize="
+				+ pageSize + ", totalNumber=" + totalNumber + ", totalPageCount=" + totalPageCount + "]";
+	}
+
+	public R<List<T>> page(List<T> result) {
+		PageInfo<T> pageInfo = new PageInfo<>(result);
+		R<List<T>> r = new R<>(result);
+		r.setPage(pageInfo.getPageNum());
+		r.setPageSize(pageInfo.getPageSize());
+		r.setTotalNumber((int) pageInfo.getTotal());
+		r.setTotalPageCount(pageInfo.getPages());
+		return r;
+	}
+
+	/**
+	 * 
+	 * @Title: pageDataTotal
+	 * @Description: 存在合计数据的分页展示
+	 * @param result
+	 * @param page
+	 *            数据当前查询页数
+	 * @return
+	 * @return: R<List<T>>
+	 */
+	public R<List<T>> pageDataTotal(List<T> result, int page, T total) {
+		PageInfo<T> pageInfo = new PageInfo<>(result);
+		int pageSize = pageInfo.getPageSize();
+		int totalNumber = (int) pageInfo.getTotal() + 1;
+		int pageNum = pageInfo.getPageNum();
+		int totalPageCount = (totalNumber - 1) / pageSize + 1;
+		// 当前页为最后一页,加入合计数据
+		if (page >= totalPageCount) {
+			if (result.size() == pageSize) {
+				result.removeAll(result);
+				pageNum++;
+			}
+			if (total != null) {
+				result.add(total);
+			}
+		}
+		R<List<T>> r = new R<>(result);
+		r.setPage(pageNum);
+		r.setPageSize(pageSize);
+		r.setTotalNumber(totalNumber);
+		r.setTotalPageCount(totalPageCount);
+		return r;
+	}
+
+	public void pageStart(String sort, String order, int page, int pageSize) {
+		if (sort != null && order != null) {
+			sort = ParamUtil.camelToUnderline(sort);
+			order = ParamUtil.getDefaultOrder(order);
+			PageHelper.startPage(page, pageSize, sort + " " + order);
+		} else {
+			PageHelper.startPage(page, pageSize);
+		}
+
+	}
+
+}

+ 93 - 0
da/src/main/java/com/datau/da/utils/ReturnUtil.java

@@ -0,0 +1,93 @@
+package com.datau.da.utils;
+
+import com.datau.da.constant.StatusCode;
+import com.datau.da.entity.ReturnData;
+import com.github.pagehelper.Page;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+public class ReturnUtil {
+
+    public static ReturnData createExceptionReturn(Exception e) {
+        String ex = e.getMessage();
+        ReturnData returnData = new ReturnData();
+        returnData.setPage(0);
+        returnData.setPageSize(0);
+        returnData.setTotalPageCount(0);
+        returnData.setTotalNumber(0);
+        if (ex.contains("StatusCode:")) {
+            return returnData.retStatus(ex.split(":")[1]);
+        }
+        return returnData.retStatus(StatusCode.FAILURE);
+    }
+    public static ReturnData createExceptionReturnNew(Exception e) {
+        String ex = e.getMessage();
+        ReturnData returnData = new ReturnData();
+        if (ex.contains("StatusCode:")) {
+            return returnData.retStatus(ex.split(":")[1]);
+        }
+
+        return returnData.retStatus(StatusCode.FAILURE);
+    }
+
+    public static void newStatusException(String statusCode) throws Exception {
+        StringBuilder sb = new StringBuilder("StatusCode:");
+        sb.append(statusCode);
+        throw new Exception(sb.toString());
+    }
+
+    public static void returnOpt(HttpServletResponse response, String code) throws Exception {
+        response.setContentType("application/json;utf-8");
+        Map<String, String> ret = new HashMap<>();
+        ret.put("msg", StatusCode.getMsg(code));
+        ret.put("code", code);
+        String json = JsonUtil.toJson(ret);
+        response.getWriter().print(json);
+        response.setStatus(200);
+    }
+
+
+
+    /**
+     * 装配分页结果
+     *
+     * @param pageResult 分页结果
+     * @param <T>        对象
+     * @return 返回结果
+     */
+    public static <T> ReturnData<List<T>> assemblyReturnData(Page<T> pageResult) {
+        ReturnData<List<T>> returnData = new ReturnData<>();
+        //当前叶
+        int page = pageResult.getPageNum();
+        //页大小
+        int pageSize = pageResult.getPageSize();
+        //总条数
+        long totalNumber = pageResult.getTotal();
+        //总页数
+        int totalPageCount = pageResult.getPages();
+        //数据
+        returnData.setTotalNumber((int) totalNumber);
+        returnData.setPage(page);
+        returnData.setTotalPageCount(totalPageCount);
+        returnData.setPageSize(pageSize);
+        returnData.setData(pageResult.getResult().isEmpty() ? null : pageResult.getResult());
+        pageResult.close();
+        return returnData;
+    }
+
+    public static <T> boolean isSkipToStartPage(Page<T> pageResult) {
+        if (pageResult.getPageNum() > 1 && pageResult.getPageSize() > 10 && pageResult.getResult().isEmpty()) {
+            pageResult.close();
+            return true;
+        }
+        return false;
+    }
+}

+ 84 - 0
da/src/main/java/com/datau/da/utils/S.java

@@ -0,0 +1,84 @@
+package com.datau.da.utils;
+
+import java.util.HashMap;
+
+/**
+ * @author 王一夫
+ * @version 1.0.0 创建于 2017/12/28
+ **/
+public final class S {
+
+	/**
+	 * 请求成功
+	 */
+	public static final String OK = "1";
+	/**
+	 * 请求失败
+	 */
+	public static final String ERROR = "-1";
+	/**
+	 * 文件数据错误
+	 */
+	public static final String FILE_DATA_ERROR = "report-001";
+	/**
+	 * 客户名称,通道名称,任务名称为必填项
+	 */
+	public static final String CUSTOMER_CHANNEL_TASK_ERROR = "report-002";
+	/**
+	 * 用户名、密码错误.
+	 */
+	public static final String USER_PASSWD_ENTNO_ERROR = "100200";
+
+	/**
+	 * token为空
+	 */
+	public static final String TOKEN_IS_NULL = "100404";
+	/**
+	 * token令牌过期
+	 */
+	public static final String TOKEN_TIME_OUT = "100405";
+	/**
+	 * 平台编号错误
+	 */
+	public static final String TOKEN_FLATFORM_ERROR = "100406";
+
+	/**
+	 * 汽车模块-任务名称已存在
+	 */
+	public static final String CAR_TASK_NAME = "100201";
+
+	/**
+	 *  电信数据监控-日期参数为空
+	 */
+	public static final String DATE_IS_NULL = "100202";
+
+	@SuppressWarnings("serial")
+	private static final HashMap<String, String> codeMsg = new HashMap<String, String>() {
+		{
+			put(OK, "请求成功.");
+			put(ERROR, "请求失败.");
+
+			put(USER_PASSWD_ENTNO_ERROR, "用户名、密码错误");
+
+			put(FILE_DATA_ERROR, "文件数据错误");
+			put(CUSTOMER_CHANNEL_TASK_ERROR, "客户名称,通道名称,任务名称为必填项");
+			put(TOKEN_IS_NULL, "token is null");
+			put(TOKEN_TIME_OUT, "token令牌过期");
+			put(TOKEN_FLATFORM_ERROR, "平台编号错误");
+			put(CAR_TASK_NAME, "任务名称已存在");
+			put(DATE_IS_NULL,"传入日期参数为空");
+		}
+	};
+
+	/**
+	 * 根据状态码获取提示信息.
+	 *
+	 * @param code
+	 *            状态吗
+	 * @return 返回状态码对应的提示信息
+	 */
+	public static String getMsg(String code) {
+		return codeMsg.get(code);
+	}
+
+}

+ 300 - 0
da/src/main/java/com/datau/da/utils/ThreadPoolUtil.java

@@ -0,0 +1,300 @@
+package com.datau.da.utils;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.*;
+
+/**
+ * @author 许明
+ * on 2019/3/6.
+ * @version 2.0.0
+ * 线程池工具类
+ */
+public class ThreadPoolUtil {
+
+    private static final Logger logger = LogManager.getLogger(ThreadPoolUtil.class);
+    private static Map<String, ThreadPoolUtil> threadPoolMap = new HashMap<>();
+    private String moduleName;// 模块名称
+    private ExecutorService servicePool;//
+    private ScheduledExecutorService schedulePool;
+
+    private ThreadPoolUtil()
+    {
+
+    }
+    /**
+     *
+     * @description 创建固定大小的线程池
+     * @param moduleName
+     *            线程池名称
+     * @param poolSize
+     *            线程池大小为 poolSize*CPU
+     * @return
+     */
+    public static ThreadPoolUtil getTheadPool(String moduleName, int poolSize)
+    {
+        if (threadPoolMap.get(moduleName) != null)
+        {
+            logger.debug("获得moduleName[" + moduleName + "]线程池成功");
+            return threadPoolMap.get(moduleName);
+        }
+        else
+        {
+            synchronized (ThreadPoolUtil.class)
+            {
+                if (threadPoolMap.get(moduleName) == null)
+                {
+
+                    ThreadPoolUtil threadPool = new ThreadPoolUtil();
+                    threadPool.moduleName = moduleName;
+                    int cpuNums = Runtime.getRuntime().availableProcessors();
+                    ExecutorService servicePool = Executors.newFixedThreadPool(cpuNums * poolSize);
+                    threadPool.setServicePool(servicePool);
+                    threadPoolMap.put(moduleName, threadPool);
+                    logger.debug("创建moduleName[" + moduleName + "]线程池 poolSize[" + cpuNums * poolSize + "]成功");
+                    return threadPool;
+                }
+            }
+        }
+        return threadPoolMap.get(moduleName);
+    }
+
+    /**
+     *
+     * @description 创建不限大小的线程池
+     * @param moduleName
+     * @return
+     */
+    public static ThreadPoolUtil getTheadPool(String moduleName)
+    {
+        if (threadPoolMap.get(moduleName) != null)
+        {
+            logger.debug("获得moduleName[" + moduleName + "]不限大小线程池成功");
+            return threadPoolMap.get(moduleName);
+        }
+        else
+        {
+            synchronized (ThreadPoolUtil.class)
+            {
+                if (threadPoolMap.get(moduleName) == null)
+                {
+                    ThreadPoolUtil threadPool = new ThreadPoolUtil();
+                    threadPool.moduleName = moduleName;
+                    ExecutorService servicePool = Executors.newCachedThreadPool();
+                    threadPool.setServicePool(servicePool);
+                    threadPoolMap.put(moduleName, threadPool);
+                    logger.debug("创建moduleName[" + moduleName + "]不限大小线程池成功");
+                    return threadPool;
+                }
+            }
+        }
+        return threadPoolMap.get(moduleName);
+    }
+
+    /**
+     *
+     * @description 创建任务调度类型的线程池
+     * @param moduleName
+     *            线程池名称
+     * @param poolSize
+     *            线程池大小为 poolSize*CPU
+     * @return
+     */
+    public static ThreadPoolUtil getScheduleThreadPool(String moduleName, int poolSize)
+    {
+        if (threadPoolMap.get(moduleName) != null)
+        {
+            logger.debug("获得moduleName[" + moduleName + "]调度类型线程池成功");
+            return threadPoolMap.get(moduleName);
+        }
+        else
+        {
+            synchronized (ThreadPoolUtil.class)
+            {
+                if (threadPoolMap.get(moduleName) == null)
+                {
+
+                    ThreadPoolUtil threadPool = new ThreadPoolUtil();
+                    threadPool.moduleName = moduleName;
+                    int cpuNums = Runtime.getRuntime().availableProcessors();
+                    ScheduledExecutorService schedulePool = Executors.newScheduledThreadPool(cpuNums * poolSize);
+                    threadPool.setSchedulePool(schedulePool);
+                    threadPoolMap.put(moduleName, threadPool);
+                    logger.debug("创建moduleName[" + moduleName + "]调度类型线程池 poolSize[" + cpuNums * poolSize + "]成功");
+                    return threadPool;
+                }
+            }
+        }
+        return threadPoolMap.get(moduleName);
+    }
+
+    /**
+     *
+     * @description 线程池中添加Runnable类型
+     * @param task
+     */
+    public void runTask(Runnable task)
+    {
+        threadPoolMap.get(moduleName).getServicePool().execute(task);
+    }
+
+    /**
+     *
+     * @description 线程池中添加Callable类型
+     * @param task
+     * @return
+     */
+    public Future<?> runTask(Callable<?> task)
+    {
+        return threadPoolMap.get(moduleName).getServicePool().submit(task);
+    }
+
+    /**
+     *
+     * @description 创建并执行在给定延迟后启用的一次性操作
+     * @param run
+     * @param delay
+     * @param unit
+     */
+    public void scheduleTask(Runnable run, long delay, TimeUnit unit)
+    {
+        threadPoolMap.get(moduleName).getSchedulePool().schedule(run, delay, unit);
+    }
+
+    /**
+     *
+     * @description 创建并执行在给定延迟后启用的 ScheduledFuture
+     * @param task
+     * @param delay
+     * @param unit
+     */
+    public void scheduleTask(Callable<?> task, long delay, TimeUnit unit)
+    {
+        threadPoolMap.get(moduleName).getSchedulePool().schedule(task, delay, unit);
+    }
+
+    /**
+     *
+     * @description 创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期
+     * @param task
+     * @param initialDelay
+     * @param period
+     * @param unit
+     */
+    public void scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit)
+    {
+        threadPoolMap.get(moduleName).getSchedulePool().scheduleAtFixedRate(task, initialDelay, period, unit);
+    }
+
+    /**
+     *
+     * @description 创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟
+     * @param task
+     * @param initialDelay
+     * @param delay
+     * @param unit
+     */
+    public void scheduleWithFixedDelay(Runnable task, long initialDelay, long delay, TimeUnit unit)
+    {
+        threadPoolMap.get(moduleName).getSchedulePool().scheduleWithFixedDelay(task, initialDelay, delay, unit);
+    }
+
+    /**
+     * @description 批量提交任务,并行执行
+     * @param tasks
+     *            要执行的任务,这些任务需要实现Callable接口
+     * @param timeout
+     *            每个任务的超时时间,单位:毫秒
+     * @return 每个任务执行完成后返回的结果集合
+     */
+    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout)
+    {
+        List<Future<T>> futures = null;
+        try
+        {
+            logger.debug("开始执行任务,要执行的任务数目为: " + tasks.size());
+            long startTime = System.currentTimeMillis();
+            if (timeout < 0)
+            {
+                futures = threadPoolMap.get(moduleName).getServicePool().invokeAll(tasks);
+            }
+            else
+            {
+                futures = threadPoolMap.get(moduleName).getServicePool().invokeAll(tasks, timeout, TimeUnit.MILLISECONDS);
+                logger.debug("设定每个任务执行的超时时间为:" + timeout);
+            }
+            long endTime = System.currentTimeMillis();
+            String time = String.valueOf(endTime - startTime);
+            logger.debug("任务执行耗时: " + time + "毫秒");
+        }
+        catch (Exception e)
+        {
+            logger.error("并行执行任务出错", e);
+        }
+        return futures;
+
+    }
+
+    /**
+     *
+     * @description 关闭线程池(线程池的状态则立刻变成SHUTDOWN状态,不能再往线程池中添加任何任务)
+     */
+    public void shutDown()
+    {
+        ExecutorService servicePool = threadPoolMap.get(moduleName).getServicePool();
+        if (servicePool != null)
+        {
+            servicePool.shutdown();
+            logger.debug("线程池     Threadpool  name [" + moduleName + "] shuntdown success");
+        }
+        ScheduledExecutorService schedulePool = threadPoolMap.get(moduleName).getSchedulePool();
+        if (schedulePool != null)
+        {
+            schedulePool.shutdown();
+            logger.debug("线程池     Threadpool  name[" + moduleName + "] shuntdown success");
+        }
+        threadPoolMap.remove(moduleName);
+    }
+
+    /**
+     *
+     * @description 立即关闭线程池(线程池的状态立刻变成STOP状态,并试图停止所有正在执行的线程,不再处理还在池队列中等待的任务)
+     */
+    public void shutdownNow()
+    {
+        ExecutorService servicePool = threadPoolMap.get(moduleName).getServicePool();
+        if (servicePool != null)
+        {
+            servicePool.shutdownNow();
+            logger.debug("线程池     Threadpool  name [" + moduleName + "] shutdownNow success");
+        }
+        ScheduledExecutorService schedulePool = threadPoolMap.get(moduleName).getSchedulePool();
+        if (schedulePool != null)
+        {
+            schedulePool.shutdownNow();
+            logger.debug("线程池     Threadpool  name [" + moduleName + "] shutdownNow success");
+        }
+        threadPoolMap.remove(moduleName);
+    }
+
+    public ExecutorService getServicePool() {
+        return servicePool;
+    }
+
+    public void setServicePool(ExecutorService servicePool) {
+        this.servicePool = servicePool;
+    }
+
+    public ScheduledExecutorService getSchedulePool() {
+        return schedulePool;
+    }
+
+    public void setSchedulePool(ScheduledExecutorService schedulePool) {
+        this.schedulePool = schedulePool;
+    }
+}

+ 33 - 0
da/src/main/java/com/datau/da/utils/TokenUtil.java

@@ -0,0 +1,33 @@
+package com.datau.da.utils;
+
+import com.datau.da.entity.token.Token;
+import org.springframework.util.StringUtils;
+
+/**
+ * token解析工具类
+ *
+ * @author 许明
+ * on 2019/3/5.
+ * @version 2.0.0
+ */
+public final class TokenUtil {
+
+
+    /**
+     * 解析Token 字符串
+     *
+     * @param token token字符串
+     * @return token token对象
+     * @throws Exception
+     */
+    public static Token parseTokenStr(String token) throws Exception {
+        if (StringUtils.isEmpty(token)) {
+            throw new Exception("令牌为空!");
+        }
+        String tokenJsonStr = AesUtil.decrypt(token,
+                CommonConfUtil.getConf("aes.key"),
+                CommonConfUtil.getConf("aes.iv"));
+        return JsonUtil.fromJson(tokenJsonStr, Token.class);
+    }
+
+}

+ 71 - 0
da/src/main/java/com/datau/da/utils/ftp/FtpClientFactory.java

@@ -0,0 +1,71 @@
+package com.datau.da.utils.ftp;
+
+import org.apache.commons.net.ftp.FTPClient;
+import org.apache.commons.pool2.BasePooledObjectFactory;
+import org.apache.commons.pool2.PooledObject;
+import org.apache.commons.pool2.impl.DefaultPooledObject;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * @author 宋显哲
+ * @version 1.0.0 创建于 2018/8/20
+ **/
+public class FtpClientFactory extends BasePooledObjectFactory<FTPClient> {
+    private static Logger logger = LogManager.getLogger(FtpClientFactory.class);
+    private FtpConfiguration configuration;
+
+    public FtpClientFactory(FtpConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    @Override
+    public FTPClient create() throws Exception {
+        FTPClient ftpClient = new FTPClient();
+        try {
+            ftpClient.setConnectTimeout(configuration.getConnectTimeOut());
+            ftpClient.setControlKeepAliveTimeout(1000);
+            ftpClient.setControlEncoding("UTF-8");
+            ftpClient.connect(configuration.getHost(), configuration.getPort());
+            boolean login = ftpClient.login(configuration.getUsername(), configuration.getPassword());
+            if (!login) {
+                logger.error("ftpClient登陆失败!");
+                throw new Exception("ftpClient登陆失败! username:" + configuration.getUsername() + " ; password:"
+                        + configuration.getPassword());
+            }
+            if (configuration.isPassiveMode()) {
+                ftpClient.enterLocalPassiveMode();
+            }
+            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
+            return ftpClient;
+        } catch (Exception e) {
+            logger.error("创建ftp连接错误 {}", e);
+            return ftpClient;
+        }
+
+    }
+
+    @Override
+    public PooledObject<FTPClient> wrap(FTPClient ftpClient) {
+        return new DefaultPooledObject<FTPClient>(ftpClient);
+    }
+
+    @Override
+    public void destroyObject(PooledObject<FTPClient> p) throws Exception {
+        FTPClient ftpClient = p.getObject();
+        ftpClient.logout();
+        ftpClient.disconnect();
+        super.destroyObject(p);
+    }
+
+    @Override
+    public boolean validateObject(PooledObject<FTPClient> p) {
+        FTPClient ftpClient = p.getObject();
+        try {
+            return ftpClient.sendNoOp();
+        } catch (Exception e) {
+            logger.error("ftp-->{}", e);
+            return false;
+        }
+    }
+}

+ 51 - 0
da/src/main/java/com/datau/da/utils/ftp/FtpClientPool.java

@@ -0,0 +1,51 @@
+package com.datau.da.utils.ftp;
+
+import org.apache.commons.net.ftp.FTPClient;
+import org.apache.commons.pool2.impl.GenericObjectPool;
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+
+/**
+ * @author 宋显哲
+ * @version 1.0.0 创建于 2018/8/20
+ **/
+public class FtpClientPool {
+    private GenericObjectPool<FTPClient> ftpClientPool;
+    private FtpConfiguration configuration;
+
+    public FtpClientPool(FtpConfiguration configuration) {
+        this.configuration = configuration;
+        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
+        poolConfig.setMaxIdle(configuration.getMaxIdle());
+        poolConfig.setMaxTotal(configuration.getMaxTotal());
+        poolConfig.setMinIdle(configuration.getMinIdle());
+        poolConfig.setMaxWaitMillis(configuration.getMaxWaitMillis());
+        poolConfig.setTestOnBorrow(true);
+        poolConfig.setTestOnCreate(true);
+        poolConfig.setTestOnReturn(true);
+        ftpClientPool = new GenericObjectPool<FTPClient>(new FtpClientFactory(this.configuration), poolConfig);
+    }
+
+    /**
+     * 获取FTP客户端
+     *
+     * @return
+     */
+    public FTPClient getFtpClient() {
+        try {
+            return ftpClientPool.borrowObject();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 将ftp连接返回连接池
+     *
+     * @param ftpClient ftpClient
+     */
+    public void returnFtpClient(FTPClient ftpClient) {
+        ftpClientPool.returnObject(ftpClient);
+    }
+
+}

+ 108 - 0
da/src/main/java/com/datau/da/utils/ftp/FtpConfiguration.java

@@ -0,0 +1,108 @@
+package com.datau.da.utils.ftp;
+
+/**
+ * @author 宋显哲
+ * @version 1.0.0 创建于 2018/8/20
+ **/
+public class FtpConfiguration {
+
+    private String host;
+    private int port;
+    private String username;
+    private String password;
+    private int connectTimeOut = 60;
+    private long maxWaitMillis = -1L;
+    private int maxTotal = 10;
+    private int maxIdle = 8;
+    private int minIdle = 0;
+    private boolean passiveMode=false;
+
+    public String getHost() {
+        return host;
+    }
+
+    public FtpConfiguration setHost(String host) {
+        this.host = host;
+        return this;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public FtpConfiguration setPort(int port) {
+        this.port = port;
+        return this;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public FtpConfiguration setUsername(String username) {
+        this.username = username;
+        return this;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public FtpConfiguration setPassword(String password) {
+        this.password = password;
+        return this;
+    }
+
+    public int getConnectTimeOut() {
+        return connectTimeOut;
+    }
+
+    public FtpConfiguration setConnectTimeOut(int connectTimeOut) {
+        this.connectTimeOut = connectTimeOut;
+        return this;
+    }
+
+    public long getMaxWaitMillis() {
+        return maxWaitMillis;
+    }
+
+    public FtpConfiguration setMaxWaitMillis(long maxWaitMillis) {
+        this.maxWaitMillis = maxWaitMillis;
+        return this;
+    }
+
+    public int getMaxTotal() {
+        return maxTotal;
+    }
+
+    public FtpConfiguration setMaxTotal(int maxTotal) {
+        this.maxTotal = maxTotal;
+        return this;
+    }
+
+    public int getMaxIdle() {
+        return maxIdle;
+    }
+
+    public FtpConfiguration setMaxIdle(int maxIdle) {
+        this.maxIdle = maxIdle;
+        return this;
+    }
+
+    public int getMinIdle() {
+        return minIdle;
+    }
+
+    public FtpConfiguration setMinIdle(int minIdle) {
+        this.minIdle = minIdle;
+        return this;
+    }
+
+    public boolean isPassiveMode() {
+        return passiveMode;
+    }
+
+    public void setPassiveMode(boolean passiveMode) {
+        this.passiveMode = passiveMode;
+    }
+}

+ 48 - 0
da/src/main/java/com/datau/da/utils/mail/MailUtil.java

@@ -0,0 +1,48 @@
+package com.datau.da.utils.mail;
+
+import com.datau.da.entity.mail.ErrorJobInfo;
+import com.datau.da.entity.mail.MailBean;
+import com.datau.da.service.job.impl.TriggerJob;
+import com.datau.da.utils.CommonConfUtil;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/**
+ * @author 许明
+ * on 2019/5/9.
+ * @version 2.0.0
+ */
+public class MailUtil {
+
+    private static final Logger logger = LogManager.getLogger(MailUtil.class);
+
+    private final static String MAIL_USER = CommonConfUtil.getConf("mail.user");
+    private final static String MAIL_PASS = CommonConfUtil.getConf("mail.pwd");
+    private final static String MAIL_SERVER = CommonConfUtil.getConf("mail.server");
+//    private final static String MAIL_TO = CommonConfUtil.getConf("mail.to");
+
+    public static void sendErrorTaskInfo(String taskId) throws Exception{
+        MailBean mb = new MailBean();
+        mb.setHost(MAIL_SERVER); // 设置SMTP主机(163),若用126,则设为:smtp.126.com
+        mb.setUsername(MAIL_USER); // 设置发件人邮箱的用户名
+        mb.setPassword(MAIL_PASS); // 设置发件人邮箱的密码,需将*号改成正确的密码
+        mb.setFrom(MAIL_USER); // 设置发件人的邮箱
+        String mailTo = TriggerJob.getSendMailsConfig();
+        mb.setTo(mailTo); // 设置收件人的邮箱
+
+        ErrorJobInfo errorJobInfo = TriggerJob.getErrorJobInfoById(taskId);
+        mb.setSubject("数据中心调度【" + errorJobInfo.getTaskName() + "】任务错误信息"); // 设置邮件的主题
+        mb.setContent("数据中心调度【taskId=" + errorJobInfo.getTaskId() + "】【taskName=" + errorJobInfo.getTaskName() + "】任务出错,请检查!"
+                + System.lineSeparator() + "具体信息如下:"
+                + System.lineSeparator() + errorJobInfo.getErrorDesc()); // 设置邮件的正文
+
+        logger.info("正在发送邮件...收件人为:[" + mailTo + "]");
+        // 发送邮件
+        if (SendMailUtil.sendMail(mb)) {
+            logger.info("发送成功!");
+            TriggerJob.updateSendedStatusById(errorJobInfo.getId(), "1");
+        } else {
+            logger.error("发送失败!");
+        }
+    }
+}

+ 96 - 0
da/src/main/java/com/datau/da/utils/mail/SendMailUtil.java

@@ -0,0 +1,96 @@
+package com.datau.da.utils.mail;
+
+import com.datau.da.entity.mail.MailBean;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import javax.activation.DataHandler;
+import javax.activation.FileDataSource;
+import javax.mail.*;
+import javax.mail.internet.*;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.Vector;
+
+/**
+ * @author 许明
+ * on 2018/11/15.
+ * @version 2.0.0
+ */
+public class SendMailUtil {
+
+    private static final Logger logger = LogManager.getLogger(SendMailUtil.class);
+
+    public static String toChinese (String text){
+        try {
+            text = MimeUtility.encodeText(new String(text.getBytes(), "UTF-8"), "UTF-8", "B");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return text;
+    }
+
+    public static boolean sendMail (MailBean mb){
+        String host = mb.getHost();
+        final String username = mb.getUsername();
+        final String password = mb.getPassword();
+        String from = mb.getFrom();
+        String to = mb.getTo();
+        String subject = mb.getSubject();
+        String content = mb.getContent();
+        String fileName = mb.getFilename();
+        Vector<String> file = mb.getFile();
+
+        Properties props = System.getProperties();
+        props.setProperty("mail.transport.protocol", "smtp");
+        props.setProperty("mail.smtp.host", host);
+        props.setProperty("mail.smtp.auth", "true");
+
+        Session session = Session.getInstance(props, new Authenticator() {
+            public PasswordAuthentication getPasswordAuthentication() {
+                return new PasswordAuthentication(username, password);
+            }
+        });
+
+        try {
+            MimeMessage msg = new MimeMessage(session);
+            msg.setFrom(new InternetAddress(from));
+            // 加载收件人地址
+            String[] toEmails = to.split(";");
+            for (int i = 0; i < toEmails.length; i++) {
+                msg.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmails[i]));
+            }
+            msg.setSubject(toChinese(subject));
+
+            Multipart mp = new MimeMultipart();
+            MimeBodyPart mbpContent = new MimeBodyPart();
+            mbpContent.setText(content);
+            mp.addBodyPart(mbpContent);
+
+            /* 往邮件中添加附件 */
+            if (file != null) {
+                Enumeration<String> efile = file.elements();
+                while (efile.hasMoreElements()) {
+                    MimeBodyPart mbpFile = new MimeBodyPart();
+                    fileName = efile.nextElement().toString();
+                    FileDataSource fds = new FileDataSource(fileName);
+                    mbpFile.setDataHandler(new DataHandler(fds));
+                    mbpFile.setFileName(toChinese(fds.getName()));
+                    mp.addBodyPart(mbpFile);
+                }
+                logger.info("往邮件中添加附件成功");
+            }
+
+            msg.setContent(mp);
+            msg.setSentDate(new Date());
+            Transport.send(msg);
+
+        } catch (MessagingException me) {
+            me.printStackTrace();
+            return false;
+        }
+        return true;
+    }
+}
+

+ 27 - 0
da/src/main/resources/CommonConfig.properties

@@ -0,0 +1,27 @@
+#数字签名公私钥和aes加密密钥
+aes.key=qwWW0_sdzxc123e6
+aes.iv=ZXCRFVTGB3GYHTGB
+
+#mysql数据导出文件路径
+mysql.into.outfile.path=/tmp
+#mysql数据导出文件内容分隔符
+mysql.into.outfile.split=###
+
+#静态资源服务器url
+staticServer.url=http://10.199.10.9:18086
+#ftp 服务器地址信息
+mcd.ftp.host=10.199.10.9
+mcd.ftp.port=18087
+mcd.ftp.username=mcdstatic
+mcd.ftp.password=mcdstatic
+mcd.ftp.timeout=6000
+mcd.ftp.maxTotal=20
+mcd.ftp.maxIdle=20
+mcd.ftp.minIdle=5
+mcd.ftp.maxWaitMillis=600000
+mcd.ftp.passiveMode=false
+
+#调度错误信息邮件发送基础配置
+mail.user=mail.dayou@data-u.com
+mail.pwd=data-u&$2017
+mail.server=smtp.data-u.com

+ 88 - 0
da/src/main/resources/application.yml

@@ -0,0 +1,88 @@
+###############常用配置项###############
+server:
+    port: 9191
+    maxHttpHeaderSize: 102400
+log:
+    file:
+        path: C:\Users\89346\Desktop\filePath
+#        path: /data/dyqd_app4/server-sr
+        name: da.log
+datasource:
+    url: 10.199.10.6:3306/dc_test
+    username: dyqd_dc
+    password: Datau$dc19   
+###############常用配置项###############
+spring:
+    cloud:
+        loadbalancer: 
+            retry: 
+                enabled: true
+    application:
+        name: da
+    jmx: 
+        enabled: false
+    datasource:
+        type: com.alibaba.druid.pool.DruidDataSource
+        driverClassName: com.mysql.jdbc.Driver
+        url: jdbc:mysql://${datasource.url}?characterEncoding=utf8&useSSL=false
+        username: ${datasource.username}
+        password: ${datasource.password}
+        initialSize: 5                             #初始化大小
+        minIdle: 5                                 #最小
+        maxActive: 20                              #最大
+        maxWait: 60000                             #获取连接等待超时的时间
+        timeBetweenEvictionRunsMillis: 60000       #间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+        minEvictableIdleTimeMillis: 300000         #一个连接在池中最小生存的时间,单位是毫秒
+        validationQuery: SELECT 1 FROM DUAL
+        testWhileIdle: true
+        testOnBorrow: false
+        testOnReturn: false
+        poolPreparedStatements: false               #打开PSCache,并且指定每个连接上PSCache的大小
+        maxPoolPreparedStatementPerConnectionSize: -1
+        filters: slf4j
+        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000  #通过connectProperties属性来打开mergeSql功能;慢SQL记录
+        useGlobalDataSourceStat: true              #合并多个DruidDataSource的监控数据
+logging:
+    config: classpath:logback-spring.xml
+    level:
+        com.datau.mdmManager.mapper: DEBUG
+mybatis:
+    configuration:
+        mapUnderscoreToCamelCase: true
+    mapper-locations: classpath:mapper/*.xml
+pagehelper:
+    helper-dialect: mysql
+    reasonable: true
+    support-methods-arguments: true
+    params: count=countSql
+ribbon:
+    ReadTimeout: 1800000
+    ConnectTimeout: 1800000
+    MaxAutoRetries: 3
+    MaxAutoRetriesNextServer: 0
+    eureka:
+        enabled: true
+eureka:
+    instance:
+        leaseRenewalIntervalInSeconds: 1
+        leaseExpirationDurationInSeconds: 5
+    client:
+        healthcheck:
+            enabled: true
+hystrix:
+    command:
+        default:
+            execution:
+                timeout:
+                    enabled: false
+        isolation:
+            thread:
+                timeoutInMilliseconds: 6000000
+feign:
+    client:
+        config:
+            default:
+                connectTimeout: 1800000
+                readTimeout: 1800000
+    hystrix:
+        enabled: false

+ 19 - 0
da/src/main/resources/bootstrap.yml

@@ -0,0 +1,19 @@
+server: localhost
+port: 9876
+#server: 10.199.10.10
+#port: 9999
+
+#spring:
+#    cloud:
+#        config:
+#            profile: test
+#            label: feature-20180424
+#            discovery: 
+#                enabled: true
+#                serviceId: cap-config
+#            failFast: true
+eureka:
+    client:
+        serviceUrl:
+            defaultZone: http://${server}:${port}/eureka
+        #enabled: false

+ 42 - 0
da/src/main/resources/logback-spring.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE xml>
+<configuration>
+    <!-- 属性文件 -->
+    <property name="processName" value="xxx"/>
+    <!-- <property name="logDir" value="/data/dyqd_app2/coc/log/run"/> -->
+    <springProperty scope="context" name="filePath" source="log.file.path"/>
+    <springProperty scope="context" name="fileName" source="log.file.name"/>
+
+    <!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->
+    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+        <!--<Encoding>UTF-8</Encoding>-->
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <pattern>%date [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
+        </layout>
+    </appender>
+
+    <!-- 配置文件轮转 -->
+    <appender name="logfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!--<Encoding>UTF-8</Encoding>-->
+        <File>${filePath}/${fileName}</File>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <FileNamePattern>${filePath}/history/service.%d{yyyy-MM-dd}.log.gz</FileNamePattern>
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <pattern>%date [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
+        </layout>
+    </appender>
+
+
+    <!-- 修改其他包的日志输出级别 -->
+    <logger name="org.apache.zookeeper">
+        <level value="WARN"/>
+    </logger>
+
+    <!-- root 默认日志配置 , 注意这里的级别哈!小心生产环境用DEBUG,压爆你的磁盘!-->
+    <root level="INFO">
+        <appender-ref ref="logfile"/>
+        <appender-ref ref="stdout"/>
+    </root>
+</configuration>

+ 204 - 0
da/src/main/resources/mapper/TaskMapper.xml

@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.datau.da.dao.TaskDao">
+
+    <insert id="addTask" parameterType="com.datau.da.entity.task.Task">
+        insert into da_info_data_collection_task
+        (id, task_name, period_type, task_status, schedule_offset, run_status, task_cron,
+        <if test="nextRunDate != null and nextRunDate != ''">
+            next_run_date,
+        </if>
+        ddl_sql, source_database_id, source_table_id, source_table_name, target_database_id,
+        target_table_id, target_table_name, user_id, create_time, update_time)
+        values
+        (#{id}, #{taskName}, #{periodType}, #{taskStatus}, #{scheduleOffset}, #{runStatus}, #{taskCron},
+        <if test="nextRunDate != null and nextRunDate != ''">
+            next_run_date,
+        </if>
+        #{ddlSql}, #{sourceDatabaseId}, #{sourceTableId}, #{sourceTableName}, #{targetDatabaseId},
+        #{targetTableId}, #{targetTableName}, #{userId}, now(), now())
+    </insert>
+
+    <select id="listTask" parameterType="com.datau.da.entity.PageParams" resultType="com.datau.da.entity.task.Task">
+        select
+            didct.id as id,
+            didct.task_name as taskName,
+            didct.task_status as taskStatus,
+            ts.sdt_name as taskStatusDesc,
+            didct.task_cron as taskCron,
+            didct.next_run_date as nextRunDate,
+            diu.nickname as userName,
+            date_format(didct.create_time, '%Y-%m-%d %T') as createTime,
+            date_format(didct.update_time, '%Y-%m-%d %T') as updateTime
+        from da_info_data_collection_task didct
+        left join dc_info_user diu on diu.id=didct.user_id
+        left join (select sdt_code,sdt_name from da_dim_sdt_code
+          where sdt_type_code=(select id from da_dim_sdt_type where sdt_type_code='task_status')) ts on ts.sdt_code=didct.task_status
+        where 1=1
+        <if test="data.taskName != null and data.taskName != ''">
+            and didct.task_name like concat('%',#{data.taskName},'%')
+        </if>
+    </select>
+
+    <select id="getTaskInfoById" resultType="com.datau.da.entity.task.Task">
+        select
+            didct.id as id,
+            didct.task_name as taskName,
+            didct.task_cron as taskCron,
+            didct.period_type as periodType,
+            didct.run_status as runStatus,
+            didct.task_status as taskStatus,
+            didct.schedule_offset as scheduleOffset,
+            didct.next_run_date as nextRunDate,
+            pt.sdt_name as periodTypeDesc,
+            didct.ddl_sql as ddlSql,
+            didct.source_database_id as sourceDatabaseId,
+            didct.source_table_id as sourceTableId,
+            didct.source_table_name as sourceTableName,
+            didct.target_database_id as targetDatabaseId,
+            didct.target_table_id as targetTableId,
+            didct.target_table_name as targetTableName
+        from da_info_data_collection_task didct
+        left join dc_info_user diu on diu.id=didct.user_id
+        left join (select sdt_code,sdt_name from da_dim_sdt_code
+          where sdt_type_code=(select id from da_dim_sdt_type where sdt_type_code='period_type')) pt on pt.sdt_code=didct.period_type
+        where didct.id=#{taskId}
+    </select>
+
+    <update id="updateTaskById" parameterType="com.datau.da.entity.task.Task">
+        update da_info_data_collection_task set
+        <trim suffixOverrides=",">
+            update_time = now(),
+            <if test="taskName!=null and taskName!='' ">
+                task_name = #{taskName},
+            </if>
+            period_type = #{periodType},
+            <if test="taskStatus!=null and taskStatus!='' ">
+                task_status = #{taskStatus},
+            </if>
+            schedule_offset = #{scheduleOffset},
+            <if test="runStatus!=null and runStatus!='' ">
+                run_status = #{runStatus},
+            </if>
+            <if test="taskCron!=null and taskCron!='' ">
+                task_cron = #{taskCron},
+            </if>
+            <if test="nextRunDate!=null and nextRunDate!='' ">
+                next_run_date = #{nextRunDate},
+            </if>
+            <if test="ddlSql!=null and ddlSql!='' ">
+                ddl_sql = #{ddlSql},
+            </if>
+            <if test="sourceDatabaseId!=null and sourceDatabaseId!='' ">
+                source_database_id = #{sourceDatabaseId},
+            </if>
+            <if test="sourceTableId!=null and sourceTableId!='' ">
+                source_table_id = #{sourceTableId},
+            </if>
+            <if test="sourceTableName!=null and sourceTableName!='' ">
+                source_table_name = #{sourceTableName},
+            </if>
+            <if test="targetDatabaseId!=null and targetDatabaseId!='' ">
+                target_database_id = #{targetDatabaseId},
+            </if>
+            <if test="targetTableId!=null and targetTableId!='' ">
+                target_table_id = #{targetTableId},
+            </if>
+            <if test="targetTableName!=null and targetTableName!='' ">
+                target_table_name = #{targetTableName},
+            </if>
+            <if test="userId!=null and userId!='' ">
+                user_id = #{userId},
+            </if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <update id="updateTaskStatusById">
+        update da_info_data_collection_task set
+        <trim suffixOverrides=",">
+            update_time = now(),
+            <if test="taskStatus!=null and taskStatus!='' ">
+                task_status = #{taskStatus},
+            </if>
+            <if test="nextRunDate!=null and nextRunDate!='' ">
+                next_run_date = #{nextRunDate},
+            </if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <update id="updateTaskRunStatusById">
+        update da_info_data_collection_task set
+        <trim suffixOverrides=",">
+            update_time = now(),
+            <if test="runStatus!=null and runStatus!='' ">
+                run_status = #{runStatus},
+            </if>
+            <if test="nextRunDate!=null and nextRunDate!='' ">
+                next_run_date = #{nextRunDate},
+            </if>
+        </trim>
+        where id = #{id}
+    </update>
+	
+	<delete id="deleteTaskById">
+		delete from da_info_data_collection_task where id=#{taskId}
+	</delete>
+
+    <select id="getAllInitJob" resultType="com.datau.da.entity.task.Task">
+        select
+            didct.id as id,
+            didct.task_name as taskName,
+            didct.task_cron as taskCron,
+            didct.period_type as periodType,
+            didct.run_status as runStatus,
+            didct.task_status as taskStatus,
+            didct.schedule_offset as scheduleOffset,
+            didct.next_run_date as nextRunDate,
+            didct.ddl_sql as ddlSql,
+            didct.source_database_id as sourceDatabaseId,
+            didct.source_table_id as sourceTableId,
+            didct.source_table_name as sourceTableName,
+            didct.target_database_id as targetDatabaseId,
+            didct.target_table_id as targetTableId,
+            didct.target_table_name as targetTableName
+        from da_info_data_collection_task didct
+    </select>
+
+    <insert id="insertTaskErrorInfo" parameterType="com.datau.da.entity.mail.ErrorJobInfo">
+        insert into da_info_task_error_record (id, task_id, task_name, error_desc, send_status, create_time, update_time)
+        values (uuid(), #{taskId}, #{taskName}, #{errorDesc}, #{sendStatus}, now(), now())
+    </insert>
+
+    <delete id="deleteTaskErrorInfo">
+        delete from da_info_task_error_record where task_id=#{taskId}
+    </delete>
+
+    <update id="updateSendedStatusById">
+        update da_info_task_error_record set send_status=#{sendStatus},update_time=now() where id=#{id}
+    </update>
+
+    <select id="getTaskSendStatusById" resultType="String">
+        select send_status as sendStatus from da_info_task_error_record where task_id=#{taskId}
+        order by update_time desc limit 1
+    </select>
+
+    <select id="getErrorJobInfoById" resultType="com.datau.da.entity.mail.ErrorJobInfo">
+        select
+            id as id,
+            task_id as taskId,
+            task_name as taskName,
+            error_desc as errorDesc,
+            send_status as sendStatus,
+            date_format(create_time, '%Y-%m-%d %T') as createTime,
+            date_format(update_time, '%Y-%m-%d %T') as updateTime
+        from da_info_task_error_record
+        where task_id=#{taskId}
+        order by update_time desc limit 1
+    </select>
+
+    <select id="getSendMailsConfig" resultType="String">
+        select send_address from da_info_send_mails_config order by update_time desc
+    </select>
+</mapper>

+ 18 - 0
da/src/main/resources/sql/数据采集出错信息统计功能提测.sql

@@ -0,0 +1,18 @@
+CREATE TABLE `da_info_task_error_record` (
+  `id` varchar(36) NOT NULL COMMENT 'uuid主键',
+  `task_id` varchar(36) NOT NULL COMMENT '任务id',
+  `task_name` varchar(50) NOT NULL COMMENT '任务名称',
+  `error_desc` text COMMENT '任务出错详情',
+  `send_status` varchar(4) DEFAULT NULL COMMENT '邮件发送状态,0:未发送,1:已发送',
+  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务出错信息记录表';
+
+CREATE TABLE `da_info_send_mails_config` (
+  `id` varchar(36) NOT NULL COMMENT 'uuid主键',
+  `send_address` varchar(100) NOT NULL COMMENT '要发送的邮箱地址',
+  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务发送邮箱配置表';

+ 84 - 0
da/src/main/resources/sql/数据采集提测.sql

@@ -0,0 +1,84 @@
+/** 字典表-编码类型表 **/
+CREATE TABLE `da_dim_sdt_type` (
+  `id` varchar(36) NOT NULL COMMENT '主键值为uuid',
+  `sdt_type_code` varchar(225) DEFAULT '-1' COMMENT '类型编码。',
+  `sdt_type_name` varchar(100) DEFAULT NULL COMMENT '类型名称',
+  `sdt_type_desc` text COMMENT '类型描述',
+  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='编码类型表';
+
+/** 字典表-编码表 **/
+CREATE TABLE `da_dim_sdt_code` (
+  `id` varchar(36) NOT NULL COMMENT '主键值为uuid',
+  `sdt_type_code` varchar(225) DEFAULT NULL COMMENT '类型编码。',
+  `sdt_code` varchar(100) DEFAULT NULL COMMENT '编码',
+  `sdt_name` text COMMENT '编码名称',
+  `sdt_desc` text COMMENT '编码描述',
+  `sdt_order` int(11) DEFAULT '-1' COMMENT '排序字段',
+  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='编码表';
+
+/** 初始化字段表数据 **/
+insert into da_dim_sdt_type (id, sdt_type_code, sdt_type_name, sdt_type_desc, create_time, update_time)
+values (uuid(), 'period_type', '周期类型', '周期类型', now(), now());
+
+insert into da_dim_sdt_type (id, sdt_type_code, sdt_type_name, sdt_type_desc, create_time, update_time)
+values (uuid(), 'task_status', '任务状态', '任务状态', now(), now());
+
+insert into da_dim_sdt_type (id, sdt_type_code, sdt_type_name, sdt_type_desc, create_time, update_time)
+values (uuid(), 'run_status', '运行状态', '运行状态', now(), now());
+
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='period_type'), '5', '秒', '秒', '6', now());
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='period_type'), '4', '分', '分', '5', now());
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='period_type'), '3', '时', '时', '4', now());
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='period_type'), '2', '日', '日', '3', now());
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='period_type'), '1', '月', '月', '2', now());
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='period_type'), '0', '自定义', '自定义', '1', now());
+
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='task_status'), '1', '启用', '启用', '1', now());
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='task_status'), '2', '停用', '停用', '2', now());
+
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='run_status'), '0', '未运行', '未运行', '1', now());
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='run_status'), '1', '等待运行', '等待运行', '2', now());
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='run_status'), '2', '运行中', '运行中', '3', now());
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='run_status'), '3', '运行完成', '运行完成', '4', now());
+insert into da_dim_sdt_code (id, sdt_type_code, sdt_code, sdt_name, sdt_desc, sdt_order, create_time)
+values (uuid(), (select id from da_dim_sdt_type where sdt_type_code='run_status'), '4', '运行失败', '运行失败', '5', now());
+
+/** 数据采集任务信息表 **/
+CREATE TABLE `da_info_data_collection_task` (
+  `id` varchar(36) NOT NULL COMMENT 'uuid主键,任务id',
+  `task_name` varchar(50) NOT NULL COMMENT '任务名称',
+  `period_type` varchar(4) NOT NULL COMMENT '周期类型,0:自定义,1:月,2:日,3:时,4:分,5:秒',
+  `schedule_offset` varchar(4) NOT NULL DEFAULT '-1' COMMENT '调度偏移量',
+  `task_status` varchar(4) NOT NULL COMMENT '任务状态,1:启用,2:停用',
+  `run_status` varchar(4) NOT NULL COMMENT '任务运行状态,0:未运行,1:等待运行,2:运行中,3:运行完成,4:运行失败',
+  `task_cron` varchar(50) NOT NULL COMMENT '任务定时cron表达式',
+  `next_run_date` datetime DEFAULT NULL COMMENT '下次运行时间',
+  `ddl_sql` text NOT NULL COMMENT '数据采集ddl语句',
+  `source_database_id` varchar(36) NOT NULL COMMENT '外键,源库id',
+  `source_table_id` varchar(50) NOT NULL COMMENT '源表id',
+  `source_table_name` varchar(50) NOT NULL COMMENT '源库表名',
+  `target_database_id` varchar(36) NOT NULL COMMENT '外键,目标库id',
+  `target_table_id` varchar(50) NOT NULL COMMENT '目标表id',
+  `target_table_name` varchar(50) NOT NULL COMMENT '目标库表名',
+  `user_id` varchar(30) NOT NULL COMMENT '操作人id',
+  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='数据采集任务信息表';

+ 8 - 0
dc-account/.idea/.gitignore

@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/../../../../../../:\workspace\报表系统src\DC-SERVER\dc-account\.idea/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/

+ 11 - 0
dc-account/.idea/misc.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="MavenProjectsManager">
+    <option name="originalFiles">
+      <list>
+        <option value="$PROJECT_DIR$/pom.xml" />
+      </list>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
+</project>

+ 6 - 0
dc-account/.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
+  </component>
+</project>

BIN
dc-account/.mvn/wrapper/maven-wrapper.jar


+ 1 - 0
dc-account/.mvn/wrapper/maven-wrapper.properties

@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip

+ 3 - 0
dc-account/WebContent/META-INF/MANIFEST.MF

@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+

+ 225 - 0
dc-account/mvnw

@@ -0,0 +1,225 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   M2_HOME - location of maven2's installed home dir
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        export JAVA_HOME="`/usr/libexec/java_home`"
+      else
+        export JAVA_HOME="/Library/Java/Home"
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=`java-config --jre-home`
+  fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+  ## resolve links - $0 may be a link to maven's home
+  PRG="$0"
+
+  # need this for relative symlinks
+  while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+      PRG="$link"
+    else
+      PRG="`dirname "$PRG"`/$link"
+    fi
+  done
+
+  saveddir=`pwd`
+
+  M2_HOME=`dirname "$PRG"`/..
+
+  # make it fully qualified
+  M2_HOME=`cd "$M2_HOME" && pwd`
+
+  cd "$saveddir"
+  # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --unix "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Migwn, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME="`(cd "$M2_HOME"; pwd)`"
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+  # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="`which javac`"
+  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=`which readlink`
+    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+      if $darwin ; then
+        javaHome="`dirname \"$javaExecutable\"`"
+        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+      else
+        javaExecutable="`readlink -f \"$javaExecutable\"`"
+      fi
+      javaHome="`dirname \"$javaExecutable\"`"
+      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="`which java`"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=`cd "$wdir/.."; pwd`
+    fi
+    # end of workaround
+  done
+  echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    echo "$(tr -s '\n' ' ' < "$1")"
+  fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+echo $MAVEN_PROJECTBASEDIR
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --path --windows "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

+ 143 - 0
dc-account/mvnw.cmd

@@ -0,0 +1,143 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%

+ 159 - 0
dc-account/pom.xml

@@ -0,0 +1,159 @@
+<?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.datau</groupId>
+	<artifactId>account</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
+	<packaging>jar</packaging>
+
+	<name>account</name>
+	<description>account</description>
+
+	<parent>
+		<groupId>org.springframework.boot</groupId>
+		<artifactId>spring-boot-starter-parent</artifactId>
+		<version>2.0.1.RELEASE</version>
+		<relativePath /> <!-- lookup parent from repository -->
+	</parent>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+		<java.version>1.8</java.version>
+		<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-redis</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-actuator</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-aop</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+
+
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
+		</dependency>
+		<!-- <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> 
+			</dependency> -->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-openfeign</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.retry</groupId>
+			<artifactId>spring-retry</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>io.springfox</groupId>
+			<artifactId>springfox-swagger2</artifactId>
+			<version>2.7.0</version>
+		</dependency>
+		<dependency>
+			<groupId>io.springfox</groupId>
+			<artifactId>springfox-swagger-ui</artifactId>
+			<version>2.7.0</version>
+		</dependency>
+		<dependency>
+			<groupId>org.mybatis.spring.boot</groupId>
+			<artifactId>mybatis-spring-boot-starter</artifactId>
+			<version>1.3.2</version>
+		</dependency>
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<scope>runtime</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>druid</artifactId>
+			<version>1.1.9</version>
+		</dependency>
+		<dependency>
+			<groupId>com.auth0</groupId>
+			<artifactId>java-jwt</artifactId>
+			<version>3.1.0</version>
+		</dependency>
+		<dependency>
+			<groupId>io.jsonwebtoken</groupId>
+			<artifactId>jjwt</artifactId>
+			<version>0.6.0</version>
+		</dependency>
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>fastjson</artifactId>
+			<version>1.2.12</version>
+		</dependency>
+		<dependency>
+			<groupId>com.github.pagehelper</groupId>
+			<artifactId>pagehelper-spring-boot-starter</artifactId>
+			<version>1.2.5</version>
+		</dependency>
+		<dependency>
+			<groupId>com.github.penggle</groupId>
+			<artifactId>kaptcha</artifactId>
+			<version>2.3.2</version>
+		</dependency>
+
+	</dependencies>
+
+	<dependencyManagement>
+		<dependencies>
+			<dependency>
+				<groupId>org.springframework.cloud</groupId>
+				<artifactId>spring-cloud-dependencies</artifactId>
+				<version>${spring-cloud.version}</version>
+				<type>pom</type>
+				<scope>import</scope>
+			</dependency>
+		</dependencies>
+	</dependencyManagement>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+			</plugin>
+			<!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> 
+				<configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> 
+				</plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> 
+				<executions> <execution> <id>make-a-jar</id> <phase>compile</phase> <goals> 
+				<goal>jar</goal> </goals> </execution> </executions> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> 
+				</configuration> </plugin> -->
+		</plugins>
+	</build>
+
+	<repositories>
+		<repository>
+			<id>spring-milestones</id>
+			<name>Spring Milestones</name>
+			<url>https://repo.spring.io/milestone</url>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+	</repositories>
+
+
+</project>

+ 33 - 0
dc-account/src/main/java/com/datau/account/AccountApplication.java

@@ -0,0 +1,33 @@
+package com.datau.account;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**  
+ * @ClassName: AccountManagerApplication 
+ * @Description: 账号管理模块启动类
+ * @author: IF
+ * @date: 2018年6月8日 下午6:07:33  
+ */
+@MapperScan("com.datau.account.mapper")
+@EnableEurekaClient
+@EnableFeignClients
+@EnableTransactionManagement
+@SpringBootApplication
+public class AccountApplication extends SpringBootServletInitializer {
+    
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
+        return builder.sources(AccountApplication.class);
+    }
+    
+	public static void main(String[] args) {
+		SpringApplication.run(AccountApplication.class, args);
+	}
+}

+ 90 - 0
dc-account/src/main/java/com/datau/account/api/AccountInfoAPI.java

@@ -0,0 +1,90 @@
+package com.datau.account.api;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import com.datau.account.dto.UserDTO;
+
+/**
+ * @ClassName: AccountInfoAPI
+ * @Description: 用户登录接口
+ * @author: IF
+ * @date: 2018年6月8日 下午6:09:40
+ */
+public interface AccountInfoAPI {
+
+	/**
+	 * 登录验证
+	 * 
+	 * @param loginInfo
+	 * @return
+	 */
+	@GetMapping("/accountChecking/login")
+	Object login(@RequestBody UserDTO user, HttpServletResponse response) throws Exception;
+
+	/**
+	 * 通过token解析userId
+	 * 
+	 * @param jwt
+	 * @return
+	 */
+	@GetMapping("/account/parseTokenId")
+	public String parseTokenId(@RequestParam("jwt") String jwt);
+
+	/**
+	 * 通过token解析第二参数,预留
+	 * 
+	 * @param jwt
+	 * @return
+	 */
+	@GetMapping("/account/parseTokenSubject")
+	public String parseTokenSubject(@RequestParam("jwt") String jwt);
+
+	/**
+	 * 保存token
+	 * 
+	 * @param id
+	 * @param token
+	 * @param minute
+	 * @return
+	 */
+	@GetMapping("/account/saveToken")
+	public String saveToken(@RequestParam("id") String id, @RequestParam("token") String token,
+			@RequestParam("minute") int minute);
+
+	/**
+	 * 删除token
+	 * 
+	 * @param id
+	 * @return
+	 */
+	@GetMapping("/account/deleteToken")
+	public String deleteToken(@RequestParam("id") String id);
+
+	/**
+	 * 根据userId获取token
+	 * 
+	 * @param accountId
+	 * @return
+	 */
+	@GetMapping("/account/getTokenByAccountId")
+	public String getTokenByAccountId(@RequestParam(value = "accountId", required = true) String accountId);
+
+	/**
+	 * 刷新token
+	 * 
+	 * @param accountId
+	 * @param minute
+	 * @return
+	 */
+	@GetMapping("/account/refreshToken")
+	public String refreshToken(@RequestParam(value = "accountId", required = true) String accountId,
+			@RequestParam(value = "minute", required = true) int minute);
+
+	@GetMapping("/account/getUserType")
+	Integer getUserType(@RequestParam(value = "userId") String userId);
+
+}

+ 20 - 0
dc-account/src/main/java/com/datau/account/config/DruidDataSourceConfiguration.java

@@ -0,0 +1,20 @@
+package com.datau.account.config;
+
+import javax.sql.DataSource;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.alibaba.druid.pool.DruidDataSource;
+
+@Configuration  
+public class DruidDataSourceConfiguration {  
+  
+    @Bean  
+    @ConfigurationProperties(prefix = "spring.datasource")  
+    public DataSource druidDataSource() {  
+        DruidDataSource druidDataSource = new DruidDataSource();  
+        return druidDataSource;  
+    }  
+}  

+ 51 - 0
dc-account/src/main/java/com/datau/account/config/KaptchaProducer.java

@@ -0,0 +1,51 @@
+/**
+ * Project Name:aiop-web File Name:MyCaptchaProducer.java Package Name:com.asiainfo.biapp.aiop.web.common
+ * Date:2017年8月29日下午2:39:40 Copyright (c) 2017, chenzhou1025@126.com All Rights Reserved.
+ *
+ */
+
+package com.datau.account.config;
+
+import java.util.Properties;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.google.code.kaptcha.Constants;
+import com.google.code.kaptcha.impl.DefaultKaptcha;
+
+/* *
+ * @Description 配置验证码
+**/
+@Configuration
+public class KaptchaProducer {
+
+    @Bean(name = "defaultKaptcha")
+    public DefaultKaptcha getMyCaptchaProducer() {
+        Properties properties = new Properties();
+        properties.setProperty("kaptcha.border", "no");
+        properties.setProperty("kaptcha.textproducer.font.color", "43,111,213");
+        properties.setProperty("kaptcha.image.width", "100");
+        properties.setProperty("kaptcha.image.height", "40");
+        properties.setProperty("kaptcha.textproducer.font.size", "30");
+        properties.setProperty("kaptcha.textproducer.char.length", "4");
+        //properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
+        // 此处需要注意服务器部署时字体问题
+        properties.setProperty("kaptcha.textproducer.font.names", "DejaVu Sans");
+        properties.setProperty("kaptcha.background.clear.from", "246,254,239");
+        properties.setProperty("kaptcha.background.clear.to", "246,254,239");
+        properties.setProperty(Constants.KAPTCHA_WORDRENDERER_IMPL,"com.google.code.kaptcha.text.impl.DefaultWordRenderer");
+        properties.setProperty(Constants.KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
+        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, "abcdef0123456789");
+        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
+
+        com.google.code.kaptcha.util.Config config = new com.google.code.kaptcha.util.Config(properties);
+
+        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+        defaultKaptcha.setConfig(config);
+
+        return defaultKaptcha;
+    }
+
+}
+

+ 43 - 0
dc-account/src/main/java/com/datau/account/config/SwaggerConfig.java

@@ -0,0 +1,43 @@
+package com.datau.account.config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.ParameterBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.schema.ModelRef;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Parameter;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+	@Bean
+	public Docket api() {
+		return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
+				// .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
+				.apis(RequestHandlerSelectors.basePackage("com.datau.account.controller")).paths(PathSelectors.any())
+				.build().pathMapping("/").globalOperationParameters(setHeaderToken());
+	}
+
+	private ApiInfo apiInfo() {
+		return new ApiInfoBuilder().title("api文档").description("数据中心->用户登录相关接口接口").version("1.0").build();
+	}
+
+	private List<Parameter> setHeaderToken() {
+		ParameterBuilder tokenPar = new ParameterBuilder();
+		List<Parameter> pars = new ArrayList<>();
+		tokenPar.name("token").description("token").modelRef(new ModelRef("string")).parameterType("header")
+				.required(false).build();
+		pars.add(tokenPar.build());
+		return pars;
+	}
+}

+ 0 - 0
dc-account/src/main/java/com/datau/account/controller/AccountInfoController.java


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