Browse Source

opai-api服务

ocr-service服务
master
maojian 3 months ago
parent
commit
f9905312a9
  1. 40
      ocr-service/.classpath
  2. 3
      ocr-service/.gitignore
  3. 23
      ocr-service/.project
  4. 187
      ocr-service/pom.xml
  5. 19
      ocr-service/src/main/java/com/bw/ocr/Application.java
  6. 37
      ocr-service/src/main/java/com/bw/ocr/cache/ConfigCache.java
  7. 39
      ocr-service/src/main/java/com/bw/ocr/controller/TaskReceiveController.java
  8. 31
      ocr-service/src/main/java/com/bw/ocr/entity/AppResultDoc.java
  9. 50
      ocr-service/src/main/java/com/bw/ocr/entity/Constants.java
  10. 208
      ocr-service/src/main/java/com/bw/ocr/handler/MainHandler.java
  11. 24
      ocr-service/src/main/java/com/bw/ocr/service/OcrTaskService.java
  12. 17
      ocr-service/src/main/java/com/bw/ocr/service/TaskReceiveService.java
  13. 329
      ocr-service/src/main/java/com/bw/ocr/service/impl/OcrTaskServiceImpl.java
  14. 55
      ocr-service/src/main/java/com/bw/ocr/service/impl/TaskReceiveServiceImpl.java
  15. 48
      ocr-service/src/main/java/com/bw/ocr/utils/DataUtil.java
  16. 177
      ocr-service/src/main/java/com/bw/ocr/utils/DateUtil.java
  17. 1004
      ocr-service/src/main/java/com/bw/ocr/utils/DownLoadUtil.java
  18. 27
      ocr-service/src/main/java/com/bw/ocr/utils/EncryptionUtil.java
  19. 41
      ocr-service/src/main/java/com/bw/ocr/utils/FileUtil.java
  20. 53
      ocr-service/src/main/java/com/bw/ocr/utils/GPTResultParseUtil.java
  21. 33
      ocr-service/src/main/java/com/bw/ocr/utils/OtherUtils.java
  22. 18
      ocr-service/src/main/java/com/bw/ocr/utils/QueueUtil.java
  23. 45
      ocr-service/src/main/java/com/bw/ocr/utils/SpringBootKafka.java
  24. 23
      ocr-service/src/main/java/com/bw/ocr/utils/ThrowMessageUtil.java
  25. 52
      ocr-service/src/main/resources/bootstrap.yml
  26. 36
      ocr-service/src/main/resources/logback-spring.xml
  27. 40
      opai-api/.classpath
  28. 3
      opai-api/.gitignore
  29. 23
      opai-api/.project
  30. 173
      opai-api/pom.xml
  31. 19
      opai-api/src/main/java/com/bw/opai/Application.java
  32. 83
      opai-api/src/main/java/com/bw/opai/app/controller/AppController.java
  33. 60
      opai-api/src/main/java/com/bw/opai/app/dto/App.java
  34. 49
      opai-api/src/main/java/com/bw/opai/app/entity/AppResultDoc.java
  35. 18
      opai-api/src/main/java/com/bw/opai/app/mapper/AppMapper.java
  36. 44
      opai-api/src/main/java/com/bw/opai/app/service/AppService.java
  37. 358
      opai-api/src/main/java/com/bw/opai/app/service/impl/AppServiceImpl.java
  38. 81
      opai-api/src/main/java/com/bw/opai/common/Res.java
  39. 30
      opai-api/src/main/java/com/bw/opai/common/ResponseCode.java
  40. 34
      opai-api/src/main/java/com/bw/opai/file/controller/FileController.java
  41. 16
      opai-api/src/main/java/com/bw/opai/file/service/FileService.java
  42. 107
      opai-api/src/main/java/com/bw/opai/file/service/impl/FileServiceImpl.java
  43. 19
      opai-api/src/main/java/com/bw/opai/utils/Constants.java
  44. 177
      opai-api/src/main/java/com/bw/opai/utils/DateUtil.java
  45. 1005
      opai-api/src/main/java/com/bw/opai/utils/DownLoadUtil.java
  46. 23
      opai-api/src/main/java/com/bw/opai/utils/ThrowMessageUtil.java
  47. 52
      opai-api/src/main/resources/bootstrap.yml
  48. 36
      opai-api/src/main/resources/logback-spring.xml
  49. 37
      pom.xml

40
ocr-service/.classpath

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

3
ocr-service/.gitignore

@ -0,0 +1,3 @@
/target/
/logs/
/.settings/

23
ocr-service/.project

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ocr-service</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

187
ocr-service/pom.xml

@ -0,0 +1,187 @@
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bw</groupId>
<artifactId>opai-service-center</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.bw</groupId>
<artifactId>ocr-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ocr-service</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.17</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<!-- 可选,处理复杂 .docx 文件时可能需要 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<build>
<!-- <pluginManagement> --><!-- lock down plugins versions to avoid using Maven defaults (may be
moved
to parent pom) -->
<plugins>
<!-- clean lifecycle, see
https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see
https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see
https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<!-- spring-boot-maven-plugin插件就是打包spring boot应用的 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.bw.ocr.Application</mainClass>
<layout>ZIP</layout>
<includes>
<include>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<type>jar</type>
<includeTypes>jar</includeTypes>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<!-- </pluginManagement> -->
</build>
</project>

19
ocr-service/src/main/java/com/bw/ocr/Application.java

@ -0,0 +1,19 @@
package com.bw.ocr;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 系统接口启动类
* @author jian.mao
* @date 2025年12月30日
* @description
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

37
ocr-service/src/main/java/com/bw/ocr/cache/ConfigCache.java

@ -0,0 +1,37 @@
package com.bw.ocr.cache;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;
/**
* @author jian.mao
* @date 2022年11月11日
* @description 静态变量类
*/
@Slf4j
public class ConfigCache {
/**启动条件**/
public static boolean isStart = true;
/*****任务队列*****/
public static LinkedBlockingDeque<Map<String, Object>> taskQueue = new LinkedBlockingDeque<Map<String,Object>>();
/****结果队列****/
public static LinkedBlockingDeque<Map<String, Object>> resultQueue = new LinkedBlockingDeque<Map<String,Object>>();
/**
* 队列录入任务
* @param queue
* @param task
*/
public static void putQueue(LinkedBlockingDeque<Map<String, Object>> queue,Map<String, Object> task){
//next app 写入队列准备调出
try {
queue.put(task);
} catch (InterruptedException e) {
log.error("队列写入data失败---");
}
}
}

39
ocr-service/src/main/java/com/bw/ocr/controller/TaskReceiveController.java

@ -0,0 +1,39 @@
package com.bw.ocr.controller;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.bw.ocr.service.TaskReceiveService;
import lombok.extern.slf4j.Slf4j;
/**
* 任务接收控制层
* @author jian.mao
* @date 2025年1月14日
* @description
*/
@Controller
@RequestMapping("/task")
@Slf4j
public class TaskReceiveController {
@Resource
private TaskReceiveService taskReceiveService;
@PostMapping("/put")
@ResponseBody
public String put(@RequestBody String param){
String response = taskReceiveService.put(param);
return response;
}
@RequestMapping(value = "/hello", method = RequestMethod.GET)
@ResponseBody
public String hello(String param, String token) {
return "123";
}
}

