11111111111

This commit is contained in:
邱波 2025-03-19 21:55:44 +08:00
commit 03316551b3
115 changed files with 6525 additions and 0 deletions

327
pom.xml Normal file
View File

@ -0,0 +1,327 @@
<?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>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.tencent</groupId>
<artifactId>materialFaceJar</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>materialFaceJar</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17</java.version>
<springboot.version>3.2.6</springboot.version>
<httpcore.version>5.2.5</httpcore.version>
<httpclilent.version>5.3.1</httpclilent.version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.16</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.13.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-text -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.12.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.16.1</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.5.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5</artifactId>
<version>${httpcore.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5-h2</artifactId>
<version>${httpcore.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>${httpclilent.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.3.4</version>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-common</artifactId>
<version>3.1.1216</version>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-facefusion</artifactId>
<version>3.1.1201</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.2.0-jre</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-commons -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>4.1.3</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profile.active>dev</profile.active>
<swaggerEnable>true</swaggerEnable>
<jdbcUser>edu_train_dev_user</jdbcUser>
<jdbcPassword>dev_user_123#!45*)6</jdbcPassword>
<jdbcUrl>jdbc:mysql://${jdbcIp}:${jdbcPort}/edu-train-dev?useUnicode=true&amp;characterEncoding=UTF-8&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=Hongkong&amp;useSSL=false&amp;allowMultiQueries=true</jdbcUrl>
<jdbcIp>47.97.80.223</jdbcIp>
<jdbcPort>13307</jdbcPort>
<log4jFile>log4j2-dev.xml</log4jFile>
<sqlPrintClass>org.apache.ibatis.logging.stdout.StdOutImpl</sqlPrintClass>
<MAX_FILE_SIZE>300MB</MAX_FILE_SIZE>
<MAX_REQUEST_FILE_SIZE>500MB</MAX_REQUEST_FILE_SIZE>
<HTTP_DEFAULT_PROXY_HOST></HTTP_DEFAULT_PROXY_HOST>
<HTTP_DEFAULT_PROXY_PORT>8080</HTTP_DEFAULT_PROXY_PORT>
<HTTP_DEFAULT_PROXY_ENABLE>false</HTTP_DEFAULT_PROXY_ENABLE>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<profile.active>test</profile.active>
<swaggerEnable>true</swaggerEnable>
<jdbcUser>edu_train_dev_user</jdbcUser>
<jdbcPassword>dev_user_123#!45*)6</jdbcPassword>
<jdbcUrl>jdbc:mysql://${jdbcIp}:${jdbcPort}/edu-train-dev?useUnicode=true&amp;characterEncoding=UTF-8&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=Hongkong&amp;useSSL=false&amp;allowMultiQueries=true</jdbcUrl>
<jdbcIp>47.97.80.223</jdbcIp>
<jdbcPort>13307</jdbcPort>
<log4jFile>log4j2</log4jFile>
<MAX_FILE_SIZE>300MB</MAX_FILE_SIZE>
<MAX_REQUEST_FILE_SIZE>500MB</MAX_REQUEST_FILE_SIZE>
<sqlPrintClass>org.apache.ibatis.logging.stdout.StdOutImpl</sqlPrintClass>
<HTTP_DEFAULT_PROXY_HOST></HTTP_DEFAULT_PROXY_HOST>
<HTTP_DEFAULT_PROXY_PORT>8080</HTTP_DEFAULT_PROXY_PORT>
<HTTP_DEFAULT_PROXY_ENABLE>false</HTTP_DEFAULT_PROXY_ENABLE>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<swaggerEnable>false</swaggerEnable>
<jdbcUser>edu_train_dev_user</jdbcUser>
<jdbcPassword>dev_user_123#!45*)6</jdbcPassword>
<jdbcUrl>jdbc:mysql://${jdbcIp}:${jdbcPort}/edu-train-dev?useUnicode=true&amp;characterEncoding=UTF-8&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=Hongkong&amp;useSSL=false&amp;allowMultiQueries=true</jdbcUrl>
<jdbcIp>47.97.80.223</jdbcIp>
<jdbcPort>13307</jdbcPort>
<MAX_FILE_SIZE>300MB</MAX_FILE_SIZE>
<MAX_REQUEST_FILE_SIZE>500MB</MAX_REQUEST_FILE_SIZE>
<log4jFile>log4j2.xml</log4jFile>
<sqlPrintClass>org.apache.ibatis.logging.log4j2.Log4j2Impl</sqlPrintClass>
<HTTP_DEFAULT_PROXY_HOST></HTTP_DEFAULT_PROXY_HOST>
<HTTP_DEFAULT_PROXY_PORT>8080</HTTP_DEFAULT_PROXY_PORT>
<HTTP_DEFAULT_PROXY_ENABLE>false</HTTP_DEFAULT_PROXY_ENABLE>
</properties>
</profile>
</profiles>
<build>
<resources>
<resource>
<directory>
src/main/resources
</directory>
<includes>
<include>rcb-${profile.active}/*</include>
<include>application.yml</include>
<include>application-${profile.active}.yml</include>
<include>${log4jFile}</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>
src/main/resources
</directory>
<includes>
<include>i18n/*</include>
<include>mapper/*</include>
<include>*/*.xlsx</include>
<include>*/*.xls</include>
<include>fonts/*</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<compilerVersion>17</compilerVersion>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.face.Application</mainClass>
<includeSystemScope>true</includeSystemScope>
<layout>JAR</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,17 @@
package com.face;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
@EnableScheduling
@EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,96 @@
package com.face;
import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.facefusion.v20220927.FacefusionClient;
import com.tencentcloudapi.facefusion.v20220927.models.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
public class PuTongRongHe
{
public static void main(String [] args) {
try{
// 实例化一个认证对象入参需要传入腾讯云账户 SecretId SecretKey此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId SecretKey 泄露并威胁账号下所有资源的安全性以下代码示例仅供参考建议采用更安全的方式来使用密钥请参见https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential("AKIDdGj28B1jKl03tY2YxEJH6jGe8VgvzpbA", "PaXHn6B50pgWEoPr7EXxCIDvTr6AGFA4");
// 实例化一个http选项可选的没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("facefusion.tencentcloudapi.com");
// 实例化一个client选项可选的没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
FacefusionClient client = new FacefusionClient(cred, "ap-chengdu", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
FuseFaceRequest req = new FuseFaceRequest();
//活动ID
req.setProjectId("at_1895073745956143104");
Path imageFile = Paths.get("F:\\体验腾讯人脸融合-素材\\222.jpg");
byte[] imageBytes = Files.readAllBytes(imageFile);
/*
InputStream imageInputStream = new FileInputStream("F:\\体验腾讯人脸融合-素材\\111.jpg");
byte[] imageBytes = new byte[imageInputStream.available()];
imageInputStream.read(imageBytes);
imageInputStream.close();*/
String imgBase =Base64.getEncoder().encodeToString(imageBytes);
//{"MaterialInfos":[{"MaterialId":"mt_1895077021871144960","MaterialStatus":21,"CreateTime":"2025-02-27 19:42:25","UpdateTime":"2025-02-27 19:42:25","MaterialFaceList":[{"FaceId":"mt_1895077021871144960_1","FaceInfo":{"X":159,"Y":360,"Width":49,"Height":64}}],"MaterialName":"微信图片_20250227194033.png","AuditResult":""},{"MaterialId":"mt_1895077032491122688","MaterialStatus":21,"CreateTime":"2025-02-27 19:42:28","UpdateTime":"2025-02-27 19:42:28","MaterialFaceList":[{"FaceId":"mt_1895077032491122688_1","FaceInfo":{"X":373,"Y":362,"Width":49,"Height":69}}],"MaterialName":"微信图片_20250227194036.png","AuditResult":""},{"MaterialId":"mt_1895077041827643392","MaterialStatus":21,"CreateTime":"2025-02-27 19:42:30","UpdateTime":"2025-02-27 19:42:30","MaterialFaceList":[{"FaceId":"mt_1895077041827643392_1","FaceInfo":{"X":242,"Y":401,"Width":57,"Height":70}}],"MaterialName":"微信图片_20250227194038.png","AuditResult":""}],"Count":3,"RequestId":"3585e437-6a27-4dc9-b59b-11f66ca4382f"}
/* Activity_Id 活动ID
Material_Id 素材ID
Face_Id 人脸模版*/
//活动里面的素材ID
req.setModelId("mt_1895077021871144960");
//图片返回方式
req.setRspImgType("url");
MergeInfo mergeInfo=new MergeInfo();
mergeInfo.setImage(imgBase);
//素材人脸和对应FaceID
mergeInfo.setTemplateFaceID("mt_1895077021871144960_1");
MergeInfo [] mergeInfos =new MergeInfo[1];
mergeInfos[0]=mergeInfo;
req.setMergeInfos(mergeInfos);
// 返回的resp是一个FuseFaceResponse的实例与请求对象对应
FuseFaceResponse resp = client.FuseFace(req);
// 输出json格式的字符串回包
System.out.println(AbstractModel.toJsonString(resp));
} catch (TencentCloudSDKException e) {
System.out.println(e.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,65 @@
package com.face;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.face.jsonBean.QiuTestRoot;
import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.facefusion.v20220927.FacefusionClient;
import com.tencentcloudapi.facefusion.v20220927.models.*;
public class SuCaiTest
{
public static void main(String [] args) {
try{
// SecretId:AKIDufDXigQwFWgdNuCG7kCRTHsFPN8fy3yg
// SecretKey:kGZheSFrHVWKvHPJ0TikZAXjicJm490d
// SecretId:AKIDdGj28B1jKl03tY2YxEJH6jGe8VgvzpbA
// SecretKey:PaXHn6B50pgWEoPr7EXxCIDvTr6AGFA4
// 实例化一个认证对象入参需要传入腾讯云账户 SecretId SecretKey此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId SecretKey 泄露并威胁账号下所有资源的安全性以下代码示例仅供参考建议采用更安全的方式来使用密钥请参见https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential("AKIDdGj28B1jKl03tY2YxEJH6jGe8VgvzpbA", "PaXHn6B50pgWEoPr7EXxCIDvTr6AGFA4");
// 实例化一个http选项可选的没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("facefusion.tencentcloudapi.com");
// 实例化一个client选项可选的没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
FacefusionClient client = new FacefusionClient(cred, "ap-chengdu", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
DescribeMaterialListRequest req = new DescribeMaterialListRequest();
//必须传这个参数
//测试API接口 at_1895073745956143104
//二次API接口 at_1895077148660760576
req.setActivityId("at_1902232245937274880");
// 返回的resp是一个DescribeMaterialListResponse的实例与请求对象对应
DescribeMaterialListResponse resp = client.DescribeMaterialList(req);
// 输出json格式的字符串回包
String qtest=AbstractModel.toJsonString(resp);
System.out.println(qtest);
ObjectMapper mapper = new ObjectMapper();
try {
QiuTestRoot person = mapper.readValue(qtest, QiuTestRoot.class);
System.out.println(person.getMaterialInfos().get(0).getMaterialFaceList().get(0).getFaceId()); // 输出: John Doe
} catch (Exception e) {
e.printStackTrace();
}
} catch (TencentCloudSDKException e) {
System.out.println(e.toString());
}
}
}

View File

@ -0,0 +1,39 @@
package com.face;
import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.facefusion.v20220927.FacefusionClient;
import com.tencentcloudapi.facefusion.v20220927.models.*;
public class ZhuanYeRongHe
{
public static void main(String [] args) {
try{
// 实例化一个认证对象入参需要传入腾讯云账户 SecretId SecretKey此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId SecretKey 泄露并威胁账号下所有资源的安全性以下代码示例仅供参考建议采用更安全的方式来使用密钥请参见https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential("AKIDdGj28B1jKl03tY2YxEJH6jGe8VgvzpbA", "PaXHn6B50pgWEoPr7EXxCIDvTr6AGFA4");
// 实例化一个http选项可选的没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("facefusion.tencentcloudapi.com");
// 实例化一个client选项可选的没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
FacefusionClient client = new FacefusionClient(cred, "ap-chengdu", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
FuseFaceUltraRequest req = new FuseFaceUltraRequest();
// 返回的resp是一个FuseFaceUltraResponse的实例与请求对象对应
FuseFaceUltraResponse resp = client.FuseFaceUltra(req);
// 输出json格式的字符串回包
System.out.println(AbstractModel.toJsonString(resp));
} catch (TencentCloudSDKException e) {
System.out.println(e.toString());
}
}
}

View File

@ -0,0 +1,14 @@
package com.face.attachment.controller;
import com.face.global.controller.ApiBaseController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
@RestController
@RequestMapping("/api/customer/v1.0/attachment")
@Slf4j
@Tag(name = "人脸融合基础管理")
public class ApiFaceInfoCustomerController extends ApiBaseController {
}

View File

@ -0,0 +1,12 @@
package com.face.attachment.controller;
import com.face.global.controller.ApiBaseController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import lombok.extern.slf4j.Slf4j;
@RestController
@RequestMapping("/api/manage/v1.0/attachment")
@Slf4j
public class ApiFaceInfoManageController extends ApiBaseController {
}

View File

@ -0,0 +1,200 @@
package com.face.attachment.controller;
import com.face.attachment.entity.FaceInfo;
import com.face.attachment.service.IFaceInfoService;
import com.face.attachment.service.vo.AttachmentVO;
import com.face.attachment.vo.*;
import com.face.global.controller.ManageBaseController;
import com.face.global.vo.ApiResult;
import com.face.global.vo.PageResponseVO;
import com.face.util.ApiResultBuilder;
import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.facefusion.v20220927.FacefusionClient;
import com.tencentcloudapi.facefusion.v20220927.models.FuseFaceRequest;
import com.tencentcloudapi.facefusion.v20220927.models.FuseFaceResponse;
import com.tencentcloudapi.facefusion.v20220927.models.MergeInfo;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.List;
@RestController
@RequestMapping("/manage/v1.0/attachment")
@Slf4j
@Tag(name = "人脸融合基础管理")
public class FaceInfoManagerController extends ManageBaseController {
@Autowired
private IFaceInfoService faceInfoService;
@Operation(summary = "修改人脸融合基础")
@PutMapping("/updateFaceInfo")
public ApiResult<Integer> updateFaceInfo(@Valid @RequestBody FaceInfoModRequestVO modRequestVO) throws Exception {
FaceInfo faceInfo = faceInfoService.updateFaceInfo(modRequestVO);
return ApiResultBuilder.getCommonBuilder(Integer.class).success(faceInfo != null
? BigInteger.ONE.intValue() : BigInteger.ZERO.intValue()).build();
}
@Operation(summary = "修改人模版脸图片")
@PostMapping("/updateImgFaceInfo")
public ApiResult<Integer> updateImgFaceInfo(@RequestParam("file") MultipartFile file,
@RequestParam(required = true, value = "faceId") String faceId) throws Exception {
FaceInfo faceInfo = faceInfoService.updateImgFaceInfo(file,faceId);
return ApiResultBuilder.getCommonBuilder(Integer.class).success(faceInfo != null
? BigInteger.ONE.intValue() : BigInteger.ZERO.intValue()).build();
}
@Operation(summary = "获取人脸融合基础详情")
@GetMapping("/getFaceInfo")
public ApiResult<FaceInfoDetailResponseVO> getFaceInfo(@RequestParam(value = "id") String id) throws Exception {
FaceInfoDetailResponseVO responseVO = faceInfoService.getFaceInfo(id);
return ApiResultBuilder.getCommonBuilder(FaceInfoDetailResponseVO.class).success(responseVO).build();
}
@Operation(summary = "分页查询人脸融合基础,包含总数")
@PostMapping("/pageAllFaceInfo")
public ApiResult<PageResponseVO<FaceInfoPageResponseVO>> pageAll(@Valid @RequestBody FaceInfoPageRequestVO pageRequestVO) throws Exception {
PageResponseVO<FaceInfoPageResponseVO> pageResponseVO = this.faceInfoService.pageAll(pageRequestVO);
return ApiResultBuilder.getPageCommonBuilder(FaceInfoPageResponseVO.class).success(pageResponseVO).build();
}
@Operation(summary = "根据腾讯活动ID和名称获取数据存入数据库")
@PostMapping("/addAllFaceInfoByTx")
public ApiResult<List<FaceInfo>> addAllFaceInfoByTx(@Valid @RequestBody FaceInfoTxRequestVO requestVO) throws Exception {
return ApiResultBuilder.getListBuilder(FaceInfo.class).success(faceInfoService.addAllFaceInfoByTx(requestVO)).build();
}
@Operation(summary = "获取所有活动")
@GetMapping("/queryAllActivity")
public ApiResult<List<FaceInfoTxRequestVO>> queryAllActivity() throws Exception {
return ApiResultBuilder.getListBuilder(FaceInfoTxRequestVO.class).success(faceInfoService.queryAllActivity()).build();
}
@Operation(summary = "获取所有人脸模版")
@PostMapping("/queryAllFaceInfo")
public ApiResult<List<FaceInfoDetailResponseVO>> queryAllFaceInfo(@Valid @RequestBody FaceInfoTxRequestVO requestVO) throws Exception {
return ApiResultBuilder.getListBuilder(FaceInfoDetailResponseVO.class).success(faceInfoService.queryAllFaceInfo(requestVO)).build();
}
@Operation(summary = "上传单个文件")
@PostMapping("/uploadSingleFile")
public ApiResult<FuseFaceResponse> uploadSingleFile(
@RequestParam("file") MultipartFile file,
@RequestParam(required = true, value = "activityId") String activityId,
@RequestParam(required = true, value = "materialId") String materialId,
@RequestParam(required = true, value = "faceId") String faceId
) throws Exception {
String imgUrl="";
FuseFaceResponse resp=null;
try{
// 实例化一个认证对象入参需要传入腾讯云账户 SecretId SecretKey此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId SecretKey 泄露并威胁账号下所有资源的安全性以下代码示例仅供参考建议采用更安全的方式来使用密钥请参见https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential("AKIDdGj28B1jKl03tY2YxEJH6jGe8VgvzpbA", "PaXHn6B50pgWEoPr7EXxCIDvTr6AGFA4");
// 实例化一个http选项可选的没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("facefusion.tencentcloudapi.com");
// 实例化一个client选项可选的没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
FacefusionClient client = new FacefusionClient(cred, "ap-chengdu", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
FuseFaceRequest req = new FuseFaceRequest();
//活动ID
req.setProjectId(activityId);
// Path imageFile = Paths.get("F:\\体验腾讯人脸融合-素材\\222.jpg");
byte[] imageBytes = file.getBytes();
/*
InputStream imageInputStream = new FileInputStream("F:\\体验腾讯人脸融合-素材\\111.jpg");
byte[] imageBytes = new byte[imageInputStream.available()];
imageInputStream.read(imageBytes);
imageInputStream.close();*/
String imgBase = Base64.getEncoder().encodeToString(imageBytes);
//{"MaterialInfos":[{"MaterialId":"mt_1895077021871144960","MaterialStatus":21,"CreateTime":"2025-02-27 19:42:25","UpdateTime":"2025-02-27 19:42:25","MaterialFaceList":[{"FaceId":"mt_1895077021871144960_1","FaceInfo":{"X":159,"Y":360,"Width":49,"Height":64}}],"MaterialName":"微信图片_20250227194033.png","AuditResult":""},{"MaterialId":"mt_1895077032491122688","MaterialStatus":21,"CreateTime":"2025-02-27 19:42:28","UpdateTime":"2025-02-27 19:42:28","MaterialFaceList":[{"FaceId":"mt_1895077032491122688_1","FaceInfo":{"X":373,"Y":362,"Width":49,"Height":69}}],"MaterialName":"微信图片_20250227194036.png","AuditResult":""},{"MaterialId":"mt_1895077041827643392","MaterialStatus":21,"CreateTime":"2025-02-27 19:42:30","UpdateTime":"2025-02-27 19:42:30","MaterialFaceList":[{"FaceId":"mt_1895077041827643392_1","FaceInfo":{"X":242,"Y":401,"Width":57,"Height":70}}],"MaterialName":"微信图片_20250227194038.png","AuditResult":""}],"Count":3,"RequestId":"3585e437-6a27-4dc9-b59b-11f66ca4382f"}
/* Activity_Id 活动ID
Material_Id 素材ID
Face_Id 人脸模版*/
//活动里面的素材ID
req.setModelId(materialId);
//图片返回方式
req.setRspImgType("url");
MergeInfo mergeInfo=new MergeInfo();
mergeInfo.setImage(imgBase);
//素材人脸和对应FaceID
mergeInfo.setTemplateFaceID(faceId);
MergeInfo [] mergeInfos =new MergeInfo[1];
mergeInfos[0]=mergeInfo;
req.setMergeInfos(mergeInfos);
// 返回的resp是一个FuseFaceResponse的实例与请求对象对应
resp = client.FuseFace(req);
// 输出json格式的字符串回包
System.out.println(AbstractModel.toJsonString(resp));
} catch (TencentCloudSDKException e) {
System.out.println(e.toString());
} catch (IOException e) {
e.printStackTrace();
}
AttachmentVO vo = new AttachmentVO();
return ApiResultBuilder.getCommonBuilder(FuseFaceResponse.class).success(resp).build();
}
}

View File

@ -0,0 +1,74 @@
package com.face.attachment.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 人脸融合基础表
*
* @author admin
* @date 2025/03/15
*/
@Data
@TableName("t_face_info")
public class FaceInfo {
/**
* 人脸模版ID
*/
@TableId
private String faceId;
/**
* 横向坐标x
*/
private Integer x;
/**
* 纵向坐标y
*/
private Integer y;
/**
* 横向坐标
*/
private Integer width;
/**
* 坐标高
*/
private Integer height;
/**
* 素材ID
*/
private String materialId;
/**
* 素材名称
*/
private String materialName;
/**
* 活动ID 一个活动多个素材 一个素材多个人脸模版
*/
private String activityId;
/**
* 图片地址
*/
private String faceUrl;
/**
* 活动名称
*/
private String activityName;
/**
* 图片BASE64编码
*/
private byte[] faceBase;
}

View File

@ -0,0 +1,21 @@
package com.face.attachment.mapper;
import com.face.attachment.entity.FaceInfo;
import java.util.List;
import com.face.attachment.vo.FaceInfoPageRequestVO;
import com.face.attachment.vo.FaceInfoPageResponseVO;
import com.face.attachment.vo.FaceInfoTxRequestVO;
import com.face.global.mapper.GlobalBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface FaceInfoMapper extends GlobalBaseMapper<FaceInfo, String> {
List<FaceInfoPageResponseVO> pageAll(@Param("page") FaceInfoPageRequestVO pageRequestVO);
Long pageCountAll(@Param("page") FaceInfoPageRequestVO pageRequestVO);
List<FaceInfoTxRequestVO> queryAllActivity();
List<FaceInfo> queryAllFaceInfo(@Param("vo") FaceInfoTxRequestVO vo);
}

View File

@ -0,0 +1,12 @@
package com.face.attachment.service;
import com.face.attachment.service.vo.AttachmentVO;
import org.springframework.web.multipart.MultipartFile;
public interface IAttachmentService {
AttachmentVO uploadFile(MultipartFile file) throws Exception;
}

View File

@ -0,0 +1,38 @@
package com.face.attachment.service;
import com.face.attachment.entity.FaceInfo;
import com.face.attachment.vo.*;
import com.face.global.service.IGlobalBaseService;
import com.face.global.vo.PageResponseVO;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* <p>
* 人脸融合基础表 服务类
* </p>
*
* @author admin
* @since 2025-03-15
*/
public interface IFaceInfoService extends IGlobalBaseService<FaceInfo, String> {
FaceInfo updateFaceInfo(FaceInfoModRequestVO modRequestVO) throws Exception;
FaceInfo updateImgFaceInfo(MultipartFile file,String faceId) throws Exception;
FaceInfoDetailResponseVO getFaceInfo(String id) throws Exception;
PageResponseVO<FaceInfoPageResponseVO> pageAll(FaceInfoPageRequestVO pageRequestVO) throws Exception;
List<FaceInfo> addAllFaceInfoByTx(FaceInfoTxRequestVO requestVO);
List<FaceInfoTxRequestVO> queryAllActivity();
List<FaceInfoDetailResponseVO> queryAllFaceInfo(FaceInfoTxRequestVO requestVO);
}

View File

@ -0,0 +1,26 @@
package com.face.attachment.service.impl;
import com.face.attachment.service.IAttachmentService;
import com.face.attachment.service.vo.AttachmentVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@Service
@Slf4j
public class AttachmentServiceImpl implements IAttachmentService {
@Override
public AttachmentVO uploadFile(MultipartFile file) throws Exception {
String fileName = file.getOriginalFilename();
AttachmentVO vo =new AttachmentVO();
return vo;
}
}

View File

@ -0,0 +1,189 @@
package com.face.attachment.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.face.attachment.entity.FaceInfo;
import com.face.attachment.mapper.FaceInfoMapper;
import com.face.attachment.service.IFaceInfoService;
import com.face.attachment.vo.*;
import com.face.global.mapper.GlobalBaseMapper;
import com.face.global.service.impl.GlobalBaseService;
import com.face.global.vo.PageResponseVO;
import com.face.jsonBean.QiuTestRoot;
import com.face.util.DataCopy;
import com.face.util.SystemExceptionUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.facefusion.v20220927.FacefusionClient;
import com.tencentcloudapi.facefusion.v20220927.models.DescribeMaterialListRequest;
import com.tencentcloudapi.facefusion.v20220927.models.DescribeMaterialListResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.util.*;
/**
* <p>
* 人脸融合基础表 服务类
* </p>
*
* @author admin
* @since 2025-03-15
*/
@Service
@Slf4j
public class FaceInfoServiceImpl extends GlobalBaseService<FaceInfo, String> implements IFaceInfoService {
@Autowired
private FaceInfoMapper faceInfoMapper;
public FaceInfoServiceImpl(GlobalBaseMapper<FaceInfo, String> globalBaseMapper, IdentifierGenerator identifierGenerator) {
super(globalBaseMapper, identifierGenerator);
}
@Transactional
@Override
public FaceInfo updateFaceInfo(FaceInfoModRequestVO modRequestVO) throws Exception {
FaceInfo faceInfo = this.getById(modRequestVO.getFaceId());
if (faceInfo == null) {
throw SystemExceptionUtils.buildBusinessException("dataNotExists");
}
DataCopy.copyExistsField(modRequestVO, faceInfo);
this.updateById(faceInfo);
return faceInfo;
}
@Override
public FaceInfo updateImgFaceInfo(MultipartFile file, String faceId) throws Exception {
FaceInfo faceInfo = this.getById(faceId);
byte[] imageBytes = file.getBytes();
String imgBase = Base64.getEncoder().encodeToString(imageBytes);
faceInfo.setFaceBase(imageBytes);
faceInfoMapper.updateById(faceInfo);
return faceInfo;
}
@Override
public FaceInfoDetailResponseVO getFaceInfo(String id) throws Exception {
FaceInfo faceInfo = this.getById(id);
if (faceInfo == null) {
throw SystemExceptionUtils.buildBusinessException("dataNotExists");
}
return DataCopy.deepCopyData(faceInfo, FaceInfoDetailResponseVO.class);
}
@Override
public PageResponseVO<FaceInfoPageResponseVO> pageAll(FaceInfoPageRequestVO pageRequestVO) throws Exception {
PageResponseVO<FaceInfoPageResponseVO> pageResponseVO = new PageResponseVO<>();
List<FaceInfoPageResponseVO> pageData = this.faceInfoMapper.pageAll(pageRequestVO);
pageResponseVO.setData(pageData);
pageResponseVO.setTotalSize(Optional.ofNullable(this.faceInfoMapper.pageCountAll(pageRequestVO)).orElse(0L));
return pageResponseVO;
}
@Override
public List<FaceInfo> addAllFaceInfoByTx(FaceInfoTxRequestVO requestVO) {
List<FaceInfo> list=new ArrayList<>();
try{
// SecretId:AKIDufDXigQwFWgdNuCG7kCRTHsFPN8fy3yg
// SecretKey:kGZheSFrHVWKvHPJ0TikZAXjicJm490d
// 实例化一个认证对象入参需要传入腾讯云账户 SecretId SecretKey此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId SecretKey 泄露并威胁账号下所有资源的安全性以下代码示例仅供参考建议采用更安全的方式来使用密钥请参见https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential("AKIDdGj28B1jKl03tY2YxEJH6jGe8VgvzpbA", "PaXHn6B50pgWEoPr7EXxCIDvTr6AGFA4");
// 实例化一个http选项可选的没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("facefusion.tencentcloudapi.com");
// 实例化一个client选项可选的没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
FacefusionClient client = new FacefusionClient(cred, "ap-chengdu", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
DescribeMaterialListRequest req = new DescribeMaterialListRequest();
//必须传这个参数
//测试API接口 at_1895073745956143104
//二次API接口 at_1895077148660760576
req.setActivityId(requestVO.getActivityId());
// 返回的resp是一个DescribeMaterialListResponse的实例与请求对象对应
DescribeMaterialListResponse resp = client.DescribeMaterialList(req);
// 输出json格式的字符串回包
String qtest= AbstractModel.toJsonString(resp);
System.out.println(qtest);
ObjectMapper mapper = new ObjectMapper();
try {
QiuTestRoot person = mapper.readValue(qtest, QiuTestRoot.class);
person.getMaterialInfos().forEach(r->{
r.getMaterialFaceList().forEach(g->{
FaceInfo faceInfo=new FaceInfo();
faceInfo.setActivityName(requestVO.getActivityName());
faceInfo.setActivityId(requestVO.getActivityId());
faceInfo.setMaterialId(r.getMaterialId());
faceInfo.setMaterialName(r.getMaterialName());
faceInfo.setFaceId(g.getFaceId());
faceInfo.setHeight(g.getFaceInfo().getHeight());
faceInfo.setWidth(g.getFaceInfo().getWidth());
faceInfo.setX(g.getFaceInfo().getX());
faceInfo.setY(g.getFaceInfo().getY());
if(null==this.getById(faceInfo.getFaceId())){
this.insert(faceInfo);
list.add(faceInfo);
}
});
});
//System.out.println(person.getMaterialInfos().get(0).getMaterialFaceList().get(0).getFaceId()); // 输出: John Doe
} catch (Exception e) {
e.printStackTrace();
}
} catch (TencentCloudSDKException e) {
System.out.println(e.toString());
}
return list;
}
@Override
public List<FaceInfoTxRequestVO> queryAllActivity() {
return faceInfoMapper.queryAllActivity();
}
@Override
public List<FaceInfoDetailResponseVO> queryAllFaceInfo(FaceInfoTxRequestVO requestVO) {
List<FaceInfo> list=faceInfoMapper.queryAllFaceInfo(requestVO);
List<FaceInfoDetailResponseVO> faceInfoDetailResponseVOList=DataCopy.deepCopyList(list,FaceInfoDetailResponseVO.class);
faceInfoDetailResponseVOList.forEach(c->{
if(c.getFaceBase() !=null ){
c.setFaceBase64Code(Base64.getEncoder().encodeToString(c.getFaceBase()));
}
});
return faceInfoDetailResponseVOList;
}
}

View File

@ -0,0 +1,19 @@
package com.face.attachment.service.vo;
import lombok.Data;
@Data
public class AttachmentVO {
private String originalFilename;
private long size;
private String downloadUrl;
private String thumbnailUrl;
private String thumbnailFileUrl;
private String downloadFileUrl;
}

View File

@ -0,0 +1,18 @@
package com.face.attachment.service.vo;
import lombok.Builder;
import lombok.Getter;
import java.io.InputStream;
@Builder
@Getter
public class DownloadAttachmentVO {
private String originalFilename;
private long size;
private String contentType;
private InputStream inputStream;
}

View File

@ -0,0 +1,19 @@
package com.face.attachment.service.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class ExcelGenerateCommVO {
@Schema(title = "机构全称")
String orgFullName;
@Schema(title = "机构状态(0-入驻1-关闭)")
String orgStatus;
@Schema(title = "订单名称")
String orderName;
@Schema(title = "电话")
String phone;
}

View File

@ -0,0 +1,48 @@
package com.face.attachment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Data
public class FaceInfoAddRequestVO {
@Schema(title = "人脸模版ID")
@NotBlank(message = "人脸模版ID不能为空")
@Size(min = 1, max = 32, message = "人脸模版ID长度必须在1到32之间")
String faceId;
@Schema(title = "横向坐标x")
Integer x;
@Schema(title = "纵向坐标y")
Integer y;
@Schema(title = "横向坐标")
Integer width;
@Schema(title = "坐标高")
Integer height;
@Schema(title = "素材ID")
String materialId;
@Schema(title = "素材名称")
@Size(max = 255, message = "素材名称长度需要小于等于255")
String materialName;
@Schema(title = "活动ID 一个活动多个素材 一个素材多个人脸模版")
@Size(max = 32, message = "活动ID 一个活动多个素材 一个素材多个人脸模版长度需要小于等于32")
String activityId;
@Schema(title = "图片地址")
@Size(max = 255, message = "图片地址长度需要小于等于255")
String faceUrl;
@Schema(title = "活动名称")
@Size(max = 255, message = "活动名称长度需要小于等于255")
String activityName;
@Schema(title = "图片BASE64编码")
byte[] faceBase;
}

View File

@ -0,0 +1,43 @@
package com.face.attachment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class FaceInfoDetailResponseVO {
@Schema(title = "人脸模版ID")
String faceId;
@Schema(title = "横向坐标x")
Integer x;
@Schema(title = "纵向坐标y")
Integer y;
@Schema(title = "横向坐标")
Integer width;
@Schema(title = "坐标高")
Integer height;
@Schema(title = "素材ID")
String materialId;
@Schema(title = "素材名称")
String materialName;
@Schema(title = "活动ID 一个活动多个素材 一个素材多个人脸模版")
String activityId;
@Schema(title = "图片地址")
String faceUrl;
@Schema(title = "活动名称")
String activityName;
@Schema(title = "图片BASE64编码")
byte[] faceBase;
@Schema(title = "图片BASE64编码")
String faceBase64Code;
}

View File

@ -0,0 +1,48 @@
package com.face.attachment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Data
public class FaceInfoModImgRequestVO {
@Schema(title = "人脸模版ID")
@NotBlank(message = "人脸模版ID不能为空")
@Size(min = 1, max = 32, message = "人脸模版ID长度必须在1到32之间")
String faceId;
@Schema(title = "横向坐标x")
Integer x;
@Schema(title = "纵向坐标y")
Integer y;
@Schema(title = "横向坐标")
Integer width;
@Schema(title = "坐标高")
Integer height;
@Schema(title = "素材ID")
String materialId;
@Schema(title = "素材名称")
@Size(max = 255, message = "素材名称长度需要小于等于255")
String materialName;
@Schema(title = "活动ID 一个活动多个素材 一个素材多个人脸模版")
@Size(max = 32, message = "活动ID 一个活动多个素材 一个素材多个人脸模版长度需要小于等于32")
String activityId;
@Schema(title = "图片地址")
@Size(max = 255, message = "图片地址长度需要小于等于255")
String faceUrl;
@Schema(title = "活动名称")
@Size(max = 255, message = "活动名称长度需要小于等于255")
String activityName;
@Schema(title = "图片BASE64编码")
byte[] faceBase;
}

View File

@ -0,0 +1,48 @@
package com.face.attachment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Data
public class FaceInfoModRequestVO {
@Schema(title = "人脸模版ID")
@NotBlank(message = "人脸模版ID不能为空")
@Size(min = 1, max = 32, message = "人脸模版ID长度必须在1到32之间")
String faceId;
@Schema(title = "横向坐标x")
Integer x;
@Schema(title = "纵向坐标y")
Integer y;
@Schema(title = "横向坐标")
Integer width;
@Schema(title = "坐标高")
Integer height;
@Schema(title = "素材ID")
String materialId;
@Schema(title = "素材名称")
@Size(max = 255, message = "素材名称长度需要小于等于255")
String materialName;
@Schema(title = "活动ID 一个活动多个素材 一个素材多个人脸模版")
@Size(max = 32, message = "活动ID 一个活动多个素材 一个素材多个人脸模版长度需要小于等于32")
String activityId;
@Schema(title = "图片地址")
@Size(max = 255, message = "图片地址长度需要小于等于255")
String faceUrl;
@Schema(title = "活动名称")
@Size(max = 255, message = "活动名称长度需要小于等于255")
String activityName;
@Schema(title = "图片BASE64编码")
byte[] faceBase;
}

View File

@ -0,0 +1,41 @@
package com.face.attachment.vo;
import com.face.global.vo.PageRequestVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class FaceInfoPageRequestVO extends PageRequestVO {
@Schema(title = "人脸模版ID")
String faceId;
@Schema(title = "横向坐标x")
Integer x;
@Schema(title = "纵向坐标y")
Integer y;
@Schema(title = "横向坐标")
Integer width;
@Schema(title = "坐标高")
Integer height;
@Schema(title = "素材ID")
String materialId;
@Schema(title = "素材名称")
String materialName;
@Schema(title = "活动ID 一个活动多个素材 一个素材多个人脸模版")
String activityId;
@Schema(title = "图片地址")
String faceUrl;
@Schema(title = "活动名称")
String activityName;
@Schema(title = "图片BASE64编码")
byte[] faceBase;
}

View File

@ -0,0 +1,40 @@
package com.face.attachment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class FaceInfoPageResponseVO {
@Schema(title = "人脸模版ID")
String faceId;
@Schema(title = "横向坐标x")
Integer x;
@Schema(title = "纵向坐标y")
Integer y;
@Schema(title = "横向坐标")
Integer width;
@Schema(title = "坐标高")
Integer height;
@Schema(title = "素材ID")
String materialId;
@Schema(title = "素材名称")
String materialName;
@Schema(title = "活动ID 一个活动多个素材 一个素材多个人脸模版")
String activityId;
@Schema(title = "图片地址")
String faceUrl;
@Schema(title = "活动名称")
String activityName;
@Schema(title = "图片BASE64编码")
byte[] faceBase;
}

View File

@ -0,0 +1,17 @@
package com.face.attachment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Data
public class FaceInfoTxRequestVO {
@Schema(title = "活动ID")
String activityId;
@Schema(title = "活动名称")
String activityName;
}

View File

@ -0,0 +1,25 @@
package com.face.global;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class GlobalThreadPool {
public static final ThreadPoolExecutor SMALL_THREAD_POOL_ABORT =
new ThreadPoolExecutor(5, 10,
60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(200),
new ThreadPoolExecutor.AbortPolicy());
public static final ThreadPoolExecutor IO_THREAD_POOL_CALL_RUN =
new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
Runtime.getRuntime().availableProcessors() * 2,
60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(200),
new ThreadPoolExecutor.CallerRunsPolicy());
public static final ThreadPoolExecutor IO_THREAD_POOL_ABORT =
new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
Runtime.getRuntime().availableProcessors() * 2,
60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(200),
new ThreadPoolExecutor.AbortPolicy());
}

View File

@ -0,0 +1,44 @@
package com.face.global.config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
@EnableConfigurationProperties(HttpClientConfig.ProxyConfigProperties.class)
public class HttpClientConfig {
@Autowired
private ProxyConfigProperties properties;
@Bean
public RestTemplate proxyRestTemplate() {
return new RestTemplate(
new BufferingClientHttpRequestFactory(new HttpComponentsClientHttpRequestFactory(
HttpClientFactory.getHttpClient(properties.getProxy(),
properties.getClient()))));
}
@Bean
public RestTemplate noProxyRestTemplate() {
return new RestTemplate(
new BufferingClientHttpRequestFactory(new HttpComponentsClientHttpRequestFactory(
HttpClientFactory.getHttpClient(null,
properties.getClient()))));
}
@ConfigurationProperties(value = "app.http.default")
@Data
public static class ProxyConfigProperties {
private ProxyProperties proxy;
private HttpClientProperties client;
}
}

View File

@ -0,0 +1,109 @@
package com.face.global.config;
import com.face.global.consts.GlobalConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.hc.client5.http.config.ConnectionConfig;
import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.hc.core5.util.Timeout;
import org.slf4j.MDC;
import java.io.IOException;
import java.time.Duration;
import java.util.Optional;
import java.util.UUID;
@Slf4j
public class HttpClientFactory {
private static final String REQUEST_START_TIME_KEY = "requestStartTime";
private static final String REQUEST_START_URI_KEY = "requestStartUri";
private static final String REQUEST_START_MARK_KEY = "requestStartMark";
public static CloseableHttpClient getHttpClient(ProxyProperties proxyProperties,
HttpClientProperties httpClientProperties) {
PoolingHttpClientConnectionManager clientConnectionManager = buildConnectionManager(httpClientProperties);
return HttpClients.custom().setProxy(getProxy(proxyProperties))
.setConnectionManager(clientConnectionManager)
.addRequestInterceptorLast((request, entity, context) -> {
String traceId = MDC.get(GlobalConstant.TRACE_ID_KEY);
if (StringUtils.isBlank(traceId)) {
traceId = UUID.randomUUID().toString().replaceAll("-", "");
}
request.setHeader(GlobalConstant.TRACE_ID_KEY, traceId);
long timestamp = System.currentTimeMillis();
String mark = UUID.randomUUID().toString().replace("-", "");
context.setAttribute(REQUEST_START_TIME_KEY, timestamp);
context.setAttribute(REQUEST_START_TIME_KEY, timestamp);
context.setAttribute(REQUEST_START_MARK_KEY, mark);
context.setAttribute(REQUEST_START_URI_KEY, request.getRequestUri());
log.info("startRequest {} {} {} {}", request.getRequestUri(), request.getHeaders(), timestamp, mark);
})
.addResponseInterceptorFirst((response, entity, context) -> {
Long requestTime = (Long) context.getAttribute(REQUEST_START_TIME_KEY);
Long timeCost = null;
if (requestTime != null && requestTime > 0) {
timeCost = System.currentTimeMillis() - requestTime;
}
log.info("endRequest {} {} {} {} {} {}", context.getAttribute(REQUEST_START_URI_KEY), requestTime,
context.getAttribute(REQUEST_START_MARK_KEY), response.getCode(), response.getHeaders(), timeCost);
})
.setRetryStrategy(new DefaultHttpRequestRetryStrategy() {
@Override
public boolean retryRequest(HttpRequest request, IOException exception, int execCount, HttpContext context) {
log.warn("retryRequestCountForRequest {} {} {} {} {}", request.getRequestUri(),
context.getAttribute(REQUEST_START_TIME_KEY),
context.getAttribute(REQUEST_START_MARK_KEY),
httpClientProperties.getRetryCount(), execCount, exception);
if (httpClientProperties.getRetryCount() < execCount) {
return false;
}
return true;
}
@Override
public boolean retryRequest(HttpResponse response, int execCount, HttpContext context) {
log.warn("retryRequestCountForResponse {} {} {} {} {} {}", context.getAttribute(REQUEST_START_URI_KEY),
context.getAttribute(REQUEST_START_TIME_KEY),
context.getAttribute(REQUEST_START_MARK_KEY),
response.getHeaders(), response.getCode(), execCount);
return false;
}
}).build();
}
private static HttpHost getProxy(ProxyProperties proxyProperties) {
if (proxyProperties == null || StringUtils.isBlank(proxyProperties.getHost())) {
return null;
}
return new HttpHost(proxyProperties.getHost(), proxyProperties.getPort());
}
private static PoolingHttpClientConnectionManager buildConnectionManager(HttpClientProperties httpClientProperties) {
return PoolingHttpClientConnectionManagerBuilder.create()
.setConnectionConfigResolver(route -> ConnectionConfig.custom()
.setConnectTimeout(Timeout.of(Optional.ofNullable(httpClientProperties.getConnectTimeout()).orElse(Duration.ofSeconds(3))))
.setSocketTimeout(Timeout.of(Optional.ofNullable(httpClientProperties.getSocketTimeout()).orElse(Duration.ofSeconds(30))))
.setValidateAfterInactivity(Timeout.of(Optional.ofNullable(httpClientProperties.getValidateAfterInactivity())
.orElse(Duration.ofSeconds(30))))
.setTimeToLive(Timeout.of(Optional.ofNullable(httpClientProperties.getTimeToLive()).orElse(Duration.ofSeconds(300))))
.build())
.setMaxConnTotal(httpClientProperties.getMaxConnTotal())
.setMaxConnPerRoute(httpClientProperties.getMaxConnPerRoute())
.setSSLSocketFactory(new SSLConnectionSocketFactory(SSLContexts.createDefault(), (s, sslSession) -> true))
.build();
}
}

View File

@ -0,0 +1,16 @@
package com.face.global.config;
import lombok.Data;
import java.time.Duration;
@Data
public class HttpClientProperties {
private Duration connectTimeout;
private Duration socketTimeout;
private Duration validateAfterInactivity;
private Duration timeToLive;
private Integer maxConnTotal;
private Integer maxConnPerRoute;
private int retryCount;
}

View File

@ -0,0 +1,19 @@
package com.face.global.config;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.commons.util.InetUtilsProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class IdConfig {
@Bean
public IdentifierGenerator identifierGenerator() {
try (InetUtils inetUtils = new InetUtils(new InetUtilsProperties());){
return new DefaultIdentifierGenerator(inetUtils.findFirstNonLoopbackAddress());
}
}
}

View File

@ -0,0 +1,10 @@
package com.face.global.config;
import lombok.Data;
@Data
public class ProxyProperties {
private String host;
private int port;
private boolean enable;
}

View File

@ -0,0 +1,78 @@
package com.face.global.config;
import com.face.global.consts.GlobalConstant;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnClass(GroupedOpenApi.class)
@ConditionalOnProperty(value = "springdoc.swagger-ui.enabled",
havingValue = "true", matchIfMissing = true)
public class SwaggerConfig {
@Bean
public GroupedOpenApi publicApi() {
return GroupedOpenApi.builder()
.group("public")
.pathsToMatch("/api/customer/**")
.build();
}
@Bean
public GroupedOpenApi mobileManageApi() {
return GroupedOpenApi.builder()
.group("mobileAdmin")
.pathsToMatch("/api/manage/**")
.build();
}
@Bean
public GroupedOpenApi adminApi() {
return GroupedOpenApi.builder()
.group("admin")
.pathsToMatch("/manage/**")
.build();
}
@Bean
public OpenAPI openApi() {
return new OpenAPI()
.addSecurityItem(new SecurityRequirement()
.addList(GlobalConstant.TOKEN_KEY))
.components(new Components()
.addSecuritySchemes(GlobalConstant.TOKEN_KEY, new SecurityScheme()
.scheme("bearer")
.description("使用" + GlobalConstant.TOKEN_START_WITH_KEY + "+返回的token" +
"这里只使用返回的token前端需要安置这种方式做header的key为" + GlobalConstant.TOKEN_KEY)
.bearerFormat("JWT")
.type(SecurityScheme.Type.HTTP))
.addParameters(GlobalConstant.TOKEN_AUTH_TYPE, new Parameter()
.in("header").name(GlobalConstant.TOKEN_AUTH_TYPE)
.required(false).schema(new StringSchema())
.description("用户的授权类型header里面key为" + GlobalConstant.TOKEN_AUTH_TYPE + ",值为登录的时候返回的授权类型"))
.addParameters(GlobalConstant.ORG_KEY, new Parameter()
.in("header").name(GlobalConstant.ORG_KEY)
.required(false).schema(new StringSchema())
.description("切换的机构信息header里面key为" + GlobalConstant.ORG_KEY + "用户选择的机构ID"))
)
// 文档描述信息
.info(new Info()
.title("api")
.description("api document")
.version("1.0")
);
}
}

View File

@ -0,0 +1,25 @@
package com.face.global.config;
import org.springframework.boot.autoconfigure.task.TaskExecutionProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
@EnableConfigurationProperties(TaskExecutionProperties.class)
public class TaskExecutorConfig {
@Primary
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor(TaskExecutionProperties taskExecutionProperties) {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(taskExecutionProperties.getPool().getCoreSize());
threadPoolTaskExecutor.setMaxPoolSize(taskExecutionProperties.getPool().getMaxSize());
threadPoolTaskExecutor.setKeepAliveSeconds((int) taskExecutionProperties.getPool().getKeepAlive().toSeconds());
threadPoolTaskExecutor.setQueueCapacity(taskExecutionProperties.getPool().getQueueCapacity());
threadPoolTaskExecutor.setAllowCoreThreadTimeOut(taskExecutionProperties.getPool().isAllowCoreThreadTimeout());
return threadPoolTaskExecutor;
}
}

View File

@ -0,0 +1,45 @@
package com.face.global.consts;
import java.time.ZoneId;
public class GlobalConstant {
public static final String TOKEN_KEY = "Authorization";
public static final String TRACE_ID_KEY = "x-request-trace-id";
public static final String ALI_TRACE_ID_KEY = "x-ali-request-trace-id";
public static final String ALI_MDC_KEY = "EagleEye-TraceID";
public static final String TIME_COST_KEY = "x-request-time-cost";
public static final String CUSTOMER_API_PATH = "/api/customer/*";
public static final String MANAGE_API_PATH = "/api/manage/*";
public static final String MANAGE_PATH = "/manage/*";
public static final String MANAGE_INTERCEPTOR_API_PATH = "/api/manage/**";
public static final String MANAGE_INTERCEPTOR_PATH = "/manage/**";
public static final String ALL_PATH = "/*";
public static final String TOKEN_START_WITH_KEY = "Bearer ";
public static final String TOKEN_AUTH_TYPE = "Authorization-Type";
public static final String ORG_KEY = "Authorization-Org";
public static final String CACHE_NAME_AND_TIME_SPLIT = "#";
public static final String STAR_SPLIT = "*";
public static final String SYSTEM_OPERATE_USER_ID = "system";
public static final ZoneId ZONE_ID = ZoneId.systemDefault();
public static final String GLOBAL_ROLE_ORG_ID = "0";
public static final String ORG_ADMIN_ROLE = "orgAdmin";
}

View File

@ -0,0 +1,5 @@
package com.face.global.controller;
public class ApiBaseController extends BaseController {
}

View File

@ -0,0 +1,4 @@
package com.face.global.controller;
public class BaseController {
}

View File

@ -0,0 +1,4 @@
package com.face.global.controller;
public class ManageBaseController extends BaseController {
}

View File

@ -0,0 +1,60 @@
package com.face.global.entity;
import com.face.global.enums.DeleteType;
import lombok.Data;
import java.util.Date;
@Data
public class BaseEntity {
private Date createDate;
private String createUser;
private String createUserType;
private String modifyUser;
private Date modifyDate;
private String modifyUserType;
private String isDelete;
public boolean checkDelete() {
return DeleteType.DELETE.getCode().equals(isDelete);
}
public void recoverForModify(BaseEntity dbBaseEntity) {
this.setCreateUser(dbBaseEntity.getCreateUser());
this.setCreateDate(dbBaseEntity.getCreateDate());
this.setCreateUserType(dbBaseEntity.getCreateUserType());
this.setIsDelete(dbBaseEntity.getIsDelete());
}
public void init(String user, String userType) {
this.initCreate(user,userType);
this.initModify(user,userType);
this.initDelete();
}
public void initCreate(String createUser, String createUserType) {
this.setCreateDate(new Date());
this.setCreateUser(createUser);
this.setCreateUserType(createUserType);
}
public void initModify(String modifyUser, String modifyUserType) {
this.setModifyDate(new Date());
this.setModifyUser(modifyUser);
this.setModifyUserType(modifyUserType);
}
public void initDelete() {
this.setIsDelete(DeleteType.NO_DELETE.getCode());
}
}

View File

@ -0,0 +1,22 @@
package com.face.global.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public enum CommonCode {
SUCCESS("200"),
NOT_VALID_TOKEN("401"),
NO_TOKEN("402"),
TOKEN_PRE_FORMATTER_ERROR("405"),
TOKEN_AUTH_TYPE_ERROR("406"),
USER_STATUS_ERROR("407"),
USER_TOKEN_ANALYSIS_ERROR("408"),
ORG_INFO_NOT_EXISTS("101"),
ORG_CHECK_ERROR("102"),
ORG_NO_PERMIT("103"),
NO_PERMIT("403"),
ERROR("500");
@Getter
private String code;
}

View File

@ -0,0 +1,12 @@
package com.face.global.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public enum DeleteType {
DELETE("1"), NO_DELETE("0");
@Getter
private String code;
}

View File

@ -0,0 +1,12 @@
package com.face.global.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public enum EnableType {
DISABLE("0"), ENABLE("1");
@Getter
private String code;
}

View File

@ -0,0 +1,12 @@
package com.face.global.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public enum OperateType {
ADD("1"), UPDATE("2"), DELETE("3"), RECOVER("4"), RECOVER_INSERT("5"),
REF_TRIGGER_ADD("6"), REF_TRIGGER_UPDATE("7"), REF_TRIGGER_DELETE("8");
@Getter
private String operateType;
}

View File

@ -0,0 +1,22 @@
package com.face.global.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
@AllArgsConstructor
public enum TransDirectEnum {
INCOME("1","收入"), OUTLAY("2","支出");
@Getter
private String key;
@Getter
private String desc;
public static TransDirectEnum getByCode(String code) {
return Arrays.stream(TransDirectEnum.values()).filter(e -> e.getKey().equals(code)).findFirst().orElse(null);
}
}

View File

@ -0,0 +1,5 @@
package com.face.global.enums;
public enum UserEventEnum {
ADD, UPDATE, DELETE, LOCK, UNLOCK, RECOVER, ADD_USER_ORG, UPDATE_USER_ORG, ADD_TEACHER;
}

View File

@ -0,0 +1,21 @@
package com.face.global.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
@AllArgsConstructor
public enum UserStatusEnum {
NORMAL("1"), LOCK("2");
@Getter
private String code;
public static UserStatusEnum codeOf(String code) {
return Arrays.stream(UserStatusEnum.values()).filter(value ->
StringUtils.equals(code, value.name())
|| StringUtils.equals(code, value.getCode())).findAny().orElse(null);
}
}

View File

@ -0,0 +1,21 @@
package com.face.global.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
@AllArgsConstructor
public enum UserTerminalEnum {
TEACHER("teacher","教师端");
@Getter
private String key;
@Getter
private String desc;
public static UserTerminalEnum getByCode(String status) {
return Arrays.stream(UserTerminalEnum.values()).filter(e -> e.getKey().equals(status)).findFirst().orElse(null);
}
}

View File

@ -0,0 +1,23 @@
package com.face.global.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
@AllArgsConstructor
public enum UserTypeEnum {
SYS_USER("sysUser"), CUSTOMER("customer");
@Getter
private String code;
public static UserTypeEnum codeOf(String codeArg) {
return Arrays.stream(UserTypeEnum.values()).filter(value ->
StringUtils.equals(codeArg, value.name())
|| StringUtils.equals(codeArg, value.getCode()))
.findAny().orElse(null);
}
}

View File

@ -0,0 +1,25 @@
package com.face.global.enums;
import com.face.global.validator.EnumValidator;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public enum ValidCodeModuleEnum implements EnumValidator {
CUSTOMER_LOGIN("customerLogin");
@Getter
private String code;
@Override
public String toString() {
return this.code;
}
@Override
public Object getValue() {
return this.code;
}
}

View File

@ -0,0 +1,25 @@
package com.face.global.enums;
import com.face.global.validator.EnumValidator;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public enum ViewFlagFlagEnum implements EnumValidator {
NOT_SHOW_MENU("0"), SHOW_MENU("1");
@Getter
private String code;
@Override
public String toString() {
return this.code;
}
@Override
public Object getValue() {
return code;
}
}

View File

@ -0,0 +1,12 @@
package com.face.global.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public enum WXResponseCode {
USER_REFUSE(43101);
@Getter
private int code;
}

View File

@ -0,0 +1,34 @@
package com.face.global.enums;
import lombok.Getter;
public enum WeekDayEnum {
MONDAY("1", "星期一"),
TUESDAY("2", "星期二"),
WEDNESDAY("3", "星期三"),
THURSDAY("4", "星期四"),
FRIDAY("5", "星期五"),
SATURDAY("6", "星期六"),
SUNDAY("0", "星期日");
@Getter
private String value;
@Getter
private String chineseName;
WeekDayEnum(String value, String chineseName) {
this.chineseName = chineseName;
this.value = value;
}
public static WeekDayEnum getWeekDayEnumByValue(String value) {
for (WeekDayEnum weekDayEnum : WeekDayEnum.values()) {
if (weekDayEnum.getValue().equals(value)) {
return weekDayEnum;
}
}
return null;
}
}

View File

@ -0,0 +1,35 @@
package com.face.global.enums;
import com.face.global.validator.EnumValidator;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public enum WxConfigTypeEnum implements EnumValidator {
CUSTOMER("customer"), SYS_USER("sysUser");
@Getter
private String code;
public static WxConfigTypeEnum getByCode(String type) {
WxConfigTypeEnum[] values = WxConfigTypeEnum.values();
for (WxConfigTypeEnum value : values) {
if (value.getCode().equals(type)) {
return value;
}
}
return null;
}
@Override
public String toString() {
return this.code;
}
@Override
public Object getValue() {
return this.code;
}
}

View File

@ -0,0 +1,17 @@
package com.face.global.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public enum WxResultEnum {
SUCCESS(0, "SUCCESS","OK"), COMMON_ERROR(-1, "ERROR", "error");
@Getter
private int code;
@Getter
private String name;
@Getter
private String msg;
}

View File

@ -0,0 +1,35 @@
package com.face.global.enums;
import com.face.global.validator.EnumValidator;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public enum WxTypeEnum implements EnumValidator {
OFFICIAL("1"), MINI("2");
@Getter
private String code;
public static WxTypeEnum getByCode(String type) {
WxTypeEnum[] values = WxTypeEnum.values();
for (WxTypeEnum value : values) {
if (value.getCode().equals(type)) {
return value;
}
}
return null;
}
@Override
public String toString() {
return this.code;
}
@Override
public Object getValue() {
return this.code;
}
}

View File

@ -0,0 +1,23 @@
package com.face.global.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
@AllArgsConstructor
public enum YesOrNoEnum {
YES("1"), NO("0");
@Getter
private String code;
public static YesOrNoEnum codeOf(String codeArg) {
return Arrays.stream(YesOrNoEnum.values()).filter(value ->
StringUtils.equals(codeArg, value.name())
|| StringUtils.equals(codeArg, value.getCode()))
.findAny().orElse(null);
}
}

View File

@ -0,0 +1,38 @@
package com.face.global.exception;
public class BusinessException extends RuntimeException {
private String code;
private String message;
private BusinessException realBusinessException;
public BusinessException(String code, String message) {
this.code = code;
this.message = message;
}
public BusinessException(String code, String message, Throwable cause) {
super(cause);
this.code = code;
this.message = message;
if (cause instanceof BusinessException && this.realBusinessException == null) {
this.realBusinessException = this;
}
}
public String getCode() {
if (this.realBusinessException != null && this != this.realBusinessException) {
return this.realBusinessException.getCode();
}
return code;
}
@Override
public String getMessage() {
if (this.realBusinessException != null && this != this.realBusinessException) {
return this.realBusinessException.getMessage();
}
return message;
}
}

View File

@ -0,0 +1,233 @@
package com.face.global.exception;
import com.face.global.enums.CommonCode;
import com.face.global.language.LanguageStore;
import com.face.util.ApiResultBuilder;
import com.face.util.HttpUtils;
import com.face.util.MessageUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.context.MessageSource;
import org.springframework.http.*;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.method.MethodValidationException;
import org.springframework.web.ErrorResponseException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.method.annotation.HandlerMethodValidationException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import org.springframework.web.servlet.resource.NoResourceFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@RestControllerAdvice
@Slf4j
public class GlobalErrorController extends ResponseEntityExceptionHandler {
public GlobalErrorController(MessageSource messageSource) {
this.setMessageSource(messageSource);
}
@ExceptionHandler(value = BusinessException.class)
public ResponseEntity<Object> dealBusinessException(HttpServletRequest request, BusinessException ex) {
this.printHttpLog(request, null, null, ex);
return this.buildErrorResponseEntity(ex.getCode(), ex.getMessage());
}
@ExceptionHandler(value = Throwable.class)
public ResponseEntity<Object> dealException(HttpServletRequest request, Throwable ex) {
this.printHttpLog(request, null, null, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), null);
}
private ResponseEntity<Object> buildErrorResponseEntity(String code, String message) {
String errorMessage = null;
if (StringUtils.isBlank(message)) {
errorMessage = MessageUtils.getMessage(code, null, LanguageStore.getLocale());
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return new ResponseEntity<>(ApiResultBuilder.getRawBuilder().baseInfo(code,
Optional.ofNullable(errorMessage)
.orElse(message)).build(), headers, HttpStatus.OK);
}
@Override
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpHeaders headers,
HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable(HttpMediaTypeNotAcceptableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleMissingPathVariable(MissingPathVariableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleMissingServletRequestPart(MissingServletRequestPartException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleServletRequestBindingException(ServletRequestBindingException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
List<String> datas = new ArrayList<>();
if (ex.getDetailMessageArguments() == null || ex.getDetailMessageArguments().length <= 0) {
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
for (Object obj : ex.getDetailMessageArguments()) {
if (obj instanceof String && StringUtils.isNotBlank(obj.toString())) {
if (obj.toString().contains(":")) {
datas.add(obj.toString().split(":")[1]);
} else {
datas.add(obj.toString());
}
}
}
if (CollectionUtils.isEmpty(datas)) {
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), StringUtils.join(datas, ","));
}
@Override
protected ResponseEntity<Object> handleHandlerMethodValidationException(HandlerMethodValidationException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleNoResourceFoundException(NoResourceFoundException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleAsyncRequestTimeoutException(AsyncRequestTimeoutException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleErrorResponseException(ErrorResponseException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleConversionNotSupported(ConversionNotSupportedException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleTypeMismatch(TypeMismatchException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleHttpMessageNotWritable(HttpMessageNotWritableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleMethodValidationException(MethodValidationException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
this.printLog(request, headers, status, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatusCode statusCode, WebRequest request) {
this.printLog(request, headers, statusCode, ex);
return this.buildErrorResponseEntity(CommonCode.ERROR.getCode(), ex.getMessage());
}
private void printLog(WebRequest request, HttpHeaders headers, HttpStatusCode status, Throwable ex) {
if (request instanceof HttpServletRequest) {
this.printHttpLog(((HttpServletRequest) request), headers, status, ex);
} else {
log.error("requestUrlFail", ex);
}
}
private void printHttpLog(HttpServletRequest request, HttpHeaders headers, HttpStatusCode status, Throwable ex) {
log.error("requestUrlFail {} {} {} {}", request.getRequestURI(), request.getParameterMap(), HttpUtils.getHeadersInfo(request, headers),
this.getStatusInfo(status), ex);
}
private Integer getStatusInfo(HttpStatusCode status) {
if (status != null) {
return status.value();
}
return null;
}
}

View File

@ -0,0 +1,24 @@
package com.face.global.language;
import java.util.Locale;
import java.util.Optional;
public class LanguageStore {
private static final Locale CN = new Locale( "zh" , "CN" );
private final static ThreadLocal<Locale> THREAD_LOCAL = new ThreadLocal<>();
public static Locale getLocale() {
return Optional.ofNullable(THREAD_LOCAL.get()).orElse(CN);
}
public static void setLocale(Locale locale) {
THREAD_LOCAL.set(locale);
}
public static void clearLocale() {
THREAD_LOCAL.remove();
}
}

View File

@ -0,0 +1,16 @@
package com.face.global.log;
public class LogStore {
private static final ThreadLocal<String> LOG_MDC_ID_STORE = new InheritableThreadLocal<>();
public static void setLogMdcId(String mdcId) {
LOG_MDC_ID_STORE.set(mdcId);
}
public static String getLogMdcId() {
return LOG_MDC_ID_STORE.get();
}
public static void clearLogMdcId() {
LOG_MDC_ID_STORE.remove();
}
}

View File

@ -0,0 +1,13 @@
package com.face.global.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
public interface GlobalBaseMapper<T, ID extends Serializable> extends BaseMapper<T> {
int insertH(Map<Object, Object> data);
int insertBatchSomeColumn(List<T> entityList);
}

View File

@ -0,0 +1,21 @@
package com.face.global.mybatisplus;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import com.face.global.mybatisplus.method.InsertH;
import java.util.List;
public class MybatisPlusSqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
methodList.add(new InsertH());
methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
return methodList;
}
}

View File

@ -0,0 +1,11 @@
package com.face.global.mybatisplus.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface HistoryColumn {
}

View File

@ -0,0 +1,25 @@
package com.face.global.mybatisplus.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.face.global.mybatisplus.MybatisPlusSqlInjector;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
/**
* <a>https://baomidou.com/pages/49cc81/#insertbatchsomecolumn</a>
*/
@Bean
public MybatisPlusSqlInjector sqlInjector() {
return new MybatisPlusSqlInjector();
}
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2011-2022, baomidou (jobob@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.face.global.mybatisplus.method;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.google.common.base.CaseFormat;
import com.face.global.entity.BaseEntity;
import com.face.global.mybatisplus.annotation.HistoryColumn;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 插入一条历史数据
*/
public class InsertH extends AbstractMethod {
private final static String SQL = "<script>\nINSERT INTO %s_h (%s) VALUES (%s)\n</script>";
public InsertH() {
super("insertH");
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
Field[] baseFields = FieldUtils.getAllFields(BaseEntity.class);
List<String> baseColumns = new ArrayList<>();
List<String> baseFieldNames = new ArrayList<>();
for (Field field : baseFields) {
baseColumns.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName()));
baseFieldNames.add(HASH_LEFT_BRACE.concat(field.getName()).concat(RIGHT_BRACE));
}
List<String> extraColumns = new ArrayList<>();
List<Field> extraFields = Arrays.stream(FieldUtils.getAllFields(modelClass))
.filter(field -> field.getAnnotation(HistoryColumn.class) != null).toList();
List<String> extraFieldNames = new ArrayList<>();
for (Field field : extraFields) {
extraColumns.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName()));
extraFieldNames.add(HASH_LEFT_BRACE.concat(field.getName()).concat(RIGHT_BRACE));
}
List<String> defaultColumns = new ArrayList<>();
defaultColumns.add("id");
defaultColumns.add("main_id");
defaultColumns.add("content");
defaultColumns.add("seqno");
defaultColumns.add("operate_type");
List<String> defaultFields = new ArrayList<>();
defaultFields.add(HASH_LEFT_BRACE.concat("id").concat(RIGHT_BRACE));
defaultFields.add(HASH_LEFT_BRACE.concat("mainId").concat(RIGHT_BRACE));
defaultFields.add(HASH_LEFT_BRACE.concat("content").concat(RIGHT_BRACE));
defaultFields.add(HASH_LEFT_BRACE.concat("seqno").concat(RIGHT_BRACE));
defaultFields.add(HASH_LEFT_BRACE.concat("operateType").concat(RIGHT_BRACE));
List<String> allColumns = new ArrayList<>();
allColumns.addAll(defaultColumns);
allColumns.addAll(baseColumns);
allColumns.addAll(extraColumns);
String defaultInsertColumn = StringUtils.join(allColumns, ",");
List<String> allFields = new ArrayList<>();
allFields.addAll(defaultFields);
allFields.addAll(baseFieldNames);
allFields.addAll(extraFieldNames);
String defaultValuesColumn = StringUtils.join(allFields, ",");
String sql = String.format(SQL, tableInfo.getTableName(), defaultInsertColumn, defaultValuesColumn);
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);
return this.addInsertMappedStatement(mapperClass, modelClass, methodName, sqlSource,
NoKeyGenerator.INSTANCE, null, null);
}
}

View File

@ -0,0 +1,80 @@
package com.face.global.service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.face.global.vo.GlobalUser;
import com.face.global.vo.Operate;
import org.apache.ibatis.annotations.Param;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
public interface IGlobalBaseService<T, ID extends Serializable> extends IService<T> {
int insert(T entity);
int deleteById(ID id);
int deleteById(T entity);
int deleteByMap(Map columnMap);
int delete(Wrapper<T> queryWrapper);
int updateByIdForInt(T entity);
int updateForInt(T entity, Wrapper<T> updateWrapper);
int updateForInt(Wrapper<T> updateWrapper);
T selectById(ID id);
T selectOne(Wrapper<T> queryWrapper);
T selectOne(Wrapper<T> queryWrapper, boolean throwEx);
boolean exists(Wrapper<T> queryWrapper);
List<T> selectByMap(Map columnMap);
Long selectCount(Wrapper<T> queryWrapper);
List<T> selectList(Wrapper<T> queryWrapper);
List<T> selectBatchIds(Collection<ID> idList);
int deleteBatchIds(Collection<ID> idList);
String generatorStringId();
long generatorLongId();
/**
* 根据entity条件复制
* @return
*/
int insertH(ID id, Function<ID, Map<String, Object>> content, @Param("operate") Operate operate);
Operate getUpdateOperate(boolean generateSeq);
Operate getInsertOperate(boolean generateSeq);
Operate getDeleteOperate(boolean generateSeq);
boolean updateSomeColumnById(List dataEntity);
GlobalUser getOperateUser();
}

View File

@ -0,0 +1,475 @@
package com.face.global.service.impl;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.override.MybatisMapperProxy;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.baomidou.mybatisplus.core.toolkit.reflect.GenericTypeUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.google.common.base.CaseFormat;
import com.face.global.consts.GlobalConstant;
import com.face.global.enums.DeleteType;
import com.face.global.enums.UserTypeEnum;
import com.face.global.mapper.GlobalBaseMapper;
import com.face.global.service.IGlobalBaseService;
import com.face.global.user.UserStore;
import com.face.global.vo.GlobalUser;
import com.face.global.vo.Operate;
import com.face.util.JsonUtils;
import com.face.util.SystemExceptionUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import static com.baomidou.mybatisplus.core.toolkit.StringPool.*;
public class GlobalBaseService<T, ID extends Serializable> implements IGlobalBaseService<T, ID> {
private GlobalBaseMapper<T, ID> globalBaseMapper;
private IdentifierGenerator identifierGenerator;
private volatile SqlSessionFactory sqlSessionFactory;
protected final Log log = LogFactory.getLog(getClass());
private Class<GlobalBaseMapper<T, ID>> mapperClass;
public GlobalBaseService(GlobalBaseMapper<T, ID> globalBaseMapper, IdentifierGenerator identifierGenerator) {
this.globalBaseMapper = globalBaseMapper;
this.identifierGenerator = identifierGenerator;
this.mapperClass = (Class<GlobalBaseMapper<T, ID>>) globalBaseMapper.getClass().getInterfaces()[0];
}
@Transactional
@Override
public int insert(T entity) {
return this.globalBaseMapper.insert(entity);
}
@Transactional
@Override
public int deleteById(ID id) {
return this.globalBaseMapper.deleteById(id);
}
@Transactional
@Override
public int deleteById(T entity) {
return this.globalBaseMapper.deleteById(entity);
}
@Transactional
@Override
public int deleteByMap(Map columnMap) {
return this.globalBaseMapper.deleteByMap(columnMap);
}
@Transactional
@Override
public int delete(Wrapper<T> queryWrapper) {
return this.globalBaseMapper.delete(queryWrapper);
}
@Transactional
@Override
public int updateByIdForInt(T entity) {
return this.globalBaseMapper.updateById(entity);
}
@Transactional
@Override
public int updateForInt(T entity, Wrapper<T> updateWrapper) {
return this.globalBaseMapper.update(entity, updateWrapper);
}
@Transactional
@Override
public int updateForInt(Wrapper<T> updateWrapper) {
return this.globalBaseMapper.update(updateWrapper);
}
@Override
public T selectById(ID id) {
return this.globalBaseMapper.selectById(id);
}
@Override
public T selectOne(Wrapper<T> queryWrapper) {
return this.globalBaseMapper.selectOne(queryWrapper);
}
@Override
public T selectOne(Wrapper<T> queryWrapper, boolean throwEx) {
return this.globalBaseMapper.selectOne(queryWrapper, throwEx);
}
@Override
public boolean exists(Wrapper<T> queryWrapper) {
return this.globalBaseMapper.exists(queryWrapper);
}
@Override
public BaseMapper<T> getBaseMapper() {
return this.globalBaseMapper;
}
@Override
public List<T> selectByMap(Map columnMap) {
return this.globalBaseMapper.selectByMap(columnMap);
}
@Override
public Long selectCount(Wrapper<T> queryWrapper) {
return this.globalBaseMapper.selectCount(queryWrapper);
}
@Override
public List<T> selectList(Wrapper<T> queryWrapper) {
return this.globalBaseMapper.selectList(queryWrapper);
}
@Override
public List<T> selectBatchIds(Collection<ID> idList) {
return this.globalBaseMapper.selectBatchIds(idList);
}
@Transactional
@Override
public int deleteBatchIds(Collection<ID> idList) {
return this.globalBaseMapper.deleteBatchIds(idList);
}
@Override
public String generatorStringId() {
return String.valueOf(identifierGenerator.nextId(null));
}
@Override
public long generatorLongId() {
return identifierGenerator.nextId(null).longValue();
}
@Transactional
@Override
public int insertH(ID id, Function<ID, Map<String, Object>> content, Operate operate) {
Map<Object, Object> data = new HashMap<>();
data.putAll(BeanMap.create(operate));
if (operate.getExtendsData() != null) {
data.putAll(operate.getExtendsData());
}
data.put("createDate", operate.getModifyDate());
data.put("isDelete", DeleteType.NO_DELETE.getCode());
data.put("createUser", operate.getModifyUser());
data.put("createUserType", operate.getModifyUserType());
if (operate.isGenerateId()) {
operate.setId(this.generatorStringId());
}
data.put("id", operate.getId());
data.put("mainId", id);
Object contentObject = content.apply(id);
if (contentObject != null) {
data.put("content", JsonUtils.toJsonString(contentObject));
}
return this.globalBaseMapper.insertH(data);
}
@Override
public Operate getUpdateOperate(boolean generateSeq) {
Operate operate = Operate.inst()
.modifyUser(this.getOperateUser().getUserId())
.modifyUserType(this.getOperateUser().getUserType()).update();
if (generateSeq) {
operate.setSeqno(this.generatorLongId());
}
return operate;
}
@Override
public Operate getInsertOperate(boolean generateSeq) {
Operate operate = Operate.inst()
.modifyUser(this.getOperateUser().getUserId())
.modifyUserType(this.getOperateUser().getUserType()).insert();
if (generateSeq) {
operate.setSeqno(this.generatorLongId());
}
return operate;
}
@Override
public Operate getDeleteOperate(boolean generateSeq) {
Operate operate = Operate.inst()
.modifyUser(this.getOperateUser().getUserId())
.modifyUserType(this.getOperateUser().getUserType())
.delete();
if (generateSeq) {
operate.setSeqno(this.generatorLongId());
}
return operate;
}
@Transactional
@Override
public boolean updateSomeColumnById(List list) {
Class modelClass = GenericTypeUtils.resolveTypeArguments(getClass(), GlobalBaseService.class)[0];
TableName tableNameAnnotation = (TableName) modelClass.getAnnotation(TableName.class);
String tableName = tableNameAnnotation.value();
Field[] baseFields = FieldUtils.getAllFields(modelClass);
List<String> keys = new ArrayList<>();
for (Field field : baseFields) {
if (field.getAnnotation(TableId.class) != null) {
keys.add(field.getName());
}
}
if (CollectionUtils.isEmpty(keys)) {
throw SystemExceptionUtils.buildBusinessException("noKeys");
}
String sqlStatement = GlobalBaseMapper.class.getName() + StringPool.DOT + "updateSomeColumnById";
Field[] updateFields = FieldUtils.getAllFields(list.get(0).getClass());
List<String> allUpdateFields = Arrays.stream(updateFields).filter(field -> {
if (keys.contains(field.getName())) {
return false;
}
TableField tableField = field.getAnnotation(TableField.class);
if (tableField == null) {
return true;
}
return tableField.updateStrategy() != FieldStrategy.NEVER;
}).map(field -> field.getName()).toList();
if (CollectionUtils.isEmpty(allUpdateFields)) {
throw SystemExceptionUtils.buildBusinessException("noUpdateColumn");
}
StringBuffer updateSql = new StringBuffer();
StringBuffer whereSql = new StringBuffer();
List<String> wheres = new ArrayList<>();
List<String> updates = new ArrayList<>();
for (String key : keys) {
wheres.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, key).concat(EQUALS)
.concat(HASH_LEFT_BRACE).concat("entity.").concat(key).concat(RIGHT_BRACE));
}
whereSql.append(String.join(" and ", wheres));
for (String key : allUpdateFields) {
updates.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, key).concat(EQUALS)
.concat(HASH_LEFT_BRACE).concat("entity.").concat(key).concat(RIGHT_BRACE));
}
updateSql.append(String.join(" and ", updates));
return SqlHelper.executeBatch(getSqlSessionFactory(), this.log, list, DEFAULT_BATCH_SIZE,
(sqlSession, data) -> {
sqlSession.update(sqlStatement, Map.of("tableName", tableName, "updateSql", updateSql.toString(), "whereSql", whereSql.toString(), "entity", data));
});
}
@Override
public GlobalUser getOperateUser() {
GlobalUser globalUser = new GlobalUser();
if (UserStore.getCurrentUser() == null) {
globalUser.setUserName(GlobalConstant.SYSTEM_OPERATE_USER_ID);
globalUser.setUserType(UserTypeEnum.SYS_USER.getCode());
globalUser.setUserId(GlobalConstant.SYSTEM_OPERATE_USER_ID);
return globalUser;
}
return UserStore.getCurrentUser();
}
protected GlobalUser getOperateUser(String userId, UserTypeEnum userTypeEnum) {
GlobalUser globalUser = new GlobalUser();
if (UserStore.getCurrentUser() == null) {
globalUser.setUserType(userTypeEnum.getCode());
globalUser.setUserId(userId);
return globalUser;
}
return UserStore.getCurrentUser();
}
protected final Class<?>[] typeArguments = GenericTypeUtils.resolveTypeArguments(getClass(), ServiceImpl.class);
@Override
public Class<T> getEntityClass() {
return (Class<T>) this.typeArguments[1];
}
protected SqlSessionFactory getSqlSessionFactory() {
if (this.sqlSessionFactory == null) {
synchronized (this) {
if (this.sqlSessionFactory == null) {
Object target = this.globalBaseMapper;
// 这个检查目前看着来说基本上可以不用判断Aop是不是存在了.
if (com.baomidou.mybatisplus.extension.toolkit.AopUtils.isLoadSpringAop()) {
while (AopUtils.isAopProxy(target)) {
target = AopProxyUtils.getSingletonTarget(target);
}
}
if (target instanceof MybatisMapperProxy) {
MybatisMapperProxy mybatisMapperProxy = (MybatisMapperProxy) Proxy.getInvocationHandler(target);
SqlSessionTemplate sqlSessionTemplate = (SqlSessionTemplate) mybatisMapperProxy.getSqlSession();
this.sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
} else if (Proxy.getInvocationHandler(target) instanceof MybatisMapperProxy) {
MybatisMapperProxy mybatisMapperProxy = (MybatisMapperProxy) Proxy.getInvocationHandler(target);
SqlSessionTemplate sqlSessionTemplate = (SqlSessionTemplate) mybatisMapperProxy.getSqlSession();
this.sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
} else {
this.sqlSessionFactory = GlobalConfigUtils.currentSessionFactory(this.getEntityClass());
}
}
}
}
return this.sqlSessionFactory;
}
/**
* 批量插入
*
* @param entityList ignore
* @param batchSize ignore
* @return ignore
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean saveBatch(Collection<T> entityList, int batchSize) {
String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE);
return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
}
/**
* 获取mapperStatementId
*
* @param sqlMethod 方法名
* @return 命名id
* @since 3.4.0
*/
protected String getSqlStatement(SqlMethod sqlMethod) {
return SqlHelper.getSqlStatement(mapperClass, sqlMethod);
}
/**
* TableId 注解存在更新记录否插入一条记录
*
* @param entity 实体对象
* @return boolean
*/
@Override
public boolean saveOrUpdate(T entity) {
if (null != entity) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(this.getEntityClass());
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
String keyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
Object idVal = tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty());
return StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal)) ? save(entity) : updateById(entity);
}
return false;
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(this.getEntityClass());
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
String keyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
return SqlHelper.saveOrUpdateBatch(getSqlSessionFactory(), this.mapperClass, log, entityList, batchSize, (sqlSession, entity) -> {
Object idVal = tableInfo.getPropertyValue(entity, keyProperty);
return StringUtils.checkValNull(idVal)
|| CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity));
}, (sqlSession, entity) -> {
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
param.put(Constants.ENTITY, entity);
sqlSession.update(getSqlStatement(SqlMethod.UPDATE_BY_ID), param);
});
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean updateBatchById(Collection<T> entityList, int batchSize) {
String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID);
return executeBatch(entityList, batchSize, (sqlSession, entity) -> {
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
param.put(Constants.ENTITY, entity);
sqlSession.update(sqlStatement, param);
});
}
@Override
public T getOne(Wrapper<T> queryWrapper, boolean throwEx) {
return this.globalBaseMapper.selectOne(queryWrapper, throwEx);
}
@Override
public Optional<T> getOneOpt(Wrapper<T> queryWrapper, boolean throwEx) {
return Optional.ofNullable(this.globalBaseMapper.selectOne(queryWrapper, throwEx));
}
@Override
public Map<String, Object> getMap(Wrapper<T> queryWrapper) {
return SqlHelper.getObject(log, this.globalBaseMapper.selectMaps(queryWrapper));
}
@Override
public <V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
return SqlHelper.getObject(log, listObjs(queryWrapper, mapper));
}
/**
* 执行批量操作
*
* @param list 数据集合
* @param batchSize 批量大小
* @param consumer 执行方法
* @param <E> 泛型
* @return 操作结果
* @since 3.3.1
*/
protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
return SqlHelper.executeBatch(getSqlSessionFactory(), this.log, list, batchSize, consumer);
}
@Override
public boolean removeById(Serializable id) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(getEntityClass());
if (tableInfo.isWithLogicDelete() && tableInfo.isWithUpdateFill()) {
return removeById(id, true);
}
return SqlHelper.retBool(getBaseMapper().deleteById(id));
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean removeByIds(Collection<?> list) {
if (CollectionUtils.isEmpty(list)) {
return false;
}
TableInfo tableInfo = TableInfoHelper.getTableInfo(getEntityClass());
if (tableInfo.isWithLogicDelete() && tableInfo.isWithUpdateFill()) {
return removeBatchByIds(list, true);
}
return SqlHelper.retBool(getBaseMapper().deleteBatchIds(list));
}
}

