Commit 34f0bdcc by Lizh

调整配置文件

parent 4d862d6f
......@@ -338,7 +338,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
// 3k. 保存仓库关联
saveWarehouseRels(dto.getWarehouseIds(), productId);
// 3l. 事务内记录日志(对齐 TS:日志与数据写入同一事务)
// 3l. 事务内记录日志
saveLogTransaction(productId, "创建商品");
});
} catch (Exception e) {
......@@ -599,7 +599,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
Set<Integer> valueIds = properties.stream().map(CustomProductInfoPropertyEntity::getValueId)
.filter(Objects::nonNull).collect(Collectors.toSet());
// 按 skuProperty 拆分为 SKU 属性和普通属性(对齐 TS:234-235)
// 按 skuProperty 拆分为 SKU 属性和普通属性
// 转换为 CustomProductInfoPropertyVO 列表
List<CustomProductInfoSkuPropertiesVO> skuProps = new ArrayList<>();
List<CustomProductInfoSkuPropertiesVO> normalProps = new ArrayList<>();
......@@ -1271,7 +1271,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
customProductItemDomainService.save(item);
itemMap.put(originalSku, item);
}
log.info("[ saveProductItems ] 逐条保存 {} 个子项, productId: {}", itemMap.size(), productId);
log.debug("[ saveProductItems ] 逐条保存 {} 个子项, productId: {}", itemMap.size(), productId);
return itemMap;
}
......
......@@ -65,7 +65,7 @@ public class CustomProductItemServiceImpl implements CustomProductItemService {
throw new ServiceException("明细列表不能为空");
}
// ① 查询商品信息(对齐 TS:30-38)
// ① 查询商品信息
CustomProductInfoEntity productInfo = customProductInfoDomainService.getById(dto.getProduct_id());
if (productInfo == null) {
throw new ServiceException("商品信息不存在");
......@@ -75,7 +75,7 @@ public class CustomProductItemServiceImpl implements CustomProductItemService {
List<CustomProductItemEntity> customProductItems =
customProductItemDomainService.selectByProductId(dto.getProduct_id());
// ③ 构建 priceMap:{ itemId → newSalesPrice }(对齐 TS:42-46)
// ③ 构建 priceMap:{ itemId → newSalesPrice }
Map<Integer, BigDecimal> priceMap = new HashMap<>();
for (UpdateSalesPriceSnakeDTO.UpdateSalesPriceItemSnakeDTO item : dto.getItems()) {
priceMap.put(item.getId(), item.getSales_price());
......@@ -98,7 +98,7 @@ public class CustomProductItemServiceImpl implements CustomProductItemService {
templateItemsMap = Collections.emptyMap();
}
// ⑤ 编程式事务(对齐 TS:47 transaction)
// ⑤ 编程式事务
try {
transactionTemplate.executeWithoutResult(status -> {
BigDecimal salesPriceMin = new BigDecimal(Integer.MAX_VALUE);
......@@ -118,31 +118,31 @@ public class CustomProductItemServiceImpl implements CustomProductItemService {
salesPriceMin = newPrice;
}
// 价格未变则跳过(对齐 TS:60)
// 价格未变则跳过
if (newPrice.compareTo(item.getSalesPrice()) == 0) {
continue;
}
// 更新明细销售价(对齐 TS:61)
// 更新明细销售价
item.setSalesPrice(newPrice);
customProductItemDomainService.updateById(item);
// 日志:SKU 更改销售价格(对齐 TS:62)
// 日志:SKU 更改销售价格
saveCustomProductLog(item.getProductId(),
item.getSku() + "更改销售价格为" + newPrice);
// 如果明细有关联模板子项,联动更新采购价(对齐 TS:63-68)
// 如果明细有关联模板子项,联动更新采购价
List<ProductTemplateItemEntity> templateItems = templateItemsMap.get(item.getId());
if (!CollectionUtils.isEmpty(templateItems)) {
for (ProductTemplateItemEntity templateItem : templateItems) {
updateCostPrice(newPrice, templateItem);
// 日志:SKU 更改采购价格(对齐 TS:66)
// 日志:SKU 更改采购价格
saveProductTemplateLog(templateItem.getTemplateId(), templateItem.getSku() + "更改采购价格为" + newPrice);
}
}
}
// ⑥ 更新商品主表的售价区间(对齐 TS:70-83)
// ⑥ 更新商品主表的售价区间
StringBuilder productLog = new StringBuilder();
// 商品最低售价有修改
if (salesPriceMin.compareTo(new BigDecimal(Integer.MAX_VALUE)) != 0) {
......@@ -180,11 +180,11 @@ public class CustomProductItemServiceImpl implements CustomProductItemService {
* 更新模板子项的采购价,并重算模板成本价区间(对齐 TS updateCostPrice:102-127)
*/
private void updateCostPrice(BigDecimal newPrice, ProductTemplateItemEntity templateItem) {
// 更新当前模板子项的 cost_price(对齐 TS:103)
// 更新当前模板子项的 cost_price
templateItem.setCostPrice(newPrice);
productTemplateItemDomainService.updateById(templateItem);
// 查询该模板下所有子项,重算 cost_price 最大/最小值(对齐 TS:104-118)
// 查询该模板下所有子项,重算 cost_price 最大/最小值
Integer templateId = templateItem.getTemplateId();
List<ProductTemplateItemEntity> allTemplateItems =
productTemplateItemDomainService.selectByTemplateId(templateId);
......
......@@ -52,7 +52,7 @@ public class TokenHandle {
@Value("${token.secret:custom}")
private String secret;
private static final String BEARER = "bearer ";
private static final String SPACE = "\\s+";
/**
* 获取用户身份信息
......@@ -67,8 +67,7 @@ public class TokenHandle {
* @param request 请求对象
* @return 用户信息,解析失败返回 null
*/
public LoginUser getLoginUser(HttpServletRequest request) {
String token = getToken(request);
public LoginUser getLoginUser(String token) {
if (!StringUtils.hasText(token)) {
return null;
}
......@@ -225,12 +224,13 @@ public class TokenHandle {
/**
* 从请求头获取令牌
*/
private String getToken(HttpServletRequest request) {
public String getToken(HttpServletRequest request) {
String token = request.getHeader(header);
if (StringUtils.hasText(token) && token.toLowerCase().startsWith(BEARER)) {
return token.substring(BEARER.length());
String[] parts = token.trim().split(SPACE);
if (parts.length > 1) {
return parts[parts.length - 1]; // 取最后一部分
}
return token;
return parts[0];
}
/**
......
......@@ -24,7 +24,10 @@ public class SecurityInterceptor implements HandlerInterceptor {
private TokenHandle tokenHandle;
@Value("${server.needAuthentication:true}")
protected boolean needAuthentication;
private boolean needAuthentication;
@Value("${server.erpRequestToken:70d8f63fe598a0d815c29d0d8a15d55b699844463d0485b505ddbc7e04ee034a}")
private String erpRequestToken;
/**
* 请求处理前执行
......@@ -32,14 +35,23 @@ public class SecurityInterceptor implements HandlerInterceptor {
*/
@Override
public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
// 设置 RequestHolder
RequestHolder.setRequestHolder(request);
//如果是测试环境,不走拦截器
if (!needAuthentication) {
return true;
}
// 设置 RequestHolder
RequestHolder.setRequestHolder(request);
String token = tokenHandle.getToken(request);
if (token == null) {
throw new InvalidTokenException("未登录或登录已过期");
}
// erp调用传入特殊Token
if (token.equals(erpRequestToken)) {
return true;
}
// 获取登录用户信息
LoginUser loginUser = tokenHandle.getLoginUser(request);
LoginUser loginUser = tokenHandle.getLoginUser(token);
// 如果用户没有登录,返回提示
if (loginUser == null) {
......
# ============================================================
# Custom Server — 数据源配置(datasource profile)
# ============================================================
spring:
datasource:
url: jdbc:mysql://172.16.19.99:3306/foxpsd-lizh?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false
username: root
password: joshine
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
# 最小空闲连接数
minimum-idle: 5
# 最大连接池大小
maximum-pool-size: 50
# 连接超时时间(60 秒)
connection-timeout: 60000
# 空闲连接超时时间(600 秒)
idle-timeout: 600000
# 最大连接生命周期(900 秒)
max-lifetime: 900000
# 验证超时时间(3 秒)
validation-timeout: 3000
# ============================================================
# Custom Server — 主配置文件
# ============================================================
# 服务器配置
server:
port: 40071
......@@ -15,29 +12,79 @@ server:
min-spare: 100
# 自定义:是否需要认证(测试时可以不认证)
needAuthentication: true
# 自定义:saasAdmin管理后台地址,获取商品类别信息
# 自定义:ERP系统基础认证信息
erpRequestToken: 70d8f63fe598a0d815c29d0d8a15d55b699844463d0485b505ddbc7e04ee034a
# 自定义:saasAdmin管理后台地址,获取类别信息
admin:
base-url: https://admin.jomalls.com
# Spring 配置
spring:
application:
name: custom-server
profiles:
active: datasource,redis
main:
allow-circular-references: true
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
# 数据源配置
datasource:
url: jdbc:mysql://172.16.19.99:3306/foxpsd-lizh?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false
username: root
password: joshine
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
# 最小空闲连接数
minimum-idle: 5
# 最大连接池大小
maximum-pool-size: 50
# 连接超时时间(60 秒)
connection-timeout: 60000
# 空闲连接超时时间(600 秒)
idle-timeout: 600000
# 最大连接生命周期(900 秒)
max-lifetime: 900000
# 验证超时时间(3 秒)
validation-timeout: 3000
# Redis 配置
data:
redis:
host: 172.16.19.100
port: 6379
password: joshine.dev
database: 7
# 读取/写入超时(毫秒)
timeout: 5000
# 连接超时(毫秒)
connect-timeout: 3000
# Jedis 连接池配置
pool:
max-active: 8
max-idle: 4
min-idle: 2
# Lettuce 连接池配置(Spring Data Redis 使用)
lettuce:
pool:
enabled: true
max-active: 8
max-idle: 4
min-idle: 2
max-wait: 5000
# Redisson 特有配置
redisson:
# 重试次数
retry-attempts: 3
# 重试间隔(毫秒)
retry-interval: 1000
# 心跳间隔(毫秒)
ping-interval: 60000
# 空闲连接超时(毫秒)
idle-timeout: 10000
# SpringDoc OpenAPI 配置
springdoc:
api-docs:
path: /api-docs
swagger-ui:
path: /swagger-ui.html
# MyBatis-Plus 配置
mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
......@@ -48,21 +95,12 @@ mybatis-plus:
global-config:
db-config:
id-type: auto
# ============================================================
# 令牌配置
# ============================================================
token:
header: Authorization
# 令牌密钥(兼容旧版本)
secret: custom
# 令牌有效期(单位:分钟)
expireTime: 720
# ============================================================
# HTTP Client 配置
# ============================================================
http:
client:
# 连接超时(毫秒)
......@@ -73,10 +111,7 @@ http:
pool-max-connections: 50
# 连接池获取连接超时(毫秒)
pool-acquire-timeout: 2000
# ============================================================
# Resilience4j 重试配置
# ============================================================
resilience4j:
retry:
configs:
......@@ -101,10 +136,7 @@ resilience4j:
instances:
remoteApi:
base-config: default
# ============================================================
# Actuator 管理端点
# ============================================================
management:
endpoints:
web:
......
# Custom Server — 主配置文件
# 服务器配置
server:
port: 40071
servlet:
context-path: /
tomcat:
uri-encoding: UTF-8
accept-count: 1000
threads:
max: 200
min-spare: 100
# 自定义,是否需要认证(测试时可以不认证)
needAuthentication: true
# 自定义,ERP系统基础认证信息
erpRequestToken: 70d8f63fe598a0d815c29d0d8a15d55b699844463d0485b505ddbc7e04ee034a
# 自定义,saasAdmin管理后台地址,获取类别信息
admin:
base-url: https://admin.jomalls.com
# Spring 配置
spring:
application:
name: custom-server
main:
allow-circular-references: true
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
# 数据源配置,配置正式环境数据源
datasource:
url: jdbc:mysql://121.40.229.7:3306/foxpsd-lizh?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false
username: foxpsd-private
password: testJm2025@$
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
# 最小空闲连接数
minimum-idle: 5
# 最大连接池大小
maximum-pool-size: 50
# 连接超时时间(60 秒)
connection-timeout: 60000
# 空闲连接超时时间(600 秒)
idle-timeout: 600000
# 最大连接生命周期(900 秒)
max-lifetime: 900000
# 验证超时时间(3 秒)
validation-timeout: 3000
# Redis 配置,配置正式环境redis地址
data:
redis:
host: 172.16.19.1
port: 6379
password: joshine.dev
database: 7
# 读取/写入超时(毫秒)
timeout: 5000
# 连接超时(毫秒)
connect-timeout: 3000
# Jedis 连接池配置
pool:
max-active: 8
max-idle: 4
min-idle: 2
# Lettuce 连接池配置(Spring Data Redis 使用)
lettuce:
pool:
enabled: true
max-active: 8
max-idle: 4
min-idle: 2
max-wait: 5000
# Redisson 特有配置
redisson:
# 重试次数
retry-attempts: 3
# 重试间隔(毫秒)
retry-interval: 1000
# 心跳间隔(毫秒)
ping-interval: 60000
# 空闲连接超时(毫秒)
idle-timeout: 10000
# SpringDoc OpenAPI 配置
springdoc:
api-docs:
path: /api-docs
swagger-ui:
path: /swagger-ui.html
# MyBatis-Plus 配置
mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
type-aliases-package: com.jomalls.custom.domain.dal.entity
configuration:
call-setters-on-nulls: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: auto
# 令牌配置
token:
header: Authorization
# 令牌密钥(兼容旧版本)
secret: custom
# HTTP Client 配置
http:
client:
# 连接超时(毫秒)
connect-timeout: 5000
# 读取超时(毫秒)
read-timeout: 30000
# 连接池最大连接数
pool-max-connections: 50
# 连接池获取连接超时(毫秒)
pool-acquire-timeout: 2000
# Resilience4j 重试配置
resilience4j:
retry:
configs:
default:
# 最大重试次数
max-attempts: 3
# 初始等待时间
wait-duration: 500ms
# 启用指数退避
enable-exponential-backoff: true
# 指数退避倍数
exponential-backoff-multiplier: 2
# 触发重试的异常
retry-exceptions:
- java.util.concurrent.TimeoutException
- java.io.IOException
- java.net.ConnectException
- org.springframework.web.reactive.function.client.WebClientResponseException
# 不触发重试的异常
ignore-exceptions:
- com.jomalls.custom.integrate.exception.RemoteServiceException
instances:
remoteApi:
base-config: default
# Actuator 管理端点
management:
endpoints:
web:
base-path: /api/v3/actuator
exposure:
include: metrics
# ============================================================
# Custom Server — Redis 配置(redis profile)
# ============================================================
spring:
data:
redis:
host: 172.16.19.100
port: 6379
password: joshine.dev
database: 7
# 读取/写入超时(毫秒)
timeout: 5000
# 连接超时(毫秒)
connect-timeout: 3000
# Jedis 连接池配置
pool:
max-active: 8
max-idle: 4
min-idle: 2
# Lettuce 连接池配置(Spring Data Redis 使用)
lettuce:
pool:
enabled: true
max-active: 8
max-idle: 4
min-idle: 2
max-wait: 5000
# Redisson 特有配置
redisson:
# 重试次数
retry-attempts: 3
# 重试间隔(毫秒)
retry-interval: 1000
# 心跳间隔(毫秒)
ping-interval: 60000
# 空闲连接超时(毫秒)
idle-timeout: 10000
......@@ -6,7 +6,7 @@
<!-- ==================== 日志路径 ==================== -->
<!--
生效优先级(由 Spring Boot LoggingApplicationListener 处理):
1. application.yml: logging.file.path: /var/log/app
1. application-dev.yml: logging.file.path: /var/log/app
2. JVM 启动参数: -DLOG_PATH=/var/log/app
3. 环境变量: export LOG_PATH=/var/log/app
4. 以上均未设置 → defaultValue: ./custom-v3/logs
......@@ -31,18 +31,11 @@
</appender>
<!-- ==================== 文件输出 ==================== -->
<!--
滚动策略:SizeAndTimeBasedRollingPolicy
- 按天 + 按大小双重滚动,单文件超过 maxFileSize 自动切分
- totalSizeCap 限制归档总量,超过自动清理最旧文件
- cleanHistoryOnStart 启动时清理超出限制的归档
-->
<!-- 系统日志:仅 INFO -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>${max.file.size}</maxFileSize>
<maxHistory>${max.history.days}</maxHistory>
<totalSizeCap>${max.total.size}</totalSizeCap>
......@@ -63,7 +56,7 @@
<appender name="file_warn" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-warn.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/sys-warn.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<fileNamePattern>${log.path}/sys-warn.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>${max.file.size}</maxFileSize>
<maxHistory>${max.history.days}</maxHistory>
<totalSizeCap>${max.total.size}</totalSizeCap>
......@@ -84,7 +77,7 @@
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>${max.file.size}</maxFileSize>
<maxHistory>${max.history.days}</maxHistory>
<totalSizeCap>${max.total.size}</totalSizeCap>
......@@ -101,8 +94,6 @@
</filter>
</appender>
<!-- ==================== 异步包装 ==================== -->
<!-- 文件 I/O 不阻塞业务线程 -->
<appender name="async_file_info" class="ch.qos.logback.classic.AsyncAppender">
<neverBlock>true</neverBlock>
<queueSize>512</queueSize>
......@@ -123,13 +114,11 @@
</appender>
<!-- ==================== 框架日志级别控制 ==================== -->
<!-- MyBatis / MyBatis-Plus:默认关闭 SQL 日志,排查问题时临时打开
<!--
MyBatis / MyBatis-Plus:默认关闭 SQL 日志,排查问题时临时打开
<logger name="org.mybatis" level="DEBUG"/>
<logger name="com.baomidou.mybatisplus" level="DEBUG"/>
-->
<!-- ==================== 环境差异配置 ==================== -->
<!-- 本地开发:项目包 DEBUG 级别,方便调试 -->
<springProfile name="default">
<logger name="com.jomalls.custom" level="DEBUG"/>
</springProfile>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment