准备上传

This commit is contained in:
2025-10-08 19:15:20 +08:00
parent 0aa7d55a23
commit 0e14a5fa1c
193 changed files with 14697 additions and 2461 deletions

View File

@@ -26,8 +26,17 @@ public class PythonBarcodeAutoStarter implements ApplicationRunner {
return;
}
log.info("启动 Python 条码识别服务...");
manager.startIfEnabled();
log.info("Python 条码识别服务已就绪");
try {
manager.startIfEnabled();
log.info("Python 条码识别服务已就绪");
} catch (RuntimeException ex) {
if (properties.isFailOnError()) {
// 让应用启动失败,遵循严格模式
throw ex;
}
// 宽松模式:记录错误并允许应用继续启动
log.error("Python 条码识别服务启动失败:{}。已忽略错误并继续启动后端python.barcode.fail-on-error=false", ex.getMessage());
}
}
@PreDestroy

View File

@@ -1,5 +1,7 @@
package com.example.demo.barcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@@ -19,6 +21,7 @@ public class PythonBarcodeProcessManager {
private final PythonBarcodeProperties properties;
private final RestTemplate restTemplate;
private Process process;
private static final Logger log = LoggerFactory.getLogger(PythonBarcodeProcessManager.class);
public PythonBarcodeProcessManager(PythonBarcodeProperties properties) {
this.properties = properties;
@@ -54,6 +57,13 @@ public class PythonBarcodeProcessManager {
pb.redirectOutput(new File(properties.getLogFile()));
}
if (log.isInfoEnabled()) {
log.info("启动 Python 服务: cmd={} cwd={} host={} port={} healthPath={} timeoutSec={}",
String.join(" ", cmd),
new File(properties.getWorkingDir()).getAbsolutePath(),
properties.getHost(), properties.getPort(), properties.getHealthPath(), properties.getStartupTimeoutSec());
}
try {
process = pb.start();
} catch (IOException e) {
@@ -94,13 +104,31 @@ public class PythonBarcodeProcessManager {
}
public boolean checkHealth() {
String url = String.format("http://%s:%d%s", properties.getHost(), properties.getPort(), properties.getHealthPath());
try {
restTemplate.getForObject(url, String.class);
return true;
} catch (RestClientException ex) {
return false;
List<String> hosts = new ArrayList<>();
String h = properties.getHost();
hosts.add(h);
// 常见误配置容错:服务绑定 0.0.0.0 / :: 时,探活应连回环地址
if ("0.0.0.0".equals(h) || "localhost".equalsIgnoreCase(h)) {
hosts.add("127.0.0.1");
}
if ("::".equals(h) || "[::]".equals(h) || "::1".equals(h)) {
hosts.add("[::1]");
}
for (String host : hosts) {
String url = String.format("http://%s:%d%s", host, properties.getPort(), properties.getHealthPath());
try {
restTemplate.getForObject(url, String.class);
if (log.isDebugEnabled() && !host.equals(h)) {
log.debug("健康检查通过(使用回退主机名):{}", url);
}
return true;
} catch (RestClientException ex) {
if (log.isDebugEnabled()) {
log.debug("健康检查失败: url={} err={}", url, ex.toString());
}
}
}
return false;
}
}

View File

@@ -40,6 +40,12 @@ public class PythonBarcodeProperties {
/** 上传大小限制MB用于 Java 侧预校验,需与 Python 端配置保持一致 */
private int maxUploadMb = 8;
/**
* 当 Python 条码服务启动或健康检查失败时,是否让整个后端应用启动失败。
* 默认 false仅记录错误并继续启动从而不影响其他功能可用性。
*/
private boolean failOnError = false;
public boolean isEnabled() {
return enabled;
}
@@ -127,6 +133,14 @@ public class PythonBarcodeProperties {
public void setMaxUploadMb(int maxUploadMb) {
this.maxUploadMb = maxUploadMb;
}
public boolean isFailOnError() {
return failOnError;
}
public void setFailOnError(boolean failOnError) {
this.failOnError = failOnError;
}
}

View File

@@ -57,7 +57,6 @@ public class ProductDtos {
public String spec;
public String origin;
public Long categoryId;
public Long unitId;
public String dedupeKey;
public BigDecimal safeMin;
public BigDecimal safeMax;

View File

@@ -7,11 +7,11 @@ spring.application.name=demo
# 正确的配置
# 格式为: jdbc:mysql://<主机名>:<端口号>/<数据库名>?参数
# 默认附带 MySQL 8 推荐参数,避免握手/时区/编码问题
spring.datasource.url=${DB_URL:jdbc:mysql://mysql.tonaspace.com:3306/partsinquiry?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8mb4&connectionCollation=utf8mb4_0900_ai_ci}
spring.datasource.url=${DB_URL}
# 用户名和密码直接写值
spring.datasource.username=${DB_USER:root}
spring.datasource.password=${DB_PASSWORD:TONA1234}
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD}
# JPA 基本配置
spring.jpa.hibernate.ddl-auto=none
@@ -106,3 +106,4 @@ python.barcode.health-path=${PY_BARCODE_HEALTH:/openapi.json}
python.barcode.startup-timeout-sec=${PY_BARCODE_TIMEOUT:20}
python.barcode.log-file=${PY_BARCODE_LOG:}
python.barcode.max-upload-mb=${PY_BARCODE_MAX_UPLOAD_MB:8}
python.barcode.fail-on-error=${PY_BARCODE_FAIL_ON_ERROR:false}