View File

@ -0,0 +1,67 @@
package com.face.global.user;
import com.face.global.vo.GlobalOrgInfo;
import com.face.global.vo.GlobalUser;
public class UserStore {
private static final ThreadLocal<GlobalUser> USER_THREAD_LOCAL_STORE = new InheritableThreadLocal<>();
private static final ThreadLocal<String> USER_TOKEN = new InheritableThreadLocal<>();
private static final ThreadLocal<GlobalOrgInfo> ORG_INFO = new InheritableThreadLocal<>();
public static void setUser(GlobalUser globalUser) {
USER_THREAD_LOCAL_STORE.set(globalUser);
}
public static void setUserToken(String token) {
USER_TOKEN.set(token);
}
public static GlobalUser getCurrentUser() {
return USER_THREAD_LOCAL_STORE.get();
}
public static String getUserToken() {
return USER_TOKEN.get();
}
public static void setOrgInfo(GlobalOrgInfo orgInfo) {
ORG_INFO.set(orgInfo);
}
public static GlobalOrgInfo getOrgInfo() {
return ORG_INFO.get();
}
public static String getCurrentOrgId() {
if (ORG_INFO.get() != null) {
return ORG_INFO.get().getOrgId();
}
return null;
}
public static void clearUserInfo () {
USER_THREAD_LOCAL_STORE.remove();
USER_TOKEN.remove();
ORG_INFO.remove();
}
public static String getCurrentUserId() {
if (UserStore.getCurrentUser() != null) {
return UserStore.getCurrentUser().getUserId();
}
return null;
}
public static String getToken() {
return UserStore.getUserToken();
}
public static String getCurrentUserType() {
if (UserStore.getCurrentUser() != null) {
return UserStore.getCurrentUser().getUserType();
}
return null;
}
}

