Ver código fonte

项目升级修改

master
Searises Hao Wang 4 semanas atrás
pai
commit
f972cd9932
9 arquivos alterados com 477 adições e 18 exclusões
  1. +7
    -7
      src/main/java/com/example/webapi/config/SwaggerConfig.java
  2. +62
    -0
      src/main/java/com/example/webapi/entity/OnceWeighing.java
  3. +62
    -0
      src/main/java/com/example/webapi/entity/postgresql/OnceWeighingPostgreSQL.java
  4. +16
    -0
      src/main/java/com/example/webapi/repository/OnceWeighingRepository.java
  5. +17
    -0
      src/main/java/com/example/webapi/repository/pg/OnceWeighingPostgreSQLRepository.java
  6. +186
    -0
      src/main/java/com/example/webapi/service/DataSyncService.java
  7. +37
    -8
      src/main/java/com/example/webapi/service/ScheduledSyncService.java
  8. +76
    -0
      src/main/resources/application-xining.yml
  9. +14
    -3
      start.sh

+ 7
- 7
src/main/java/com/example/webapi/config/SwaggerConfig.java Ver arquivo

@@ -43,7 +43,7 @@ public class SwaggerConfig {
.tags(new springfox.documentation.service.Tag("车辆管理", "车辆信息相关接口"))
.tags(new springfox.documentation.service.Tag("称重记录", "称重记录相关接口"));
}
/**
* API信息配置
*/
@@ -55,7 +55,7 @@ public class SwaggerConfig {
.contact(new Contact("开发团队", "http://www.example.com", "dev@example.com"))
.build();
}
/**
* 获取全局请求参数
* 注意:在Swagger UI中这些参数设置为非必需,以便能够正常访问Swagger界面
@@ -63,7 +63,7 @@ public class SwaggerConfig {
*/
private List<Parameter> getGlobalParameters() {
List<Parameter> parameters = new ArrayList<>();
// AK (Access Key) - 在Swagger中设为非必需,便于测试
Parameter akParam = new ParameterBuilder()
.name("ak")
@@ -73,7 +73,7 @@ public class SwaggerConfig {
.required(false) // 改为false,让Swagger UI可以正常访问
.build();
parameters.add(akParam);
// Timestamp - 在Swagger中设为非必需,便于测试
Parameter timestampParam = new ParameterBuilder()
.name("timestamp")
@@ -83,7 +83,7 @@ public class SwaggerConfig {
.required(false) // 改为false,让Swagger UI可以正常访问
.build();
parameters.add(timestampParam);
// Signature - 在Swagger中设为非必需,便于测试
Parameter signatureParam = new ParameterBuilder()
.name("signature")
@@ -93,7 +93,7 @@ public class SwaggerConfig {
.required(false) // 改为false,让Swagger UI可以正常访问
.build();
parameters.add(signatureParam);
return parameters;
}
}
}

+ 62
- 0
src/main/java/com/example/webapi/entity/OnceWeighing.java Ver arquivo

@@ -0,0 +1,62 @@
package com.example.webapi.entity;

import lombok.Data;
import javax.persistence.*;
import java.util.Date;

@Data
@Entity
@Table(name = "TB_ONCEWEIGHING")
public class OnceWeighing {
@Id
@Column(name = "NODEID", length = 22, nullable = false)
private String nodeId;

@Column(name = "LISTID", length = 18)
private String listId;

@Column(name = "WEIGHT")
private Double weight;

@Column(name = "SPEED")
private Double speed;

@Column(name = "NODETIME")
private Date nodeTime;

@Column(name = "OPERATORID", length = 8)
private String operatorId;

@Column(name = "VEHICLETYPE", length = 10)
private String vehicleType;

@Column(name = "VEHICLEID", length = 10)
private String vehicleId;

@Column(name = "MANAGEFLAG")
private Boolean manageFlag;

@Column(name = "SNAPPICTIME", length = 14)
private String snapPicTime;

@Column(name = "UPLOADFLAG")
private Boolean uploadFlag;

@Column(name = "USELESSFLAG")
private Boolean uselessFlag;

@Column(name = "DEMO", length = 50)
private String demo;

@Column(name = "SCALEID", length = 10)
private String scaleId;

@Column(name = "GROSSORTARE", length = 1)
private String grossOrTare;

@Column(name = "BEFOREANDAFTERSLANTCARRY")
private Double beforeAndAfterSlantCarry;

@Column(name = "LEFTANDRIGHTLANTCARRY")
private Double leftAndRightLantCarry;
}

+ 62
- 0
src/main/java/com/example/webapi/entity/postgresql/OnceWeighingPostgreSQL.java Ver arquivo

@@ -0,0 +1,62 @@
package com.example.webapi.entity.postgresql;

import lombok.Data;
import javax.persistence.*;
import java.util.Date;

@Data
@Entity
@Table(name = "tb_once_weighing")
public class OnceWeighingPostgreSQL {
@Id
@Column(name = "node_id", length = 22, nullable = false)
private String nodeId;

@Column(name = "list_id", length = 18)
private String listId;

@Column(name = "weight")
private Double weight;

@Column(name = "speed")
private Double speed;

@Column(name = "node_time")
private Date nodeTime;

@Column(name = "operator_id", length = 8)
private String operatorId;

@Column(name = "vehicle_type", length = 10)
private String vehicleType;

@Column(name = "vehicle_id", length = 10)
private String vehicleId;

@Column(name = "manage_flag")
private Boolean manageFlag;

@Column(name = "snap_pic_time", length = 14)
private String snapPicTime;

@Column(name = "upload_flag")
private Boolean uploadFlag;

@Column(name = "useless_flag")
private Boolean uselessFlag;

@Column(name = "demo", length = 50)
private String demo;

@Column(name = "scale_id", length = 10)
private String scaleId;

@Column(name = "gross_or_tare", length = 1)
private String grossOrTare;

@Column(name = "before_and_after_slant_carry")
private Double beforeAndAfterSlantCarry;

@Column(name = "left_and_right_lant_carry")
private Double leftAndRightLantCarry;
}

+ 16
- 0
src/main/java/com/example/webapi/repository/OnceWeighingRepository.java Ver arquivo

@@ -0,0 +1,16 @@
package com.example.webapi.repository;

import com.example.webapi.entity.OnceWeighing;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;
import java.util.List;

@Repository("onceWeighingRepository")
public interface OnceWeighingRepository extends JpaRepository<OnceWeighing, String>, JpaSpecificationExecutor<OnceWeighing> {
List<OnceWeighing> findByUploadFlag(Boolean uploadFlag);
List<OnceWeighing> findByNodeTimeAfter(java.util.Date nodeTime);
Page<OnceWeighing> findByNodeTimeNotNullOrderByNodeTimeDesc(Pageable pageable);
}

+ 17
- 0
src/main/java/com/example/webapi/repository/pg/OnceWeighingPostgreSQLRepository.java Ver arquivo

@@ -0,0 +1,17 @@
package com.example.webapi.repository.pg;

import com.example.webapi.entity.postgresql.OnceWeighingPostgreSQL;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;

@Repository
public interface OnceWeighingPostgreSQLRepository extends JpaRepository<OnceWeighingPostgreSQL, String> {
@Query("SELECT o FROM OnceWeighingPostgreSQL o WHERE o.uploadFlag = :uploadFlag")
List<OnceWeighingPostgreSQL> findByUploadFlag(@Param("uploadFlag") Boolean uploadFlag);

@Query("SELECT MAX(o.nodeTime) FROM OnceWeighingPostgreSQL o WHERE o.nodeTime IS NOT NULL")
java.util.Date findMaxNodeTime();
}

+ 186
- 0
src/main/java/com/example/webapi/service/DataSyncService.java Ver arquivo

@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class DataSyncService {
@@ -34,6 +35,13 @@ public class DataSyncService {
@Qualifier("twiceWeighingPostgreSQLRepository")
private TwiceWeighingPostgreSQLRepository twiceWeighingPostgreSQLRepository;

@Autowired
@Qualifier("onceWeighingRepository")
private com.example.webapi.repository.OnceWeighingRepository onceWeighingRepository;

@Autowired
private com.example.webapi.repository.pg.OnceWeighingPostgreSQLRepository onceWeighingPostgreSQLRepository;

/**
* 同步单条数据
*/
@@ -349,4 +357,182 @@ public class DataSyncService {
target.setIronNumber(source.getIronNumber());
target.setDirection(source.getDirection());
}

/**
* 一次过磅-同步所有未上传的数据 - 分批处理
*/
@Transactional(transactionManager = "postgresqlTransactionManager")
public int syncOnceUnuploadedRecords() {
return syncOnceUnuploadedRecords(500);
}

/**
* 一次过磅-同步所有未上传的数据 - 指定批次大小
*/
@Transactional(transactionManager = "postgresqlTransactionManager")
public int syncOnceUnuploadedRecords(int batchSize) {
try {
List<com.example.webapi.entity.OnceWeighing> unuploadedRecords = onceWeighingRepository.findByUploadFlag(false);
int totalRecords = unuploadedRecords.size();
int successCount = 0;
int batchCount = 0;
for (int i = 0; i < totalRecords; i += batchSize) {
int endIndex = Math.min(i + batchSize, totalRecords);
List<com.example.webapi.entity.OnceWeighing> batchRecords = unuploadedRecords.subList(i, endIndex);
batchCount++;
int batchSuccessCount = processOnceBatch(batchRecords);
successCount += batchSuccessCount;
}
return successCount;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}

/**
* 一次过磅-全量同步
*/
@Transactional(transactionManager = "postgresqlTransactionManager")
public int syncOnceAllData() {
return syncOnceAllData(500);
}

@Transactional(transactionManager = "postgresqlTransactionManager")
public int syncOnceAllData(int batchSize) {
try {
List<com.example.webapi.entity.OnceWeighing> allRecords = onceWeighingRepository.findAll();
// org.springframework.data.domain.PageRequest pageRequest = org.springframework.data.domain.PageRequest.of(0, 500, org.springframework.data.domain.Sort.by(org.springframework.data.domain.Sort.Direction.DESC, "nodeTime"));
// List<com.example.webapi.entity.OnceWeighing> allRecords = onceWeighingRepository.findByNodeTimeNotNullOrderByNodeTimeDesc(pageRequest).getContent();
int totalRecords = allRecords.size();
int successCount = 0;
int batchCount = 0;
for (int i = 0; i < totalRecords; i += batchSize) {
int endIndex = Math.min(i + batchSize, totalRecords);
List<com.example.webapi.entity.OnceWeighing> batchRecords = allRecords.subList(i, endIndex);
batchCount++;
int batchSuccessCount = processOnceBatch(batchRecords);
successCount += batchSuccessCount;
}
return successCount;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}

/**
* 一次过磅-增量同步(基于node_time,数据库层面过滤)
*/
@Transactional(transactionManager = "postgresqlTransactionManager")
public int syncOnceIncrementalData() {
try {
// 获取PostgreSQL中最大的node_time(数据库层面)
java.util.Date maxNodeTime = onceWeighingPostgreSQLRepository.findMaxNodeTime();
if (maxNodeTime == null) {
return syncOnceAllData();
}
// 数据库层面过滤增量数据
List<com.example.webapi.entity.OnceWeighing> incrementalRecords = onceWeighingRepository.findByNodeTimeAfter(maxNodeTime);
int successCount = 0;
for (com.example.webapi.entity.OnceWeighing source : incrementalRecords) {
try {
com.example.webapi.entity.postgresql.OnceWeighingPostgreSQL target = convertOnceToPostgreSQL(source);
java.util.Optional<com.example.webapi.entity.postgresql.OnceWeighingPostgreSQL> existingRecord = onceWeighingPostgreSQLRepository.findById(source.getNodeId());
if (existingRecord.isPresent()) {
com.example.webapi.entity.postgresql.OnceWeighingPostgreSQL existing = existingRecord.get();
updateOncePostgreSQLRecord(existing, source);
onceWeighingPostgreSQLRepository.saveAndFlush(existing);
} else {
onceWeighingPostgreSQLRepository.saveAndFlush(target);
}
successCount++;
} catch (Exception e) {
System.err.println("同步记录失败,NODEID: " + source.getNodeId() + ", 错误: " + e.getMessage());
}
}
return successCount;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}

/**
* 一次过磅-批量处理
*/
private int processOnceBatch(List<com.example.webapi.entity.OnceWeighing> batchRecords) {
int successCount = 0;
List<com.example.webapi.entity.postgresql.OnceWeighingPostgreSQL> entitiesToSave = new java.util.ArrayList<>();
for (com.example.webapi.entity.OnceWeighing source : batchRecords) {
try {
com.example.webapi.entity.postgresql.OnceWeighingPostgreSQL target = convertOnceToPostgreSQL(source);
entitiesToSave.add(target);
successCount++;
} catch (Exception e) {
System.err.println("处理记录失败,NODEID: " + source.getNodeId() + ", 错误: " + e.getMessage());
}
}
if (!entitiesToSave.isEmpty()) {
try {
onceWeighingPostgreSQLRepository.saveAllAndFlush(entitiesToSave);
} catch (Exception e) {
for (com.example.webapi.entity.postgresql.OnceWeighingPostgreSQL entity : entitiesToSave) {
try {
onceWeighingPostgreSQLRepository.save(entity);
} catch (Exception ex) {
System.err.println("单条插入失败,NODEID: " + entity.getNodeId() + ", 错误: " + ex.getMessage());
}
}
}
}
return successCount;
}

/**
* 一次过磅-SQLServer实体转PostgreSQL实体
*/
private com.example.webapi.entity.postgresql.OnceWeighingPostgreSQL convertOnceToPostgreSQL(com.example.webapi.entity.OnceWeighing source) {
com.example.webapi.entity.postgresql.OnceWeighingPostgreSQL target = new com.example.webapi.entity.postgresql.OnceWeighingPostgreSQL();
target.setNodeId(source.getNodeId());
target.setListId(source.getListId());
target.setWeight(source.getWeight());
target.setSpeed(source.getSpeed());
target.setNodeTime(source.getNodeTime());
target.setOperatorId(source.getOperatorId());
target.setVehicleType(source.getVehicleType());
target.setVehicleId(source.getVehicleId());
target.setManageFlag(source.getManageFlag());
target.setSnapPicTime(source.getSnapPicTime());
target.setUploadFlag(source.getUploadFlag());
target.setUselessFlag(source.getUselessFlag());
target.setDemo(source.getDemo());
target.setScaleId(source.getScaleId());
target.setGrossOrTare(source.getGrossOrTare());
target.setBeforeAndAfterSlantCarry(source.getBeforeAndAfterSlantCarry());
target.setLeftAndRightLantCarry(source.getLeftAndRightLantCarry());
return target;
}

/**
* 一次过磅-更新PostgreSQL记录
*/
private void updateOncePostgreSQLRecord(com.example.webapi.entity.postgresql.OnceWeighingPostgreSQL target, com.example.webapi.entity.OnceWeighing source) {
target.setListId(source.getListId());
target.setWeight(source.getWeight());
target.setSpeed(source.getSpeed());
target.setNodeTime(source.getNodeTime());
target.setOperatorId(source.getOperatorId());
target.setVehicleType(source.getVehicleType());
target.setVehicleId(source.getVehicleId());
target.setManageFlag(source.getManageFlag());
target.setSnapPicTime(source.getSnapPicTime());
target.setUploadFlag(source.getUploadFlag());
target.setUselessFlag(source.getUselessFlag());
target.setDemo(source.getDemo());
target.setScaleId(source.getScaleId());
target.setGrossOrTare(source.getGrossOrTare());
target.setBeforeAndAfterSlantCarry(source.getBeforeAndAfterSlantCarry());
target.setLeftAndRightLantCarry(source.getLeftAndRightLantCarry());
}
}

+ 37
- 8
src/main/java/com/example/webapi/service/ScheduledSyncService.java Ver arquivo

@@ -34,25 +34,54 @@ public class ScheduledSyncService implements CommandLineRunner {
}
}

// /**
// * 每天凌晨2点执行全量同步检查
// */
// @Scheduled(cron = "0 0 2 * * ?")
// public void dailyFullSync() {
// try {
// logger.info("开始每日全量同步检查...");
// int count = dataSyncService.syncIncrementalData();
// logger.info("每日全量同步检查完成,成功同步 {} 条记录", count);
// } catch (Exception e) {
// logger.error("每日全量同步检查过程中发生错误: {}", e.getMessage(), e);
// }
// }

/**
* 每天凌晨2点执行全量同步检查
* 每5分钟执行一次一次过磅增量同步
*/
@Scheduled(cron = "0 0 2 * * ?")
public void dailyFullSync() {
@Scheduled(fixedRate = 300000) // 5分钟 = 300000毫秒
public void syncOnceIncrementalData() {
try {
logger.info("开始每日全量同步检查...");
int count = dataSyncService.syncIncrementalData();
logger.info("每日全量同步检查完成,成功同步 {} 条记录", count);
logger.info("开始定时一次过磅增量同步数据...");
int count = dataSyncService.syncOnceIncrementalData();
logger.info("定时一次过磅增量同步完成,成功同步 {} 条记录", count);
} catch (Exception e) {
logger.error("每日全量同步检查过程中发生错误: {}", e.getMessage(), e);
logger.error("定时一次过磅增量同步过程中发生错误: {}", e.getMessage(), e);
}
}

// /**
// * 每天凌晨2点执行一次过磅全量同步检查
// */
// @Scheduled(cron = "0 5 2 * * ?") // 比二次过磅晚5分钟
// public void dailyOnceFullSync() {
// try {
// logger.info("开始每日一次过磅全量同步检查...");
// int count = dataSyncService.syncOnceAllData();
// logger.info("每日一次过磅全量同步检查完成,成功同步 {} 条记录", count);
// } catch (Exception e) {
// logger.error("每日一次过磅全量同步检查过程中发生错误: {}", e.getMessage(), e);
// }
// }

@Override
public void run(String... args) throws Exception {
System.out.println("项目启动后执行增量同步------------------");
try {
syncIncrementalData();
// syncIncrementalData();
syncOnceIncrementalData();
} catch (Exception e) {
logger.error("启动时增量同步失败: {}", e.getMessage(), e);
}


+ 76
- 0
src/main/resources/application-xining.yml Ver arquivo

@@ -0,0 +1,76 @@
server:
port: 8806
servlet:
context-path: /fuquanapi

spring:
application:
name: fuquanapi
main:
allow-bean-definition-overriding: true
datasource:
# SQL Server数据源配置
sqlserver:
# 西宁火车煤 - 备用配置
url: jdbc:sqlserver://192.168.35.216:1433;SelectMethod=cursor;rewriteBatchedStatements=true;DatabaseName=WY_DATAMANAGE;encrypt=false;trustServerCertificate=true
username: sa
password: sa
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://112.33.47.173:6789;SelectMethod=cursor;rewriteBatchedStatements=true;DatabaseName=WY_DATAMANAGE20250731;encrypt=false;trustServerCertificate=true
# username: admin
# password: admin@Erp2021
# driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
# 连接池配置
hikari:
maximum-pool-size: 10
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000

# PostgreSQL数据源配置
postgresql:
url: jdbc:postgresql://192.168.35.10:5435/auseft_web
username: postgres
password: Auseft@2025
driver-class-name: org.postgresql.Driver
# 连接池配置
hikari:
maximum-pool-size: 10
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
jpa:
hibernate:
ddl-auto: none
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.SQLServer2008Dialect
format_sql: true
physical_naming_strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
use_sql_comments: true
# 禁用默认数据源自动配置
open-in-view: false
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mvc:
pathmatch:
matching-strategy: ant_path_matcher

# API客户端配置
api:
client:
ak: 2760cd7c-cc0e-4034-86f3-d58e89f03d80
sk: e2c0e9c1aaa72a0b1444f879c86a9034bf2f03be31a58b1e5b3b077948da75cf

# 日志配置
logging:
level:
com.example.webapi: DEBUG
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

# Swagger配置 - Swagger2不需要额外配置

+ 14
- 3
start.sh Ver arquivo

@@ -12,8 +12,6 @@ APP_CONTEXT_PATH="/fuquanapi"

# JVM配置
JVM_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:+UseStringDeduplication"
JVM_OPTS="$JVM_OPTS -Dserver.port=$APP_PORT"
JVM_OPTS="$JVM_OPTS -Dserver.servlet.context-path=$APP_CONTEXT_PATH"

# 日志配置
LOG_DIR="./logs"
@@ -55,6 +53,16 @@ check_jar() {
print_message $GREEN "找到应用JAR文件: $APP_JAR"
}

# 检查配置文件
check_config() {
if [ -f "./application.yml" ]; then
print_message $GREEN "找到外部配置文件: ./application.yml"
print_message $BLUE "Spring Boot将自动使用外部配置文件"
else
print_message $YELLOW "未找到外部配置文件 ./application.yml,将使用JAR包内的默认配置"
fi
}

# 创建日志目录
create_log_dir() {
if [ ! -d "$LOG_DIR" ]; then
@@ -81,6 +89,9 @@ check_running() {
# 启动应用
start_app() {
print_message $BLUE "正在启动 $APP_NAME..."
# 检查配置文件
check_config

# 启动应用
nohup java $JVM_OPTS -jar "$APP_JAR" > "$LOG_FILE" 2>&1 &
@@ -236,4 +247,4 @@ main() {
}

# 执行主函数
main "$@"
main "$@"

Carregando…
Cancelar
Salvar