fix(wave3-staging): yudao 单体启动装配修复 + application-staging.yaml(mini-desktop 真启动通过)

首次真启动整个 yudao-server 单体暴露预存装配缺陷(此前只验编译+单测)。按 live 错误栈两层根因修复:
- 撤销 yudao-server/pom.xml 对 spring-cloud-starter-openfeign 的排除——framework starter
  (YudaoSecurityRpcAutoConfiguration 等)自带 @EnableFeignClients 需 openfeign 在 classpath
- 补 yudao 上游漏标的 primary=false:OAuth2TokenCommonApi/TenantCommonApi/ApiAccessLogCommonApi/
  ApiErrorLogCommonApi 四个 @FeignClient + 对应 4 个 *ApiImpl 加 @Primary(同 PermissionApiImpl 范式),
  使单体内本地实现胜过 Feign 远程代理
- application-staging.yaml:DB/Redis→隔离容器 13306/16379(${ENV} 占位非明文)、nacos/xxl 关、
  mock-enable、tenant.enable=false(单租户)、openfeign 回环 48080

验证(主 agent 独立 mini-desktop 观测 + 本机编译):Started YudaoServerApplication;Flyway V1-V9 全 success;
24 张 game_* 表;/v3/api-docs 87 paths 9 模块无 game/ 前缀;POST /app-api/project/1/publish→admitted+gates 含 key=compliance;
本机 mvn -am compile BUILD SUCCESS。Application.java 未改(原 @EnableFeignClients 假设会致双 primary 冲突,实测不需要)。
P1 遗留:admin-api @PreAuthorize 端点撞 yudao 单体嵌套 Feign 回环 404(app-api 主链路不受影响)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zizi 2026-06-09 04:55:23 +00:00
parent b3bb7667ad
commit d7fac9038d
10 changed files with 181 additions and 11 deletions

View File