View File

@ -0,0 +1,9 @@
package com.face.global.validator;
/**
* 枚举验证接口
*
*/
public interface EnumValidator {
Object getValue();
}

View File

@ -0,0 +1,70 @@
package com.face.global.validator.enums;
import com.face.global.validator.EnumValidator;
import com.face.global.validator.impl.EnumConstraintValidator;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 枚举检查注解
*
*/
@Documented
@Constraint(validatedBy = EnumConstraintValidator.class)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Repeatable(EnumCheck.List.class)
public @interface EnumCheck {
/**
* 提示信息
*
*/
String message() default "{javax.validation.constraints.EnumCheck.message}";
/**
* 分组
*
*/
Class<?>[] groups() default { };
/**
* 扩展对象
*
*/
Class<? extends Payload>[] payload() default { };
/**
* 必须实现EnumValidator接口的枚举类
*
*/
Class<? extends EnumValidator> clazz();
/**
* 调用的方法名称
*/
String method() default "getValue";
/**
* Defines several {@code @In} constraints on the same element.
*
* @see EnumCheck
*/
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@interface List {
/**
* In数组
*/
EnumCheck[] value();
}
}

View File

@ -0,0 +1,28 @@
package com.face.global.validator.enums;
import com.face.global.validator.impl.MaxDoubleConstraintValidator;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Constraint(validatedBy = MaxDoubleConstraintValidator.class)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface MaxDouble {
String message() default "{jakarta.validation.constraints.Max.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
double value();
}

