init
This commit is contained in:
8
studio/.gitignore
vendored
Normal file
8
studio/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
### IDEA ###
|
||||
.idea/*
|
||||
*.iml
|
||||
*/target/*
|
||||
*/*.iml
|
||||
/.gradle/
|
||||
application.pid
|
||||
spy.log
|
||||
0
studio/.gitkeep
Normal file
0
studio/.gitkeep
Normal file
40
studio/assembly/pom.xml
Normal file
40
studio/assembly/pom.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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">
|
||||
<parent>
|
||||
<artifactId>studio</artifactId>
|
||||
<groupId>com.platform</groupId>
|
||||
<version>0.4.x</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>assembly</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<finalName>${project.parent.artifactId}-release-${project.version}</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/package.xml</descriptor>
|
||||
</descriptors>
|
||||
<outputDirectory>${project.parent.basedir}/build/</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
424
studio/assembly/src/main/assembly/package.xml
Normal file
424
studio/assembly/src/main/assembly/package.xml
Normal file
@@ -0,0 +1,424 @@
|
||||
<assembly>
|
||||
<id>${project.version}</id>
|
||||
|
||||
<formats>
|
||||
<format>tar.gz</format>
|
||||
</formats>
|
||||
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/install/16gmaster</directory>
|
||||
<outputDirectory>./16gmaster</outputDirectory>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/install/sql</directory>
|
||||
<outputDirectory>./sql</outputDirectory>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/install/16gslave</directory>
|
||||
<outputDirectory>./16gslave</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/install/16gdata</directory>
|
||||
<outputDirectory>./16gdata</outputDirectory>
|
||||
</fileSet>
|
||||
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/install</directory>
|
||||
<outputDirectory>./</outputDirectory>
|
||||
<includes>
|
||||
<include>README.md</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/config/target
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/config</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/config/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/config</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/eureka/target
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/eureka</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/eureka/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/eureka</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/gateway/target</directory>
|
||||
<outputDirectory>./16gdata/gateway</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/gateway/target/classes</directory>
|
||||
<outputDirectory>./16gdata/gateway</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-market-service-parent/data-market-service-integration/target
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/data-market-service-integration</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-market-service-parent/data-market-service-integration/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/data-market-service-integration</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-compare-service-parent/data-compare-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/data-compare-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-compare-service-parent/data-compare-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/data-compare-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-cluster-service-parent/data-cluster-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/data-cluster-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-cluster-service-parent/data-cluster-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/data-cluster-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-system-service-parent/data-system-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/data-system-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-system-service-parent/data-system-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/data-system-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/service-data-dts-parent/service-data-dts/target
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/service-data-dts</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/service-data-dts-parent/service-data-dts/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/service-data-dts</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/system-service-parent/system-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/system-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/system-service-parent/system-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/system-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-market-service-parent/data-market-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/data-market-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-market-service-parent/data-market-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/data-market-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-market-service-parent/data-market-service-mapping/target
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/data-market-service-mapping</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-market-service-parent/data-market-service-mapping/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/data-market-service-mapping</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-masterdata-service-parent/data-masterdata-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/data-masterdata-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-masterdata-service-parent/data-masterdata-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/data-masterdata-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-metadata-service-parent/data-metadata-service-console/target
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/data-metadata-service-console</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-metadata-service-parent/data-metadata-service-console/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/data-metadata-service-console</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-metadata-service-parent/data-metadata-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/data-metadata-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-metadata-service-parent/data-metadata-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gmaster/data-metadata-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-quality-service-parent/data-quality-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/data-quality-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-quality-service-parent/data-quality-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/data-quality-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-standard-service-parent/data-standard-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gdata/data-standard-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-standard-service-parent/data-standard-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gdata/data-standard-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-visual-service-parent/data-visual-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gdata/data-visual-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/data-visual-service-parent/data-visual-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gdata/data-visual-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/quartz-service-parent/quartz-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gdata/quartz-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/quartz-service-parent/quartz-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gdata/quartz-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/workflow-service-parent/workflow-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/workflow-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/workflow-service-parent/workflow-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gslave/workflow-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/email-service-parent/email-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gdata/email-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/email-service-parent/email-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gdata/email-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/file-service-parent/file-service/target
|
||||
</directory>
|
||||
<outputDirectory>./16gdata/file-service</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/modules/file-service-parent/file-service/target/classes
|
||||
</directory>
|
||||
<outputDirectory>./16gdata/file-service</outputDirectory>
|
||||
<includes>
|
||||
<include>bootstrap.yml</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
<fileSet>
|
||||
<directory>${project.parent.basedir}/ui</directory>
|
||||
<outputDirectory>./16gmaster/ui</outputDirectory>
|
||||
</fileSet>
|
||||
|
||||
</fileSets>
|
||||
</assembly>
|
||||
73
studio/box/pom.xml
Normal file
73
studio/box/pom.xml
Normal file
@@ -0,0 +1,73 @@
|
||||
<?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">
|
||||
<parent>
|
||||
<artifactId>studio</artifactId>
|
||||
<groupId>com.platform</groupId>
|
||||
<version>0.4.x</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>box</artifactId>
|
||||
<name>box</name>
|
||||
|
||||
<properties>
|
||||
<mail.version>1.4.7</mail.version>
|
||||
<qiniu.version>7.9.3</qiniu.version>
|
||||
<alipay.version>4.22.57.ALL</alipay.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- 同时需要common模块和logging模块只需要引入logging模块即可 -->
|
||||
<dependency>
|
||||
<groupId>com.platform</groupId>
|
||||
<artifactId>logging</artifactId>
|
||||
<version>0.4.x</version>
|
||||
</dependency>
|
||||
<!--Spring boot Web容器-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<!--邮件依赖-->
|
||||
<dependency>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
<version>${mail.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--七牛云存储-->
|
||||
<dependency>
|
||||
<groupId>com.qiniu</groupId>
|
||||
<artifactId>qiniu-java-sdk</artifactId>
|
||||
<version>${qiniu.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--支付宝依赖-->
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
<version>${alipay.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--Spring boot Web容器-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.platform</groupId>
|
||||
<artifactId>common-mybatis</artifactId>
|
||||
<version>0.4.x</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
package com.platform.config;
|
||||
|
||||
import org.springframework.boot.web.servlet.MultipartConfigFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import javax.servlet.MultipartConfigElement;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @date 2023-01-27
|
||||
* @author AllDataDC
|
||||
* https://blog.csdn.net/llibin1024530411/article/details/79474953
|
||||
*/
|
||||
@Configuration
|
||||
public class MultipartConfig {
|
||||
|
||||
/**
|
||||
* 文件上传临时路径
|
||||
*/
|
||||
@Bean
|
||||
MultipartConfigElement multipartConfigElement() {
|
||||
MultipartConfigFactory factory = new MultipartConfigFactory();
|
||||
String location = System.getProperty("user.home") + "/.studio/file/tmp";
|
||||
File tmpFile = new File(location);
|
||||
if (!tmpFile.exists()) {
|
||||
if (!tmpFile.mkdirs()) {
|
||||
System.out.println("create was not successful.");
|
||||
}
|
||||
}
|
||||
factory.setLocation(location);
|
||||
return factory.createMultipartConfig();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
|
||||
package com.platform.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 支付宝配置类
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "tool_alipay_config")
|
||||
public class AlipayConfig implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "config_id")
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
private Long id;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "应用ID")
|
||||
private String appId;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "商户私钥")
|
||||
private String privateKey;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "支付宝公钥")
|
||||
private String publicKey;
|
||||
|
||||
@ApiModelProperty(value = "签名方式")
|
||||
private String signType="RSA2";
|
||||
|
||||
@Column(name = "gateway_url")
|
||||
@ApiModelProperty(value = "支付宝开放安全地址", hidden = true)
|
||||
private String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
|
||||
|
||||
@ApiModelProperty(value = "编码", hidden = true)
|
||||
private String charset= "utf-8";
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "异步通知地址")
|
||||
private String notifyUrl;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "订单完成后返回的页面")
|
||||
private String returnUrl;
|
||||
|
||||
@ApiModelProperty(value = "类型")
|
||||
private String format="JSON";
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "商户号")
|
||||
private String sysServiceProviderId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
package com.platform.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 邮件配置类,数据存覆盖式存入数据存
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Entity
|
||||
@Data
|
||||
@Table(name = "tool_email_config")
|
||||
public class EmailConfig implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "config_id")
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
private Long id;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "邮件服务器SMTP地址")
|
||||
private String host;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "邮件服务器 SMTP 端口")
|
||||
private String port;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "发件者用户名")
|
||||
private String user;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "密码")
|
||||
private String pass;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "收件人")
|
||||
private String fromUser;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
package com.platform.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.*;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import com.platform.base.BaseEntity;
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name="tool_local_storage")
|
||||
@NoArgsConstructor
|
||||
public class LocalStorage extends BaseEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "storage_id")
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "真实文件名")
|
||||
private String realName;
|
||||
|
||||
@ApiModelProperty(value = "文件名")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "后缀")
|
||||
private String suffix;
|
||||
|
||||
@ApiModelProperty(value = "路径")
|
||||
private String path;
|
||||
|
||||
@ApiModelProperty(value = "类型")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty(value = "大小")
|
||||
private String size;
|
||||
|
||||
public LocalStorage(String realName,String name, String suffix, String path, String type, String size) {
|
||||
this.realName = realName;
|
||||
this.name = name;
|
||||
this.suffix = suffix;
|
||||
this.path = path;
|
||||
this.type = type;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void copy(LocalStorage source){
|
||||
BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
|
||||
package com.platform.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 七牛云对象存储配置类
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "tool_qiniu_config")
|
||||
public class QiniuConfig implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "config_id")
|
||||
@ApiModelProperty(value = "ID")
|
||||
private Long id;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "accessKey")
|
||||
private String accessKey;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "secretKey")
|
||||
private String secretKey;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "存储空间名称作为唯一的 Bucket 识别符")
|
||||
private String bucket;
|
||||
|
||||
/**
|
||||
* Zone表示与机房的对应关系
|
||||
* 华东 Zone.zone0()
|
||||
* 华北 Zone.zone1()
|
||||
* 华南 Zone.zone2()
|
||||
* 北美 Zone.zoneNa0()
|
||||
* 东南亚 Zone.zoneAs0()
|
||||
*/
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "Zone表示与机房的对应关系")
|
||||
private String zone;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "外链域名,可自定义,需在七牛云绑定")
|
||||
private String host;
|
||||
|
||||
@ApiModelProperty(value = "空间类型:公开/私有")
|
||||
private String type = "公开";
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
package com.platform.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.UpdateTimestamp;
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* 上传成功后,存储结果
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "tool_qiniu_content")
|
||||
public class QiniuContent implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "content_id")
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "name")
|
||||
@ApiModelProperty(value = "文件名")
|
||||
private String key;
|
||||
|
||||
@ApiModelProperty(value = "空间名")
|
||||
private String bucket;
|
||||
|
||||
@ApiModelProperty(value = "大小")
|
||||
private String size;
|
||||
|
||||
@ApiModelProperty(value = "文件地址")
|
||||
private String url;
|
||||
|
||||
@ApiModelProperty(value = "文件类型")
|
||||
private String suffix;
|
||||
|
||||
@ApiModelProperty(value = "空间类型:公开/私有")
|
||||
private String type = "公开";
|
||||
|
||||
@UpdateTimestamp
|
||||
@ApiModelProperty(value = "创建或更新时间")
|
||||
@Column(name = "update_time")
|
||||
private Timestamp updateTime;
|
||||
}
|
||||
30
studio/box/src/main/java/com/platform/domain/vo/EmailVo.java
Normal file
30
studio/box/src/main/java/com/platform/domain/vo/EmailVo.java
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
package com.platform.domain.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 发送邮件时,接收参数的类
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27 12:02:14
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class EmailVo {
|
||||
|
||||
/** 收件人,支持多个收件人 */
|
||||
@NotEmpty
|
||||
private List<String> tos;
|
||||
|
||||
@NotBlank
|
||||
private String subject;
|
||||
|
||||
@NotBlank
|
||||
private String content;
|
||||
}
|
||||
49
studio/box/src/main/java/com/platform/domain/vo/TradeVo.java
Normal file
49
studio/box/src/main/java/com/platform/domain/vo/TradeVo.java
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
package com.platform.domain.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* 交易详情,按需应该存入数据库,这里存入数据库,仅供临时测试
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Data
|
||||
public class TradeVo {
|
||||
|
||||
/** (必填)商品描述 */
|
||||
@NotBlank
|
||||
private String body;
|
||||
|
||||
/** (必填)商品名称 */
|
||||
@NotBlank
|
||||
private String subject;
|
||||
|
||||
/** (必填)商户订单号,应该由后台生成 */
|
||||
@ApiModelProperty(hidden = true)
|
||||
private String outTradeNo;
|
||||
|
||||
/** (必填)第三方订单号 */
|
||||
@ApiModelProperty(hidden = true)
|
||||
private String tradeNo;
|
||||
|
||||
/** (必填)价格 */
|
||||
@NotBlank
|
||||
private String totalAmount;
|
||||
|
||||
/** 订单状态,已支付,未支付,作废 */
|
||||
@ApiModelProperty(hidden = true)
|
||||
private String state;
|
||||
|
||||
/** 创建时间,存入数据库时需要 */
|
||||
@ApiModelProperty(hidden = true)
|
||||
private Timestamp createTime;
|
||||
|
||||
/** 作废时间,存入数据库时需要 */
|
||||
@ApiModelProperty(hidden = true)
|
||||
private Date cancelTime;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
package com.platform.repository;
|
||||
|
||||
import com.platform.domain.AlipayConfig;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
public interface AliPayRepository extends JpaRepository<AlipayConfig,Long> {
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
package com.platform.repository;
|
||||
|
||||
import com.platform.domain.EmailConfig;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
public interface EmailRepository extends JpaRepository<EmailConfig,Long> {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
package com.platform.repository;
|
||||
|
||||
import com.platform.domain.LocalStorage;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
public interface LocalStorageRepository extends JpaRepository<LocalStorage, Long>, JpaSpecificationExecutor<LocalStorage> {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
package com.platform.repository;
|
||||
|
||||
import com.platform.domain.QiniuConfig;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
public interface QiNiuConfigRepository extends JpaRepository<QiniuConfig,Long> {
|
||||
|
||||
/**
|
||||
* 编辑类型
|
||||
* @param type
|
||||
*/
|
||||
@Modifying
|
||||
@Query(value = "update QiniuConfig set type = ?1")
|
||||
void update(String type);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
package com.platform.repository;
|
||||
|
||||
import com.platform.domain.QiniuContent;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
public interface QiniuContentRepository extends JpaRepository<QiniuContent,Long>, JpaSpecificationExecutor<QiniuContent> {
|
||||
|
||||
/**
|
||||
* 根据key查询
|
||||
* @param key 文件名
|
||||
* @return QiniuContent
|
||||
*/
|
||||
QiniuContent findByKey(String key);
|
||||
}
|
||||
121
studio/box/src/main/java/com/platform/rest/AliPayController.java
Normal file
121
studio/box/src/main/java/com/platform/rest/AliPayController.java
Normal file
@@ -0,0 +1,121 @@
|
||||
|
||||
package com.platform.rest;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.platform.annotation.rest.AnonymousAccess;
|
||||
import com.platform.annotation.Log;
|
||||
import com.platform.annotation.rest.AnonymousGetMapping;
|
||||
import com.platform.domain.vo.TradeVo;
|
||||
import com.platform.domain.AlipayConfig;
|
||||
import com.platform.utils.AliPayStatusEnum;
|
||||
import com.platform.utils.AlipayUtils;
|
||||
import com.platform.service.AliPayService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/api/aliPay")
|
||||
@Api(tags = "工具:支付宝管理")
|
||||
public class AliPayController {
|
||||
|
||||
private final AlipayUtils alipayUtils;
|
||||
private final AliPayService alipayService;
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<AlipayConfig> queryAliConfig() {
|
||||
return new ResponseEntity<>(alipayService.find(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("配置支付宝")
|
||||
@ApiOperation("配置支付宝")
|
||||
@PutMapping
|
||||
public ResponseEntity<Object> updateAliPayConfig(@Validated @RequestBody AlipayConfig alipayConfig) {
|
||||
alipayService.config(alipayConfig);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("支付宝PC网页支付")
|
||||
@ApiOperation("PC网页支付")
|
||||
@PostMapping(value = "/toPayAsPC")
|
||||
public ResponseEntity<String> toPayAsPc(@Validated @RequestBody TradeVo trade) throws Exception {
|
||||
AlipayConfig aliPay = alipayService.find();
|
||||
trade.setOutTradeNo(alipayUtils.getOrderCode());
|
||||
String payUrl = alipayService.toPayAsPc(aliPay, trade);
|
||||
return ResponseEntity.ok(payUrl);
|
||||
}
|
||||
|
||||
@Log("支付宝手机网页支付")
|
||||
@ApiOperation("手机网页支付")
|
||||
@PostMapping(value = "/toPayAsWeb")
|
||||
public ResponseEntity<String> toPayAsWeb(@Validated @RequestBody TradeVo trade) throws Exception {
|
||||
AlipayConfig alipay = alipayService.find();
|
||||
trade.setOutTradeNo(alipayUtils.getOrderCode());
|
||||
String payUrl = alipayService.toPayAsWeb(alipay, trade);
|
||||
return ResponseEntity.ok(payUrl);
|
||||
}
|
||||
|
||||
@ApiIgnore
|
||||
@AnonymousGetMapping("/return")
|
||||
@ApiOperation("支付之后跳转的链接")
|
||||
public ResponseEntity<String> returnPage(HttpServletRequest request, HttpServletResponse response) {
|
||||
AlipayConfig alipay = alipayService.find();
|
||||
response.setContentType("text/html;charset=" + alipay.getCharset());
|
||||
//内容验签,防止黑客篡改参数
|
||||
if (alipayUtils.rsaCheck(request, alipay)) {
|
||||
//商户订单号
|
||||
String outTradeNo = new String(request.getParameter("out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
//支付宝交易号
|
||||
String tradeNo = new String(request.getParameter("trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
System.out.println("商户订单号" + outTradeNo + " " + "第三方交易号" + tradeNo);
|
||||
|
||||
// 根据业务需要返回数据,这里统一返回OK
|
||||
return new ResponseEntity<>("payment successful", HttpStatus.OK);
|
||||
} else {
|
||||
// 根据业务需要返回数据
|
||||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
@ApiIgnore
|
||||
@RequestMapping("/notify")
|
||||
@AnonymousAccess
|
||||
@ApiOperation("支付异步通知(要公网访问),接收异步通知,检查通知内容app_id、out_trade_no、total_amount是否与请求中的一致,根据trade_status进行后续业务处理")
|
||||
public ResponseEntity<Object> notify(HttpServletRequest request) {
|
||||
AlipayConfig alipay = alipayService.find();
|
||||
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||
//内容验签,防止黑客篡改参数
|
||||
if (alipayUtils.rsaCheck(request, alipay)) {
|
||||
//交易状态
|
||||
String tradeStatus = new String(request.getParameter("trade_status").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
// 商户订单号
|
||||
String outTradeNo = new String(request.getParameter("out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
//支付宝交易号
|
||||
String tradeNo = new String(request.getParameter("trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
//付款金额
|
||||
String totalAmount = new String(request.getParameter("total_amount").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||
//验证
|
||||
if (tradeStatus.equals(AliPayStatusEnum.SUCCESS.getValue()) || tradeStatus.equals(AliPayStatusEnum.FINISHED.getValue())) {
|
||||
// 验证通过后应该根据业务需要处理订单
|
||||
}
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
package com.platform.rest;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.platform.annotation.Log;
|
||||
import com.platform.domain.vo.EmailVo;
|
||||
import com.platform.domain.EmailConfig;
|
||||
import com.platform.service.EmailService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 发送邮件
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27 6:55:53
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("api/email")
|
||||
@Api(tags = "工具:邮件管理")
|
||||
public class EmailController {
|
||||
|
||||
private final EmailService emailService;
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<Object> queryEmailConfig(){
|
||||
return new ResponseEntity<>(emailService.find(),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("配置邮件")
|
||||
@PutMapping
|
||||
@ApiOperation("配置邮件")
|
||||
public ResponseEntity<Object> updateEmailConfig(@Validated @RequestBody EmailConfig emailConfig) throws Exception {
|
||||
emailService.config(emailConfig,emailService.find());
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("发送邮件")
|
||||
@PostMapping
|
||||
@ApiOperation("发送邮件")
|
||||
public ResponseEntity<Object> sendEmail(@Validated @RequestBody EmailVo emailVo){
|
||||
emailService.send(emailVo,emailService.find());
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
package com.platform.rest;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.platform.annotation.Log;
|
||||
import com.platform.domain.LocalStorage;
|
||||
import com.platform.exception.BadRequestException;
|
||||
import com.platform.service.LocalStorageService;
|
||||
import com.platform.service.dto.LocalStorageQueryCriteria;
|
||||
import com.platform.utils.FileUtil;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import io.swagger.annotations.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "工具:本地存储管理")
|
||||
@RequestMapping("/api/localStorage")
|
||||
public class LocalStorageController {
|
||||
|
||||
private final LocalStorageService localStorageService;
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation("查询文件")
|
||||
@PreAuthorize("@el.check('storage:list')")
|
||||
public ResponseEntity<Object> queryFile(LocalStorageQueryCriteria criteria, Pageable pageable){
|
||||
return new ResponseEntity<>(localStorageService.queryAll(criteria,pageable),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("导出数据")
|
||||
@GetMapping(value = "/download")
|
||||
@PreAuthorize("@el.check('storage:list')")
|
||||
public void exportFile(HttpServletResponse response, LocalStorageQueryCriteria criteria) throws IOException {
|
||||
localStorageService.download(localStorageService.queryAll(criteria), response);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@ApiOperation("上传文件")
|
||||
@PreAuthorize("@el.check('storage:add')")
|
||||
public ResponseEntity<Object> createFile(@RequestParam String name, @RequestParam("file") MultipartFile file){
|
||||
localStorageService.create(name, file);
|
||||
return new ResponseEntity<>(HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@ApiOperation("上传图片")
|
||||
@PostMapping("/pictures")
|
||||
public ResponseEntity<Object> uploadPicture(@RequestParam MultipartFile file){
|
||||
// 判断文件是否为图片
|
||||
String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
|
||||
if(!FileUtil.IMAGE.equals(FileUtil.getFileType(suffix))){
|
||||
throw new BadRequestException("只能上传图片");
|
||||
}
|
||||
LocalStorage localStorage = localStorageService.create(null, file);
|
||||
return new ResponseEntity<>(localStorage, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@Log("修改文件")
|
||||
@ApiOperation("修改文件")
|
||||
@PreAuthorize("@el.check('storage:edit')")
|
||||
public ResponseEntity<Object> updateFile(@Validated @RequestBody LocalStorage resources){
|
||||
localStorageService.update(resources);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@Log("删除文件")
|
||||
@DeleteMapping
|
||||
@ApiOperation("多选删除")
|
||||
public ResponseEntity<Object> deleteFile(@RequestBody Long[] ids) {
|
||||
localStorageService.deleteAll(ids);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
108
studio/box/src/main/java/com/platform/rest/QiniuController.java
Normal file
108
studio/box/src/main/java/com/platform/rest/QiniuController.java
Normal file
@@ -0,0 +1,108 @@
|
||||
|
||||
package com.platform.rest;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.platform.annotation.Log;
|
||||
import com.platform.domain.QiniuConfig;
|
||||
import com.platform.domain.QiniuContent;
|
||||
import com.platform.service.dto.QiniuQueryCriteria;
|
||||
import com.platform.service.QiNiuService;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 发送邮件
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27 6:55:53
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/api/qiNiuContent")
|
||||
@Api(tags = "工具:七牛云存储管理")
|
||||
public class QiniuController {
|
||||
|
||||
private final QiNiuService qiNiuService;
|
||||
|
||||
@GetMapping(value = "/config")
|
||||
public ResponseEntity<Object> queryQiNiuConfig(){
|
||||
return new ResponseEntity<>(qiNiuService.find(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("配置七牛云存储")
|
||||
@ApiOperation("配置七牛云存储")
|
||||
@PutMapping(value = "/config")
|
||||
public ResponseEntity<Object> updateQiNiuConfig(@Validated @RequestBody QiniuConfig qiniuConfig){
|
||||
qiNiuService.config(qiniuConfig);
|
||||
qiNiuService.update(qiniuConfig.getType());
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("导出数据")
|
||||
@GetMapping(value = "/download")
|
||||
public void exportQiNiu(HttpServletResponse response, QiniuQueryCriteria criteria) throws IOException {
|
||||
qiNiuService.downloadList(qiNiuService.queryAll(criteria), response);
|
||||
}
|
||||
|
||||
@ApiOperation("查询文件")
|
||||
@GetMapping
|
||||
public ResponseEntity<Object> queryQiNiu(QiniuQueryCriteria criteria, Pageable pageable){
|
||||
return new ResponseEntity<>(qiNiuService.queryAll(criteria,pageable),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("上传文件")
|
||||
@ApiOperation("上传文件")
|
||||
@PostMapping
|
||||
public ResponseEntity<Object> uploadQiNiu(@RequestParam MultipartFile file){
|
||||
QiniuContent qiniuContent = qiNiuService.upload(file,qiNiuService.find());
|
||||
Map<String,Object> map = new HashMap<>(3);
|
||||
map.put("id",qiniuContent.getId());
|
||||
map.put("errno",0);
|
||||
map.put("data",new String[]{qiniuContent.getUrl()});
|
||||
return new ResponseEntity<>(map,HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("同步七牛云数据")
|
||||
@ApiOperation("同步七牛云数据")
|
||||
@PostMapping(value = "/synchronize")
|
||||
public ResponseEntity<Object> synchronizeQiNiu(){
|
||||
qiNiuService.synchronize(qiNiuService.find());
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("下载文件")
|
||||
@ApiOperation("下载文件")
|
||||
@GetMapping(value = "/download/{id}")
|
||||
public ResponseEntity<Object> downloadQiNiu(@PathVariable Long id){
|
||||
Map<String,Object> map = new HashMap<>(1);
|
||||
map.put("url", qiNiuService.download(qiNiuService.findByContentId(id),qiNiuService.find()));
|
||||
return new ResponseEntity<>(map,HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("删除文件")
|
||||
@ApiOperation("删除文件")
|
||||
@DeleteMapping(value = "/{id}")
|
||||
public ResponseEntity<Object> deleteQiNiu(@PathVariable Long id){
|
||||
qiNiuService.delete(qiNiuService.findByContentId(id),qiNiuService.find());
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("删除多张图片")
|
||||
@ApiOperation("删除多张图片")
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Object> deleteAllQiNiu(@RequestBody Long[] ids) {
|
||||
qiNiuService.deleteAll(ids, qiNiuService.find());
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
package com.platform.service;
|
||||
|
||||
import com.platform.domain.vo.TradeVo;
|
||||
import com.platform.domain.AlipayConfig;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
public interface AliPayService {
|
||||
|
||||
/**
|
||||
* 查询配置
|
||||
* @return AlipayConfig
|
||||
*/
|
||||
AlipayConfig find();
|
||||
|
||||
/**
|
||||
* 更新配置
|
||||
* @param alipayConfig 支付宝配置
|
||||
* @return AlipayConfig
|
||||
*/
|
||||
AlipayConfig config(AlipayConfig alipayConfig);
|
||||
|
||||
/**
|
||||
* 处理来自PC的交易请求
|
||||
* @param alipay 支付宝配置
|
||||
* @param trade 交易详情
|
||||
* @return String
|
||||
* @throws Exception 异常
|
||||
*/
|
||||
String toPayAsPc(AlipayConfig alipay, TradeVo trade) throws Exception;
|
||||
|
||||
/**
|
||||
* 处理来自手机网页的交易请求
|
||||
* @param alipay 支付宝配置
|
||||
* @param trade 交易详情
|
||||
* @return String
|
||||
* @throws Exception 异常
|
||||
*/
|
||||
String toPayAsWeb(AlipayConfig alipay, TradeVo trade) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
package com.platform.service;
|
||||
|
||||
import com.platform.domain.vo.EmailVo;
|
||||
import com.platform.domain.EmailConfig;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
public interface EmailService {
|
||||
|
||||
/**
|
||||
* 更新邮件配置
|
||||
* @param emailConfig 邮箱配置
|
||||
* @param old /
|
||||
* @return /
|
||||
* @throws Exception /
|
||||
*/
|
||||
EmailConfig config(EmailConfig emailConfig, EmailConfig old) throws Exception;
|
||||
|
||||
/**
|
||||
* 查询配置
|
||||
* @return EmailConfig 邮件配置
|
||||
*/
|
||||
EmailConfig find();
|
||||
|
||||
/**
|
||||
* 发送邮件
|
||||
* @param emailVo 邮件发送的内容
|
||||
* @param emailConfig 邮件配置
|
||||
* @throws Exception /
|
||||
*/
|
||||
void send(EmailVo emailVo, EmailConfig emailConfig);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
package com.platform.service;
|
||||
|
||||
import com.platform.domain.LocalStorage;
|
||||
import com.platform.service.dto.LocalStorageDto;
|
||||
import com.platform.service.dto.LocalStorageQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
public interface LocalStorageService {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param criteria 条件
|
||||
* @param pageable 分页参数
|
||||
* @return /
|
||||
*/
|
||||
Object queryAll(LocalStorageQueryCriteria criteria, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 查询全部数据
|
||||
* @param criteria 条件
|
||||
* @return /
|
||||
*/
|
||||
List<LocalStorageDto> queryAll(LocalStorageQueryCriteria criteria);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
* @param id /
|
||||
* @return /
|
||||
*/
|
||||
LocalStorageDto findById(Long id);
|
||||
|
||||
/**
|
||||
* 上传
|
||||
* @param name 文件名称
|
||||
* @param file 文件
|
||||
* @return
|
||||
*/
|
||||
LocalStorage create(String name, MultipartFile file);
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @param resources 文件信息
|
||||
*/
|
||||
void update(LocalStorage resources);
|
||||
|
||||
/**
|
||||
* 多选删除
|
||||
* @param ids /
|
||||
*/
|
||||
void deleteAll(Long[] ids);
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
* @param localStorageDtos 待导出的数据
|
||||
* @param response /
|
||||
* @throws IOException /
|
||||
*/
|
||||
void download(List<LocalStorageDto> localStorageDtos, HttpServletResponse response) throws IOException;
|
||||
}
|
||||
104
studio/box/src/main/java/com/platform/service/QiNiuService.java
Normal file
104
studio/box/src/main/java/com/platform/service/QiNiuService.java
Normal file
@@ -0,0 +1,104 @@
|
||||
|
||||
package com.platform.service;
|
||||
|
||||
import com.platform.domain.QiniuConfig;
|
||||
import com.platform.domain.QiniuContent;
|
||||
import com.platform.service.dto.QiniuQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
public interface QiNiuService {
|
||||
|
||||
/**
|
||||
* 查配置
|
||||
* @return QiniuConfig
|
||||
*/
|
||||
QiniuConfig find();
|
||||
|
||||
/**
|
||||
* 修改配置
|
||||
* @param qiniuConfig 配置
|
||||
* @return QiniuConfig
|
||||
*/
|
||||
QiniuConfig config(QiniuConfig qiniuConfig);
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param criteria 条件
|
||||
* @param pageable 分页参数
|
||||
* @return /
|
||||
*/
|
||||
Object queryAll(QiniuQueryCriteria criteria, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
* @param criteria 条件
|
||||
* @return /
|
||||
*/
|
||||
List<QiniuContent> queryAll(QiniuQueryCriteria criteria);
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
* @param file 文件
|
||||
* @param qiniuConfig 配置
|
||||
* @return QiniuContent
|
||||
*/
|
||||
QiniuContent upload(MultipartFile file, QiniuConfig qiniuConfig);
|
||||
|
||||
/**
|
||||
* 查询文件
|
||||
* @param id 文件ID
|
||||
* @return QiniuContent
|
||||
*/
|
||||
QiniuContent findByContentId(Long id);
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
* @param content 文件信息
|
||||
* @param config 配置
|
||||
* @return String
|
||||
*/
|
||||
String download(QiniuContent content, QiniuConfig config);
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* @param content 文件
|
||||
* @param config 配置
|
||||
*/
|
||||
void delete(QiniuContent content, QiniuConfig config);
|
||||
|
||||
/**
|
||||
* 同步数据
|
||||
* @param config 配置
|
||||
*/
|
||||
void synchronize(QiniuConfig config);
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* @param ids 文件ID数组
|
||||
* @param config 配置
|
||||
*/
|
||||
void deleteAll(Long[] ids, QiniuConfig config);
|
||||
|
||||
/**
|
||||
* 更新数据
|
||||
* @param type 类型
|
||||
*/
|
||||
void update(String type);
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
* @param queryAll /
|
||||
* @param response /
|
||||
* @throws IOException /
|
||||
*/
|
||||
void downloadList(List<QiniuContent> queryAll, HttpServletResponse response) throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
package com.platform.service.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.platform.base.BaseDTO;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class LocalStorageDto extends BaseDTO implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String realName;
|
||||
|
||||
private String name;
|
||||
|
||||
private String suffix;
|
||||
|
||||
private String type;
|
||||
|
||||
private String size;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
package com.platform.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
import com.platform.annotation.Query;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Data
|
||||
public class LocalStorageQueryCriteria{
|
||||
|
||||
@Query(blurry = "name,suffix,type,createBy,size")
|
||||
private String blurry;
|
||||
|
||||
@Query(type = Query.Type.BETWEEN)
|
||||
private List<Timestamp> createTime;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
package com.platform.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import com.platform.annotation.Query;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* sm.ms图床
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27 09:52:09
|
||||
*/
|
||||
@Data
|
||||
public class PictureQueryCriteria{
|
||||
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private String filename;
|
||||
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private String username;
|
||||
|
||||
@Query(type = Query.Type.BETWEEN)
|
||||
private List<Timestamp> createTime;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
package com.platform.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import com.platform.annotation.Query;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27 09:54:37
|
||||
*/
|
||||
@Data
|
||||
public class QiniuQueryCriteria{
|
||||
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private String key;
|
||||
|
||||
@Query(type = Query.Type.BETWEEN)
|
||||
private List<Timestamp> createTime;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
|
||||
package com.platform.service.impl;
|
||||
|
||||
import com.alipay.api.AlipayClient;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.request.AlipayTradePagePayRequest;
|
||||
import com.alipay.api.request.AlipayTradeWapPayRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.platform.domain.vo.TradeVo;
|
||||
import com.platform.domain.AlipayConfig;
|
||||
import com.platform.exception.BadRequestException;
|
||||
import com.platform.repository.AliPayRepository;
|
||||
import com.platform.service.AliPayService;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@CacheConfig(cacheNames = "aliPay")
|
||||
public class AliPayServiceImpl implements AliPayService {
|
||||
|
||||
private final AliPayRepository alipayRepository;
|
||||
|
||||
@Override
|
||||
@Cacheable(key = "'config'")
|
||||
public AlipayConfig find() {
|
||||
Optional<AlipayConfig> alipayConfig = alipayRepository.findById(1L);
|
||||
return alipayConfig.orElseGet(AlipayConfig::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CachePut(key = "'config'")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public AlipayConfig config(AlipayConfig alipayConfig) {
|
||||
alipayConfig.setId(1L);
|
||||
return alipayRepository.save(alipayConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toPayAsPc(AlipayConfig alipay, TradeVo trade) throws Exception {
|
||||
|
||||
if(alipay.getId() == null){
|
||||
throw new BadRequestException("请先添加相应配置,再操作");
|
||||
}
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(alipay.getGatewayUrl(), alipay.getAppId(), alipay.getPrivateKey(), alipay.getFormat(), alipay.getCharset(), alipay.getPublicKey(), alipay.getSignType());
|
||||
|
||||
// 创建API对应的request(电脑网页版)
|
||||
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
|
||||
|
||||
// 订单完成后返回的页面和异步通知地址
|
||||
request.setReturnUrl(alipay.getReturnUrl());
|
||||
request.setNotifyUrl(alipay.getNotifyUrl());
|
||||
// 填充订单参数
|
||||
request.setBizContent("{" +
|
||||
" \"out_trade_no\":\""+trade.getOutTradeNo()+"\"," +
|
||||
" \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
|
||||
" \"total_amount\":"+trade.getTotalAmount()+"," +
|
||||
" \"subject\":\""+trade.getSubject()+"\"," +
|
||||
" \"body\":\""+trade.getBody()+"\"," +
|
||||
" \"extend_params\":{" +
|
||||
" \"sys_service_provider_id\":\""+alipay.getSysServiceProviderId()+"\"" +
|
||||
" }"+
|
||||
" }");//填充业务参数
|
||||
// 调用SDK生成表单, 通过GET方式,口可以获取url
|
||||
return alipayClient.pageExecute(request, "GET").getBody();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toPayAsWeb(AlipayConfig alipay, TradeVo trade) throws Exception {
|
||||
if(alipay.getId() == null){
|
||||
throw new BadRequestException("请先添加相应配置,再操作");
|
||||
}
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(alipay.getGatewayUrl(), alipay.getAppId(), alipay.getPrivateKey(), alipay.getFormat(), alipay.getCharset(), alipay.getPublicKey(), alipay.getSignType());
|
||||
|
||||
double money = Double.parseDouble(trade.getTotalAmount());
|
||||
double maxMoney = 5000;
|
||||
if(money <= 0 || money >= maxMoney){
|
||||
throw new BadRequestException("测试金额过大");
|
||||
}
|
||||
// 创建API对应的request(手机网页版)
|
||||
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
|
||||
request.setReturnUrl(alipay.getReturnUrl());
|
||||
request.setNotifyUrl(alipay.getNotifyUrl());
|
||||
request.setBizContent("{" +
|
||||
" \"out_trade_no\":\""+trade.getOutTradeNo()+"\"," +
|
||||
" \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
|
||||
" \"total_amount\":"+trade.getTotalAmount()+"," +
|
||||
" \"subject\":\""+trade.getSubject()+"\"," +
|
||||
" \"body\":\""+trade.getBody()+"\"," +
|
||||
" \"extend_params\":{" +
|
||||
" \"sys_service_provider_id\":\""+alipay.getSysServiceProviderId()+"\"" +
|
||||
" }"+
|
||||
" }");
|
||||
return alipayClient.pageExecute(request, "GET").getBody();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
|
||||
package com.platform.service.impl;
|
||||
|
||||
import cn.hutool.extra.mail.Mail;
|
||||
import cn.hutool.extra.mail.MailAccount;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.platform.domain.EmailConfig;
|
||||
import com.platform.domain.vo.EmailVo;
|
||||
import com.platform.exception.BadRequestException;
|
||||
import com.platform.repository.EmailRepository;
|
||||
import com.platform.service.EmailService;
|
||||
import com.platform.utils.EncryptUtils;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@CacheConfig(cacheNames = "email")
|
||||
public class EmailServiceImpl implements EmailService {
|
||||
|
||||
private final EmailRepository emailRepository;
|
||||
|
||||
@Override
|
||||
@CachePut(key = "'config'")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public EmailConfig config(EmailConfig emailConfig, EmailConfig old) throws Exception {
|
||||
emailConfig.setId(1L);
|
||||
if(!emailConfig.getPass().equals(old.getPass())){
|
||||
// 对称加密
|
||||
emailConfig.setPass(EncryptUtils.desEncrypt(emailConfig.getPass()));
|
||||
}
|
||||
return emailRepository.save(emailConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(key = "'config'")
|
||||
public EmailConfig find() {
|
||||
Optional<EmailConfig> emailConfig = emailRepository.findById(1L);
|
||||
return emailConfig.orElseGet(EmailConfig::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void send(EmailVo emailVo, EmailConfig emailConfig){
|
||||
if(emailConfig.getId() == null){
|
||||
throw new BadRequestException("请先配置,再操作");
|
||||
}
|
||||
// 封装
|
||||
MailAccount account = new MailAccount();
|
||||
// 设置用户
|
||||
String user = emailConfig.getFromUser().split("@")[0];
|
||||
account.setUser(user);
|
||||
account.setHost(emailConfig.getHost());
|
||||
account.setPort(Integer.parseInt(emailConfig.getPort()));
|
||||
account.setAuth(true);
|
||||
try {
|
||||
// 对称解密
|
||||
account.setPass(EncryptUtils.desDecrypt(emailConfig.getPass()));
|
||||
} catch (Exception e) {
|
||||
throw new BadRequestException(e.getMessage());
|
||||
}
|
||||
account.setFrom(emailConfig.getUser()+"<"+emailConfig.getFromUser()+">");
|
||||
// ssl方式发送
|
||||
account.setSslEnable(true);
|
||||
// 使用STARTTLS安全连接
|
||||
account.setStarttlsEnable(true);
|
||||
String content = emailVo.getContent();
|
||||
// 发送
|
||||
try {
|
||||
int size = emailVo.getTos().size();
|
||||
Mail.create(account)
|
||||
.setTos(emailVo.getTos().toArray(new String[size]))
|
||||
.setTitle(emailVo.getSubject())
|
||||
.setContent(content)
|
||||
.setHtml(true)
|
||||
//关闭session
|
||||
.setUseGlobalSession(false)
|
||||
.send();
|
||||
}catch (Exception e){
|
||||
throw new BadRequestException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
|
||||
package com.platform.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.platform.config.FileProperties;
|
||||
import com.platform.domain.LocalStorage;
|
||||
import com.platform.service.dto.LocalStorageDto;
|
||||
import com.platform.service.dto.LocalStorageQueryCriteria;
|
||||
import com.platform.service.mapstruct.LocalStorageMapper;
|
||||
import com.platform.exception.BadRequestException;
|
||||
import com.platform.utils.*;
|
||||
import com.platform.repository.LocalStorageRepository;
|
||||
import com.platform.service.LocalStorageService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class LocalStorageServiceImpl implements LocalStorageService {
|
||||
|
||||
private final LocalStorageRepository localStorageRepository;
|
||||
private final LocalStorageMapper localStorageMapper;
|
||||
private final FileProperties properties;
|
||||
|
||||
@Override
|
||||
public Object queryAll(LocalStorageQueryCriteria criteria, Pageable pageable){
|
||||
Page<LocalStorage> page = localStorageRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
|
||||
return PageUtil.toPage(page.map(localStorageMapper::toDto));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<LocalStorageDto> queryAll(LocalStorageQueryCriteria criteria){
|
||||
return localStorageMapper.toDto(localStorageRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalStorageDto findById(Long id){
|
||||
LocalStorage localStorage = localStorageRepository.findById(id).orElseGet(LocalStorage::new);
|
||||
ValidationUtil.isNull(localStorage.getId(),"LocalStorage","id",id);
|
||||
return localStorageMapper.toDto(localStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public LocalStorage create(String name, MultipartFile multipartFile) {
|
||||
FileUtil.checkSize(properties.getMaxSize(), multipartFile.getSize());
|
||||
String suffix = FileUtil.getExtensionName(multipartFile.getOriginalFilename());
|
||||
String type = FileUtil.getFileType(suffix);
|
||||
File file = FileUtil.upload(multipartFile, properties.getPath().getPath() + type + File.separator);
|
||||
if(ObjectUtil.isNull(file)){
|
||||
throw new BadRequestException("上传失败");
|
||||
}
|
||||
try {
|
||||
name = StringUtils.isBlank(name) ? FileUtil.getFileNameNoEx(multipartFile.getOriginalFilename()) : name;
|
||||
LocalStorage localStorage = new LocalStorage(
|
||||
file.getName(),
|
||||
name,
|
||||
suffix,
|
||||
file.getPath(),
|
||||
type,
|
||||
FileUtil.getSize(file.length())
|
||||
);
|
||||
return localStorageRepository.save(localStorage);
|
||||
}catch (Exception e){
|
||||
FileUtil.del(file);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void update(LocalStorage resources) {
|
||||
LocalStorage localStorage = localStorageRepository.findById(resources.getId()).orElseGet(LocalStorage::new);
|
||||
ValidationUtil.isNull( localStorage.getId(),"LocalStorage","id",resources.getId());
|
||||
localStorage.copy(resources);
|
||||
localStorageRepository.save(localStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteAll(Long[] ids) {
|
||||
for (Long id : ids) {
|
||||
LocalStorage storage = localStorageRepository.findById(id).orElseGet(LocalStorage::new);
|
||||
FileUtil.del(storage.getPath());
|
||||
localStorageRepository.delete(storage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void download(List<LocalStorageDto> queryAll, HttpServletResponse response) throws IOException {
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
for (LocalStorageDto localStorageDTO : queryAll) {
|
||||
Map<String,Object> map = new LinkedHashMap<>();
|
||||
map.put("文件名", localStorageDTO.getRealName());
|
||||
map.put("备注名", localStorageDTO.getName());
|
||||
map.put("文件类型", localStorageDTO.getType());
|
||||
map.put("文件大小", localStorageDTO.getSize());
|
||||
map.put("创建者", localStorageDTO.getCreateBy());
|
||||
map.put("创建日期", localStorageDTO.getCreateTime());
|
||||
list.add(map);
|
||||
}
|
||||
FileUtil.downloadExcel(list, response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
|
||||
package com.platform.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.qiniu.common.QiniuException;
|
||||
import com.qiniu.http.Response;
|
||||
import com.qiniu.storage.BucketManager;
|
||||
import com.qiniu.storage.Configuration;
|
||||
import com.qiniu.storage.UploadManager;
|
||||
import com.qiniu.storage.model.DefaultPutRet;
|
||||
import com.qiniu.storage.model.FileInfo;
|
||||
import com.qiniu.util.Auth;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.platform.domain.QiniuConfig;
|
||||
import com.platform.domain.QiniuContent;
|
||||
import com.platform.repository.QiniuContentRepository;
|
||||
import com.platform.service.dto.QiniuQueryCriteria;
|
||||
import com.platform.utils.QiNiuUtil;
|
||||
import com.platform.exception.BadRequestException;
|
||||
import com.platform.repository.QiNiuConfigRepository;
|
||||
import com.platform.service.QiNiuService;
|
||||
import com.platform.utils.FileUtil;
|
||||
import com.platform.utils.PageUtil;
|
||||
import com.platform.utils.QueryHelp;
|
||||
import com.platform.utils.ValidationUtil;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@CacheConfig(cacheNames = "qiNiu")
|
||||
public class QiNiuServiceImpl implements QiNiuService {
|
||||
|
||||
private final QiNiuConfigRepository qiNiuConfigRepository;
|
||||
private final QiniuContentRepository qiniuContentRepository;
|
||||
|
||||
@Value("${qiniu.max-size}")
|
||||
private Long maxSize;
|
||||
|
||||
@Override
|
||||
@Cacheable(key = "'config'")
|
||||
public QiniuConfig find() {
|
||||
Optional<QiniuConfig> qiniuConfig = qiNiuConfigRepository.findById(1L);
|
||||
return qiniuConfig.orElseGet(QiniuConfig::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CachePut(key = "'config'")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public QiniuConfig config(QiniuConfig qiniuConfig) {
|
||||
qiniuConfig.setId(1L);
|
||||
String http = "http://", https = "https://";
|
||||
if (!(qiniuConfig.getHost().toLowerCase().startsWith(http)||qiniuConfig.getHost().toLowerCase().startsWith(https))) {
|
||||
throw new BadRequestException("外链域名必须以http://或者https://开头");
|
||||
}
|
||||
return qiNiuConfigRepository.save(qiniuConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object queryAll(QiniuQueryCriteria criteria, Pageable pageable){
|
||||
return PageUtil.toPage(qiniuContentRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QiniuContent> queryAll(QiniuQueryCriteria criteria) {
|
||||
return qiniuContentRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public QiniuContent upload(MultipartFile file, QiniuConfig qiniuConfig) {
|
||||
FileUtil.checkSize(maxSize, file.getSize());
|
||||
if(qiniuConfig.getId() == null){
|
||||
throw new BadRequestException("请先添加相应配置,再操作");
|
||||
}
|
||||
// 构造一个带指定Zone对象的配置类
|
||||
Configuration cfg = new Configuration(QiNiuUtil.getRegion(qiniuConfig.getZone()));
|
||||
UploadManager uploadManager = new UploadManager(cfg);
|
||||
Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey());
|
||||
String upToken = auth.uploadToken(qiniuConfig.getBucket());
|
||||
try {
|
||||
String key = file.getOriginalFilename();
|
||||
if(qiniuContentRepository.findByKey(key) != null) {
|
||||
key = QiNiuUtil.getKey(key);
|
||||
}
|
||||
Response response = uploadManager.put(file.getBytes(), key, upToken);
|
||||
//解析上传成功的结果
|
||||
|
||||
DefaultPutRet putRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);
|
||||
QiniuContent content = qiniuContentRepository.findByKey(FileUtil.getFileNameNoEx(putRet.key));
|
||||
if(content == null){
|
||||
//存入数据库
|
||||
QiniuContent qiniuContent = new QiniuContent();
|
||||
qiniuContent.setSuffix(FileUtil.getExtensionName(putRet.key));
|
||||
qiniuContent.setBucket(qiniuConfig.getBucket());
|
||||
qiniuContent.setType(qiniuConfig.getType());
|
||||
qiniuContent.setKey(FileUtil.getFileNameNoEx(putRet.key));
|
||||
qiniuContent.setUrl(qiniuConfig.getHost()+"/"+putRet.key);
|
||||
qiniuContent.setSize(FileUtil.getSize(Integer.parseInt(file.getSize()+"")));
|
||||
return qiniuContentRepository.save(qiniuContent);
|
||||
}
|
||||
return content;
|
||||
} catch (Exception e) {
|
||||
throw new BadRequestException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public QiniuContent findByContentId(Long id) {
|
||||
QiniuContent qiniuContent = qiniuContentRepository.findById(id).orElseGet(QiniuContent::new);
|
||||
ValidationUtil.isNull(qiniuContent.getId(),"QiniuContent", "id",id);
|
||||
return qiniuContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String download(QiniuContent content,QiniuConfig config){
|
||||
String finalUrl;
|
||||
String type = "公开";
|
||||
if(type.equals(content.getType())){
|
||||
finalUrl = content.getUrl();
|
||||
} else {
|
||||
Auth auth = Auth.create(config.getAccessKey(), config.getSecretKey());
|
||||
// 1小时,可以自定义链接过期时间
|
||||
long expireInSeconds = 3600;
|
||||
finalUrl = auth.privateDownloadUrl(content.getUrl(), expireInSeconds);
|
||||
}
|
||||
return finalUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delete(QiniuContent content, QiniuConfig config) {
|
||||
//构造一个带指定Zone对象的配置类
|
||||
Configuration cfg = new Configuration(QiNiuUtil.getRegion(config.getZone()));
|
||||
Auth auth = Auth.create(config.getAccessKey(), config.getSecretKey());
|
||||
BucketManager bucketManager = new BucketManager(auth, cfg);
|
||||
try {
|
||||
bucketManager.delete(content.getBucket(), content.getKey() + "." + content.getSuffix());
|
||||
qiniuContentRepository.delete(content);
|
||||
} catch (QiniuException ex) {
|
||||
qiniuContentRepository.delete(content);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void synchronize(QiniuConfig config) {
|
||||
if(config.getId() == null){
|
||||
throw new BadRequestException("请先添加相应配置,再操作");
|
||||
}
|
||||
//构造一个带指定Zone对象的配置类
|
||||
Configuration cfg = new Configuration(QiNiuUtil.getRegion(config.getZone()));
|
||||
Auth auth = Auth.create(config.getAccessKey(), config.getSecretKey());
|
||||
BucketManager bucketManager = new BucketManager(auth, cfg);
|
||||
//文件名前缀
|
||||
String prefix = "";
|
||||
//每次迭代的长度限制,最大1000,推荐值 1000
|
||||
int limit = 1000;
|
||||
//指定目录分隔符,列出所有公共前缀(模拟列出目录效果)。缺省值为空字符串
|
||||
String delimiter = "";
|
||||
//列举空间文件列表
|
||||
BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(config.getBucket(), prefix, limit, delimiter);
|
||||
while (fileListIterator.hasNext()) {
|
||||
//处理获取的file list结果
|
||||
QiniuContent qiniuContent;
|
||||
FileInfo[] items = fileListIterator.next();
|
||||
for (FileInfo item : items) {
|
||||
if(qiniuContentRepository.findByKey(FileUtil.getFileNameNoEx(item.key)) == null){
|
||||
qiniuContent = new QiniuContent();
|
||||
qiniuContent.setSize(FileUtil.getSize(Integer.parseInt(item.fsize+"")));
|
||||
qiniuContent.setSuffix(FileUtil.getExtensionName(item.key));
|
||||
qiniuContent.setKey(FileUtil.getFileNameNoEx(item.key));
|
||||
qiniuContent.setType(config.getType());
|
||||
qiniuContent.setBucket(config.getBucket());
|
||||
qiniuContent.setUrl(config.getHost()+"/"+item.key);
|
||||
qiniuContentRepository.save(qiniuContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAll(Long[] ids, QiniuConfig config) {
|
||||
for (Long id : ids) {
|
||||
delete(findByContentId(id), config);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void update(String type) {
|
||||
qiNiuConfigRepository.update(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadList(List<QiniuContent> queryAll, HttpServletResponse response) throws IOException {
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
for (QiniuContent content : queryAll) {
|
||||
Map<String,Object> map = new LinkedHashMap<>();
|
||||
map.put("文件名", content.getKey());
|
||||
map.put("文件类型", content.getSuffix());
|
||||
map.put("空间名称", content.getBucket());
|
||||
map.put("文件大小", content.getSize());
|
||||
map.put("空间类型", content.getType());
|
||||
map.put("创建日期", content.getUpdateTime());
|
||||
list.add(map);
|
||||
}
|
||||
FileUtil.downloadExcel(list, response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
package com.platform.service.mapstruct;
|
||||
|
||||
import com.platform.base.BaseMapper;
|
||||
import com.platform.service.dto.LocalStorageDto;
|
||||
import com.platform.domain.LocalStorage;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface LocalStorageMapper extends BaseMapper<LocalStorageDto, LocalStorage> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
package com.platform.utils;
|
||||
|
||||
/**
|
||||
* 支付状态
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
public enum AliPayStatusEnum {
|
||||
|
||||
/** 交易成功 */
|
||||
FINISHED("TRADE_FINISHED"),
|
||||
|
||||
/** 支付成功 */
|
||||
SUCCESS("TRADE_SUCCESS"),
|
||||
|
||||
/** 交易创建 */
|
||||
BUYER_PAY("WAIT_BUYER_PAY"),
|
||||
|
||||
/** 交易关闭 */
|
||||
CLOSED("TRADE_CLOSED");
|
||||
|
||||
private final String value;
|
||||
|
||||
AliPayStatusEnum(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
71
studio/box/src/main/java/com/platform/utils/AlipayUtils.java
Normal file
71
studio/box/src/main/java/com/platform/utils/AlipayUtils.java
Normal file
@@ -0,0 +1,71 @@
|
||||
|
||||
package com.platform.utils;
|
||||
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.internal.util.AlipaySignature;
|
||||
import com.platform.domain.AlipayConfig;
|
||||
import org.springframework.stereotype.Component;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 支付宝工具类
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27 14:04:35
|
||||
*/
|
||||
@Component
|
||||
public class AlipayUtils {
|
||||
|
||||
/**
|
||||
* 生成订单号
|
||||
* @return String
|
||||
*/
|
||||
public String getOrderCode() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
int a = (int)(Math.random() * 9000.0D) + 1000;
|
||||
System.out.println(a);
|
||||
Date date = new Date();
|
||||
String str = sdf.format(date);
|
||||
String[] split = str.split("-");
|
||||
String s = split[0] + split[1] + split[2];
|
||||
String[] split1 = s.split(" ");
|
||||
String s1 = split1[0] + split1[1];
|
||||
String[] split2 = s1.split(":");
|
||||
return split2[0] + split2[1] + split2[2] + a;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验签名
|
||||
* @param request HttpServletRequest
|
||||
* @param alipay 阿里云配置
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean rsaCheck(HttpServletRequest request, AlipayConfig alipay){
|
||||
|
||||
// 获取支付宝POST过来反馈信息
|
||||
Map<String,String> params = new HashMap<>(1);
|
||||
Map<String, String[]> requestParams = request.getParameterMap();
|
||||
for (Object o : requestParams.keySet()) {
|
||||
String name = (String) o;
|
||||
String[] values = requestParams.get(name);
|
||||
String valueStr = "";
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
valueStr = (i == values.length - 1) ? valueStr + values[i]
|
||||
: valueStr + values[i] + ",";
|
||||
}
|
||||
params.put(name, valueStr);
|
||||
}
|
||||
|
||||
try {
|
||||
return AlipaySignature.rsaCheckV1(params,
|
||||
alipay.getPublicKey(),
|
||||
alipay.getCharset(),
|
||||
alipay.getSignType());
|
||||
} catch (AlipayApiException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
studio/box/src/main/java/com/platform/utils/QiNiuUtil.java
Normal file
57
studio/box/src/main/java/com/platform/utils/QiNiuUtil.java
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
package com.platform.utils;
|
||||
|
||||
import com.qiniu.storage.Region;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 七牛云存储工具类
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
public class QiNiuUtil {
|
||||
|
||||
private static final String HUAD = "华东";
|
||||
|
||||
private static final String HUAB = "华北";
|
||||
|
||||
private static final String HUAN = "华南";
|
||||
|
||||
private static final String BEIM = "北美";
|
||||
|
||||
/**
|
||||
* 得到机房的对应关系
|
||||
* @param zone 机房名称
|
||||
* @return Region
|
||||
*/
|
||||
public static Region getRegion(String zone){
|
||||
|
||||
if(HUAD.equals(zone)){
|
||||
return Region.huadong();
|
||||
} else if(HUAB.equals(zone)){
|
||||
return Region.huabei();
|
||||
} else if(HUAN.equals(zone)){
|
||||
return Region.huanan();
|
||||
} else if (BEIM.equals(zone)){
|
||||
return Region.beimei();
|
||||
// 否则就是东南亚
|
||||
} else {
|
||||
return Region.qvmHuadong();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认不指定key的情况下,以文件内容的hash值作为文件名
|
||||
* @param file 文件名
|
||||
* @return String
|
||||
*/
|
||||
public static String getKey(String file){
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
Date date = new Date();
|
||||
return FileUtil.getFileNameNoEx(file) + "-" +
|
||||
sdf.format(date) +
|
||||
"." +
|
||||
FileUtil.getExtensionName(file);
|
||||
}
|
||||
}
|
||||
BIN
studio/common/aspose-words-20.3.jar
Normal file
BIN
studio/common/aspose-words-20.3.jar
Normal file
Binary file not shown.
115
studio/common/common-core/pom.xml
Normal file
115
studio/common/common-core/pom.xml
Normal file
@@ -0,0 +1,115 @@
|
||||
<?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">
|
||||
<parent>
|
||||
<artifactId>common</artifactId>
|
||||
<groupId>com.platform</groupId>
|
||||
<version>0.4.x</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<version>0.4.x</version>
|
||||
<artifactId>common-core</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<!-- SpringWeb模块 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!--io常用工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons.io.version}</version>
|
||||
</dependency>
|
||||
<!--文件上传工具类 -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>${commons.fileupload.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>${commons.beanutils.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-extension</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
</dependency>
|
||||
<!--jackson模块-->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.module</groupId>
|
||||
<artifactId>jackson-module-parameter-names</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jdk8</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
</dependency>
|
||||
<!-- jwt -->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.platform</groupId>
|
||||
<artifactId>common-service-api</artifactId>
|
||||
<version>0.4.x</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.platform</groupId>
|
||||
<artifactId>common-log</artifactId>
|
||||
<version>0.4.x</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,5 @@
|
||||
package cn.datax.common.base;
|
||||
|
||||
public abstract class BaseController {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.datax.common.base;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface BaseDao<T> extends BaseMapper<T> {
|
||||
|
||||
List<T> selectListDataScope(@Param("ew") Wrapper<T> queryWrapper, @Param("dataScope") DataScope dataScope);
|
||||
|
||||
IPage<T> selectPageDataScope(IPage<T> page, @Param("ew") Wrapper<T> queryWrapper, @Param("dataScope") DataScope dataScope);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cn.datax.common.base;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
public interface BaseService<T> extends IService<T> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package cn.datax.common.base;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public abstract class BaseServiceImpl<M extends BaseDao<T>, T> extends ServiceImpl<M, T> implements BaseService<T> {
|
||||
|
||||
@Autowired
|
||||
protected M baseDao;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.datax.common.base;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public abstract class DataFlowBaseEntity extends DataScopeBaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 工作流状态(1待提交,2已退回,3审核中,4通过,5不通过,6已撤销)
|
||||
*/
|
||||
@TableField(value = "flow_status", fill = FieldFill.INSERT)
|
||||
private String flowStatus;
|
||||
|
||||
/**
|
||||
* 流程实例ID
|
||||
*/
|
||||
@TableField(value = "process_instance_id")
|
||||
private String processInstanceId;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.datax.common.base;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 数据权限查询参数
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DataScope {
|
||||
|
||||
/**
|
||||
* 表的部门字段
|
||||
*/
|
||||
private String deptScopeName = "create_dept";
|
||||
|
||||
/**
|
||||
* 表的用户字段
|
||||
*/
|
||||
private String userScopeName = "create_by";
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.datax.common.base;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public abstract class DataScopeBaseEntity extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 创建人所属部门
|
||||
*/
|
||||
@TableField(value = "create_dept", fill = FieldFill.INSERT)
|
||||
private String createDept;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package cn.datax.common.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@Configuration
|
||||
public class JacksonConfig {
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
@ConditionalOnMissingBean(ObjectMapper.class)
|
||||
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder){
|
||||
builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
ObjectMapper objectMapper = builder.createXmlMapper(false)
|
||||
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
||||
.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
|
||||
.timeZone(TimeZone.getTimeZone("Asia/Shanghai"))
|
||||
.build();
|
||||
// null数据不返回
|
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
// 反序列化时候遇到不匹配的属性并不抛出异常
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
// 序列化时候遇到空对象不抛出异常
|
||||
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
|
||||
// 反序列化的时候如果是无效子类型,不抛出异常
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
|
||||
// 不使用默认的dateTime进行序列化,
|
||||
objectMapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false);
|
||||
// 数据精度问题
|
||||
SimpleModule simpleModule = new SimpleModule()
|
||||
.addSerializer(Long.class, ToStringSerializer.instance)
|
||||
.addSerializer(Long.TYPE, ToStringSerializer.instance)
|
||||
.addSerializer(BigInteger.class, ToStringSerializer.instance)
|
||||
.addSerializer(BigDecimal.class, ToStringSerializer.instance);
|
||||
objectMapper.registerModule(simpleModule);
|
||||
|
||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||
javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
javaTimeModule.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||
javaTimeModule.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
|
||||
javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
javaTimeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||
javaTimeModule.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
|
||||
objectMapper.registerModule(javaTimeModule).registerModule(new ParameterNamesModule());
|
||||
return objectMapper;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.datax.common.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate(ClientHttpRequestFactory factory){
|
||||
return new RestTemplate(factory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
|
||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
||||
factory.setReadTimeout(5000);
|
||||
factory.setConnectTimeout(5000);
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package cn.datax.common.core;
|
||||
|
||||
public class DataConstant {
|
||||
|
||||
/**
|
||||
* Oauth2安全相关常量
|
||||
*/
|
||||
public enum Security {
|
||||
//请求头TOKEN名称
|
||||
TOKENHEADER("gatewayToken"),
|
||||
//请求头TOKEN值
|
||||
TOKENVALUE("datax:gateway:123456"),
|
||||
//OAUTH2请求头
|
||||
AUTHORIZATION("Authorization"),
|
||||
//OAUTH2令牌类型
|
||||
TOKENTYPE("bearer "),
|
||||
//security授权角色前缀
|
||||
ROLEPREFIX("ROLE_");
|
||||
|
||||
Security(String val){
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
private final String val;
|
||||
|
||||
public String getVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用的是否
|
||||
*/
|
||||
public enum TrueOrFalse {
|
||||
FALSE("0",false),
|
||||
TRUE("1",true);
|
||||
|
||||
TrueOrFalse(String key, boolean val){
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
private final String key;
|
||||
private final boolean val;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public boolean getVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户认证返回额外信息
|
||||
*/
|
||||
public enum UserAdditionalInfo {
|
||||
LICENSE("license", "datax"),
|
||||
USER("user", "用户"),
|
||||
USERID("user_id", "用户ID"),
|
||||
USERNAME("username", "用户名"),
|
||||
NICKNAME("nickname", "用户昵称"),
|
||||
DEPT("user_dept", "用户部门"),
|
||||
ROLE("user_role", "用户角色"),
|
||||
POST("user_post", "用户岗位");
|
||||
|
||||
UserAdditionalInfo(String key, String val){
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
private final String key;
|
||||
private final String val;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用的启用禁用状态
|
||||
*/
|
||||
public enum EnableState {
|
||||
DISABLE("0","禁用"),
|
||||
ENABLE("1","启用");
|
||||
|
||||
EnableState(String key, String val){
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
private final String key;
|
||||
private final String val;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 流程审核状态
|
||||
*/
|
||||
public enum AuditState{
|
||||
WAIT("1","待提交"),
|
||||
BACK("2", "已退回"),
|
||||
AUDIT("3","审核中"),
|
||||
AGREE("4","通过"),
|
||||
REJECT("5","不通过"),
|
||||
CANCEL("6", "已撤销");
|
||||
|
||||
AuditState(String key, String val){
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
private final String key;
|
||||
private final String val;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单类型
|
||||
*/
|
||||
public enum MenuType{
|
||||
MODULE("0","模块"),
|
||||
MENU("1","菜单"),
|
||||
BUTTON("2","按钮");
|
||||
|
||||
MenuType(String key, String val){
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
private final String key;
|
||||
private final String val;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据范围
|
||||
*/
|
||||
public enum DataScope{
|
||||
ALL("1","全部数据权限"),
|
||||
CUSTOM("2","自定义数据权限"),
|
||||
DEPT("3","本部门数据权限"),
|
||||
DEPTANDCHILD("4","本部门及以下数据权限"),
|
||||
SELF("5","仅本人数据权限");
|
||||
DataScope(String key, String val){
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
private final String key;
|
||||
private final String val;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Api状态
|
||||
*/
|
||||
public enum ApiState{
|
||||
WAIT("1","待发布"),
|
||||
RELEASE("2","已发布"),
|
||||
CANCEL("3","已下线");
|
||||
ApiState(String key, String val){
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
private final String key;
|
||||
private final String val;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package cn.datax.common.core;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class DataRole implements Serializable {
|
||||
|
||||
private static final long serialVersionUID=1L;
|
||||
|
||||
private String id;
|
||||
private String dataScope;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package cn.datax.common.core;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DataUser extends User {
|
||||
|
||||
private String id;
|
||||
private String nickname;
|
||||
private String dept;
|
||||
private List<DataRole> roles;
|
||||
private List<String> posts;
|
||||
|
||||
public DataUser(String id, String nickname, String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
|
||||
this.id = id;
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
public boolean isAdmin() {
|
||||
return isAdmin(this.getUsername());
|
||||
}
|
||||
|
||||
public static boolean isAdmin(String username) {
|
||||
return ObjectUtil.equal(username, "admin");
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
public String getDept() {
|
||||
return dept;
|
||||
}
|
||||
|
||||
public void setDept(String dept) {
|
||||
this.dept = dept;
|
||||
}
|
||||
|
||||
public List<DataRole> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<DataRole> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
public List<String> getPosts() {
|
||||
return posts;
|
||||
}
|
||||
|
||||
public void setPosts(List<String> posts) {
|
||||
this.posts = posts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DataUser{" +
|
||||
"id='" + id + '\'' +
|
||||
", nickname='" + nickname + '\'' +
|
||||
", dept='" + dept + '\'' +
|
||||
", roles=" + roles +
|
||||
", posts=" + posts +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.datax.common.core;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class JsonPage<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Integer pageNum;
|
||||
private Integer pageSize;
|
||||
private Integer total;
|
||||
private List<T> data;
|
||||
|
||||
public JsonPage(Long pageNum, Long pageSize, Long total, List<T> data) {
|
||||
this.pageNum = pageNum.intValue();
|
||||
this.pageSize = pageSize.intValue();
|
||||
this.total = total.intValue();
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package cn.datax.common.core;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Getter
|
||||
public class R implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private boolean success;
|
||||
private int code;
|
||||
private String msg;
|
||||
private Object data;
|
||||
private long timestamp;
|
||||
|
||||
private R() {}
|
||||
|
||||
public static R error() {
|
||||
return error(null);
|
||||
}
|
||||
|
||||
public static R error(String message) {
|
||||
return error(null, message);
|
||||
}
|
||||
|
||||
public static R error(Integer code, String message) {
|
||||
if(code == null) {
|
||||
code = 500;
|
||||
}
|
||||
if(message == null) {
|
||||
message = "服务器内部错误";
|
||||
}
|
||||
return build(code, false, message);
|
||||
}
|
||||
|
||||
public static R ok() {
|
||||
return ok(null);
|
||||
}
|
||||
|
||||
public static R ok(String message) {
|
||||
return ok(null, message);
|
||||
}
|
||||
|
||||
public static R ok(Integer code, String message) {
|
||||
if(code == null) {
|
||||
code = 200;
|
||||
}
|
||||
if(message == null) {
|
||||
message = "操作成功";
|
||||
}
|
||||
return build(code, true, message);
|
||||
}
|
||||
|
||||
public static R build(int code, boolean success, String message) {
|
||||
return new R()
|
||||
.setCode(code)
|
||||
.setSuccess(success)
|
||||
.setMessage(message)
|
||||
.setTimestamp(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public R setCode(int code) {
|
||||
this.code = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
public R setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
return this;
|
||||
}
|
||||
public R setMessage(String msg) {
|
||||
this.msg = msg;
|
||||
return this;
|
||||
}
|
||||
|
||||
public R setData(Object data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public R setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.datax.common.core;
|
||||
|
||||
public interface RedisConstant {
|
||||
|
||||
String MARKET_API_KEY = "data:market:apis";
|
||||
|
||||
String MARKET_API_MASK_KEY = "data:market:api:masks";
|
||||
|
||||
String SYSTEM_DICT_KEY = "data:system:dicts";
|
||||
|
||||
String SYSTEM_CONFIG_KEY = "data:system:configs";
|
||||
|
||||
String METADATA_SOURCE_KEY = "data:metadata:sources";
|
||||
|
||||
String METADATA_TABLE_KEY = "data:metadata:tables";
|
||||
|
||||
String METADATA_COLUMN_KEY = "data:metadata:columns";
|
||||
|
||||
String METADATA_AUTHORIZE_KEY = "data:metadata:authorizes";
|
||||
|
||||
String STANDARD_DICT_KEY = "data:standard:dicts";
|
||||
|
||||
String WORKFLOW_BUSINESS_KEY = "data:workflow:business";
|
||||
|
||||
String VISUAL_SET_KEY = "data:visual:sets";
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
package cn.datax.common.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
|
||||
/**
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
* 统一异常处理
|
||||
*/
|
||||
@Getter
|
||||
public class BadRequestException extends RuntimeException{
|
||||
|
||||
private Integer status = BAD_REQUEST.value();
|
||||
|
||||
public BadRequestException(String msg){
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public BadRequestException(HttpStatus status, String msg){
|
||||
super(msg);
|
||||
this.status = status.value();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.datax.common.exception;
|
||||
|
||||
public class DataException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DataException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public DataException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
public DataException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DataException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DataException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package cn.datax.common.exception;
|
||||
|
||||
import cn.datax.common.core.R;
|
||||
import cn.datax.common.utils.ThrowableUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
/**
|
||||
* 处理自定义异常
|
||||
*/
|
||||
@ExceptionHandler(DataException.class)
|
||||
public R handleWithException(DataException e) {
|
||||
log.error("自定义异常信息 ex={},StackTrace={}", e.getMessage(), ThrowableUtil.getStackTrace(e));
|
||||
return R.error(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求的 JSON 参数在请求体内的参数校验
|
||||
*/
|
||||
@ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
|
||||
public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
|
||||
String message = StringUtils.collectionToCommaDelimitedString(
|
||||
e.getBindingResult().getFieldErrors()
|
||||
.stream()
|
||||
.map(FieldError::getDefaultMessage)
|
||||
.collect(Collectors.toList()));
|
||||
log.error("参数校验异常信息 ex={},StackTrace={}", e.getMessage(), ThrowableUtil.getStackTrace(e));
|
||||
return R.error(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求的 URL 参数检验
|
||||
*/
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
public R handleConstraintViolationException(ConstraintViolationException e) {
|
||||
String message = StringUtils.collectionToCommaDelimitedString(
|
||||
e.getConstraintViolations()
|
||||
.stream()
|
||||
.map(ConstraintViolation::getMessage)
|
||||
.collect(Collectors.toList()));
|
||||
log.error("参数校验异常信息 ex={},StackTrace={}", e.getMessage(), ThrowableUtil.getStackTrace(e));
|
||||
return R.error(message);
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public R handleException(Exception e) {
|
||||
log.error("全局异常信息ex={},StackTrace={}", e.getMessage(), ThrowableUtil.getStackTrace(e));
|
||||
return R.error(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package cn.datax.common.mapstruct;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Mapper文件基类
|
||||
* 更多的用法需自行实现
|
||||
* @param <D> 目标对象,一般为DTO对象
|
||||
* @param <E> 源对象,一般为需要转换的对象
|
||||
* @param <V> 目标对象,一般为VO对象
|
||||
*/
|
||||
public interface EntityMapper<D, E, V> {
|
||||
|
||||
/**
|
||||
* 将源对象转换为DTO对象
|
||||
* @param e
|
||||
* @return D
|
||||
*/
|
||||
D toDTO(E e);
|
||||
|
||||
/**
|
||||
* 将源对象集合转换为DTO对象集合
|
||||
* @param es
|
||||
* @return List<D>
|
||||
*/
|
||||
List<D> toDTO(List<E> es);
|
||||
|
||||
/**
|
||||
* 将源对象转换为VO对象
|
||||
* @param e
|
||||
* @return D
|
||||
*/
|
||||
V toVO(E e);
|
||||
|
||||
/**
|
||||
* 将源对象集合转换为VO对象集合
|
||||
* @param es
|
||||
* @return List<D>
|
||||
*/
|
||||
List<V> toVO(List<E> es);
|
||||
|
||||
/**
|
||||
* 将目标对象转换为源对象
|
||||
* @param d
|
||||
* @return E
|
||||
*/
|
||||
E toEntity(D d);
|
||||
|
||||
/**
|
||||
* 将目标对象集合转换为源对象集合
|
||||
* @param ds
|
||||
* @return List<E>
|
||||
*/
|
||||
List<E> toEntity(List<D> ds);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package cn.datax.common.utils;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class HttpUtil {
|
||||
|
||||
public static final String METHOD_POST = "POST";
|
||||
public static final String METHOD_GET = "GET";
|
||||
|
||||
public static String getBodyString(HttpServletRequest request) {
|
||||
String method = request.getMethod();
|
||||
String bodyString;
|
||||
if (METHOD_GET.equals(method)) {
|
||||
bodyString = doGet(request);
|
||||
} else if (METHOD_POST.equals(method)) {
|
||||
bodyString = doPost(request);
|
||||
} else {
|
||||
// 其他请求方式暂不处理
|
||||
return null;
|
||||
}
|
||||
return bodyString;
|
||||
}
|
||||
|
||||
private static String doPost(HttpServletRequest request) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
InputStream inputStream;
|
||||
BufferedReader bufferedReader;
|
||||
try {
|
||||
//将数据保存到数组中,每次读取的时候,都读取一遍
|
||||
inputStream = request.getInputStream();
|
||||
//将字节数组当做输出的目的地
|
||||
//字节流转换为字符流(处理流)
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
|
||||
String line = "";
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("数据读取异常", e);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String doGet(HttpServletRequest request) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
Enumeration<String> parameterNames = request.getParameterNames();
|
||||
while (parameterNames.hasMoreElements()) {
|
||||
String nextElement = parameterNames.nextElement();
|
||||
String parameter = request.getParameter(nextElement);
|
||||
map.put(nextElement, parameter);
|
||||
}
|
||||
try {
|
||||
return new ObjectMapper().writeValueAsString(map);
|
||||
} catch (JsonProcessingException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package cn.datax.common.utils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.*;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class IPUtil {
|
||||
|
||||
public static String getLocalIP() throws SocketException {
|
||||
String localIP = null;
|
||||
Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||
InetAddress ip = null;
|
||||
while (allNetInterfaces.hasMoreElements()) {
|
||||
NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
|
||||
Enumeration addresses = netInterface.getInetAddresses();
|
||||
while (addresses.hasMoreElements()) {
|
||||
ip = (InetAddress) addresses.nextElement();
|
||||
if (ip != null && ip instanceof Inet4Address) {
|
||||
localIP = ip.getHostAddress();
|
||||
if (!"127.0.0.1".equalsIgnoreCase(localIP)) {
|
||||
return localIP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return localIP;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前网络ip
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static String getIpAddr(HttpServletRequest request) {
|
||||
String ipAddress = request.getHeader("x-forwarded-for");
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
|
||||
ipAddress = request.getRemoteAddr();
|
||||
if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {
|
||||
//根据网卡取本机配置的IP
|
||||
InetAddress inet = null;
|
||||
try {
|
||||
inet = InetAddress.getLocalHost();
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
ipAddress = inet.getHostAddress();
|
||||
}
|
||||
}
|
||||
//对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
|
||||
if (ipAddress != null && ipAddress.length() > 15) { //"***.***.***.***".length() = 15
|
||||
if (ipAddress.indexOf(",") > 0) {
|
||||
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
|
||||
}
|
||||
}
|
||||
return ipAddress;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package cn.datax.common.utils;
|
||||
|
||||
import cn.datax.service.system.api.dto.JwtUserDto;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Date;
|
||||
|
||||
@Slf4j
|
||||
public class JwtUtil {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取凭证信息
|
||||
*
|
||||
* @param token jwt token串
|
||||
* @return Claims
|
||||
*/
|
||||
public static Claims getClaimByToken(String token) {
|
||||
try {
|
||||
if (StringUtils.startsWithIgnoreCase(token, "Bearer ")) {
|
||||
token = token.split(" ")[1];
|
||||
}
|
||||
return Jwts.parser()
|
||||
.setSigningKey("ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=")
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
}catch (Exception e){
|
||||
HttpServletRequest request =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
String authorization = request.getHeader("Authorization");
|
||||
String url = request.getRequestURL().toString();
|
||||
String uri = request.getRequestURI();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取过期时间
|
||||
*
|
||||
* @param token jwt token 串
|
||||
* @return Date
|
||||
*/
|
||||
public Date getExpiration(String token) {
|
||||
return getClaimByToken(token).getExpiration();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 验证token是否失效
|
||||
*
|
||||
* @param token token
|
||||
* @return true:过期 false:没过期
|
||||
*/
|
||||
public boolean isExpired(String token) {
|
||||
try {
|
||||
final Date expiration = getExpiration(token);
|
||||
return expiration.before(new Date());
|
||||
} catch (Exception e) {
|
||||
log.error("[JwtUtils --> isExpired]: {}", e.getMessage());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * 检验是否为 jwt 格式的字符串
|
||||
// *
|
||||
// * 说明: jwt 字符串由三部分组成, 分别用 . 分隔开, 所以认为有两个 . 的字符串就是jwt形式的字符串
|
||||
// * @param token jwt token串
|
||||
// * @return boolean
|
||||
// */
|
||||
// public boolean isJwtStr(String token){
|
||||
// return StringUtils.countOccurrencesOf(token, ".") == 2;
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* 获取 jwt 中的账户名
|
||||
*
|
||||
* @param token jwt token 串
|
||||
* @return String
|
||||
*/
|
||||
public String getAccountName(String token){
|
||||
String subject = getClaimByToken(token).getSubject();
|
||||
JwtUserDto jwtContent = JSONObject.parseObject(subject, JwtUserDto.class);
|
||||
jwtContent.getUsername();
|
||||
return jwtContent.getUsername();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取 jwt 的账户对象
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
public static String getTokenSubjectObject(String token){
|
||||
Claims claimByToken = getClaimByToken(token);
|
||||
String subject = claimByToken.getSubject();
|
||||
String body = JSONObject.toJSONString(subject);
|
||||
Object parse = JSON.parse(body);
|
||||
String s = parse.toString();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取 jwt 账户信息的json字符串
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
public String getTokenSubjectStr(String token){
|
||||
String body = JSONObject.toJSONString(getClaimByToken(token).getSubject());
|
||||
Object parse = JSON.parse(body);
|
||||
return parse.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package cn.datax.common.utils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.DESKeySpec;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import java.security.Key;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Base64;
|
||||
|
||||
public class MD5Util {
|
||||
|
||||
/** 向量(同时拥有向量和密匙才能解密),此向量必须是8byte,多少都报错 */
|
||||
private final byte[] DESIV = new byte[] { 0x22, 0x54, 0x36, 110, 0x40, (byte) 0xac, (byte) 0xad, (byte) 0xdf };
|
||||
/** 自定义密钥,个数不能太短,太短报错,过长,它默认只取前N位(N的具体值,大家另行查找资料) */
|
||||
private final String deSkey = "cloudcloud";
|
||||
/** 加密算法的参数接口 */
|
||||
private AlgorithmParameterSpec iv = null;
|
||||
private Key key = null;
|
||||
private String charset = "UTF-8";
|
||||
|
||||
private static volatile MD5Util instance;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @throws Exception
|
||||
*/
|
||||
private MD5Util() throws Exception {
|
||||
// 设置密钥参数
|
||||
DESKeySpec keySpec = new DESKeySpec(deSkey.getBytes(this.charset));
|
||||
// 设置向量
|
||||
iv = new IvParameterSpec(DESIV);
|
||||
// 获得密钥工厂
|
||||
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
|
||||
// 得到密钥对象
|
||||
key = keyFactory.generateSecret(keySpec);
|
||||
}
|
||||
|
||||
public static MD5Util getInstance() throws Exception {
|
||||
if(instance == null) {
|
||||
synchronized (MD5Util.class) {
|
||||
if(instance == null) {
|
||||
instance = new MD5Util();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
String value = "1246656415670484994";
|
||||
MD5Util mt = new MD5Util();
|
||||
System.out.println("加密前的字符:" + value);
|
||||
System.out.println("加密后的字符:" + mt.encode(value));
|
||||
System.out.println("解密后的字符:" + mt.decode(mt.encode(value)));
|
||||
System.out.println("字符串的MD5值:"+ getMD5Value(value));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密
|
||||
* @param data
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public String encode(String data) throws Exception {
|
||||
// 得到加密对象Cipher
|
||||
Cipher enCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
|
||||
// 设置工作模式为加密模式,给出密钥和向量
|
||||
enCipher.init(Cipher.ENCRYPT_MODE, key, iv);
|
||||
byte[] pasByte = enCipher.doFinal(data.getBytes(this.charset));
|
||||
return Base64.getEncoder().encodeToString(pasByte);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
* @param data
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public String decode(String data) throws Exception {
|
||||
Cipher deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
|
||||
deCipher.init(Cipher.DECRYPT_MODE, key, iv);
|
||||
//此处注意doFinal()的参数的位数必须是8的倍数,否则会报错(通过encode加密的字符串读出来都是8的倍数位,但写入文件再读出来,就可能因为读取的方式的问题,导致最后此处的doFinal()的参数的位数不是8的倍数)
|
||||
//此处必须用base64Decoder,若用data。getBytes()则获取的字符串的byte数组的个数极可能不是8的倍数,而且不与上面的BASE64Encoder对应(即使解密不报错也不会得到正确结果)
|
||||
byte[] pasByte = deCipher.doFinal(Base64.getDecoder().decode(data));
|
||||
return new String(pasByte, this.charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取MD5的值,可用于对比校验
|
||||
* @param sourceStr
|
||||
* @return
|
||||
*/
|
||||
private static String getMD5Value(String sourceStr) {
|
||||
String result = "";
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
md.update(sourceStr.getBytes());
|
||||
byte b[] = md.digest();
|
||||
int i;
|
||||
StringBuffer buf = new StringBuffer("");
|
||||
for (int offset = 0; offset < b.length; offset++) {
|
||||
i = b[offset];
|
||||
if (i < 0) {
|
||||
i += 256;
|
||||
}
|
||||
if (i < 16) {
|
||||
buf.append("0");
|
||||
}
|
||||
buf.append(Integer.toHexString(i));
|
||||
}
|
||||
result = buf.toString();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package cn.datax.common.utils;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 消息模板格式化
|
||||
*/
|
||||
public class MsgFormatUtil {
|
||||
|
||||
private static String REGEX = "(\\{([a-zA-Z]+)\\})";
|
||||
|
||||
public static String TEMPALTE_NICKNAME = "nickname";
|
||||
public static String TEMPALTE_DATETIME = "datetime";
|
||||
public static String TEMPALTE_BUSINESS_NAME = "businessName";
|
||||
public static String TEMPALTE_BUSINESS_KEY = "businessKey";
|
||||
|
||||
/**
|
||||
* 根据模板及参数获得内容
|
||||
* @param tempalte
|
||||
* @param parameters
|
||||
* @return
|
||||
*/
|
||||
public static String getContent(String tempalte, Map<String, String> parameters) {
|
||||
if (StrUtil.isBlank(tempalte)) {
|
||||
tempalte = "业务名称:{businessName},发起人:{nickname},业务编号:{businessKey}";
|
||||
}
|
||||
Pattern p = Pattern.compile(REGEX);
|
||||
Matcher m = p.matcher(tempalte);
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
while (m.find()){
|
||||
String key = m.group(2);
|
||||
String value = null;
|
||||
if (parameters.containsKey(key)){
|
||||
value = parameters.get(key);
|
||||
}
|
||||
value = (value == null) ? "" : value;
|
||||
m.appendReplacement(stringBuffer, value);
|
||||
}
|
||||
m.appendTail(stringBuffer);
|
||||
return stringBuffer.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String tempalte = "{name}你好,今年{age}岁";
|
||||
Map<String,String> parameters = new HashMap<>();
|
||||
parameters.put("name", "chris");
|
||||
parameters.put("age", "22");
|
||||
System.out.println(getContent(tempalte, parameters));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package cn.datax.common.utils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class PageUtil implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static Integer DEFAULT_MAX_COUNT = 5000;
|
||||
|
||||
// 当前页码
|
||||
private Integer pageNum = 1;
|
||||
// 分页条数
|
||||
private Integer pageSize = 20;
|
||||
|
||||
public Integer getPageNum() {
|
||||
return pageNum;
|
||||
}
|
||||
|
||||
public void setPageNum(Integer pageNum) {
|
||||
this.pageNum = pageNum;
|
||||
}
|
||||
|
||||
public Integer getPageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public void setPageSize(Integer pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
if (this.pageSize > 0) {
|
||||
this.pageSize = this.pageSize > DEFAULT_MAX_COUNT ? DEFAULT_MAX_COUNT : this.pageSize;
|
||||
} else {
|
||||
this.pageSize = 20;
|
||||
}
|
||||
}
|
||||
|
||||
public PageUtil(Integer pageNum, Integer pageSize) {
|
||||
this.pageNum = pageNum;
|
||||
this.pageSize = pageSize;
|
||||
if (this.pageSize > 0) {
|
||||
this.pageSize = this.pageSize > DEFAULT_MAX_COUNT ? DEFAULT_MAX_COUNT : this.pageSize;
|
||||
} else {
|
||||
this.pageSize = 20;
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getOffset() {
|
||||
pageSize = pageSize == null ? 20 : pageSize;
|
||||
pageNum = pageNum == null ? 1 : pageNum;
|
||||
int offset = pageNum > 0 ? (pageNum - 1) * pageSize : 0;
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cn.datax.common.utils;
|
||||
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 获取 HttpServletRequest
|
||||
*
|
||||
*/
|
||||
public class RequestHolder {
|
||||
|
||||
public static HttpServletRequest getHttpServletRequest() {
|
||||
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
}
|
||||
|
||||
public static HttpServletResponse getHttpServletResponse() {
|
||||
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package cn.datax.common.utils;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ResponseUtil {
|
||||
|
||||
/**
|
||||
* 设置响应
|
||||
*
|
||||
* @param response HttpServletResponse
|
||||
* @param contentType content-type
|
||||
* @param status http状态码
|
||||
* @param value 响应内容
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static void makeResponse(HttpServletResponse response, String contentType,
|
||||
int status, Object value) throws IOException {
|
||||
response.setContentType(contentType);
|
||||
response.setStatus(status);
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
response.getOutputStream().write(objectMapper.writeValueAsBytes(value));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package cn.datax.common.utils;
|
||||
|
||||
|
||||
import com.platform.exception.BadRequestException;
|
||||
|
||||
|
||||
import cn.datax.service.system.api.dto.JwtUserDto;
|
||||
import cn.datax.service.system.api.feign.UserServiceFeign;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class SecurityUtil {
|
||||
|
||||
@Autowired
|
||||
private UserServiceFeign userServiceFeign;
|
||||
|
||||
@Autowired
|
||||
private JwtUtil jwtUtil;
|
||||
|
||||
/**
|
||||
* 获取用户
|
||||
*
|
||||
* @return user
|
||||
*/
|
||||
public static JwtUserDto getDataUser() {
|
||||
UserServiceFeign userServiceFeign = SpringContextHolder.getBean(UserServiceFeign.class);
|
||||
return userServiceFeign.loginByUsername(getCurrentUsername());
|
||||
}
|
||||
|
||||
public static String getCurrentUsername() {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
String authorization = request.getHeader("Authorization");
|
||||
if (null == authorization) {
|
||||
authorization = RequestContextHolder.getRequestAttributes().getAttribute("token", 1).toString();
|
||||
}
|
||||
String tokenSubjectObject = JwtUtil.getTokenSubjectObject(authorization);
|
||||
if (tokenSubjectObject == null) {
|
||||
throw new BadRequestException(HttpStatus.UNAUTHORIZED, "当前登录状态过期");
|
||||
}
|
||||
return tokenSubjectObject;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户ID
|
||||
*
|
||||
* @return id
|
||||
*/
|
||||
public static String getUserId() {
|
||||
JwtUserDto user = getDataUser();
|
||||
if (user != null) {
|
||||
return user.getUser().getId() + "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户部门
|
||||
*
|
||||
* @return id
|
||||
*/
|
||||
public static String getUserDeptId() {
|
||||
JwtUserDto user = getDataUser();
|
||||
if (user != null) {
|
||||
return user.getUser().getDeptId() + "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户名称
|
||||
*
|
||||
* @return username
|
||||
*/
|
||||
public static String getUserName() {
|
||||
JwtUserDto user = getDataUser();
|
||||
if (user != null) {
|
||||
return user.getUsername();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户昵称
|
||||
*
|
||||
* @return nickname
|
||||
*/
|
||||
public static String getNickname() {
|
||||
JwtUserDto user = getDataUser();
|
||||
if (user != null) {
|
||||
return user.getUser().getNickName();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户角色
|
||||
*
|
||||
* @return username
|
||||
*/
|
||||
public static List<String> getUserRoleIds() {
|
||||
JwtUserDto user = getDataUser();
|
||||
if (user != null) {
|
||||
List<String> roles = new ArrayList<>(user.getRoles());
|
||||
return roles;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户
|
||||
*
|
||||
* @return user
|
||||
*/
|
||||
public static boolean isAdmin() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
|
||||
package cn.datax.common.utils;
|
||||
|
||||
import cn.datax.common.exception.BadRequestException;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 获取当前登录的用户
|
||||
* @author AllDataDC
|
||||
* @date 2023-01-27
|
||||
*/
|
||||
@Slf4j
|
||||
public class SecurityUtils {
|
||||
|
||||
/**
|
||||
* 获取当前登录的用户
|
||||
* @return UserDetails
|
||||
*/
|
||||
public static UserDetails getCurrentUser() {
|
||||
UserDetailsService userDetailsService = SpringContextHolder.getBean(UserDetailsService.class);
|
||||
return userDetailsService.loadUserByUsername(getCurrentUsername());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统用户名称
|
||||
*
|
||||
* @return 系统用户名称
|
||||
*/
|
||||
public static String getCurrentUsername() {
|
||||
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication == null) {
|
||||
throw new BadRequestException(HttpStatus.UNAUTHORIZED, "当前登录状态过期");
|
||||
}
|
||||
if (authentication.getPrincipal() instanceof UserDetails) {
|
||||
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||
return userDetails.getUsername();
|
||||
}
|
||||
throw new BadRequestException(HttpStatus.UNAUTHORIZED, "找不到当前登录的信息");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统用户ID
|
||||
* @return 系统用户ID
|
||||
*/
|
||||
public static Long getCurrentUserId() {
|
||||
UserDetails userDetails = getCurrentUser();
|
||||
return new JSONObject(new JSONObject(userDetails).get("user")).get("id", Long.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的数据权限
|
||||
* @return /
|
||||
*/
|
||||
public static List<Long> getCurrentUserDataScope(){
|
||||
UserDetails userDetails = getCurrentUser();
|
||||
JSONArray array = JSONUtil.parseArray(new JSONObject(userDetails).get("dataScopes"));
|
||||
return JSONUtil.toList(array,Long.class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 获取数据权限级别
|
||||
// * @return 级别
|
||||
// */
|
||||
// public static String getDataScopeType() {
|
||||
// List<Long> dataScopes = getCurrentUserDataScope();
|
||||
// if(dataScopes.size() != 0){
|
||||
// return "";
|
||||
// }
|
||||
// return DataScopeEnum.ALL.getValue();
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package cn.datax.common.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Lazy(false)
|
||||
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
|
||||
|
||||
private static ApplicationContext applicationContext = null;
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(SpringContextHolder.class);
|
||||
|
||||
/**
|
||||
* 取得存储在静态变量中的ApplicationContext.
|
||||
*/
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getBean(String name) {
|
||||
return (T) applicationContext.getBean(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
|
||||
*/
|
||||
public static <T> T getBean(Class<T> requiredType) {
|
||||
return applicationContext.getBean(requiredType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除SpringContextHolder中的ApplicationContext为Null.
|
||||
*/
|
||||
public static void clearHolder() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
|
||||
}
|
||||
applicationContext = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现ApplicationContextAware接口, 注入Context到静态变量中.
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
||||
SpringContextHolder.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现DisposableBean接口, 在Context关闭时清理静态变量.
|
||||
*/
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
SpringContextHolder.clearHolder();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.datax.common.utils;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* 异常工具
|
||||
*/
|
||||
public class ThrowableUtil {
|
||||
|
||||
/**
|
||||
* 获取堆栈信息
|
||||
* @param throwable
|
||||
* @return
|
||||
*/
|
||||
public static String getStackTrace(Throwable throwable){
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
try {
|
||||
throwable.printStackTrace(pw);
|
||||
return sw.toString();
|
||||
} finally {
|
||||
pw.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
cn.datax.common.config.JacksonConfig,\
|
||||
cn.datax.common.config.RestTemplateConfig,\
|
||||
cn.datax.common.exception.GlobalExceptionHandler,\
|
||||
cn.datax.common.utils.SpringContextHolder
|
||||
50
studio/common/common-database/pom.xml
Normal file
50
studio/common/common-database/pom.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?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">
|
||||
<parent>
|
||||
<artifactId>common</artifactId>
|
||||
<groupId>com.platform</groupId>
|
||||
<version>0.4.x</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<version>0.4.x</version>
|
||||
<artifactId>common-database</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mariadb.jdbc</groupId>
|
||||
<artifactId>mariadb-java-client</artifactId>
|
||||
<version>${mariadb.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.oracle.database.jdbc</groupId>
|
||||
<artifactId>ojdbc8</artifactId>
|
||||
<version>${oracle.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${postgresql.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.sqlserver</groupId>
|
||||
<artifactId>mssql-jdbc</artifactId>
|
||||
<version>${sqlserver.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.dameng</groupId>
|
||||
<artifactId>DmJdbcDriver18</artifactId>
|
||||
<version>${dameng.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,14 @@
|
||||
package cn.datax.common.database;
|
||||
|
||||
import cn.datax.common.database.constants.DbQueryProperty;
|
||||
|
||||
public interface DataSourceFactory {
|
||||
|
||||
/**
|
||||
* 创建数据源实例
|
||||
*
|
||||
* @param property
|
||||
* @return
|
||||
*/
|
||||
DbQuery createDbQuery(DbQueryProperty property);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package cn.datax.common.database;
|
||||
|
||||
import cn.datax.common.database.core.DbColumn;
|
||||
import cn.datax.common.database.core.DbTable;
|
||||
import org.springframework.jdbc.core.RowCallbackHandler;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
/**
|
||||
* 表数据查询接口
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public interface DbDialect {
|
||||
|
||||
RowMapper<DbTable> tableMapper();
|
||||
|
||||
RowMapper<DbColumn> columnMapper();
|
||||
|
||||
/**
|
||||
* 获取指定表的所有列
|
||||
*
|
||||
* @param dbName
|
||||
* @param tableName
|
||||
* @return
|
||||
*/
|
||||
String columns(String dbName, String tableName);
|
||||
|
||||
/**
|
||||
* 获取数据库下的 所有表
|
||||
*
|
||||
* @param dbName
|
||||
* @return
|
||||
*/
|
||||
String tables(String dbName);
|
||||
|
||||
/**
|
||||
* 构建 分页 sql
|
||||
*
|
||||
* @param sql
|
||||
* @param offset
|
||||
* @param count
|
||||
* @return
|
||||
*/
|
||||
String buildPaginationSql(String sql, long offset, long count);
|
||||
|
||||
/**
|
||||
* 包装 count sql
|
||||
*
|
||||
* @param sql
|
||||
* @return
|
||||
*/
|
||||
String count(String sql);
|
||||
|
||||
/**
|
||||
* oracl 读取long 类型会流关闭,是oracle的bug,需要特殊处理
|
||||
* @return
|
||||
*/
|
||||
default RowMapper<DbColumn> columnLongMapper() {
|
||||
return null;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package cn.datax.common.database;
|
||||
|
||||
import cn.datax.common.database.core.DbColumn;
|
||||
import cn.datax.common.database.core.DbTable;
|
||||
import cn.datax.common.database.core.PageResult;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 表数据查询接口
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public interface DbQuery {
|
||||
|
||||
/**
|
||||
* 获取数据库连接
|
||||
*/
|
||||
Connection getConnection();
|
||||
|
||||
/**
|
||||
* 检测连通性
|
||||
*/
|
||||
boolean valid();
|
||||
|
||||
/**
|
||||
* 关闭数据源
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* 获取指定表 具有的所有字段列表
|
||||
* @param dbName
|
||||
* @param tableName
|
||||
* @return
|
||||
*/
|
||||
List<DbColumn> getTableColumns(String dbName, String tableName);
|
||||
|
||||
/**
|
||||
* 获取指定数据库下 所有的表信息
|
||||
*
|
||||
* @param dbName
|
||||
* @return
|
||||
*/
|
||||
List<DbTable> getTables(String dbName);
|
||||
|
||||
/**
|
||||
* 获取总数
|
||||
*
|
||||
* @param sql
|
||||
* @return
|
||||
*/
|
||||
int count(String sql);
|
||||
|
||||
/**
|
||||
* 获取总数带查询参数
|
||||
*
|
||||
* @param sql
|
||||
* @return
|
||||
*/
|
||||
int count(String sql, Object[] args);
|
||||
|
||||
/**
|
||||
* 获取总数带查询参数 NamedParameterJdbcTemplate
|
||||
*
|
||||
* @param sql
|
||||
* @return
|
||||
*/
|
||||
int count(String sql, Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 查询结果列表
|
||||
*
|
||||
* @param sql
|
||||
* @return
|
||||
*/
|
||||
List<Map<String, Object>> queryList(String sql);
|
||||
|
||||
/**
|
||||
* 查询结果列表带查询参数
|
||||
*
|
||||
* @param sql
|
||||
* @param args
|
||||
* @return
|
||||
*/
|
||||
List<Map<String, Object>> queryList(String sql, Object[] args);
|
||||
|
||||
/**
|
||||
* 查询结果分页
|
||||
*
|
||||
* @param sql
|
||||
* @param offset
|
||||
* @param size
|
||||
* @return
|
||||
*/
|
||||
PageResult<Map<String, Object>> queryByPage(String sql, long offset, long size);
|
||||
|
||||
/**
|
||||
* 查询结果分页带查询参数
|
||||
* @param sql
|
||||
* @param args
|
||||
* @param offset
|
||||
* @param size
|
||||
* @return
|
||||
*/
|
||||
PageResult<Map<String, Object>> queryByPage(String sql, Object[] args, long offset, long size);
|
||||
|
||||
/**
|
||||
* 查询结果分页带查询参数 NamedParameterJdbcTemplate
|
||||
* @param sql
|
||||
* @param params
|
||||
* @param offset
|
||||
* @param size
|
||||
* @return
|
||||
*/
|
||||
PageResult<Map<String, Object>> queryByPage(String sql, Map<String, Object> params, long offset, long size);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.datax.common.database;
|
||||
|
||||
import cn.datax.common.database.constants.DbType;
|
||||
import cn.datax.common.database.dialect.DialectRegistry;
|
||||
|
||||
/**
|
||||
* 方言工厂类
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public class DialectFactory {
|
||||
|
||||
private static final DialectRegistry DIALECT_REGISTRY = new DialectRegistry();
|
||||
|
||||
public static DbDialect getDialect(DbType dbType) {
|
||||
return DIALECT_REGISTRY.getDialect(dbType);
|
||||
}
|
||||
}
|
||||
123
studio/common/common-database/src/main/java/cn/datax/common/database/cache/DefaultSqlCache.java
vendored
Normal file
123
studio/common/common-database/src/main/java/cn/datax/common/database/cache/DefaultSqlCache.java
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
package cn.datax.common.database.cache;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class DefaultSqlCache extends LinkedHashMap<String, DefaultSqlCache.ExpireNode<Object>> implements SqlCache {
|
||||
|
||||
private int capacity;
|
||||
|
||||
private long expire;
|
||||
|
||||
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
|
||||
public DefaultSqlCache(int capacity, long expire) {
|
||||
super((int) Math.ceil(capacity / 0.75) + 1, 0.75f, true);
|
||||
// 容量
|
||||
this.capacity = capacity;
|
||||
// 固定过期时间
|
||||
this.expire = expire;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String key, Object value, long ttl) {
|
||||
long expireTime = Long.MAX_VALUE;
|
||||
if (ttl >= 0) {
|
||||
expireTime = System.currentTimeMillis() + (ttl == 0 ? this.expire : ttl);
|
||||
}
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
// 封装成过期时间节点
|
||||
put(key, new ExpireNode<>(expireTime, value));
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(String key) {
|
||||
lock.readLock().lock();
|
||||
ExpireNode<Object> expireNode;
|
||||
try {
|
||||
expireNode = super.get(key);
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
if (expireNode == null) {
|
||||
return null;
|
||||
}
|
||||
// 惰性删除过期的
|
||||
if (this.expire > -1L && expireNode.expire < System.currentTimeMillis()) {
|
||||
try {
|
||||
lock.writeLock().lock();
|
||||
super.remove(key);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return expireNode.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String key) {
|
||||
try {
|
||||
lock.writeLock().lock();
|
||||
Iterator<Map.Entry<String, ExpireNode<Object>>> iterator = super.entrySet().iterator();
|
||||
// 清除key的缓存
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, ExpireNode<Object>> entry = iterator.next();
|
||||
if (entry.getKey().equals(key)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<String, ExpireNode<Object>> eldest) {
|
||||
if (this.expire > -1L && size() > capacity) {
|
||||
clean();
|
||||
}
|
||||
// lru淘汰
|
||||
return size() > this.capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理已过期的数据
|
||||
*/
|
||||
private void clean() {
|
||||
try {
|
||||
lock.writeLock().lock();
|
||||
Iterator<Map.Entry<String, ExpireNode<Object>>> iterator = super.entrySet().iterator();
|
||||
long now = System.currentTimeMillis();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, ExpireNode<Object>> next = iterator.next();
|
||||
// 判断是否过期
|
||||
if (next.getValue().expire < now) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 过期时间节点
|
||||
*/
|
||||
static class ExpireNode<V> {
|
||||
long expire;
|
||||
Object value;
|
||||
public ExpireNode(long expire, Object value) {
|
||||
this.expire = expire;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
studio/common/common-database/src/main/java/cn/datax/common/database/cache/SqlCache.java
vendored
Normal file
38
studio/common/common-database/src/main/java/cn/datax/common/database/cache/SqlCache.java
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
package cn.datax.common.database.cache;
|
||||
|
||||
import cn.datax.common.database.utils.MD5Util;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* SQL缓存接口
|
||||
*/
|
||||
public interface SqlCache {
|
||||
|
||||
/**
|
||||
* 计算key
|
||||
*/
|
||||
default String buildSqlCacheKey(String sql, Object[] args) {
|
||||
return MD5Util.encrypt(sql + ":" + Arrays.toString(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* 存入缓存
|
||||
* @param key key
|
||||
* @param value 值
|
||||
*/
|
||||
void put(String key, Object value, long ttl);
|
||||
|
||||
/**
|
||||
* 获取缓存
|
||||
* @param key key
|
||||
* @return
|
||||
*/
|
||||
<T> T get(String key);
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
* @param key key
|
||||
*/
|
||||
void delete(String key);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.datax.common.database.constants;
|
||||
|
||||
import cn.datax.common.database.exception.DataQueryException;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class DbQueryProperty implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String dbType;
|
||||
private String host;
|
||||
private String username;
|
||||
private String password;
|
||||
private Integer port;
|
||||
private String dbName;
|
||||
private String sid;
|
||||
|
||||
/**
|
||||
* 参数合法性校验
|
||||
*/
|
||||
public void viald() {
|
||||
if (StringUtils.isEmpty(dbType) || StringUtils.isEmpty(host) ||
|
||||
StringUtils.isEmpty(username) || StringUtils.isEmpty(password) ||
|
||||
StringUtils.isEmpty(port)) {
|
||||
throw new DataQueryException("参数不完整");
|
||||
}
|
||||
if (DbType.OTHER.getDb().equals(dbType)) {
|
||||
throw new DataQueryException("不支持的数据库类型");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package cn.datax.common.database.constants;
|
||||
|
||||
/**
|
||||
* 数据库类型
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public enum DbType {
|
||||
|
||||
/**
|
||||
* MYSQL
|
||||
*/
|
||||
MYSQL("1", "MySql数据库", "jdbc:mysql://${host}:${port}/${dbName}?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8"),
|
||||
/**
|
||||
* MARIADB
|
||||
*/
|
||||
MARIADB("2", "MariaDB数据库", "jdbc:mariadb://${host}:${port}/${dbName}"),
|
||||
/**
|
||||
* ORACLE
|
||||
*/
|
||||
ORACLE("3", "Oracle11g及以下数据库", "jdbc:oracle:thin:@${host}:${port}:${sid}"),
|
||||
/**
|
||||
* oracle12c new pagination
|
||||
*/
|
||||
ORACLE_12C("4", "Oracle12c+数据库", "jdbc:oracle:thin:@${host}:${port}:${sid}"),
|
||||
/**
|
||||
* POSTGRESQL
|
||||
*/
|
||||
POSTGRE_SQL("5", "PostgreSql数据库", "jdbc:postgresql://${host}:${port}/${dbName}"),
|
||||
/**
|
||||
* SQLSERVER2005
|
||||
*/
|
||||
SQL_SERVER2008("6", "SQLServer2008及以下数据库", "jdbc:sqlserver://${host}:${port};DatabaseName=${dbName}"),
|
||||
/**
|
||||
* SQLSERVER
|
||||
*/
|
||||
SQL_SERVER("7", "SQLServer2012+数据库", "jdbc:sqlserver://${host}:${port};DatabaseName=${dbName}"),
|
||||
/**
|
||||
* DMDb
|
||||
*/
|
||||
DMDB("9", "DM数据库", "jdbc:dm://${host}:${port}/${dbName}"),
|
||||
/**
|
||||
* UNKONWN DB
|
||||
*/
|
||||
OTHER("8", "其他数据库", "");
|
||||
|
||||
/**
|
||||
* 数据库名称
|
||||
*/
|
||||
private final String db;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String desc;
|
||||
|
||||
/**
|
||||
* url
|
||||
*/
|
||||
private final String url;
|
||||
|
||||
public String getDb() {
|
||||
return this.db;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return this.desc;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
DbType(String db, String desc, String url) {
|
||||
this.db = db;
|
||||
this.desc = desc;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库类型
|
||||
*
|
||||
* @param dbType 数据库类型字符串
|
||||
*/
|
||||
public static DbType getDbType(String dbType) {
|
||||
for (DbType type : DbType.values()) {
|
||||
if (type.db.equals(dbType)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return OTHER;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package cn.datax.common.database.core;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DbColumn {
|
||||
|
||||
/**
|
||||
* 列名
|
||||
*/
|
||||
private String colName;
|
||||
|
||||
/**
|
||||
* 数据类型
|
||||
*/
|
||||
private String dataType;
|
||||
|
||||
/**
|
||||
* 数据长度
|
||||
*/
|
||||
private String dataLength;
|
||||
|
||||
/**
|
||||
* 数据精度
|
||||
*/
|
||||
private String dataPrecision;
|
||||
|
||||
/**
|
||||
* 数据小数位
|
||||
*/
|
||||
private String dataScale;
|
||||
|
||||
/**
|
||||
* 是否主键
|
||||
*/
|
||||
private Boolean colKey;
|
||||
|
||||
/**
|
||||
* 是否允许为空
|
||||
*/
|
||||
private Boolean nullable;
|
||||
|
||||
/**
|
||||
* 列的序号
|
||||
*/
|
||||
private Integer colPosition;
|
||||
|
||||
/**
|
||||
* 列默认值
|
||||
*/
|
||||
private String dataDefault;
|
||||
|
||||
/**
|
||||
* 列注释
|
||||
*/
|
||||
private String colComment;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package cn.datax.common.database.core;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DbTable {
|
||||
|
||||
/**
|
||||
* 表名
|
||||
*/
|
||||
private String tableName;
|
||||
|
||||
/**
|
||||
* 表注释
|
||||
*/
|
||||
private String tableComment;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.datax.common.database.core;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PageResult<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Integer pageNum;
|
||||
private Integer pageSize;
|
||||
private Integer total;
|
||||
private List<T> data;
|
||||
|
||||
public PageResult(Integer total, List<T> data) {
|
||||
this.total = total;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package cn.datax.common.database.datasource;
|
||||
|
||||
import cn.datax.common.database.*;
|
||||
import cn.datax.common.database.constants.DbQueryProperty;
|
||||
import cn.datax.common.database.constants.DbType;
|
||||
import cn.datax.common.database.exception.DataQueryException;
|
||||
import cn.datax.common.database.query.AbstractDbQueryFactory;
|
||||
import cn.datax.common.database.query.CacheDbQueryFactoryBean;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
public abstract class AbstractDataSourceFactory implements DataSourceFactory {
|
||||
|
||||
@Override
|
||||
public DbQuery createDbQuery(DbQueryProperty property) {
|
||||
property.viald();
|
||||
DbType dbType = DbType.getDbType(property.getDbType());
|
||||
DataSource dataSource = createDataSource(property);
|
||||
DbQuery dbQuery = createDbQuery(dataSource, dbType);
|
||||
return dbQuery;
|
||||
}
|
||||
|
||||
public DbQuery createDbQuery(DataSource dataSource, DbType dbType) {
|
||||
DbDialect dbDialect = DialectFactory.getDialect(dbType);
|
||||
if(dbDialect == null){
|
||||
throw new DataQueryException("该数据库类型正在开发中");
|
||||
}
|
||||
AbstractDbQueryFactory dbQuery = new CacheDbQueryFactoryBean();
|
||||
dbQuery.setDataSource(dataSource);
|
||||
dbQuery.setJdbcTemplate(new JdbcTemplate(dataSource));
|
||||
dbQuery.setDbDialect(dbDialect);
|
||||
return dbQuery;
|
||||
}
|
||||
|
||||
public DataSource createDataSource(DbQueryProperty property) {
|
||||
HikariDataSource dataSource = new HikariDataSource();
|
||||
// if (property.getDbType().equals("9")) {
|
||||
// dataSource.setDriverClassName("dm.jdbc.driver.DmDriver");
|
||||
// }
|
||||
dataSource.setJdbcUrl(trainToJdbcUrl(property));
|
||||
dataSource.setUsername(property.getUsername());
|
||||
dataSource.setPassword(property.getPassword());
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
protected String trainToJdbcUrl(DbQueryProperty property) {
|
||||
String url = DbType.getDbType(property.getDbType()).getUrl();
|
||||
if (StringUtils.isEmpty(url)) {
|
||||
throw new DataQueryException("无效数据库类型!");
|
||||
}
|
||||
url = url.replace("${host}", property.getHost());
|
||||
url = url.replace("${port}", String.valueOf(property.getPort()));
|
||||
if (DbType.ORACLE.getDb().equals(property.getDbType()) || DbType.ORACLE_12C.getDb().equals(property.getDbType())) {
|
||||
url = url.replace("${sid}", property.getSid());
|
||||
} else {
|
||||
url = url.replace("${dbName}", property.getDbName());
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package cn.datax.common.database.datasource;
|
||||
|
||||
import cn.datax.common.database.constants.DbQueryProperty;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class CacheDataSourceFactoryBean extends AbstractDataSourceFactory {
|
||||
|
||||
/**
|
||||
* 数据源缓存
|
||||
*/
|
||||
private static Map<String, DataSource> dataSourceMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public DataSource createDataSource(DbQueryProperty property) {
|
||||
String key = property.getDbType() + ":" + property.getHost()
|
||||
+ ":" + property.getPort() + ":" + property.getUsername()
|
||||
+ ":" + property.getPassword() + ":" + property.getDbName()
|
||||
+ ":" + property.getSid();
|
||||
String s = compress(key);
|
||||
DataSource dataSource = dataSourceMap.get(s);
|
||||
if (null == dataSource) {
|
||||
synchronized (CacheDataSourceFactoryBean.class) {
|
||||
dataSource = super.createDataSource(property);
|
||||
dataSourceMap.put(s, dataSource);
|
||||
}
|
||||
}
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
// 压缩
|
||||
public static String compress(String str) {
|
||||
if (str == null || str.length() == 0) {
|
||||
return str;
|
||||
}
|
||||
MessageDigest md = null;
|
||||
try {
|
||||
md = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
md.update(str.getBytes());
|
||||
byte b[] = md.digest();
|
||||
int i;
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int offset = 0; offset < b.length; offset++) {
|
||||
i = b[offset];
|
||||
if (i < 0)
|
||||
i += 256;
|
||||
if (i < 16)
|
||||
buf.append("0");
|
||||
buf.append(Integer.toHexString(i));
|
||||
}
|
||||
// System.out.println("MD5(" + str + ",32小写) = " + buf.toString());
|
||||
// System.out.println("MD5(" + str + ",32大写) = " + buf.toString().toUpperCase());
|
||||
// System.out.println("MD5(" + str + ",16小写) = " + buf.toString().substring(8, 24));
|
||||
// System.out.println("MD5(" + str + ",16大写) = " + buf.toString().substring(8, 24).toUpperCase());
|
||||
return buf.toString().substring(8, 24).toUpperCase();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package cn.datax.common.database.datasource;
|
||||
|
||||
public class DefaultDataSourceFactoryBean extends AbstractDataSourceFactory {
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.datax.common.database.dialect;
|
||||
|
||||
import cn.datax.common.database.DbDialect;
|
||||
|
||||
/**
|
||||
* 方言抽象类
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public abstract class AbstractDbDialect implements DbDialect {
|
||||
|
||||
@Override
|
||||
public String columns(String dbName, String tableName) {
|
||||
return "select column_name AS COLNAME, ordinal_position AS COLPOSITION, column_default AS DATADEFAULT, is_nullable AS NULLABLE, data_type AS DATATYPE, " +
|
||||
"character_maximum_length AS DATALENGTH, numeric_precision AS DATAPRECISION, numeric_scale AS DATASCALE, column_key AS COLKEY, column_comment AS COLCOMMENT " +
|
||||
"from information_schema.columns where table_schema = '" + dbName + "' and table_name = '" + tableName + "' order by ordinal_position ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tables(String dbName) {
|
||||
return "SELECT table_name AS TABLENAME, table_comment AS TABLECOMMENT FROM information_schema.tables where table_schema = '" + dbName + "' ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildPaginationSql(String originalSql, long offset, long count) {
|
||||
// 获取 分页实际条数
|
||||
StringBuilder sqlBuilder = new StringBuilder(originalSql);
|
||||
sqlBuilder.append(" LIMIT ").append(offset).append(" , ").append(count);
|
||||
return sqlBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String count(String sql) {
|
||||
return "SELECT COUNT(*) FROM ( " + sql + " ) TEMP";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package cn.datax.common.database.dialect;
|
||||
|
||||
import cn.datax.common.database.DbDialect;
|
||||
import cn.datax.common.database.constants.DbType;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DialectRegistry {
|
||||
|
||||
private final Map<DbType, DbDialect> dialect_enum_map = new EnumMap<>(DbType.class);
|
||||
|
||||
public DialectRegistry() {
|
||||
dialect_enum_map.put(DbType.MARIADB, new MariaDBDialect());
|
||||
dialect_enum_map.put(DbType.MYSQL, new MySqlDialect());
|
||||
dialect_enum_map.put(DbType.ORACLE_12C, new Oracle12cDialect());
|
||||
dialect_enum_map.put(DbType.ORACLE, new OracleDialect());
|
||||
dialect_enum_map.put(DbType.POSTGRE_SQL, new PostgreDialect());
|
||||
dialect_enum_map.put(DbType.SQL_SERVER2008, new SQLServer2008Dialect());
|
||||
dialect_enum_map.put(DbType.SQL_SERVER, new SQLServerDialect());
|
||||
dialect_enum_map.put(DbType.DMDB, new DmDBDialect());
|
||||
dialect_enum_map.put(DbType.OTHER, new UnknownDialect());
|
||||
}
|
||||
|
||||
public DbDialect getDialect(DbType dbType) {
|
||||
return dialect_enum_map.get(dbType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package cn.datax.common.database.dialect;
|
||||
|
||||
import cn.datax.common.database.core.DbColumn;
|
||||
import cn.datax.common.database.core.DbTable;
|
||||
import cn.datax.common.database.exception.DataQueryException;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.util.StringUtils;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
|
||||
public class DmDBDialect extends AbstractDbDialect {
|
||||
|
||||
@Override
|
||||
public String columns(String dbName, String tableName) {
|
||||
return "select columns.column_name AS colName, columns.data_type AS DATATYPE, columns.data_length AS DATALENGTH, columns.data_precision AS DATAPRECISION, " +
|
||||
"columns.data_scale AS DATASCALE, columns.nullable AS NULLABLE, columns.column_id AS COLPOSITION, columns.data_default AS DATADEFAULT, comments.comments AS COLCOMMENT," +
|
||||
"case when t.column_name is null then 0 else 1 end as COLKEY " +
|
||||
"from sys.user_tab_columns columns LEFT JOIN sys.user_col_comments comments ON columns.table_name = comments.table_name AND columns.column_name = comments.column_name " +
|
||||
"left join ( " +
|
||||
"select col.column_name as column_name, con.table_name as table_name from user_constraints con, user_cons_columns col " +
|
||||
"where con.constraint_name = col.constraint_name and con.constraint_type = 'P' " +
|
||||
") t on t.table_name = columns.table_name and columns.column_name = t.column_name " +
|
||||
"where columns.table_name = UPPER('" + tableName + "') order by columns.column_id ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tables(String dbName) {
|
||||
return "select a.table_name as TABLENAME,b.comments AS TABLECOMMENT from dba_tables a join user_tab_comments b " +
|
||||
"on a.table_name = b.table_name where a.owner='" + dbName + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowMapper<DbColumn> columnMapper() {
|
||||
return (ResultSet rs, int rowNum) -> {
|
||||
DbColumn entity = new DbColumn();
|
||||
entity.setColName(rs.getString("COLNAME"));
|
||||
entity.setDataType(rs.getString("DATATYPE"));
|
||||
entity.setDataLength(rs.getString("DATALENGTH"));
|
||||
entity.setDataPrecision(rs.getString("DATAPRECISION"));
|
||||
entity.setDataScale(rs.getString("DATASCALE"));
|
||||
entity.setColKey("1".equals(rs.getString("COLKEY")) ? true : false);
|
||||
entity.setNullable("1".equals(rs.getString("NULLABLE")) ? true : false);
|
||||
entity.setColPosition(rs.getInt("COLPOSITION"));
|
||||
entity.setDataDefault(rs.getString("DATADEFAULT"));
|
||||
entity.setColComment(rs.getString("COLCOMMENT"));
|
||||
return entity;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowMapper<DbTable> tableMapper() {
|
||||
return (ResultSet rs, int rowNum) -> {
|
||||
DbTable entity = new DbTable();
|
||||
entity.setTableName(rs.getString("TABLENAME"));
|
||||
entity.setTableComment(rs.getString("TABLECOMMENT"));
|
||||
return entity;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package cn.datax.common.database.dialect;
|
||||
|
||||
/**
|
||||
* MariaDB 数据库方言
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public class MariaDBDialect extends MySqlDialect {
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package cn.datax.common.database.dialect;
|
||||
|
||||
import cn.datax.common.database.core.DbColumn;
|
||||
import cn.datax.common.database.core.DbTable;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
|
||||
/**
|
||||
* MySql 数据库方言
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public class MySqlDialect extends AbstractDbDialect {
|
||||
|
||||
@Override
|
||||
public RowMapper<DbColumn> columnMapper() {
|
||||
return (ResultSet rs, int rowNum) -> {
|
||||
DbColumn entity = new DbColumn();
|
||||
entity.setColName(rs.getString("COLNAME"));
|
||||
entity.setDataType(rs.getString("DATATYPE"));
|
||||
entity.setDataLength(rs.getString("DATALENGTH"));
|
||||
entity.setDataPrecision(rs.getString("DATAPRECISION"));
|
||||
entity.setDataScale(rs.getString("DATASCALE"));
|
||||
entity.setColKey("PRI".equals(rs.getString("COLKEY")));
|
||||
entity.setNullable("YES".equals(rs.getString("NULLABLE")));
|
||||
entity.setColPosition(rs.getInt("COLPOSITION"));
|
||||
entity.setDataDefault(rs.getString("DATADEFAULT"));
|
||||
entity.setColComment(rs.getString("COLCOMMENT"));
|
||||
return entity;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowMapper<DbTable> tableMapper() {
|
||||
return (ResultSet rs, int rowNum) -> {
|
||||
DbTable entity = new DbTable();
|
||||
entity.setTableName(rs.getString("TABLENAME"));
|
||||
entity.setTableComment(rs.getString("TABLECOMMENT"));
|
||||
return entity;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package cn.datax.common.database.dialect;
|
||||
|
||||
/**
|
||||
* ORACLE Oracle12c+数据库方言
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public class Oracle12cDialect extends OracleDialect {
|
||||
|
||||
@Override
|
||||
public String buildPaginationSql(String originalSql, long offset, long count) {
|
||||
StringBuilder sqlBuilder = new StringBuilder(originalSql);
|
||||
sqlBuilder.append(" OFFSET ").append(offset).append(" ROWS FETCH NEXT ").append(count).append(" ROWS ONLY ");
|
||||
return sqlBuilder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package cn.datax.common.database.dialect;
|
||||
|
||||
import cn.datax.common.database.core.DbColumn;
|
||||
import cn.datax.common.database.core.DbTable;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Oracle Oracle11g及以下数据库方言
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public class OracleDialect extends AbstractDbDialect {
|
||||
|
||||
@Override
|
||||
public String columns(String dbName, String tableName) {
|
||||
return "select columns.column_name AS colName, columns.data_type AS DATATYPE, columns.data_length AS DATALENGTH, columns.data_precision AS DATAPRECISION, " +
|
||||
"columns.data_scale AS DATASCALE, columns.nullable AS NULLABLE, columns.column_id AS COLPOSITION, columns.data_default AS DATADEFAULT, comments.comments AS COLCOMMENT," +
|
||||
"case when t.column_name is null then 0 else 1 end as COLKEY " +
|
||||
"from sys.user_tab_columns columns LEFT JOIN sys.user_col_comments comments ON columns.table_name = comments.table_name AND columns.column_name = comments.column_name " +
|
||||
"left join ( " +
|
||||
"select col.column_name as column_name, con.table_name as table_name from user_constraints con, user_cons_columns col " +
|
||||
"where con.constraint_name = col.constraint_name and con.constraint_type = 'P' " +
|
||||
") t on t.table_name = columns.table_name and columns.column_name = t.column_name " +
|
||||
"where columns.table_name = UPPER('" + tableName + "') order by columns.column_id ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tables(String dbName) {
|
||||
return "select tables.table_name AS TABLENAME, comments.comments AS TABLECOMMENT from sys.user_tables tables " +
|
||||
"LEFT JOIN sys.user_tab_comments comments ON tables.table_name = comments.table_name ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildPaginationSql(String originalSql, long offset, long count) {
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("SELECT * FROM ( SELECT TMP.*, ROWNUM ROW_ID FROM ( ");
|
||||
sqlBuilder.append(originalSql).append(" ) TMP WHERE ROWNUM <=").append((offset >= 1) ? (offset + count) : count);
|
||||
sqlBuilder.append(") WHERE ROW_ID > ").append(offset);
|
||||
return sqlBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowMapper<DbColumn> columnLongMapper() {
|
||||
return (ResultSet rs, int rowNum) -> {
|
||||
DbColumn entity = new DbColumn();
|
||||
entity.setDataDefault(rs.getString("DATADEFAULT"));
|
||||
return entity;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowMapper<DbColumn> columnMapper() {
|
||||
return (ResultSet rs, int rowNum) -> {
|
||||
DbColumn entity = new DbColumn();
|
||||
entity.setColName(rs.getString("COLNAME"));
|
||||
entity.setDataType(rs.getString("DATATYPE"));
|
||||
entity.setDataLength(rs.getString("DATALENGTH"));
|
||||
entity.setDataPrecision(rs.getString("DATAPRECISION"));
|
||||
entity.setDataScale(rs.getString("DATASCALE"));
|
||||
entity.setColKey("1".equals(rs.getString("COLKEY")));
|
||||
entity.setNullable("Y".equals(rs.getString("NULLABLE")));
|
||||
//long类型,单独处理
|
||||
//entity.setDataDefault(rs.getString("DATADEFAULT"));
|
||||
entity.setColPosition(rs.getInt("COLPOSITION"));
|
||||
entity.setColComment(rs.getString("COLCOMMENT"));
|
||||
return entity;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowMapper<DbTable> tableMapper() {
|
||||
return (ResultSet rs, int rowNum) -> {
|
||||
DbTable entity = new DbTable();
|
||||
entity.setTableName(rs.getString("TABLENAME"));
|
||||
entity.setTableComment(rs.getString("TABLECOMMENT"));
|
||||
return entity;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package cn.datax.common.database.dialect;
|
||||
|
||||
import cn.datax.common.database.core.DbColumn;
|
||||
import cn.datax.common.database.core.DbTable;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
|
||||
/**
|
||||
* Postgre 数据库方言
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public class PostgreDialect extends AbstractDbDialect {
|
||||
|
||||
@Override
|
||||
public String columns(String dbName, String tableName) {
|
||||
return "select col.column_name AS COLNAME, col.ordinal_position AS COLPOSITION, col.column_default AS DATADEFAULT, col.is_nullable AS NULLABLE, col.udt_name AS DATATYPE, " +
|
||||
"col.character_maximum_length AS DATALENGTH, col.numeric_precision AS DATAPRECISION, col.numeric_scale AS DATASCALE, des.description AS COLCOMMENT, " +
|
||||
"case when t.colname is null then 0 else 1 end as COLKEY " +
|
||||
"from information_schema.columns col left join pg_description des on col.table_name::regclass = des.objoid and col.ordinal_position = des.objsubid " +
|
||||
"left join ( " +
|
||||
"select pg_attribute.attname as colname from pg_constraint inner join pg_class on pg_constraint.conrelid = pg_class.oid " +
|
||||
"inner join pg_attribute on pg_attribute.attrelid = pg_class.oid and pg_attribute.attnum = any(pg_constraint.conkey) " +
|
||||
"where pg_class.relname = '" + tableName + "' and pg_constraint.contype = 'p' " +
|
||||
") t on t.colname = col.column_name " +
|
||||
"where col.table_catalog = '" + dbName + "' and col.table_schema = 'public' and col.table_name = '" + tableName + "' order by col.ordinal_position ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tables(String dbName) {
|
||||
return "select relname AS TABLENAME, cast(obj_description(relfilenode, 'pg_class') as varchar) AS TABLECOMMENT from pg_class " +
|
||||
"where relname in (select tablename from pg_tables where schemaname = 'public' and tableowner = '" + dbName + "' and position('_2' in tablename) = 0) ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildPaginationSql(String originalSql, long offset, long count) {
|
||||
StringBuilder sqlBuilder = new StringBuilder(originalSql);
|
||||
sqlBuilder.append(" LIMIT ").append(count).append(" offset ").append(offset);
|
||||
return sqlBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowMapper<DbColumn> columnMapper() {
|
||||
return (ResultSet rs, int rowNum) -> {
|
||||
DbColumn entity = new DbColumn();
|
||||
entity.setColName(rs.getString("COLNAME"));
|
||||
entity.setDataType(rs.getString("DATATYPE"));
|
||||
entity.setDataLength(rs.getString("DATALENGTH"));
|
||||
entity.setDataPrecision(rs.getString("DATAPRECISION"));
|
||||
entity.setDataScale(rs.getString("DATASCALE"));
|
||||
entity.setColKey("1".equals(rs.getString("COLKEY")) ? true : false);
|
||||
entity.setNullable("YES".equals(rs.getString("NULLABLE")) ? true : false);
|
||||
entity.setColPosition(rs.getInt("COLPOSITION"));
|
||||
entity.setDataDefault(rs.getString("DATADEFAULT"));
|
||||
entity.setColComment(rs.getString("COLCOMMENT"));
|
||||
return entity;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowMapper<DbTable> tableMapper() {
|
||||
return (ResultSet rs, int rowNum) -> {
|
||||
DbTable entity = new DbTable();
|
||||
entity.setTableName(rs.getString("TABLENAME"));
|
||||
entity.setTableComment(rs.getString("TABLECOMMENT"));
|
||||
return entity;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package cn.datax.common.database.dialect;
|
||||
|
||||
import cn.datax.common.database.core.DbColumn;
|
||||
import cn.datax.common.database.core.DbTable;
|
||||
import cn.datax.common.database.exception.DataQueryException;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
|
||||
/**
|
||||
* SQLServer 2005 数据库方言
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public class SQLServer2008Dialect extends AbstractDbDialect {
|
||||
|
||||
@Override
|
||||
public String columns(String dbName, String tableName) {
|
||||
return "select columns.name AS colName, columns.column_id AS COLPOSITION, columns.max_length AS DATALENGTH, columns.precision AS DATAPRECISION, columns.scale AS DATASCALE, " +
|
||||
"columns.is_nullable AS NULLABLE, types.name AS DATATYPE, CAST(ep.value AS NVARCHAR(128)) AS COLCOMMENT, e.text AS DATADEFAULT, " +
|
||||
"(select top 1 ind.is_primary_key from sys.index_columns ic left join sys.indexes ind on ic.object_id = ind.object_id and ic.index_id = ind.index_id and ind.name like 'PK_%' where ic.object_id=columns.object_id and ic.column_id=columns.column_id) AS COLKEY " +
|
||||
"from sys.columns columns LEFT JOIN sys.types types ON columns.system_type_id = types.system_type_id " +
|
||||
"LEFT JOIN syscomments e ON columns.default_object_id= e.id " +
|
||||
"LEFT JOIN sys.extended_properties ep ON ep.major_id = columns.object_id AND ep.minor_id = columns.column_id AND ep.name = 'MS_Description' " +
|
||||
"where columns.object_id = object_id('" + tableName + "') order by columns.column_id ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tables(String dbName) {
|
||||
return "select tables.name AS TABLENAME, CAST(ep.value AS NVARCHAR(128)) AS TABLECOMMENT " +
|
||||
"from sys.tables tables LEFT JOIN sys.extended_properties ep ON ep.major_id = tables.object_id AND ep.minor_id = 0";
|
||||
}
|
||||
|
||||
private static String getOrderByPart(String sql) {
|
||||
String loweredString = sql.toLowerCase();
|
||||
int orderByIndex = loweredString.indexOf("order by");
|
||||
if (orderByIndex != -1) {
|
||||
return sql.substring(orderByIndex);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildPaginationSql(String originalSql, long offset, long count) {
|
||||
StringBuilder pagingBuilder = new StringBuilder();
|
||||
String orderby = getOrderByPart(originalSql);
|
||||
String distinctStr = "";
|
||||
|
||||
String loweredString = originalSql.toLowerCase();
|
||||
String sqlPartString = originalSql;
|
||||
if (loweredString.trim().startsWith("select")) {
|
||||
int index = 6;
|
||||
if (loweredString.startsWith("select distinct")) {
|
||||
distinctStr = "DISTINCT ";
|
||||
index = 15;
|
||||
}
|
||||
sqlPartString = sqlPartString.substring(index);
|
||||
}
|
||||
pagingBuilder.append(sqlPartString);
|
||||
|
||||
// if no ORDER BY is specified use fake ORDER BY field to avoid errors
|
||||
if (StringUtils.isEmpty(orderby)) {
|
||||
orderby = "ORDER BY CURRENT_TIMESTAMP";
|
||||
}
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("WITH selectTemp AS (SELECT ").append(distinctStr).append("TOP 100 PERCENT ")
|
||||
.append(" ROW_NUMBER() OVER (").append(orderby).append(") as __row_number__, ").append(pagingBuilder)
|
||||
.append(") SELECT * FROM selectTemp WHERE __row_number__ BETWEEN ")
|
||||
//FIX#299:原因:mysql中limit 10(offset,size) 是从第10开始(不包含10),;而这里用的BETWEEN是两边都包含,所以改为offset+1
|
||||
.append(offset + 1)
|
||||
.append(" AND ")
|
||||
.append(offset + count).append(" ORDER BY __row_number__");
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowMapper<DbColumn> columnMapper() {
|
||||
return (ResultSet rs, int rowNum) -> {
|
||||
DbColumn entity = new DbColumn();
|
||||
entity.setColName(rs.getString("COLNAME"));
|
||||
entity.setDataType(rs.getString("DATATYPE"));
|
||||
entity.setDataLength(rs.getString("DATALENGTH"));
|
||||
entity.setDataPrecision(rs.getString("DATAPRECISION"));
|
||||
entity.setDataScale(rs.getString("DATASCALE"));
|
||||
entity.setColKey("1".equals(rs.getString("COLKEY")) ? true : false);
|
||||
entity.setNullable("1".equals(rs.getString("NULLABLE")) ? true : false);
|
||||
entity.setColPosition(rs.getInt("COLPOSITION"));
|
||||
entity.setDataDefault(rs.getString("DATADEFAULT"));
|
||||
entity.setColComment(rs.getString("COLCOMMENT"));
|
||||
return entity;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowMapper<DbTable> tableMapper() {
|
||||
return (ResultSet rs, int rowNum) -> {
|
||||
DbTable entity = new DbTable();
|
||||
entity.setTableName(rs.getString("TABLENAME"));
|
||||
entity.setTableComment(rs.getString("TABLECOMMENT"));
|
||||
return entity;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package cn.datax.common.database.dialect;
|
||||
|
||||
/**
|
||||
* SQLServer 数据库方言
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public class SQLServerDialect extends SQLServer2008Dialect {
|
||||
|
||||
@Override
|
||||
public String buildPaginationSql(String originalSql, long offset, long count) {
|
||||
StringBuilder sqlBuilder = new StringBuilder(originalSql);
|
||||
sqlBuilder.append(" OFFSET ").append(offset).append(" ROWS FETCH NEXT ").append(count).append(" ROWS ONLY ");
|
||||
return sqlBuilder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package cn.datax.common.database.dialect;
|
||||
|
||||
import cn.datax.common.database.core.DbColumn;
|
||||
import cn.datax.common.database.core.DbTable;
|
||||
import cn.datax.common.database.exception.DataQueryException;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
/**
|
||||
* 未知 数据库方言
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public class UnknownDialect extends AbstractDbDialect {
|
||||
|
||||
@Override
|
||||
public String columns(String dbName, String tableName) {
|
||||
throw new DataQueryException("不支持的数据库类型");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tables(String dbName) {
|
||||
throw new DataQueryException("不支持的数据库类型");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildPaginationSql(String sql, long offset, long count) {
|
||||
throw new DataQueryException("不支持的数据库类型");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String count(String sql) {
|
||||
throw new DataQueryException("不支持的数据库类型");
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowMapper<DbColumn> columnMapper() {
|
||||
throw new DataQueryException("不支持的数据库类型");
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowMapper<DbTable> tableMapper() {
|
||||
throw new DataQueryException("不支持的数据库类型");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package cn.datax.common.database.exception;
|
||||
|
||||
public class DataQueryException extends RuntimeException {
|
||||
|
||||
public DataQueryException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package cn.datax.common.database.query;
|
||||
|
||||
import cn.datax.common.database.DbDialect;
|
||||
import cn.datax.common.database.DbQuery;
|
||||
import cn.datax.common.database.core.DbColumn;
|
||||
import cn.datax.common.database.core.DbTable;
|
||||
import cn.datax.common.database.core.PageResult;
|
||||
import cn.datax.common.database.dialect.OracleDialect;
|
||||
import cn.datax.common.database.dialect.PostgreDialect;
|
||||
import cn.datax.common.database.dialect.DmDBDialect;
|
||||
import cn.datax.common.database.exception.DataQueryException;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import lombok.Setter;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Setter
|
||||
public abstract class AbstractDbQueryFactory implements DbQuery {
|
||||
|
||||
protected DataSource dataSource;
|
||||
|
||||
protected JdbcTemplate jdbcTemplate;
|
||||
|
||||
protected DbDialect dbDialect;
|
||||
|
||||
@Override
|
||||
public Connection getConnection() {
|
||||
try {
|
||||
return dataSource.getConnection();
|
||||
} catch (SQLException e) {
|
||||
throw new DataQueryException("获取数据库连接出错");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean valid() {
|
||||
Connection conn = null;
|
||||
try {
|
||||
conn = dataSource.getConnection();
|
||||
return conn.isValid(0);
|
||||
} catch (SQLException e) {
|
||||
throw new DataQueryException("检测连通性出错:"+e.getMessage());
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
throw new DataQueryException("关闭数据库连接出错");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (dataSource instanceof HikariDataSource) {
|
||||
((HikariDataSource) dataSource).close();
|
||||
} else {
|
||||
throw new DataQueryException("不合法数据源类型");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DbColumn> getTableColumns(String dbName, String tableName) {
|
||||
String sql = dbDialect.columns(dbName, tableName);
|
||||
if (dbDialect instanceof OracleDialect) {
|
||||
List<DbColumn> longColumns = jdbcTemplate.query(sql, dbDialect.columnLongMapper());
|
||||
List<DbColumn> queryColumns = jdbcTemplate.query(sql, dbDialect.columnMapper());
|
||||
for (int i = 0; i < longColumns.size(); i++) {
|
||||
DbColumn longColumn = longColumns.get(i);
|
||||
DbColumn otherColumn = queryColumns.get(i);
|
||||
otherColumn.setDataDefault(longColumn.getDataDefault());
|
||||
}
|
||||
return queryColumns;
|
||||
}
|
||||
return jdbcTemplate.query(sql, dbDialect.columnMapper());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DbTable> getTables(String dbName) {
|
||||
String sql = null;
|
||||
if (dbDialect instanceof PostgreDialect) {
|
||||
//如果数据源为PostgreSql,同步元数据时默认owner为登录账号(userName),故不能传递dbName需传递userName
|
||||
HikariDataSource hikariDataSource = (HikariDataSource) dataSource;
|
||||
String username = hikariDataSource.getUsername();
|
||||
sql = dbDialect.tables(username);
|
||||
} else {
|
||||
sql = dbDialect.tables(dbName);
|
||||
}
|
||||
return jdbcTemplate.query(sql, dbDialect.tableMapper());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int count(String sql) {
|
||||
return jdbcTemplate.queryForObject(dbDialect.count(sql), Integer.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int count(String sql, Object[] args) {
|
||||
return jdbcTemplate.queryForObject(dbDialect.count(sql), args, Integer.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int count(String sql, Map<String, Object> params) {
|
||||
NamedParameterJdbcTemplate namedJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
|
||||
return namedJdbcTemplate.queryForObject(dbDialect.count(sql), params, Integer.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> queryList(String sql) {
|
||||
return jdbcTemplate.queryForList(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> queryList(String sql, Object[] args) {
|
||||
return jdbcTemplate.queryForList(sql, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<Map<String, Object>> queryByPage(String sql, long offset, long size) {
|
||||
int total = count(sql);
|
||||
String pageSql = dbDialect.buildPaginationSql(sql, offset, size);
|
||||
List<Map<String, Object>> records = jdbcTemplate.queryForList(pageSql);
|
||||
return new PageResult<>(total, records);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<Map<String, Object>> queryByPage(String sql, Object[] args, long offset, long size) {
|
||||
int total = count(sql, args);
|
||||
String pageSql = dbDialect.buildPaginationSql(sql, offset, size);
|
||||
List<Map<String, Object>> records = jdbcTemplate.queryForList(pageSql, args);
|
||||
return new PageResult<>(total, records);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<Map<String, Object>> queryByPage(String sql, Map<String, Object> params, long offset, long size) {
|
||||
int total = count(sql, params);
|
||||
String pageSql = dbDialect.buildPaginationSql(sql, offset, size);
|
||||
NamedParameterJdbcTemplate namedJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
|
||||
List<Map<String, Object>> records = namedJdbcTemplate.queryForList(pageSql, params);
|
||||
return new PageResult<>(total, records);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user