31
ocr-service/src/main/java/com/bw/ocr/entity/AppResultDoc.java

@ -0,0 +1,31 @@
package com.bw.ocr.entity;
import java.io.Serializable;
import java.util.Map;
import lombok.Data;
/**
* ES 索引opai_app_result
* 应用执行结果文档
*
* @author jian.mao
*/
@Data
public class AppResultDoc implements Serializable {
private static final long serialVersionUID = 1L;
/** 完成时间(毫秒时间戳) */
private Long finishTime;
/** 执行状态 */
private Integer status;
/** 执行结果(可索引) */
private Map<String, Object> result;
/** 最后修改时间(毫秒时间戳) */
private Long lastEdit;
}

50
ocr-service/src/main/java/com/bw/ocr/entity/Constants.java

@ -0,0 +1,50 @@
package com.bw.ocr.entity;
/**
* 常量实体类
* @author jian.mao
* @date 2022年11月15日
* @description
*/
public class Constants {
/**
* 空字符串常量
*/
public static final String EMPTY = "";
/************************应用参数*************************************/
public static final String CODE = "code";
public static final String MESSAGE = "message";
/******************************api使用*******************************/
public static final String CONTENT = "content";
public static final String WROD_COUNT = "wordCount";
public static final String TRACE = "trace";
public static final String PARSE_FIAL = "解析失败";
public static final String FILEURL = "fileUrl";
public static final String CREATEURL = "createUrl";
public static final String JOBURL = "jobUrl";
public static final String QUERYURL = "queryUrl";
public static final String FILECONTENTS = "FileContents";
public static final String FILENAME = "FileName";
public static final String OPENPASSWORD = "OpenPassword";
public static final String OWNERPASSWORD = "OwnerPassword";
public static final String LOCATIONPATH = "LocationPath";
public static final String SUCCESS = "success";
public static final String FAILED = "failed";
public static final String WORDS_RESULT = "words_result";
public static final String WORDS = "words";
public static final String JOBID = "jobId";
public static final String PROGRESS = "Progress";
public static final String JOBDOCUMENTS = "JobDocuments";
public static final String OutputDocuments = "OutputDocuments";
public static final String FILES = "Files";
public static final String IDRENAME = "#id";
/**
* 任务id
*/
public static final String TASKID = "taskId";
}

208
ocr-service/src/main/java/com/bw/ocr/handler/MainHandler.java

