准备上传
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user