View File

@ -0,0 +1,27 @@
package com.face.global.validator.enums;
import com.face.global.validator.impl.MinDoubleConstraintValidator;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Constraint(validatedBy = MinDoubleConstraintValidator.class)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface MinDouble {
String message() default "{jakarta.validation.constraints.Min.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
double value();
}

View File

@ -0,0 +1,54 @@
package com.face.global.validator.impl;
import com.face.global.validator.enums.EnumCheck;
import com.face.util.SystemExceptionUtils;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Method;
import java.util.Objects;
/**
* 枚举验证器实现
*/
@Slf4j
public class EnumConstraintValidator implements ConstraintValidator<EnumCheck, Object> {
/**
* 注解对象
*/
private EnumCheck annotation;
/**
* 初始化方法
*
* @param constraintAnnotation 注解对象
*/
@Override
public void initialize(EnumCheck constraintAnnotation) {
this.annotation = constraintAnnotation;
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
if (Objects.isNull(value)) {
return true;
}
Object[] enumConstants = annotation.clazz().getEnumConstants();
try {
// 核心代码实现
Method method = annotation.clazz().getMethod(annotation.method());
for (Object enumConstant : enumConstants) {
if (value.equals(method.invoke(enumConstant))) {
return true;
}
}
} catch (Exception e) {
log.error("validEnumFail", e);
throw SystemExceptionUtils.buildBusinessException("validEnumFail");
}
return false;
}
}