@ -0,0 +1,208 @@
package com.bw.ocr.handler;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.bw.ocr.cache.ConfigCache;
import com.bw.ocr.service.OcrTaskService;
import com.bw.ocr.utils.DateUtil;
import com.bw.ocr.utils.FileUtil;
import lombok.extern.slf4j.Slf4j;
/**
* @author jian.mao
* @date 2025年1月13日
* @description
*/
@Component
@Order(value = 1)
@RefreshScope
@Slf4j
public class MainHandler implements ApplicationRunner {
@Value("${task.task-queue-path}")
private String taskPath;
@Value("${task.result-task-queue-path}")
private String resultTaskPath;
@Autowired
private OcrTaskService ocrTaskService;
/***线程池参数***/
@Value("${threadPool.corePoolSize}")
private int corePoolSize;
@Value("${threadPool.maximumPoolSize}")
private int maximumPoolSize;
@Value("${threadPool.keepAliveTime}")
private long keepAliveTime;
@Value("${threadPool.queueSize}")
private int queueSize;
/**
*执行入口
*/
@Override
public void run(ApplicationArguments args) throws Exception {
//线程池方式
ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(queueSize),
new ThreadPoolExecutor.CallerRunsPolicy()
);
//消费创建任务队列数据
Thread consumerThread = new Thread(() -> {
while (true) {
try {
// 从队列中获取任务
Map<String, Object> task = ConfigCache.taskQueue.take();
// 提交给线程池执行
executor.execute(() -> createTask(task));
} catch (InterruptedException e) {
// 恢复中断状态
Thread.currentThread().interrupt();
log.error("任务消费线程被中断");
break;
}
}
});
consumerThread.start();
log.info("创建任务消费线程启动-----");
//消费结果任务队列数据
Thread resultConsumerThread = new Thread(() -> {
while (true) {
try {
// 从队列中获取任务
Map<String, Object> task = ConfigCache.resultQueue.take();
// 提交给线程池执行
executor.execute(() -> getResult(task));
} catch (InterruptedException e) {
// 恢复中断状态
Thread.currentThread().interrupt();
log.error("任务消费线程被中断");
break;
}
DateUtil.sleep(3000);
}
});
resultConsumerThread.start();
log.info("结果任务消费线程启动-----");
//启动加载缓存任务
readTask(taskPath, ConfigCache.taskQueue);
readTask(resultTaskPath, ConfigCache.resultQueue);
//停止处理
waitDown();
}
/**
* 创建任务执行方法
* @param task
*/
private void createTask(Map<String, Object> task) {
ocrTaskService.create(task);
}
private void getResult(Map<String, Object> task) {
ocrTaskService.parse(task);
}
/****************************************************************load******************************************************************************/
/**
* 加载文件中的任务
* @param path 文件地址
* @param queue 队列
*/
@SuppressWarnings("unchecked")
public static void readTask(String path, LinkedBlockingDeque<Map<String, Object>> queue) {
File file = new File(path);
if (file.exists()) {
List<String> tasks = null;
try {
tasks = FileUtils.readLines(file, "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
for (String taskStr : tasks) {
Map<String, Object> task = JSONObject.parseObject(taskStr);
try {
queue.put(task);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
file.delete();
}
}
/*******************************************************************stop************************************************************************/
/**
* 结束触发钩子
*/
public void waitDown() {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// 停止线程
ConfigCache.isStart = false;
log.info("stop-------");
writeTsskToFile();
}
});
}
/**
* 任务持久化到硬盘
*/
public void writeTsskToFile() {
while (true) {
if (ConfigCache.taskQueue.size() > 0) {
try {
Map<String, Object> task = ConfigCache.taskQueue.take();
FileUtil.writeFile(taskPath, JSONObject.toJSONString(task));
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
log.info("taskQueue write is file end");
break;
}
}
while (true) {
if (ConfigCache.resultQueue.size() > 0) {
try {
Map<String, Object> task = ConfigCache.resultQueue.take();
FileUtil.writeFile(resultTaskPath, JSONObject.toJSONString(task));
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
log.info("taskQueue write is file end");
break;
}
}
}
}

24
ocr-service/src/main/java/com/bw/ocr/service/OcrTaskService.java

@ -0,0 +1,24 @@
package com.bw.ocr.service;
import java.util.Map;
/**
* ocr识别处理接口
* @author jian.mao
* @date 2025年2月18日
* @description
*/
public interface OcrTaskService {
/**
* ocr远端任务
* @param task
*/
public void create(Map<String, Object> task);
/**
* 解析结果
* @param task
*/
public void parse(Map<String, Object> task);
}

17
ocr-service/src/main/java/com/bw/ocr/service/TaskReceiveService.java

@ -0,0 +1,17 @@
package com.bw.ocr.service;
/**
* 任务接收服务层
* @author jian.mao
* @date 2025年1月14日
* @description
*/
public interface TaskReceiveService {
/**
* 任务新增
* @param dataJson
* @return
*/
public String put(String dataJson);
}

329
ocr-service/src/main/java/com/bw/ocr/service/impl/OcrTaskServiceImpl.java
File diff suppressed because it is too large
View File

55
ocr-service/src/main/java/com/bw/ocr/service/impl/TaskReceiveServiceImpl.java

@ -0,0 +1,55 @@
package com.bw.ocr.service.impl;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.bw.ocr.cache.ConfigCache;
import com.bw.ocr.entity.Constants;
import com.bw.ocr.service.TaskReceiveService;
import lombok.extern.slf4j.Slf4j;
/**
* 任务接收服务层实现类
* @author jian.mao
* @date 2025年1月14日
* @description
*/
@Service
@Slf4j
public class TaskReceiveServiceImpl implements TaskReceiveService {
@Override
public String put(String dataJson) {
Map<String, Object> response = new HashMap<>(16);
int code = 200;
String message = "success";
Map<String, Object> task = null;
try {
task = JSONObject.parseObject(dataJson);
} catch (Exception e) {
log.error("参数结构不合法,", e);
code = 100010;
message = "参数不合法";
}
// 写入队列
try {
if(task.containsKey(Constants.TRACE) && (boolean)task.get(Constants.TRACE)){
ConfigCache.taskQueue.putFirst(task);
}else{
ConfigCache.taskQueue.put(task);
}
} catch (InterruptedException e) {
log.error("任务写入队列异常,", e);
code = 100011;
message = "任务写入队列失败";
}
response.put(Constants.CODE, code);
response.put(Constants.MESSAGE, message);
return JSONObject.toJSONString(response);
}
}

48
ocr-service/src/main/java/com/bw/ocr/utils/DataUtil.java

@ -0,0 +1,48 @@
package com.bw.ocr.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import java.util.Map;
/**
* @author:jinming
* @className:DataUtil
* @version:1.0
* @description: 获取dataValue的值
* @Date:2023/11/1 9:54
*/
public class DataUtil {
/**
*
* @param key 传入的key
* @param dataMap 数据map
* @return 根据传入的参数进行判断解析返回正确的dataValue
*/
public static Object getValue(String key, Map dataMap) {
Object dataValue;
String isJson = "#json#";
if (key.contains(isJson)) {
//进行第一次拆分获取#json#前面的部分
String[] keySplit = key.split(isJson);
String firstDataKey = keySplit[0];
String[] firstDataKeySplit = firstDataKey.split(":");
//取出前半部分对应的JSON数据并转换为JSONObject
String dataJson = (String) dataMap.get(firstDataKeySplit[0]);
JSONObject dataJsonObject = JSON.parseObject(dataJson);
//根据key的后半部分取出对应JSONObject中的值
String firstDataKeyJson = (String) JSONPath.eval(dataJsonObject, firstDataKeySplit[1]);
String secDataKey = keySplit[1];
JSONObject firstDataJsonObject = JSON.parseObject(firstDataKeyJson);
dataValue = JSONPath.eval(firstDataJsonObject, secDataKey);
return dataValue;
}
String[] keySplit = key.split(":");
String jsonPath = keySplit[1];
String dataJson = (String) dataMap.get(keySplit[0]);
JSONObject dataJsonObject = JSON.parseObject(dataJson);
dataValue = JSONPath.eval(dataJsonObject, jsonPath);
return dataValue;
}
}

177
ocr-service/src/main/java/com/bw/ocr/utils/DateUtil.java

@ -0,0 +1,177 @@
package com.bw.ocr.utils;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
/**
* 日期工具类
*
* @author jian.mao
* @date 2022年11月15日
* @description
*/
@Slf4j
public class DateUtil {
/**
* @return
*/
public static String getTimeStrForNow() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH");
return sdf.format(new Date());
}
public static String getTimeStrForDay(long time) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
return sdf.format(new Date(time * 1000));
}
public static String getTimeStrForDay() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
return sdf.format(new Date());
}
public static String getDateTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(new Date());
return time;
}
public static String getDateTime(Long timestap) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(new Date(timestap));
return time;
}
public static String getDate(Long timestap) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String time = sdf.format(new Date(timestap));
return time;
}
public static String getDateTimeForMonth() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
String time = sdf.format(new Date());
return time;
}
/**
* 休眠
*
* @param millis 毫秒
*/
public static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 1. @Description:时间戳转时间
* 2. @Author: ying.zhao
* 3. @Date: 2023/3/28
*/
public static String timestampToDate(String time) {
int thirteen = 13;
int ten = 10;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// if (time.length() == thirteen) {
if (time.length() > ten) {
return sdf.format(new Date(Long.parseLong(time)));
} else {
return sdf.format(new Date(Integer.parseInt(time) * 1000L));
}
}
public static String parseCreated(String jsonTime){
String formattedDateTime = getDateTime();
try {
// 使用fastjson解析JSON数据
JSONObject jsonObject = JSON.parseObject(jsonTime);
// 获取日期和时间的值
JSONObject dateObject = jsonObject.getJSONObject("date");
int day = dateObject.getIntValue("day");
int month = dateObject.getIntValue("month");
int year = dateObject.getIntValue("year");
JSONObject timeObject = jsonObject.getJSONObject("time");
int hour = timeObject.getIntValue("hour");
int minute = timeObject.getIntValue("minute");
int second = timeObject.getIntValue("second");
// 创建LocalDateTime对象
LocalDateTime dateTime = LocalDateTime.of(year, month, day, hour, minute, second);
// 定义日期时间格式化器
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 格式化日期时间
formattedDateTime = dateTime.format(formatter);
} catch (Exception e) {
log.info("日期转换失败:{}",e);
}
return formattedDateTime;
}
/**
* 字符串转换日期
* @param format
* @param date
* @return
*/
public static Date strToDate(String format,String date){
SimpleDateFormat sdf = new SimpleDateFormat(format);
if (date == null || date.equals("")){
return new Date();
}else{
Date ru = null;
try {
ru = sdf.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return ru;
}
}
/**
* 日期格式话
* @param format 日期格式
* @param dater 要转换的日期,默认当前时间
* @return
*/
public static String FormatDate(String format,Date date){
String fromatDate = null;
SimpleDateFormat sdf = new SimpleDateFormat(format);
if (date == null){
fromatDate = sdf.format(new Date());
}else{
fromatDate = sdf.format(date);
}
return fromatDate;
}
public static void main(String[] args) {
String time = timestampToDate("955814400000");
System.out.println(time);
}
}

1004
ocr-service/src/main/java/com/bw/ocr/utils/DownLoadUtil.java
File diff suppressed because it is too large
View File