@ -11,7 +11,7 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(name = RpcConstants.INFRA_NAME) // TODO 芋艿fallbackFactory =
@FeignClient(name = RpcConstants.INFRA_NAME, primary = false) // staging 单体启动修法 primary=false使本地 @RestController 实现胜出 PermissionCommonApi 同范式修上游漏标 // TODO 芋艿fallbackFactory =
@Tag(name = "RPC 服务 - API 访问日志")
public interface ApiAccessLogCommonApi {

View File

@ -11,7 +11,7 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(name = RpcConstants.INFRA_NAME) // TODO 芋艿fallbackFactory =
@FeignClient(name = RpcConstants.INFRA_NAME, primary = false) // staging 单体启动修法 primary=false使本地 @RestController 实现胜出 PermissionCommonApi 同范式修上游漏标 // TODO 芋艿fallbackFactory =
@Tag(name = "RPC 服务 - API 异常日志")
public interface ApiErrorLogCommonApi {

View File

@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
@FeignClient(name = RpcConstants.SYSTEM_NAME) // TODO 芋艿fallbackFactory =
@FeignClient(name = RpcConstants.SYSTEM_NAME, primary = false) // staging 单体启动修法 primary=false使本地 @RestController 实现胜出 PermissionCommonApi 同范式修上游漏标 // TODO 芋艿fallbackFactory =
@Tag(name = "RPC 服务 - OAuth2.0 令牌")
public interface OAuth2TokenCommonApi {

View File

@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@FeignClient(name = RpcConstants.SYSTEM_NAME) // TODO 芋艿fallbackFactory =
@FeignClient(name = RpcConstants.SYSTEM_NAME, primary = false) // staging 单体启动修法 primary=false使本地 @RestController 实现胜出 PermissionCommonApi 同范式修上游漏标 // TODO 芋艿fallbackFactory =
@Tag(name = "RPC 服务 - 多租户")
public interface TenantCommonApi {

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiAccessLogCreate
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.infra.service.logger.ApiAccessLogService;
import org.springframework.validation.annotation.Validated;
import org.springframework.context.annotation.Primary;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
@ -12,6 +13,7 @@ import jakarta.annotation.Resource;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@RestController // 提供 RESTful API 接口 Feign 调用
@Primary // staging 单体启动修法 ApiAccessLogCommonApi(@FeignClient primary=false) 配套本地实现声明 @Primary 唯一胜出 PermissionApiImpl 范式
@Validated
public class ApiAccessLogApiImpl implements ApiAccessLogCommonApi {

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateR
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.infra.service.logger.ApiErrorLogService;
import org.springframework.validation.annotation.Validated;
import org.springframework.context.annotation.Primary;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
@ -12,6 +13,7 @@ import jakarta.annotation.Resource;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@RestController // 提供 RESTful API 接口 Feign 调用
@Primary // staging 单体启动修法 ApiErrorLogCommonApi(@FeignClient primary=false) 配套本地实现声明 @Primary 唯一胜出 PermissionApiImpl 范式
@Validated
public class ApiErrorLogApiImpl implements ApiErrorLogCommonApi {

View File

@ -11,11 +11,13 @@ import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.context.annotation.Primary;
import org.springframework.web.bind.annotation.RestController;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@RestController // 提供 RESTful API 接口 Feign 调用
@Primary // staging 单体启动修法 OAuth2TokenCommonApi(@FeignClient primary=false) 配套本地实现声明 @Primary 唯一胜出 PermissionApiImpl 范式
@Validated
public class OAuth2TokenApiImpl implements OAuth2TokenCommonApi {

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import org.springframework.validation.annotation.Validated;
import org.springframework.context.annotation.Primary;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
@ -13,6 +14,7 @@ import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@RestController // 提供 RESTful API 接口 Feign 调用
@Primary // staging 单体启动修法 TenantCommonApi(@FeignClient primary=false) 配套本地实现声明 @Primary 唯一胜出 PermissionApiImpl 范式
@Validated
public class TenantApiImpl implements TenantCommonApi {

View File

@ -223,13 +223,9 @@
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-rpc</artifactId>
<!-- 目的yudao-server 单体启动,禁用 openfeign -->
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</exclusion>
</exclusions>
<!-- staging 单体启动修法:撤销对 openfeign 的排除,让 spring-cloud-starter-openfeign 进入 classpath。
framework 自带 @EnableFeignClients(YudaoSecurityRpcAutoConfiguration 等)需 openfeign 在 classpath本地 @Primary *ApiImpl 同进程覆盖远程调用。
nacos discovery/config 仍 enabled=false不做真实注册发现。 -->
</dependency>
</dependencies>

View File

@ -0,0 +1,166 @@
# 造梦AI game-staging 单体启动 profile仅 mini-desktop 隔离环境)
# 基于 application-local.yaml差异DB/Redis 指向隔离容器(13306/16379)+强密码(经 .env 注入占位符nacos/xxl 关mock-enable=true。
server:
port: 48080
--- #################### 单体启动:允许 Bean 覆盖 ####################
# 多个 yudao 模块声明同名 @FeignClient单体内会产生同名 FeignClientSpecification开启 Bean 覆盖yudao 单体标准接法)。
spring:
main:
allow-bean-definition-overriding: true
--- #################### 数据库相关配置 ####################
spring:
autoconfigure:
exclude:
- org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration
- org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration
datasource:
druid:
web-stat-filter:
enabled: true
stat-view-servlet:
enabled: true
url-pattern: /druid/*
filter:
stat:
enabled: true
log-slow-sql: true
slow-sql-millis: 100
merge-sql: true
wall:
config:
multi-statement-allow: true
dynamic:
druid:
initial-size: 1
min-idle: 1
max-active: 20
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 600000
max-evictable-idle-time-millis: 1800000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
primary: master
datasource:
master:
url: jdbc:mysql://127.0.0.1:13306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true
username: root
password: ${MYSQL_ROOT_PASSWORD}
slave:
lazy: true
url: jdbc:mysql://127.0.0.1:13306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true
username: root
password: ${MYSQL_ROOT_PASSWORD}
flyway:
enabled: true
url: jdbc:mysql://127.0.0.1:13306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
user: root
password: ${MYSQL_ROOT_PASSWORD}
data:
redis:
host: 127.0.0.1
port: 16379
database: 0
password: ${REDIS_PASSWORD}
--- #################### Spring Cloud 禁用(单体,不注册发现)####################
spring:
cloud:
nacos:
discovery:
enabled: false
config:
enabled: false
# staging 单体 Feign 直连OpenFeign 原生 url 强制回环本机 48080绕过 yudao EnvLoadBalancer/NacosBalancer。
openfeign:
client:
config:
system-server:
url: http://127.0.0.1:48080
infra-server:
url: http://127.0.0.1:48080
--- #################### 定时任务 ####################
xxl:
job:
enabled: false
admin:
addresses: http://127.0.0.1:9090/xxl-job-admin
--- #################### 消息队列 ####################
rocketmq:
name-server: 127.0.0.1:9876
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: rabbit
password: rabbit
kafka:
bootstrap-servers: 127.0.0.1:9092
--- #################### 服务保障 ####################
lock4j:
acquire-timeout: 3000
expire: 30000
--- #################### 监控 ####################
management:
endpoints:
web:
base-path: /actuator
exposure:
include: "*"
spring:
boot:
admin:
client:
enabled: false
context-path: /admin
logging:
level:
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR
debug: false
--- #################### 微信dummy满足 WxMpService 自动配置实例化)####################
wx:
mp:
app-id: wx5b23ba7a5589ecbb
secret: 2a7b3b20c537e52e74afd395eb85f61f
config-storage:
type: RedisTemplate
key-prefix: wx
http-client-type: HttpClient
miniapp:
appid: wxc4598c446f8a9cb3
secret: 4a1a04e07f6a4a0751b39c3064a92c8b
config-storage:
type: RedisTemplate
key-prefix: wa
http-client-type: HttpClient
--- #################### 芋道配置 ####################
yudao:
tenant:
enable: false # staging 单租户隔离环境:关闭多租户校验拦截器(避免 framework tenant valid 走 Feign
captcha:
enable: false
security:
mock-enable: true
permit-all-urls: # staging 放行 actuator 健康检查(无需鉴权,便于探活)
- /actuator/**
access-log:
enable: false
demo: false
--- #################### iot ####################
pf4j:
pluginsDir: ../plugins