View File

@ -0,0 +1,37 @@
package com.face.global.validator.impl;
import com.face.global.validator.enums.MaxDouble;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import lombok.extern.slf4j.Slf4j;
import java.util.Objects;
@Slf4j
public class MaxDoubleConstraintValidator implements ConstraintValidator<MaxDouble, Object> {
/**
* 注解对象
*/
private MaxDouble annotation;
/**
* 初始化方法
*
* @param constraintAnnotation 注解对象
*/
@Override
public void initialize(MaxDouble constraintAnnotation) {
this.annotation = constraintAnnotation;
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
if (Objects.isNull(value)) {
return true;
}
if (!(value instanceof Double)) {
return true;
}
return ((Double) value).compareTo(annotation.value()) <= 0;
}
}

View File

@ -0,0 +1,41 @@
package com.face.global.validator.impl;
import com.face.global.validator.enums.MinDouble;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import lombok.extern.slf4j.Slf4j;
import java.util.Objects;
/**
* double
*/
@Slf4j
public class MinDoubleConstraintValidator implements ConstraintValidator<MinDouble, Object> {
/**
* 注解对象
*/
private MinDouble annotation;
/**
* 初始化方法
*
* @param constraintAnnotation 注解对象
*/
@Override
public void initialize(MinDouble constraintAnnotation) {
this.annotation = constraintAnnotation;
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
if (Objects.isNull(value)) {
return true;
}
if (!(value instanceof Double)) {
return true;
}
return ((Double) value).compareTo(annotation.value()) >= 0;
}
}