27
ocr-service/src/main/java/com/bw/ocr/utils/EncryptionUtil.java

@ -0,0 +1,27 @@
package com.bw.ocr.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* @author jian.mao
* @date 2023年3月10日
* @description
*/
public class EncryptionUtil {
public static String md5(String text) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(text.getBytes());
byte[] bytes = md.digest();
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
}

41
ocr-service/src/main/java/com/bw/ocr/utils/FileUtil.java

@ -0,0 +1,41 @@
package com.bw.ocr.utils;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* 文件工具类
* @author jian.mao
* @date 2023年7月14日
* @description
*/
public class FileUtil {
/**
* 数据写入文件
* @param Path 文件路径
* @param result 数据
* @throws IOException
*/
public static void writeFile(String path,String result){
try {
FileWriter fw = new FileWriter(path,true);
fw.write(result+"\n");
fw.flush();
fw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void delFile(String path) {
try {
File file = new File(path);
file.delete();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}

53
ocr-service/src/main/java/com/bw/ocr/utils/GPTResultParseUtil.java

@ -0,0 +1,53 @@
package com.bw.ocr.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author:jinming
* @className:GPTResultParseUtil
* @version:1.0
* @description:
* @Date:2024/6/28 10:11
*/
public class GPTResultParseUtil {
public static Map<String, Object> parseGPTResult(Map<String, Object> output, String gptContent) {
Map<String, Object> jsonResult = new HashMap<>();
try {
// 替换```json, ``` \n
String jsonContent = gptContent.replace("```json", "").replace("```", "").replace("\n", "");
JSONObject jsonGPT = JSON.parseObject(jsonContent);
for (String key : output.keySet()) {
if (jsonGPT.containsKey(key)) {
jsonResult.put(key, jsonGPT.get(key));
}
}
return jsonResult;
} catch (JSONException e) {
try {
// 直接解析失败使用正则表达式匹配外层的 {}
Pattern pattern = Pattern.compile("\\{.*\\}", Pattern.DOTALL);
Matcher matcher = pattern.matcher(gptContent.replace("\n", ""));
if (matcher.find()) {
JSONObject jsonGPT = JSON.parseObject(matcher.group());
for (String key : output.keySet()) {
if (jsonGPT.containsKey(key)) {
jsonResult.put(key, jsonGPT.get(key));
}
}
return jsonResult;
} else {
return null;
}
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
}
}

33
ocr-service/src/main/java/com/bw/ocr/utils/OtherUtils.java

@ -0,0 +1,33 @@
package com.bw.ocr.utils;
import java.security.MessageDigest;
/**
* 其他工具类
* @author jian.mao
* @date 2023年9月19日
* @description
*/
public class OtherUtils {
public static String getMd5(String string) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] bs = md5.digest(string.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder(40);
for (byte x : bs) {
if ((x & 0xff) >> 4 == 0) {
sb.append("0").append(Integer.toHexString(x & 0xff));
} else {
sb.append(Integer.toHexString(x & 0xff));
}
}
return sb.toString();
} catch (Exception e) {
return "nceaform" + System.currentTimeMillis();
}
}
}

18
ocr-service/src/main/java/com/bw/ocr/utils/QueueUtil.java

@ -0,0 +1,18 @@
package com.bw.ocr.utils;
import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;
/**
* @author:jinming
* @className:QueueUtil
* @version:1.0
* @description:
* @Date:2023/7/13 15:00
*/
public class QueueUtil {
public static LinkedBlockingDeque<Map<String, Object>> taskQueue = new LinkedBlockingDeque<Map<String, Object>>();
public static LinkedBlockingDeque<String> sendQueue = new LinkedBlockingDeque<String>();
}

45
ocr-service/src/main/java/com/bw/ocr/utils/SpringBootKafka.java

@ -0,0 +1,45 @@
package com.bw.ocr.utils;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
/**
* @PROJECT_NAME: companybusinesscrawl
* @DESCRIPTION:SpringBootKafka 工具类
* @DATE: 2023/4/6 11:09
*/
@Slf4j
@Component
public class SpringBootKafka {
@Autowired
private KafkaTemplate<String, Object> kafkaTemplate;
/**
* 自定义topicKafkaTemplate
*/
/**
* public static final String TOPIC = "companyBussTest";
**/
public void send(String topic, String message) {
//发送消息
ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(topic, message);
future.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
@Override
public void onFailure(Throwable throwable) {
//发送失败的处理
log.info(topic + " - 生产者 发送消息失败:" + throwable.getMessage());
}
@Override
public void onSuccess(SendResult<String, Object> stringObjectSendResult) {
//成功的处理
log.info(topic + " - 生产者 发送消息成功" );
}
});
}
}

23
ocr-service/src/main/java/com/bw/ocr/utils/ThrowMessageUtil.java

@ -0,0 +1,23 @@
package com.bw.ocr.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* @author jian.mao
* @date 2023年3月22日
* @description
*/
public class ThrowMessageUtil {
/**
* 获取异常信息
* @param t
* @return
*/
public static String getErrmessage(Throwable t){
StringWriter stringWriter=new StringWriter();
t.printStackTrace(new PrintWriter(stringWriter,true));
return stringWriter.getBuffer().toString();
}
}

52
ocr-service/src/main/resources/bootstrap.yml

@ -0,0 +1,52 @@
# ==================== 必须文件:bootstrap.yml ====================
# 这个文件用于配置Nacos客户端,优先级最高
spring:
application:
name: ocr-service # 服务名,对应Nacos中的Data ID
cloud:
nacos:
# ======== 配置中心 ========
config:
server-addr: 127.0.0.1:8848 # Nacos地址
username: nacos # 用户名
password: nacos # 密码
group: public_dev # 分组
namespace: opai # 命名空间(默认public)
file-extension: yaml # 配置文件格式
timeout: 5000 # 超时时间(ms)
# 核心配置:开启动态刷新
refresh-enabled: true # 必须为true!
# 主配置文件(从Nacos加载)
data-id: ${spring.application.name}.${spring.cloud.nacos.config.file-extension}
# 共享配置文件(可选)
shared-configs[0]:
data-id: application.yaml # 公共配置
group: public_dev # 公共分组
namespace: opai
refresh: true # 公共配置也要刷新
# 扩展配置(可选)
# extension-configs[0]:
# data-id: datasource.yaml
# group: dev
# refresh: true
# ======== 服务发现 ========
discovery:
server-addr: ${spring.cloud.nacos.config.server-addr}
username: ${spring.cloud.nacos.config.username}
password: ${spring.cloud.nacos.config.password}
group: ${spring.cloud.nacos.config.group}
namespace: ${spring.cloud.nacos.config.namespace}
logging:
level:
root: info
com.alibaba.nacos.client.config.impl: WARN
file:
path: ../logs

36
ocr-service/src/main/resources/logback-spring.xml

@ -0,0 +1,36 @@
<configuration>
<!-- 属性文件:在properties文件中找到对应的配置项 -->
<springProperty scope="context" name="log-path" source="logging.file.path"/>
<!--<springProperty scope="context" name="logging.level" source="logging.level.com.bfd"/>-->
<!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->
<!-- <appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %line %-5level %logger{50} - %msg%n</Pattern>
</encoder>
</appender> -->
<appender name="GLMAPPER-LOGGERONE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>
${log-path}/ocr-service.log
</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${log-path}/ocr-service.log.%d{yyyy-MM-dd}</FileNamePattern>
<MaxHistory>7</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %line %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<root level="info">
<appender-ref ref="GLMAPPER-LOGGERONE"/>
<!-- <appender-ref ref="STDOUT"/> -->
</root>
</configuration>

40
opai-api/.classpath

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

3
opai-api/.gitignore

@ -0,0 +1,3 @@
/target/
/logs/
/.settings/

23
opai-api/.project

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>opai-api</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

173
opai-api/pom.xml

@ -0,0 +1,173 @@
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bw</groupId>
<artifactId>opai-service-center</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.bw</groupId>
<artifactId>opai-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>opai-api</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Spring Boot JDBC / MySQL 数据源 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MyBatis-Plus Boot Starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.17</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.bw.opai.Application</mainClass>
<layout>ZIP</layout>
<includes>
<include>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<type>jar</type>
<includeTypes>jar</includeTypes>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<!-- </pluginManagement> -->
</build>
</project>

19
opai-api/src/main/java/com/bw/opai/Application.java

@ -0,0 +1,19 @@
package com.bw.opai;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 系统接口启动类
* @author jian.mao
* @date 2025年12月30日
* @description
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

83
opai-api/src/main/java/com/bw/opai/app/controller/AppController.java

@ -0,0 +1,83 @@
package com.bw.opai.app.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.bw.opai.app.service.AppService;
import com.bw.opai.common.Res;
import lombok.extern.slf4j.Slf4j;
/**
* 应用控制层
* @author jian.mao
* @date 2025年12月31日
* @description
*/
@RestController
@Slf4j
@RefreshScope
@RequestMapping("/apps")
public class AppController {
@Autowired
private AppService appService;
/**
* 获取应用列表
* @param page 页码默认第1页
* @param limit 每页条数默认10条
* @return 应用列表
*/
@GetMapping("/list")
public Res<?> getApps(
@RequestParam(value = "page", defaultValue = "1", required = false) Integer page,
@RequestParam(value = "size", defaultValue = "10", required = false) Integer size) {
return appService.getApps(page, size);
}
/**
* 根据应用 ID 查询详情
* @param id 应用 ID
* @return 应用详情
*/
@GetMapping("/detail/{id}")
public Res<?> getAppDetail(@PathVariable("id") Integer id) {
return appService.getAppDetail(id);
}
/**
* 启动应用
* @param param JSON 请求参数
* @return 启动结果
*/
@PostMapping("/start")
public Res<?> startApp(@RequestBody Map<String, Object> param) {
return appService.startApp(param);
}
/**
* 查询当前登录用户的任务列表ES
*/
@GetMapping("/tasks")
public Res<?> getMyTasks(
@RequestParam(value = "page", defaultValue = "1", required = false) Integer page,
@RequestParam(value = "size", defaultValue = "10", required = false) Integer size) {
return appService.getMyTasks(page, size);
}
}

60
opai-api/src/main/java/com/bw/opai/app/dto/App.java

@ -0,0 +1,60 @@
package com.bw.opai.app.dto;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 应用表
* @author jian.mao
* @date 2026年1月4日
* @description
*/
@Data
@TableName("app")
public class App {
/**
* 应用id
*/
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private Integer createUserId;
private String createUser;
private Integer updateUserId;
private String updateUser;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
/**
* 删除标识
*/
@TableLogic
private Integer del;
/**
* 应用logo
*/
private String logo;
/**
* 功能
*/
private String feature;
/**
* 名称
*/
private String name;
/**
* 说明
*/
private String description;
/**
* 应用接口地址
*/
private String api;
}

49
opai-api/src/main/java/com/bw/opai/app/entity/AppResultDoc.java

@ -0,0 +1,49 @@
package com.bw.opai.app.entity;
import java.io.Serializable;
import java.util.Map;
import lombok.Data;
/**
* ES 索引opai_app_result
* 应用执行结果文档
*
* @author jian.mao
*/
@Data
public class AppResultDoc implements Serializable {
private static final long serialVersionUID = 1L;
/** 应用ID */
private Integer appId;
/** 应用名称 */
private String appName;
/** 用户ID */
private String userId;
/** 任务参数(可索引) */
private Map<String, Object> task;
/** 创建时间(毫秒时间戳) */
private Long createTime;
/** 完成时间(毫秒时间戳) */
private Long finishTime;
/** 执行状态 */
private Integer status;
/** 执行结果(可索引) */
private Map<String, Object> result;
/** 逻辑删除标识:0-未删除 1-已删除 */
private Integer del;
/** 最后修改时间(毫秒时间戳) */
private Long lastEdit;
}

18
opai-api/src/main/java/com/bw/opai/app/mapper/AppMapper.java

@ -0,0 +1,18 @@
package com.bw.opai.app.mapper;
import org.apache.ibatis.annotations.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bw.opai.app.dto.App;
/**
* 应用mapper
* @author jian.mao
* @date 2026年1月4日
* @description
*/
@Mapper
public interface AppMapper extends BaseMapper<App> {
}

44
opai-api/src/main/java/com/bw/opai/app/service/AppService.java

@ -0,0 +1,44 @@
package com.bw.opai.app.service;
import java.util.Map;
import com.bw.opai.common.Res;
/**
* 应用服务层接口
* @author jian.mao
* @date 2026年1月4日
* @description
*/
public interface AppService {
/**
* 应用列表
* @param page 页码数
* @param limit 条数
* @return
*/
public Res<?> getApps(Integer page,Integer size);
/**
* 根据id查询应用
* @param id
* @return
*/
public Res<?> getAppDetail(Integer id);
/**
* 应用启动
* @param param
* @return
*/
public Res<?> startApp(Map<String, Object> param);
/**
* 查询当前账号任务
* @param page
* @param size
* @return
*/
public Res<?> getMyTasks(Integer page, Integer size);
}

358
opai-api/src/main/java/com/bw/opai/app/service/impl/AppServiceImpl.java

@ -0,0 +1,358 @@
package com.bw.opai.app.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bw.opai.app.dto.App;
import com.bw.opai.app.entity.AppResultDoc;
import com.bw.opai.app.mapper.AppMapper;
import com.bw.opai.app.service.AppService;
import com.bw.opai.common.Res;
import com.bw.opai.utils.Constants;
import com.bw.opai.utils.DownLoadUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
@RefreshScope
@RequiredArgsConstructor
public class AppServiceImpl implements AppService {
private final AppMapper appMapper;
@Value("${elasticsearch.url}")
private String esUrl;
@Value("${elasticsearch.username}")
private String esUser;
@Value("${elasticsearch.password}")
private String esPassword;
@Value("${elasticsearch.index-name}")
private String indexName;
@Override
public Res<?> getApps(Integer page, Integer size) {
// 参数校验
if (page == null || page < 1) {
page = 1;
}
if (size == null || size < 1 || size > 100) {
// 限制最大查询条数防止过度查询
size = 10;
}
try {
Page<App> pageParam = new Page<>(page, size);
QueryWrapper<App> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("del", 0);
Page<App> result = appMapper.selectPage(pageParam, queryWrapper);
// 调用公共分页封装方法
return Res.page(result);
} catch (Exception e) {
log.error("查询应用列表失败", e);
return Res.fail("查询应用列表失败");
}
}
@Override
public Res<?> getAppDetail(Integer id) {
try {
if (id == null || id <= 0) {
return Res.fail("应用ID不合法");
}
// 根据 ID 查询
App app = appMapper.selectById(id);
// del = 0 表示未删除
if (app == null || app.getDel() != 0) {
return Res.fail("未找到对应应用");
}
return Res.ok(app);
} catch (Exception e) {
log.error("查询应用详情失败, id={}", id, e);
return Res.fail("查询应用详情失败");
}
}
@Override
public Res<?> startApp(Map<String, Object> param) {
// TODO Auto-generated method stub
if (param == null || param.isEmpty()) {
return Res.fail("请求参数不能为空");
}
try {
// 这里写你的启动逻辑
// 比如获取应用ID -> 更新状态 -> 返回结果
Integer appId = param.get("id") == null ? null : Integer.valueOf(param.get("id").toString());
if (appId == null) {
return Res.fail("应用ID不能为空");
}
//任务id校验
String taskId = param.get("taskId") == null||param.get("taskId").toString().equals("")? null : param.get("taskId").toString();
if (taskId == null) {
return Res.fail("任务ID不能为空");
}
// 伪示例根据 ID 查询应用并启动
App app = appMapper.selectById(appId);
if (app == null || app.getDel() != 0) {
return Res.fail("未找到对应应用");
}
//应用调用
String appUrl = app.getApi();
String downloadRes = DownLoadUtil.doPost(appUrl, JSONObject.toJSONString(param));
if (downloadRes.contains(Constants.DOWNLOAD_ERROR_SUFFIX)) {
//下载失败直接返回
log.error("启动应用请求异常, param={},download error:{}", param, downloadRes);
return Res.fail("启动应用请求异常");
}
//任务记录写入es
long now = System.currentTimeMillis();
AppResultDoc esEntity = new AppResultDoc();
esEntity.setAppId(app.getId());
esEntity.setAppName(app.getName());
//用户token -- 先给默认值
esEntity.setUserId("1");
esEntity.setTask(param);
esEntity.setResult(null);
esEntity.setCreateTime(now);
esEntity.setFinishTime(null);
// 运行中 0 是运行中1是完成2是失败
esEntity.setStatus(0);
esEntity.setDel(0);
esEntity.setLastEdit(now);
// ---------- 写入 ES ----------
boolean isSuccess = save(esEntity, taskId);
if(!isSuccess) {
//记录写入失败直接返回错误信息
log.error("启动应用记录写入异常, param={}", param);
return Res.fail("启动应用记录写入异常");
}
// ---------- 返回 ----------
return Res.ok(esEntity);
} catch (Exception e) {
log.error("启动应用未知异常, param={}", param, e);
return Res.fail("启动应用未知异常");
}
}
/**
* 节点数据持久化
* @param esEntity
* @return
*/
private boolean save(AppResultDoc esEntity,String docId){
// 创建凭据提供者
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(esUser, esPassword));
// 创建一个 HttpClient设置凭据提供者
CloseableHttpClient httpClient = null;
try {
// 创建一个 HTTP POST 请求用于写入数据到索引
if(esUser != null && !esUser.trim().equals(Constants.EMPTY)){
// 创建凭据提供者
httpClient = HttpClients.custom()
.setDefaultCredentialsProvider(credentialsProvider)
.build();
}else{
httpClient = HttpClients.custom().build();
}
StringBuffer host = new StringBuffer();
host.append(esUrl);
host.append("/");
host.append(indexName);
host.append("/_doc/");
// Elasticsearch主机索引名称和文档ID
host.append(docId);
HttpPost httpPost = new HttpPost(host.toString());
// 设置请求体包含要写入的文档数据
StringEntity entity = new StringEntity(JSONObject.toJSONString(esEntity), ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 发送请求并获取响应
HttpResponse response = httpClient.execute(httpPost);
// 处理响应
int statusCode = response.getStatusLine().getStatusCode();
String responseBody = EntityUtils.toString(response.getEntity());
int code = 201;
int updateCode = 200;
if (statusCode == code) {
log.info("数据成功写入到索引:{},文档ID:{},appid:{},userId:{}",indexName,docId,esEntity.getAppId(),esEntity.getUserId());
return true;
}else if(statusCode == updateCode){
log.info("数据成功更新到索引:{},文档ID:{},appid:{},userId:{}",indexName,docId,esEntity.getAppId(),esEntity.getUserId());
return true;
} else {
log.error("数据写入失败:{},文档ID:{},appid:{},es响应内容:{}",indexName,docId,esEntity.getAppId(),responseBody);
return false;
}
} catch (Exception e) {
log.error("数据写入异常:",e);
return false;
} finally {
try {
if(httpClient != null) {
httpClient.close();
}
} catch (Exception ignored){}
}
}
@Override
public Res<?> getMyTasks(Integer page, Integer size) {
if (page == null || page < 1) {
page = 1;
}
if (size == null || size < 1 || size > 100) {
size = 10;
}
// 从登录上下文获取 userId你项目里已有 先写死
String userId = "1";
if (userId == null || userId.trim().equals("")) {
return Res.fail("未获取到用户信息");
}
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials(esUser, esPassword)
);
CloseableHttpClient httpClient = null;
try {
if (esUser != null && !esUser.trim().equals("")) {
httpClient = HttpClients.custom()
.setDefaultCredentialsProvider(credentialsProvider)
.build();
} else {
httpClient = HttpClients.custom().build();
}
// ================== 构建查询 DSL ==================
int from = (page - 1) * size;
Map<String, Object> query = new HashMap<String, Object>();
query.put("from", from);
query.put("size", size);
// must 条件
List<Map<String, Object>> mustList = new ArrayList<Map<String, Object>>();
Map<String, Object> termUser = new HashMap<String, Object>();
termUser.put("userId", userId);
Map<String, Object> termUserWrap = new HashMap<String, Object>();
termUserWrap.put("term", termUser);
mustList.add(termUserWrap);
Map<String, Object> termDel = new HashMap<String, Object>();
termDel.put("del", 0);
Map<String, Object> termDelWrap = new HashMap<String, Object>();
termDelWrap.put("term", termDel);
mustList.add(termDelWrap);
Map<String, Object> bool = new HashMap<String, Object>();
bool.put("must", mustList);
Map<String, Object> queryBody = new HashMap<String, Object>();
queryBody.put("bool", bool);
query.put("query", queryBody);
// sort
List<Map<String, Object>> sortList = new ArrayList<Map<String, Object>>();
Map<String, Object> order = new HashMap<String, Object>();
order.put("order", "desc");
Map<String, Object> sortField = new HashMap<String, Object>();
sortField.put("createTime", order);
sortList.add(sortField);
query.put("sort", sortList);
// ================== 发起 HTTP 请求 ==================
StringBuffer host = new StringBuffer();
host.append(esUrl)
.append("/")
.append(indexName)
.append("/_search");
HttpPost httpPost = new HttpPost(host.toString());
httpPost.setHeader("Content-Type", "application/json");
StringEntity entity = new StringEntity(
JSONObject.toJSONString(query),
ContentType.APPLICATION_JSON
);
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
if (statusCode != 200) {
log.error("ES 查询失败 status={}, body={}", statusCode, responseBody);
return Res.fail("ES 查询失败");
}
// ================== 解析返回 ==================
JSONObject json = JSONObject.parseObject(responseBody);
JSONObject hits = json.getJSONObject("hits");
Long total = hits.getJSONObject("total").getLong("value");
List<AppResultDoc> list = new ArrayList<AppResultDoc>();
JSONArray hitList = hits.getJSONArray("hits");
for (int i = 0; i < hitList.size(); i++) {
JSONObject source = hitList.getJSONObject(i).getJSONObject("_source");
AppResultDoc item = source.toJavaObject(AppResultDoc.class);
list.add(item);
}
Map<String, Object> result = new HashMap<String, Object>();
result.put("page", page);
result.put("size", size);
result.put("total", total);
result.put("list", list);
return Res.ok(result);
} catch (Exception e) {
log.error("查询用户任务失败 userId={}", userId, e);
return Res.fail("查询任务失败");
} finally {
if (httpClient != null) {
try {
httpClient.close();
} catch (Exception ignored) {}
}
}
}
}

81
opai-api/src/main/java/com/bw/opai/common/Res.java

@ -0,0 +1,81 @@
package com.bw.opai.common;
import java.util.HashMap;
import java.util.Map;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
/**
* 通用返回对象
*
* @author jian.mao
* @date 2025年9月17日
* @description
* @param <T>
*/
public class Res<T> {
private int resCode;
private String resMsg;
private T data;
public Res() {
}
public Res(int resCode, String resMsg, T data) {
this.resCode = resCode;
this.resMsg = resMsg;
this.data = data;
}
/**
* 分页结果封装
* @param page MyBatis-Plus 分页对象
* @param <T> 实体类型
* @return Res<Map> 包含 total/page/size/records
*/
public static <T> Res<Map<String, Object>> page(Page<T> page) {
Map<String, Object> pageData = new HashMap<>();
pageData.put("total", page.getTotal());
pageData.put("page", page.getCurrent());
pageData.put("size", page.getSize());
pageData.put("records", page.getRecords());
return Res.ok(pageData);
}
public static <T> Res<T> ok(T data) {
return new Res<T>(ResponseCode.SUCCESS.code(), ResponseCode.SUCCESS.message(), data);
}
public static <T> Res<T> fail(String msg) {
return new Res<T>(ResponseCode.FAIL.code(), msg, null);
}
public static <T> Res<T> checkError(T error) {
return new Res<T>(ResponseCode.FAIL.code(), ResponseCode.CHECKERROR.message(), error);
}
// getter & setter
public int getResCode() {
return resCode;
}
public void setResCode(int resCode) {
this.resCode = resCode;
}
public String getResMsg() {
return resMsg;
}
public void setResMsg(String resMsg) {
this.resMsg = resMsg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}

30
opai-api/src/main/java/com/bw/opai/common/ResponseCode.java

@ -0,0 +1,30 @@
package com.bw.opai.common;
/**
* 状态码管理
* @author jian.mao
* @date 2025年9月17日
* @description
*/
public enum ResponseCode {
SUCCESS(0, "success"),
FAIL(-1, "fail"),
CHECKERROR(400, "paramsError");
private final int code;
private final String message;
ResponseCode(int code, String message) {
this.code = code;
this.message = message;
}
public int code() {
return code;
}
public String message() {
return message;
}
}

34
opai-api/src/main/java/com/bw/opai/file/controller/FileController.java

@ -0,0 +1,34 @@
package com.bw.opai.file.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.bw.opai.common.Res;
import com.bw.opai.file.service.FileService;
import lombok.extern.slf4j.Slf4j;
/**
* 文件操作控制层
* @author jian.mao
* @date 2026年1月6日
* @description
*/
@RestController
@Slf4j
@RefreshScope
@RequestMapping("/file")
public class FileController {
@Autowired
private FileService fileService;
@PostMapping("/upload")
public Res<?> uploadFile(@RequestParam("file") MultipartFile file) {
return fileService.uploadFile(file);
}
}

16
opai-api/src/main/java/com/bw/opai/file/service/FileService.java

@ -0,0 +1,16 @@
package com.bw.opai.file.service;
import org.springframework.web.multipart.MultipartFile;
import com.bw.opai.common.Res;
/**
* 文件操作业务接口
* @author jian.mao
* @date 2026年1月6日
* @description
*/
public interface FileService {
public Res<?> uploadFile(MultipartFile file);
}

107
opai-api/src/main/java/com/bw/opai/file/service/impl/FileServiceImpl.java

@ -0,0 +1,107 @@
package com.bw.opai.file.service.impl;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.JSONObject;
import com.bw.opai.common.Res;
import com.bw.opai.file.service.FileService;
import lombok.extern.slf4j.Slf4j;
/**
* 文件操作服务实现类
* @author jian.mao
* @date 2026年1月6日
* @description
*/
@Service
@Slf4j
@RefreshScope
public class FileServiceImpl implements FileService {
@Value("${gofast.upload-url}")
private String gofastUploadUrl;
@Value("${gofast.access-prefix}")
private String gofastAccessPrefix;
@Override
public Res<?> uploadFile(MultipartFile file) {
if (file == null || file.isEmpty()) {
return Res.fail("上传文件不能为空");
}
CloseableHttpClient httpClient = HttpClients.createDefault();
try {
HttpPost httpPost = new HttpPost(gofastUploadUrl);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
// 文件流
builder.addBinaryBody(
"file",
file.getInputStream(),
ContentType.APPLICATION_OCTET_STREAM,
file.getOriginalFilename()
);
// 👇 关键要求 GoFast 返回 JSON
builder.addTextBody("output", "json");
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
CloseableHttpResponse response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
log.info("GoFast upload response: {}", responseBody);
if (statusCode != 200) {
return Res.fail("文件服务器上传失败");
}
// 解析返回 JSON
JSONObject json = JSONObject.parseObject(responseBody);
// 根据你 GoFast 实际返回字段调整
String path = json.getString("path");
String url = gofastAccessPrefix + path;
Map<String, Object> result = new HashMap<String, Object>();
result.put("fileName", file.getOriginalFilename());
result.put("fileSize", file.getSize());
result.put("url", url);
return Res.ok(result);
} catch (Exception e) {
log.error("上传到 GoFast 失败", e);
return Res.fail("文件上传失败");
} finally {
try {
httpClient.close();
} catch (Exception ignored) {}
}
}
}

19
opai-api/src/main/java/com/bw/opai/utils/Constants.java

@ -0,0 +1,19 @@
package com.bw.opai.utils;
/**
* 常量类
* @author jian.mao
* @date 2025年11月6日
* @description
*/
public class Constants {
/***空常量****/
public static final String EMPTY = "";
/**
* 请求失败结果前缀
*/
public static final String DOWNLOAD_ERROR_SUFFIX = "Download failed error is:";
}

177
opai-api/src/main/java/com/bw/opai/utils/DateUtil.java

@ -0,0 +1,177 @@
package com.bw.opai.utils;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
/**
* 日期工具类
*
* @author jian.mao
* @date 2022年11月15日
* @description
*/
@Slf4j
public class DateUtil {
/**
* @return
*/
public static String getTimeStrForNow() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH");
return sdf.format(new Date());
}
public static String getTimeStrForDay(long time) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
return sdf.format(new Date(time * 1000));
}
public static String getTimeStrForDay() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
return sdf.format(new Date());
}
public static String getDateTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(new Date());
return time;
}
public static String getDateTime(Long timestap) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(new Date(timestap));
return time;
}
public static String getDate(Long timestap) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String time = sdf.format(new Date(timestap));
return time;
}
public static String getDateTimeForMonth() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
String time = sdf.format(new Date());
return time;
}
/**
* 休眠
*
* @param millis 毫秒
*/
public static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 1. @Description:时间戳转时间
* 2. @Author: ying.zhao
* 3. @Date: 2023/3/28
*/
public static String timestampToDate(String time) {
int thirteen = 13;
int ten = 10;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// if (time.length() == thirteen) {
if (time.length() > ten) {
return sdf.format(new Date(Long.parseLong(time)));
} else {
return sdf.format(new Date(Integer.parseInt(time) * 1000L));
}
}
public static String parseCreated(String jsonTime){
String formattedDateTime = getDateTime();
try {
// 使用fastjson解析JSON数据
JSONObject jsonObject = JSON.parseObject(jsonTime);
// 获取日期和时间的值
JSONObject dateObject = jsonObject.getJSONObject("date");
int day = dateObject.getIntValue("day");
int month = dateObject.getIntValue("month");
int year = dateObject.getIntValue("year");
JSONObject timeObject = jsonObject.getJSONObject("time");
int hour = timeObject.getIntValue("hour");
int minute = timeObject.getIntValue("minute");
int second = timeObject.getIntValue("second");
// 创建LocalDateTime对象
LocalDateTime dateTime = LocalDateTime.of(year, month, day, hour, minute, second);
// 定义日期时间格式化器
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 格式化日期时间
formattedDateTime = dateTime.format(formatter);
} catch (Exception e) {
log.info("日期转换失败:{}",e);
}
return formattedDateTime;
}
/**
* 字符串转换日期
* @param format
* @param date
* @return
*/
public static Date strToDate(String format,String date){
SimpleDateFormat sdf = new SimpleDateFormat(format);
if (date == null || date.equals("")){
return new Date();
}else{
Date ru = null;
try {
ru = sdf.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return ru;
}
}
/**
* 日期格式话
* @param format 日期格式
* @param dater 要转换的日期,默认当前时间
* @return
*/
public static String FormatDate(String format,Date date){
String fromatDate = null;
SimpleDateFormat sdf = new SimpleDateFormat(format);
if (date == null){
fromatDate = sdf.format(new Date());
}else{
fromatDate = sdf.format(date);
}
return fromatDate;
}
public static void main(String[] args) {
String time = timestampToDate("955814400000");
System.out.println(time);
}
}

1005
opai-api/src/main/java/com/bw/opai/utils/DownLoadUtil.java
File diff suppressed because it is too large
View File

23
opai-api/src/main/java/com/bw/opai/utils/ThrowMessageUtil.java

@ -0,0 +1,23 @@
package com.bw.opai.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* @author jian.mao
* @date 2023年3月22日
* @description
*/
public class ThrowMessageUtil {
/**
* 获取异常信息
* @param t
* @return
*/
public static String getErrmessage(Throwable t){
StringWriter stringWriter=new StringWriter();
t.printStackTrace(new PrintWriter(stringWriter,true));
return stringWriter.getBuffer().toString();
}
}

52
opai-api/src/main/resources/bootstrap.yml

@ -0,0 +1,52 @@
# ==================== 必须文件:bootstrap.yml ====================
# 这个文件用于配置Nacos客户端,优先级最高
spring:
application:
name: opai-api # 服务名,对应Nacos中的Data ID
cloud:
nacos:
# ======== 配置中心 ========
config:
server-addr: 127.0.0.1:8848 # Nacos地址
username: nacos # 用户名
password: nacos # 密码
group: public_dev # 分组
namespace: opai # 命名空间(默认public)
file-extension: yaml # 配置文件格式
timeout: 5000 # 超时时间(ms)
# 核心配置:开启动态刷新
refresh-enabled: true # 必须为true!
# 主配置文件(从Nacos加载)
data-id: ${spring.application.name}.${spring.cloud.nacos.config.file-extension}
# 共享配置文件(可选)
shared-configs[0]:
data-id: application.yaml # 公共配置
group: public_dev # 公共分组
namespace: opai
refresh: true # 公共配置也要刷新
# 扩展配置(可选)
# extension-configs[0]:
# data-id: datasource.yaml
# group: dev
# refresh: true
# ======== 服务发现 ========
discovery:
server-addr: ${spring.cloud.nacos.config.server-addr}
username: ${spring.cloud.nacos.config.username}
password: ${spring.cloud.nacos.config.password}
group: ${spring.cloud.nacos.config.group}
namespace: ${spring.cloud.nacos.config.namespace}
logging:
level:
root: info
com.alibaba.nacos.client.config.impl: WARN
file:
path: ../logs

36
opai-api/src/main/resources/logback-spring.xml

@ -0,0 +1,36 @@
<configuration>
<!-- 属性文件:在properties文件中找到对应的配置项 -->
<springProperty scope="context" name="log-path" source="logging.file.path"/>
<!--<springProperty scope="context" name="logging.level" source="logging.level.com.bfd"/>-->
<!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->
<!-- <appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %line %-5level %logger{50} - %msg%n</Pattern>
</encoder>
</appender> -->
<appender name="GLMAPPER-LOGGERONE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>
${log-path}/opai-api.log
</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${log-path}/opai-api.log.%d{yyyy-MM-dd}</FileNamePattern>
<MaxHistory>7</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %line %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<root level="info">
<appender-ref ref="GLMAPPER-LOGGERONE"/>
<!-- <appender-ref ref="STDOUT"/> -->
</root>
</configuration>

37
pom.xml

@ -1,6 +1,41 @@
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.bw</groupId> <groupId>com.bw</groupId>
<artifactId>opai-service-center</artifactId> <artifactId>opai-service-center</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>opai-api</module>
<module>ocr-service</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<!-- Spring Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR9</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Alibaba -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project> </project>
Loading…
Cancel
Save