View File

@ -0,0 +1,29 @@
package com.face.global.vo;
import lombok.Data;
/**
* @Description:
* @author: admin
* @date: 2018年09月30日 20:13
*/
@Data
public class ApiResult<R> {
private R data;
private String code;
private String message;
public ApiResult(String code, String message, R data) {
this.data = data;
this.code = code;
this.message = message;
}
public ApiResult(String code, String message) {
this.code = code;
this.message = message;
}
}

View File

@ -0,0 +1,10 @@
package com.face.global.vo;
import lombok.Data;
@Data
public class DefaultAuthUser {
private String phone;
private String password;
}

View File

@ -0,0 +1,15 @@
package com.face.global.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class ExcelResponseVO {
@Schema(title = "数据")
List allData;
@Schema(title = "错误标识")
Boolean errorFlag;
}

View File

@ -0,0 +1,24 @@
package com.face.global.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GlobalOrgInfo {
private String orgId;
private String orgName;
private String orgFullName;
private long visitTime;
/**
* 是否是平台
*/
private boolean plat;
}

View File

@ -0,0 +1,38 @@
package com.face.global.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GlobalUser {
private String userId;
private String userName;
private String userType;
private String minOpenId;
private String unionId;
private String wxType;
private Map<String, Object> otherProperties;
public String getString(String key, String defaultValue) {
return Optional.ofNullable(otherProperties.get(key)).map(Objects::toString).orElse(defaultValue);
}
public Boolean getBoolean(String key, Boolean defaultValue) {
return Optional.ofNullable(otherProperties.get(key))
.map(data -> Boolean.parseBoolean(data.toString()))
.orElse(defaultValue);
}
}

View File

@ -0,0 +1,125 @@
package com.face.global.vo;
import com.face.global.enums.OperateType;
import com.face.global.enums.UserTypeEnum;
import lombok.Data;
import java.util.Date;
import java.util.Map;
@Data
public class Operate {
/**
* 主表id
*/
private String mainId;
/**
* id
*/
private String id;
/**
* 历史序列
*/
private long seqno;
/**
* 操作状态1-新增2-修改3-删除
*/
private String operateType;
/**
* 最后操作人
*/
private String modifyUser;
/**
* 最后操作时间
*/
private Date modifyDate;
private String modifyUserType;
private boolean generateId;
private Map<String, Object> extendsData;
public Operate() {
this.modifyDate = new Date();
this.generateId = true;
}
public Operate extendsData(Map<String, Object> extendsData) {
this.extendsData = extendsData;
return this;
}
public static Operate inst() {
return new Operate();
}
public Operate seqno(long seqno) {
this.seqno = seqno;
return this;
}
public Operate mainId(String mainId) {
this.mainId = mainId;
return this;
}
public Operate id(String id) {
this.id = id;
return this;
}
public Operate generateId(boolean generateId) {
this.generateId = generateId;
return this;
}
public Operate insert() {
this.operateType = OperateType.ADD.getOperateType();
return this;
}
public Operate update() {
this.operateType = OperateType.UPDATE.getOperateType();
return this;
}
public Operate customerType() {
this.modifyUserType = UserTypeEnum.CUSTOMER.getCode();
return this;
}
public Operate sysUserType() {
this.modifyUserType = UserTypeEnum.SYS_USER.getCode();
return this;
}
public Operate modifyUserType(String modifyUserType) {
this.modifyUserType = modifyUserType;
return this;
}
public Operate delete() {
this.operateType = OperateType.DELETE.getOperateType();
return this;
}
public Operate modifyUser(String user) {
this.modifyUser = user;
return this;
}
public Operate operateType(String operateType) {
this.operateType = operateType;
return this;
}
}

View File

@ -0,0 +1,46 @@
package com.face.global.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
public class PageRequestVO {
@Getter
@Setter
@Min(value = 1)
private int pageIndex;
@Getter
@Setter
@Min(value = 1)
@Max(value = 200)
private int pageSize;
@Getter
@Setter
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date createStartDate;
@Getter
@Setter
@JsonFormat(pattern = "yyyy-MM-dd" , timezone = "GMT+8")
private Date createEndDate;
private int start;
public int getStart() {
return (pageIndex - 1) * pageSize;
}
@Getter
@Setter
private String myUserId;
@Getter
@Setter
private String myOrgId;
}

View File

@ -0,0 +1,11 @@
package com.face.global.vo;
import lombok.Data;
import java.util.List;
@Data
public class PageResponseFinanceVO<T> {
private long totalSize;
private List<T> data;
}

View File

@ -0,0 +1,11 @@
package com.face.global.vo;
import lombok.Data;
import java.util.List;
@Data
public class PageResponseVO<T> {
private long totalSize;
private List<T> data;
}

View File

@ -0,0 +1,28 @@
package com.face.global.vo;
import lombok.Data;
import java.util.Date;
import java.util.Map;
@Data
public class TimeCostLog {
private Long startTimeValue;
private Date startTime;
private Long endTimeValue;
private Date endTime;
private String userId;
private String userName;
private String orgId;
private String orgName;
private boolean start;
private String traceId;
private String authType;
private String ip;
private Map requestParams;
private Map requestHeaders;
private Map responseHeaders;
private String uri;
private String method;
private long timeCost;
}

View File

@ -0,0 +1,24 @@
package com.face.jsonBean;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
public class ImgToBase64 {
public static void main(String[] args) throws IOException {
Path imageFile = Paths.get("F:\\体验腾讯人脸融合-素材\\222.jpg");
byte[] imageBytes = Files.readAllBytes(imageFile);
/*
InputStream imageInputStream = new FileInputStream("F:\\体验腾讯人脸融合-素材\\111.jpg");
byte[] imageBytes = new byte[imageInputStream.available()];
imageInputStream.read(imageBytes);
imageInputStream.close();*/
String imgBase = Base64.getEncoder().encodeToString(imageBytes);
}
}

View File

@ -0,0 +1,46 @@
package com.face.jsonBean;
import com.fasterxml.jackson.annotation.JsonProperty;
public class JsonFaceInfo {
@JsonProperty("X")
private int x;
@JsonProperty("Y")
int y;
@JsonProperty("Width")
int width;
@JsonProperty("Height")
int height;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}

View File

@ -0,0 +1,30 @@
package com.face.jsonBean;
import com.fasterxml.jackson.annotation.JsonProperty;
public class JsonMaterialFace {
//人脸ID
@JsonProperty("FaceId")
private String faceId;
//人脸坐标信息
@JsonProperty("FaceInfo")
private JsonFaceInfo faceInfo;
public String getFaceId() {
return faceId;
}
public void setFaceId(String faceId) {
this.faceId = faceId;
}
public JsonFaceInfo getFaceInfo() {
return faceInfo;
}
public void setFaceInfo(JsonFaceInfo faceInfo) {
this.faceInfo = faceInfo;
}
}

View File

@ -0,0 +1,86 @@
package com.face.jsonBean;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
public class JsonMaterialInfo {
//素材ID
@JsonProperty("MaterialId")
private String materialId;
//素材状态
@JsonProperty("MaterialStatus")
private int materialStatus;
@JsonProperty("CreateTime")
private String createTime;
@JsonProperty("UpdateTime")
private String updateTime;
//素材人脸模版
@JsonProperty("MaterialFaceList")
List<JsonMaterialFace> materialFaceList;
//素材名称
@JsonProperty("MaterialName")
private String materialName;
//授权信息
@JsonProperty("AuditResult")
private String auditResult;
public String getMaterialId() {
return materialId;
}
public void setMaterialId(String materialId) {
this.materialId = materialId;
}
public int getMaterialStatus() {
return materialStatus;
}
public void setMaterialStatus(int materialStatus) {
this.materialStatus = materialStatus;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
public List<JsonMaterialFace> getMaterialFaceList() {
return materialFaceList;
}
public void setMaterialFaceList(List<JsonMaterialFace> materialFaceList) {
this.materialFaceList = materialFaceList;
}
public String getMaterialName() {
return materialName;
}
public void setMaterialName(String materialName) {
this.materialName = materialName;
}
public String getAuditResult() {
return auditResult;
}
public void setAuditResult(String auditResult) {
this.auditResult = auditResult;
}
}

View File

@ -0,0 +1,44 @@
package com.face.jsonBean;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
public class QiuTestRoot {
//素材数组
@JsonProperty("MaterialInfos")
List<JsonMaterialInfo> materialInfos;
//素材个数
@JsonProperty("Count")
int count;
//活动ID
@JsonProperty("RequestId")
private String requestId;
public List<JsonMaterialInfo> getMaterialInfos() {
return materialInfos;
}
public void setMaterialInfos(List<JsonMaterialInfo> materialInfos) {
this.materialInfos = materialInfos;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
}

View File

@ -0,0 +1,50 @@
package com.face.util;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AesUtil {
private static final String DEFAULT_CHARSET = "UTF-8";
/**
* 加密方法
*
* @param data 要加密的数据
* @param key 加密key
* @param iv 加密iv
* @return 加密的结果
* @throws Exception
*/
public static String encrypt(String data, String key, String iv) throws Exception {
//"算法/模式/补码方式"PKCS5Padding"
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] plaintext = data.getBytes(DEFAULT_CHARSET);
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(plaintext);
return new Base64().encodeToString(encrypted);
}
/**
* 解密方法
*
* @param data 要解密的数据
* @param key 解密key
* @param iv 解密iv
* @return 解密的结果
* @throws Exception
*/
public static String decrypt(String data, String key, String iv) throws Exception {
byte[] encrypted = new Base64().decode(data);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
byte[] original = cipher.doFinal(encrypted);
return new String(original, DEFAULT_CHARSET);
}
}

View File

@ -0,0 +1,100 @@
package com.face.util;
import com.face.global.enums.CommonCode;
import com.face.global.language.LanguageStore;
import com.face.global.vo.ApiResult;
import com.face.global.vo.PageResponseFinanceVO;
import com.face.global.vo.PageResponseVO;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
/**
* @Description:
* @author: admin
* @date: 2018年10月01日 12:57w
*/
public class ApiResultBuilder<T, R> {
private String code;
private String message;
private R data;
private Class<T> cls;
public static <T> ApiResultBuilder<T, List<T>> getListBuilder(Class<T> cls) {
ApiResultBuilder<T, List<T>> builder = new ApiResultBuilder<>();
builder.cls = cls;
return builder;
}
public static <T> ApiResultBuilder<T, T> getCommonBuilder(Class<T> cls) {
ApiResultBuilder<T, T> builder = new ApiResultBuilder<>();
builder.cls = cls;
return builder;
}
public static ApiResultBuilder<Object, Object> getRawBuilder() {
return new ApiResultBuilder<>();
}
public ApiResultBuilder<T, R> success(R data) {
this.code = CommonCode.SUCCESS.getCode();
this.message = getMessage();
this.data = data;
return this;
}
private String getMessage() {
if (StringUtils.isNotBlank(this.message)) {
return message;
}
return MessageUtils.getMessage(this.code, null, LanguageStore.getLocale());
}
public ApiResultBuilder<T, R> success() {
this.code = CommonCode.SUCCESS.getCode();
this.message = this.getMessage();
return this;
}
public ApiResultBuilder<T, R> error() {
this.code = CommonCode.ERROR.getCode();
this.message = this.getMessage();
return this;
}
public ApiResultBuilder<T, R> error(String message) {
this.code = CommonCode.ERROR.toString();
this.message = message;
return this;
}
public ApiResultBuilder<T, R> baseInfo(String code, String message) {
this.code = code;
this.message = message;
return this;
}
public ApiResult<R> build() {
return new ApiResult<>(this.code, this.message, this.data);
}
public static <T> ApiResultBuilder<T, PageResponseVO<T>> getPageCommonBuilder(Class<T> cls) {
ApiResultBuilder<T, PageResponseVO<T>> builder = new ApiResultBuilder<>();
builder.cls = cls;
return builder;
}
public static <T> ApiResultBuilder<T, PageResponseFinanceVO<T>> getPageFinanceCommonBuilder(Class<T> cls) {
ApiResultBuilder<T, PageResponseFinanceVO<T>> builder = new ApiResultBuilder<>();
builder.cls = cls;
return builder;
}
}

View File

@ -0,0 +1,86 @@
package com.face.util;
import com.face.global.enums.CommonCode;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
@Slf4j
public class BatchExecuteUtils {
public static <T, ID> void pageAllById(int pageSize, ID startMaxId,
PageMaxIdFunction<T, ID> pageFunction,
Consumer<List<T>> pageConsumer,
Function<T, ID> idFunction, Class<T> dataCls,
Class<ID> idCls) {
List<T> datas;
ID startId = startMaxId;
do {
try {
PageMaxParam pageMaxParam = PageMaxParam.builder().maxId(startId)
.pageIndex(1).pageSize(pageSize).build();
datas = pageFunction.pageByMax(pageMaxParam);
pageConsumer.accept(datas);
if (!CollectionUtils.isEmpty(datas)) {
startId = idFunction.apply(datas.get(datas.size() - 1));
}
} catch (Exception e) {
log.error("pageAllByIdFail {}", startMaxId, e);
throw SystemExceptionUtils.buildBusinessException(CommonCode.ERROR.getCode(), e);
}
} while (!CollectionUtils.isEmpty(datas) && datas.size() >= pageSize);
}
public interface PageMaxIdFunction<T, ID> {
List<T> pageByMax(PageMaxParam<ID> pageMaxParam);
}
@Builder
@Getter
public static class PageMaxParam<ID> {
private int pageIndex;
private int pageSize;
private ID maxId;
}
public static <T> void pageAll(int pageSize,
PageFunction<T, PageParam> pageFunction,
Consumer<List<T>> pageConsumer,
Class<T> dataCls) {
List<T> datas;
int pageIndex = 1;
do {
try {
PageParam pageParam = PageParam.builder()
.pageIndex(pageIndex).pageSize(pageSize).build();
datas = pageFunction.page(pageParam);
pageConsumer.accept(datas);
if (CollectionUtils.isEmpty(datas) || datas.size() >= pageSize) {
break;
}
pageIndex ++;
} catch (Throwable e) {
log.error("pageAllFail", e);
throw SystemExceptionUtils.buildBusinessException(CommonCode.ERROR.getCode(), e);
}
} while (!CollectionUtils.isEmpty(datas) && datas.size() >= pageSize);
}
public interface PageFunction<T, PageParam> {
List<T> page(PageParam pageMaxParam) throws Throwable;
}
@Builder
@Getter
public static class PageParam {
private int pageIndex;
private int pageSize;
}
}

View File

@ -0,0 +1,159 @@
/**
* All rights Reserved, Designed By http://www.pete-cat.com/
*
* @Title: DataCopy.java
* @Package com.petecat.formdesigner.util
* @Description:复制数据工具类
* @author: 成都皮特猫科技
* @date:2017年11月27日 下午4:41:51
* @version V1.0
* @Copyright: 2017 www.pete-cat.com Inc. All rights reserved.
* 注意本内容仅限于成都皮特猫信息技术有限公司内部传阅禁止外泄以及用于其他的商业目
*/
package com.face.util;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.cglib.beans.BeanCopier;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Slf4j
public class DataCopy {
private static final LoadingCache<CopyKey, BeanCopier> BEAN_COPIER = CacheBuilder.newBuilder()
// 设置缓存个数
.maximumSize(500)
.build(new CacheLoader<>() {
@Override
public BeanCopier load(CopyKey copyKey) {
return BeanCopier.create(copyKey.getSourseClass(), copyKey.getDestClass(), false);
}
});
public static <T> T shallowCopyData(Object source, Class<T> cls) {
try {
T obj = cls.newInstance();
copyDataInner(source, obj);
return obj;
} catch (Exception e) {
log.error("copyDataFail", e);
throw SystemExceptionUtils.buildBusinessException("copyFail");
}
}
private static void copyDataInner(Object source, Object obj) {
try {
String key = source.getClass().getName().concat("_").concat(obj.getClass().getName());
BeanCopier beanCopier = BEAN_COPIER.get(CopyKey.builder().key(key)
.sourseClass(source.getClass()).destClass(obj.getClass()).build());
beanCopier.copy(source, obj, null);
} catch (Exception e) {
log.error("copyDataFail", e);
throw SystemExceptionUtils.buildBusinessException("copyFail");
}
}
public static <T> List<T> shallowCopyList(List<?> datas, Class<T> cls) {
if (datas != null) {
return datas.stream().map((t) -> {
T obj = shallowCopyData(t, cls);
return obj;
}).collect(Collectors.toList());
}
return null;
}
public static <T> List<T> deepCopyList(List<?> datas, TypeReference<List<T>> typeReference) {
try {
return JsonUtils.parseObject(JsonUtils.toJsonString(datas), typeReference);
} catch (Exception e) {
log.error("copyDataFail", e);
throw SystemExceptionUtils.buildBusinessException("copyFail");
}
}
public static <T> T deepCopyData(Object source, Class<T> cls) {
if (source == null) {
return null;
}
try {
return JsonUtils.parseObject(JsonUtils.toJsonString(source), cls);
} catch (Exception e) {
log.error("copyDataFail", e);
throw SystemExceptionUtils.buildBusinessException("copyFail");
}
}
public static <T> List<T> deepCopyList(List<?> datas, Class<T> cls) {
try {
return datas.stream().map(data -> deepCopyData(data, cls)).collect(Collectors.toList());
} catch (Exception e) {
log.error("copyDataFail", e);
throw SystemExceptionUtils.buildBusinessException("copyFail");
}
}
@Builder
@Getter
static class CopyKey {
private String key;
private Class destClass;
private Class sourseClass;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CopyKey copyKey = (CopyKey) o;
return Objects.equals(key, copyKey.key);
}
@Override
public int hashCode() {
return Objects.hashCode(key);
}
}
public static void copyExistsField(Object source, Object target) {
try {
List<Field> sourceFields = FieldUtils.getAllFieldsList(source.getClass());
List<Field> targetFields = FieldUtils.getAllFieldsList(target.getClass());
Object value = null;
for (Field targetField : targetFields) {
List<Field> fields =
sourceFields.stream().filter(field -> StringUtils.equals(field.getName(),
targetField.getName())).toList();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())) {
continue;
}
try {
value = FieldUtils.readField(field, source, true);
FieldUtils.writeField(targetField, target, value, true);
} catch (Exception e) {
log.warn("copyExistsFieldFail {} {}", field, value, e);
}
}
}
} catch (Exception e) {
log.error("copyExistsField", e);
throw SystemExceptionUtils.buildBusinessException("copyFail");
}
}
}

View File

@ -0,0 +1,695 @@
package com.face.util;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
* 日期获取工具类
*/
public class DateUtils {
public final static String DEFAULT_TIMEZONE = "GMT+8";
public final static String ISO_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS";
public final static String ISO_SHORT_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
public final static String DEFAULT_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public final static String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public final static String DEFAULT_ONLY_TIME_FORMAT = "HH:mm:ss";
public final static String SHORT_TIME_FORMAT = "yyyy-MM-dd HH:mm";
public final static String FULL_SEQ_FORMAT = "yyyyMMddHHmmssSSS";
public final static String FULL_FORMAT = "yyyyMMddHHmmssSSS";
public final static String[] MULTI_FORMAT = {DEFAULT_DATE_FORMAT, DEFAULT_TIME_FORMAT, ISO_DATE_TIME_FORMAT, ISO_SHORT_DATE_TIME_FORMAT,
SHORT_TIME_FORMAT, "yyyy-MM"};
public final static String FORMAT_YYYY = "yyyy";
public final static String FORMAT_YYYYMM = "yyyyMM";
public final static String FORMAT_YYYYMMDD = "yyyyMMdd";
public final static String FORMAT_YYYYMMDDHH = "yyyyMMddHH";
public final static String FORMAT_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public final static String FORMAT_CORN = "ss mm HH dd MM ? yyyy";
public final static String ZONE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX";
public final static String[] MULTI_FORMAT_ALL = {DEFAULT_TIME_FORMAT, ZONE_TIME_FORMAT, FULL_FORMAT, DEFAULT_DATE_FORMAT, ISO_DATE_TIME_FORMAT, ISO_SHORT_DATE_TIME_FORMAT,
SHORT_TIME_FORMAT};
/**
* 日期转字符串
* 默认格式: {@linkplain DateUtils#DEFAULT_DATE_FORMAT}
*
* @param date 日期对象
* @return 返回格式化字符串
*/
public static String formatDate(Date date) {
if (date == null) {
return "";
}
return new SimpleDateFormat(DEFAULT_DATE_FORMAT).format(date);
}
/**
* 将日期时间对象转化为日期数字
*
* @param date 日期字符串 {@linkplain DateUtils#SHORT_TIME_FORMAT}
* @param format 格式字符串
* @return 返回日期数字
*/
public static String formatDate(Date date, String format) {
if (date == null) {
return null;
}
return new SimpleDateFormat(format).format(date);
}
/**
* 将日期时间对象转化为corn表达式
*
* @param date 时间点
* @return convert Date to cron ,eg. "0 06 10 15 10 ? 2018"
*/
public static String formatDateToCorn(Date date) {
if (date == null) {
return null;
}
return new SimpleDateFormat(FORMAT_CORN).format(date);
}
/**
* 将日期时间对象转化为日期数字
*
* @param date 日期字符串 {@linkplain DateUtils#SHORT_TIME_FORMAT}
* @param format 格式字符串
* @return 返回日期数字
*/
public static Integer formatDateToInt(Date date, String format) {
if (date == null) {
return null;
}
return Integer.valueOf(new SimpleDateFormat(format).format(date));
}
/**
* 将日期时间对象转化为日期数字
*
* @param date 日期字符串 {@linkplain DateUtils#SHORT_TIME_FORMAT}
* @param format 格式字符串
* @return 返回日期数字
*/
public static Long formatDateToLong(Date date, String format) {
if (date == null) {
return null;
}
return Long.valueOf(new SimpleDateFormat(format).format(date));
}
/**
* 将日期时间对象转化为日期字符串
*
* @param date 日期字符串 {@linkplain DateUtils#DEFAULT_TIME_FORMAT}
* @return 返回日期字符串
*/
public static String formatTime(Date date) {
if (date == null) {
return null;
}
return new SimpleDateFormat(DEFAULT_TIME_FORMAT).format(date);
}
/**
* 将日期时间对象转化为日期字符串
*
* @param date 日期字符串 {@linkplain DateUtils#SHORT_TIME_FORMAT}
* @return 返回日期字符串
*/
public static String formatShortTime(Date date) {
if (date == null) {
return null;
}
return new SimpleDateFormat(SHORT_TIME_FORMAT).format(date);
}
/**
* 将日期时间字符串转化为日期对象
*
* @param date 日期字符串
* @param format 格式串
* @return 返回日期对象
*/
public static Date parseDate(String date, String format) {
if (date == null) {
return null;
}
try {
return new SimpleDateFormat(format).parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
/**
* 将日期时间字符串转化为日期对象
*
* @param date 日期字符串
* @param format 格式串
* @return 返回日期对象
*/
public static Date parseTime(String date, String format) {
if (date == null) {
return null;
}
try {
return new SimpleDateFormat(format).parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
/**
* 将日期时间字符串转化为日期对象
*
* @param date 日期字符串 {@linkplain DateUtils#DEFAULT_TIME_FORMAT}
* @return 返回日期对象
*/
public static Date parseDate(String date) {
return parseDate(date, DEFAULT_DATE_FORMAT);
}
/**
* 将日期时间字符串转化为日期对象
*
* @param date 日期字符串 {@linkplain DateUtils#DEFAULT_TIME_FORMAT}
* @return 返回日期对象
*/
public static Date parseTime(String date) {
return parseTime(date, DEFAULT_TIME_FORMAT);
}
/**
* 对差异时间的格式化显示方便人工查看
*
* @param diffMillis 差异时间(毫秒)
* @return 人能看懂的字符串
*/
public static String getHumanDisplayForTimediff(Long diffMillis) {
if (diffMillis == null) {
return "";
}
long day = diffMillis / (24 * 60 * 60 * 1000);
long hour = (diffMillis / (60 * 60 * 1000) - day * 24);
long min = ((diffMillis / (60 * 1000)) - day * 24 * 60 - hour * 60);
long se = (diffMillis / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
StringBuilder sb = new StringBuilder();
if (day > 0) {
sb.append(day).append("D");
}
DecimalFormat df = new DecimalFormat("00");
sb.append(df.format(hour)).append(":");
sb.append(df.format(min)).append(":");
sb.append(df.format(se));
return sb.toString();
}
/**
* 获取日期相差天数
*
* @param beginDate 字符串类型开始日期
* @param endDate 字符串类型结束日期
* @return Long 日期相差天数
*/
public static Long getDiffDay(String beginDate, String endDate) {
SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
Long checkday = 0L;
//开始结束相差天数
try {
checkday = (formatter.parse(endDate).getTime() - formatter.parse(beginDate).getTime()) / (1000 * 24 * 60 * 60);
} catch (ParseException e) {
e.printStackTrace();
checkday = null;
}
return checkday;
}
/**
* 获取日期相差天数
*
* @param beginDate Date类型开始日期
* @param endDate Date类型结束日期
* @return Long 相差天数
*/
public static Long getDiffDay(Date beginDate, Date endDate) {
SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
String strBeginDate = format.format(beginDate);
String strEndDate = format.format(endDate);
return getDiffDay(strBeginDate, strEndDate);
}
/**
* N天之后
*
* @param n 天数
* @param date 日期
* @return n天之后
*/
public static Date nDaysAfter(Integer n, Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH) + n);
return cal.getTime();
}
/**
* N年之后
*
* @param n 年数
* @param date 日期
* @return n年之后
*/
public static Date nYearsAfter(Integer n, Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + n);
return cal.getTime();
}
/**
* N天之前
*
* @param n 天数
* @param date 日期
* @return N天之后
*/
public static Date nDaysAgo(Integer n, Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH) - n);
return cal.getTime();
}
/**
* N年之前
*
* @param n 年数
* @param date 日期
* @return n年之前
*/
public static Date nYearsAgo(Integer n, Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - n);
return cal.getTime();
}
/**
* 指定日期在全年中的第几周
*
* @param date 日期
* @return 返回日期在这一年中的周数
*/
public static Integer getWeekOfYear(Date date) {
Calendar c = Calendar.getInstance();
c.setTime(date);
return Integer.valueOf(formatDate(date, FORMAT_YYYY) + c.get(Calendar.WEEK_OF_YEAR));
}
/**
* 获取当前日期时间
*
* @return 返回当前日期时间
*/
public static Date getCurrentDateTime() {
return new Date();
}
/**
* 获取当前日期
*
* @return 返回当前日期
*/
public static Date getCurrentDate() {
Calendar calendar = Calendar.getInstance();
//获取年份
int year = calendar.get(Calendar.YEAR);
//获取月份
int month = calendar.get(Calendar.MONTH);
//获取日
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
/**
* 日期格式化为年月日的日期
*
* @param date 日期
* @return 年月日的日期
*/
public static Date formatDate2Date(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(date.getTime());
//获取年份
int year = calendar.get(Calendar.YEAR);
//获取月份
int month = calendar.get(Calendar.MONTH);
//获取日
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
//根据传入日期查询该日期前五天内全部日期不考虑跨月情况
public static List<String> getDatesList(String pdate) {
List<String> datesList = new ArrayList<>();
List<LocalDate> previousFiveDays = new ArrayList<>();
LocalDate date2 = LocalDate.parse(pdate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// 逐一计算前五天的日期
for (int i = 0; i < 5; i++) {
//判断是不是在一个月份如果不是则不添加反正则添加
// if (date2.minusDays(i).getMonthValue() == date2.getMonthValue()) {
// previousFiveDays.add(date2.minusDays(i));
// }
previousFiveDays.add(date2.minusDays(i));
}
// 格式化日期为字符串
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
for (LocalDate date : previousFiveDays) {
String day = date.format(formatter);
datesList.add(day);
}
return datesList;
}
//根据传入的开始时间结束时间查询该范围内的全部时间
public static List<String> getRangeDateList(String sdate, String edate) {
LocalDate startDate = LocalDate.parse(sdate);
LocalDate endDate = LocalDate.parse(edate);
List<LocalDate> dateList = new ArrayList<>();
List<String> rangeList = new ArrayList<>();
LocalDate currentDate = startDate;
while (!currentDate.isAfter(endDate)) {
dateList.add(currentDate);
currentDate = currentDate.plus(Period.ofDays(1));
}
//格式转换
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
for (LocalDate date : dateList) {
String day = date.format(formatter);
rangeList.add(day);
}
return rangeList;
}
//根据月份获取该月的全部日期信息
public static List<String> getMonthDates(String pdate) {
List<String> dateList = new ArrayList<>();
List<Date> dates = new ArrayList<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = sdf.parse(pdate);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.DAY_OF_MONTH, 1);
int month = calendar.get(Calendar.MONTH);
while (calendar.get(Calendar.MONTH) == month) {
dates.add(calendar.getTime());
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
} catch (ParseException e) {
e.printStackTrace();
}
for (Date date1 : dates) {
dateList.add(sdf.format(date1));
}
return dateList;
}
//获取传入月份的开始时间和结束时间
public static List<String> getBEDateOfMonth(String month) {
List<String> dateList = new ArrayList<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = sdf.parse(month);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
// 获取给定日期所在月份的开始时间
calendar.set(Calendar.DAY_OF_MONTH, 1);
Date monthStartDate = calendar.getTime();
// 获取给定日期所在月份的结束时间
calendar.add(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.add(Calendar.DAY_OF_MONTH, -1);
Date monthEndDate = calendar.getTime();
String startDate = sdf.format(monthStartDate);
String endDate = sdf.format(monthEndDate);
dateList.add(startDate);
dateList.add(endDate);
} catch (ParseException e) {
e.printStackTrace();
}
return dateList;
}
//获取上一个月
public static String getLastMonth(String month) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = format.parse(month);
Calendar calendar = Calendar.getInstance();
// 设置为当前时间
calendar.setTime(date);
calendar.add(Calendar.MONTH, -1);
// 设置为上一个月
//calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
date = calendar.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
return format.format(date);
}
//获取起止时间
public static List<String> getStartStopTime(String startMonth, String endMonth) {
List<String> list = new ArrayList<>();
//开始时间
startMonth = startMonth.substring(0, 7) + "-01";
//结束时间
// 将字符串转换为 LocalDate 对象
LocalDate date = LocalDate.parse(endMonth, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// 获取该月的最后一天
endMonth = date.withDayOfMonth(date.lengthOfMonth()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
list.add(startMonth);
list.add(endMonth);
return list;
}
//获取传入月份范围的全部月份的起止时间
public static Map<String, List<String>> getMonthStartEnd(String start, String end) {
Map<String, List<String>> map = new HashMap<>();
List<String> startMonthList = new ArrayList<>();
List<String> endMonthList = new ArrayList<>();
// 将字符串转换为 LocalDate 对象
LocalDate startMonth = LocalDate.parse(start, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
LocalDate endMonth = LocalDate.parse(end, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// 遍历月份范围并输出每个月的开始和结束时间
LocalDate currentMonth = startMonth;
while (!currentMonth.isAfter(endMonth)) {
String firstDayOfMonth = currentMonth.withDayOfMonth(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
String lastDayOfMonth = currentMonth.withDayOfMonth(currentMonth.lengthOfMonth()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
startMonthList.add(firstDayOfMonth);
endMonthList.add(lastDayOfMonth);
// 下一个月
currentMonth = currentMonth.plusMonths(1);
}
map.put("start", startMonthList);
map.put("end", endMonthList);
return map;
}
//获取月份的天数
public static int getDaysNumByYearMonth(String date) {
int year = Integer.parseInt(date.substring(0, 4));
int month = Integer.parseInt(date.substring(5, 7));
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.DATE, 1);
calendar.roll(Calendar.DATE, -1);
return calendar.get(Calendar.DATE);
}
public static String getWeekByDate(String date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
Date givenDate = sdf.parse(date); // 替换为你要检查的日期
Calendar calendar = Calendar.getInstance();
calendar.setTime(givenDate);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
String weekday;
switch (dayOfWeek) {
case Calendar.SUNDAY:
weekday = "0";
break;
case Calendar.MONDAY:
weekday = "1";
break;
case Calendar.TUESDAY:
weekday = "2";
break;
case Calendar.WEDNESDAY:
weekday = "3";
break;
case Calendar.THURSDAY:
weekday = "4";
break;
case Calendar.FRIDAY:
weekday = "5";
break;
case Calendar.SATURDAY:
weekday = "6";
break;
default:
throw new IllegalStateException("Unexpected value: " + dayOfWeek);
}
System.out.println("给定日期是:" + weekday);
return weekday;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Date stringToDate(String dateString, String format) {
SimpleDateFormat formatter = new SimpleDateFormat(format);
try {
return formatter.parse(dateString);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
public static String getWeekByDateName(String date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
Date givenDate = sdf.parse(date); // 替换为你要检查的日期
Calendar calendar = Calendar.getInstance();
calendar.setTime(givenDate);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
String weekday;
switch (dayOfWeek) {
case Calendar.SUNDAY:
weekday = "星期天";
break;
case Calendar.MONDAY:
weekday = "星期一";
break;
case Calendar.TUESDAY:
weekday = "星期二";
break;
case Calendar.WEDNESDAY:
weekday = "星期三";
break;
case Calendar.THURSDAY:
weekday = "星期四";
break;
case Calendar.FRIDAY:
weekday = "星期五";
break;
case Calendar.SATURDAY:
weekday = "星期六";
break;
default:
throw new IllegalStateException("Unexpected value: " + dayOfWeek);
}
System.out.println("给定日期是:" + weekday);
return weekday;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 根据年月获取月初第一天日期
* @param year
* @param month
* @return
*/
public static String getFirstDay(int year,int month,String format) {
Calendar cale = Calendar.getInstance();
cale.set(Calendar.YEAR,year); //赋值年份
cale.set(Calendar.MONTH, month-1);//赋值月份
int lastDay = cale.getActualMinimum(Calendar.DAY_OF_MONTH);//获取月最大天数
cale.set(Calendar.DAY_OF_MONTH, lastDay);//设置日历中月份的最大天数
SimpleDateFormat sdf = new SimpleDateFormat(format);//格式化日期yyyy-MM-dd
String lastDayOfMonth = sdf.format(cale.getTime());
return lastDayOfMonth;
}
/**
* 根据年月获取月末最后一天日期
* @param year
* @param month
* @return
*/
public static String getLastDay(int year,int month,String format) {
Calendar cale = Calendar.getInstance();
cale.set(Calendar.YEAR,year);//赋值年份
cale.set(Calendar.MONTH, month-1);//赋值月份
int lastDay = cale.getActualMaximum(Calendar.DAY_OF_MONTH);//获取月最大天数
cale.set(Calendar.DAY_OF_MONTH, lastDay);//设置日历中月份的最大天数
SimpleDateFormat sdf = new SimpleDateFormat(format); //格式化日期yyyy-MM-dd
String lastDayOfMonth = sdf.format(cale.getTime());
return lastDayOfMonth;
}
public static void main(String[] args) {
List<String> cdf=DateUtils.getBEDateOfMonth("02");
}
}

View File

@ -0,0 +1,120 @@
package com.face.util;
import com.google.common.collect.Lists;
import com.face.global.consts.GlobalConstant;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import java.net.InetAddress;
import java.util.*;
@Slf4j
public class HttpUtils {
public static Map getHeadersInfo(HttpServletRequest request, HttpHeaders headers) {
Map datas = new HashMap();
if (headers != null) {
headers.entrySet().forEach(stringListEntry ->
datas.put(stringListEntry.getKey(), stringListEntry.getValue()));
} else {
Enumeration<String> keys = request.getHeaderNames();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
datas.put(key, Lists.newArrayList(request.getHeaders(key).asIterator()));
}
}
datas.remove(GlobalConstant.TOKEN_KEY);
datas.remove(GlobalConstant.TOKEN_KEY.toLowerCase(Locale.ROOT));
return datas;
}
public static String getUri(ServletRequest servletRequest) {
if (servletRequest instanceof HttpServletRequest) {
return ((HttpServletRequest) servletRequest).getRequestURI();
}
return servletRequest.getRequestId();
}
public static Map<String, String[]> getParams(ServletRequest servletRequest) {
return servletRequest.getParameterMap();
}
public static Map getHeaders(ServletRequest servletRequest) {
if (servletRequest instanceof HttpServletRequest) {
return getHeadersInfo((HttpServletRequest) servletRequest, null);
}
return new HashMap<>();
}
public static Map getHeaders(ServletResponse servletResponse) {
if (servletResponse instanceof HttpServletResponse) {
return getHeadersInfo((HttpServletResponse) servletResponse);
}
return new HashMap<>();
}
public static Map getHeadersInfo(HttpServletResponse response) {
Map datas = new HashMap();
Collection<String> keys = response.getHeaderNames();
for (String key : keys) {
datas.put(key, response.getHeaders(key));
}
datas.remove(GlobalConstant.TOKEN_KEY);
return datas;
}
public static void addHeader(ServletResponse servletResponse, String key, String id) {
try {
if (StringUtils.isBlank(id)) {
return;
}
if (servletResponse instanceof HttpServletResponse) {
((HttpServletResponse) servletResponse).addHeader(key, id);
}
} catch (Exception e) {
}
}
public static String getReqIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
if (StringUtils.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)
&& StringUtils.contains(ip, ",")) {
// 多次反向代理后会有多个IP值第一个为真实IP
ip = StringUtils.substringBefore(ip, ",");
}
// 处理localhost访问
if (StringUtils.isBlank(ip) || "unkown".equalsIgnoreCase(ip) || StringUtils.split(ip, ".").length != 4) {
try {
InetAddress inetAddress = InetAddress.getLocalHost();
ip = inetAddress.getHostAddress();
} catch (Exception e) {
}
}
return ip;
}
}

View File

@ -0,0 +1,13 @@
package com.face.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class JsonUtil {
private static final ObjectMapper objectMapper = new ObjectMapper();
public static <T> T fromJson(String jsonString, Class<T> clazz) throws IOException {
return objectMapper.readValue(jsonString, clazz);
}
}

View File

@ -0,0 +1,129 @@
package com.face.util;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.google.common.collect.Sets;
import com.face.global.enums.CommonCode;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;
@Slf4j
public class JsonUtils {
@Getter
private static ObjectMapper OBJECT_MAPPER;
private static final Set<String> FORMAT_DATES = Sets.newHashSet("yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd");
public static class DateJsonDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
String valueStr = p.getValueAsString();
if (StringUtils.isBlank(valueStr)) {
return null;
}
if (NumberUtils.isCreatable(valueStr)) {
return new Date(Long.parseLong(valueStr));
}
for (String format : FORMAT_DATES) {
try {
return new SimpleDateFormat(format).parse(valueStr);
} catch (Exception e) {
// ignore
}
}
throw new IllegalArgumentException(valueStr.concat(" convert date fail"));
}
}
static {
OBJECT_MAPPER = JsonMapper.builder()
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true)
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
.build();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(Date.class, new DateJsonDeserializer());
OBJECT_MAPPER.registerModule(simpleModule);
}
public static String toJsonString(Object value) {
return toJsonString(value, false);
}
public static String toJsonString(Object value, boolean throwException) {
try {
return OBJECT_MAPPER.writeValueAsString(value);
} catch (Exception e) {
log.error("toJsonStringFail", e);
throwBusinessException(throwException, e);
}
return null;
}
public static <T> T parseObject(String value, TypeReference<T> typeReference) {
return parseObject(value, typeReference, false);
}
public static <T> T parseObject(String value, JavaType javaType) {
return parseObject(value, javaType, false);
}
public static <T> T parseObject(String value, JavaType javaType, boolean throwException) {
try {
return OBJECT_MAPPER.readValue(value, javaType);
} catch (Exception e) {
log.error("parseObjectFail", e);
throwBusinessException(throwException, e);
}
return null;
}
public static <T> T parseObject(String value, TypeReference<T> typeReference, boolean throwException) {
try {
return OBJECT_MAPPER.readValue(value, typeReference);
} catch (Exception e) {
log.error("parseObjectFail", e);
throwBusinessException(throwException, e);
}
return null;
}
public static <T> T parseObject(String value, Class<T> cls) {
return parseObject(value, cls, false);
}
public static <T> T parseObject(String value, Class<T> cls, boolean throwException) {
try {
return OBJECT_MAPPER.readValue(value, cls);
} catch (Exception e) {
log.error("parseObjectFail", e);
throwBusinessException(throwException, e);
}
return null;
}
private static void throwBusinessException(boolean throwException, Exception exception) {
if (throwException) {
throw SystemExceptionUtils.buildBusinessException(CommonCode.ERROR.getCode(), new Object[]{}, exception);
}
}
public static TypeFactory getTypeFactory() {
return OBJECT_MAPPER.getTypeFactory();
}
}

View File

@ -0,0 +1,39 @@
package com.face.util;
import com.face.util.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import java.util.Locale;
@Slf4j
public class MessageUtils {
public static String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) {
try {
return SpringUtils.getMessageSource().getMessage(code, args, defaultMessage, locale);
} catch (Exception e) {
log.warn("getMessageFail {} {}", code, args, e);
}
return defaultMessage;
}
public static String getMessage(String code, @Nullable Object[] args, Locale locale) {
try {
return SpringUtils.getMessageSource().getMessage(code, args, locale);
} catch (Exception e) {
log.warn("getMessageFail {} {}", code, args, e);
}
return code;
}
public static String getMessageReturnNull(String code, @Nullable Object[] args, Locale locale) {
try {
return SpringUtils.getMessageSource().getMessage(code, args, locale);
} catch (Exception e) {
log.warn("getMessageFail {} {}", code, args, e);
}
return null;
}
}

View File

@ -0,0 +1,24 @@
package com.face.util;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.text.DecimalFormat;
public class NumberUtils {
public static String formatYuanAmt(Integer amountFen) {
if (amountFen == null) {
return StringUtils.EMPTY;
}
DecimalFormat df = new DecimalFormat("0.00");
return df.format(BigDecimal.valueOf(amountFen).divide(BigDecimal.valueOf(100)));
}
public static String formatYuanAmt(BigDecimal amountYuan) {
if (amountYuan == null) {
return StringUtils.EMPTY;
}
DecimalFormat df = new DecimalFormat("0.00");
return df.format(amountYuan);
}
}

View File

@ -0,0 +1,24 @@
package com.face.util;
import org.apache.commons.lang3.StringUtils;
import java.util.Objects;
public class ObjectUtils {
public static boolean equalsNullBlank(Object left, Object right) {
if (left == null && right == null) {
return true;
}
if (left == null && right instanceof String) {
if (StringUtils.isBlank(right.toString())) {
return true;
}
}
if (left instanceof String && right == null) {
if (StringUtils.isBlank(left.toString())) {
return true;
}
}
return Objects.equals(left, right);
}
}

View File

@ -0,0 +1,31 @@
package com.face.util;
import com.face.global.language.LanguageStore;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import java.io.IOException;
public class ResponseUtils {
public static void writeError(String code, String message, HttpServletResponse response) throws IOException {
String errorMessage;
if (StringUtils.isNotBlank(message)) {
errorMessage = message;
} else {
errorMessage = MessageUtils.getMessage(code,
null, LanguageStore.getLocale());
}
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(JsonUtils.toJsonString(
ApiResultBuilder.getRawBuilder().baseInfo(code, errorMessage).build()));
response.getWriter().flush();
}
public static void writeString(String message, HttpServletResponse response) throws IOException {
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
response.getWriter().write(message);
response.getWriter().flush();
}
}

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