WWW.YOUINFO.SITE
标签聚合 spring

/tag/spring

LinuxDo 最新话题 · 2026-06-01 12:50:39+08:00 · tech

因为现在很多都可以直接 vibe coding 的,我会 java,但是需要接单可能 spring 用的不熟练,我很多有 go 和 nodejs 的多个项目经验,主要是现在想补一补 spring 的短板,希望前辈指教下,给个合适自用/接单的企业级脚手架/框架模板 我看过几个项目,yudao 和 ruoyi-vue-plus,这应该是国内比较好的,但是似乎 java 更依赖生成器,不过这个似乎也可以 ai 代劳?写个 skill? 然后 jeecgBoot 宣称是 ai 优先,有没有用过的佬 1 个帖子 - 1 位参与者 阅读完整话题

LinuxDo 最新话题 · 2026-05-31 16:17:53+08:00 · tech

示例图: 背景图:via-Foxtail-Grass Studio-Remember*C -spring- (2011.02) 介绍: Windows Terminal外壳,Git Bash核心 特性: 1.选择=复制,右击=粘贴 2.Acrylic毛玻璃材质 3.AdwaitaMono等宽字体 食用方法: 1.安装字体,安装Git,安装Windows Terminal github.com GitHub - ryanoasis/nerd-fonts: Iconic font aggregator, collection, & patcher.... Iconic font aggregator, collection, & patcher. 3,600+ icons, 50+ patched fonts: Hack, Source Code Pro, more. Glyph collections: Font Awesome, Material Design Icons, Octicons, & more git-scm.com Git Microsoft Store - 下载适用于 Windows 电脑的应用、游戏等 Windows Terminal - Windows官方下载 | 微软应用商店 | Microsoft Store Windows 终端程序是一款新式、快速、高效、强大且高效的终端应用程序,适用于命令行工具和命令提示符,PowerShell和 WSL 等 Shell 用户。主要功能包括多个选项卡、窗格、Unicode、和 UTF-8 字符支持,GPU 加速文本渲染引擎以及自定义主题、样式和配置。 这是一个开源项目,我们欢迎社区参与。如要参与,请访问 https://github.com/microsoft/terminal 2.打开终端, 按下 Ctrl + Shift + , 粘贴以下代码,保存重启即可 { "$help": "https://aka.ms/terminal-documentation", "$schema": "https://aka.ms/terminal-profiles-schema", "actions": [], "copyFormatting": "none", "copyOnSelect": true, "defaultProfile": "{00000000-0000-0000-0000-000000000001}", "newTabMenu": [ { "type": "remainingProfiles" } ], "profiles": { "defaults": { "antialiasingMode": "grayscale", "colorScheme": "One Half Dark", "font": { "face": "AdwaitaMono Nerd Font", "size": 15.0 }, "opacity": 75, "startingDirectory": "%USERPROFILE%", "useAcrylic": true }, "list": [ { "commandline": "\"C:\\Program Files\\Git\\bin\\bash.exe\" --login -i", "guid": "{00000000-0000-0000-0000-000000000001}", "icon": "C:\\Program Files\\Git\\mingw64\\share\\git\\git-for-windows.ico", "name": "Git Bash", "startingDirectory": "%USERPROFILE%" }, { "commandline": "powershell.exe -NoLogo", "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}", "name": "Windows PowerShell", "startingDirectory": "%USERPROFILE%" }, { "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}", "hidden": true, "name": "Command Prompt" }, { "guid": "{b453ae62-4e3d-5e58-b989-0a998ec441b8}", "hidden": true, "name": "Azure Cloud Shell", "source": "Windows.Terminal.Azure" } ] }, "schemes": [ { "background": "#0C0C0C", "black": "#0C0C0C", "blue": "#0037DA", "brightBlack": "#767676", "brightBlue": "#3B78FF", "brightCyan": "#61D6D6", "brightGreen": "#16C60C", "brightPurple": "#B4009E", "brightRed": "#E74856", "brightWhite": "#F2F2F2", "brightYellow": "#F9F1A5", "cursorColor": "#FFFFFF", "cyan": "#3A96DD", "foreground": "#CCCCCC", "green": "#13A10E", "name": "Campbell", "purple": "#881798", "red": "#C50F1F", "selectionBackground": "#FFFFFF", "white": "#CCCCCC", "yellow": "#C19C00" }, { "background": "#012456", "black": "#0C0C0C", "blue": "#0037DA", "brightBlack": "#767676", "brightBlue": "#3B78FF", "brightCyan": "#61D6D6", "brightGreen": "#16C60C", "brightPurple": "#B4009E", "brightRed": "#E74856", "brightWhite": "#F2F2F2", "brightYellow": "#F9F1A5", "cursorColor": "#FFFFFF", "cyan": "#3A96DD", "foreground": "#CCCCCC", "green": "#13A10E", "name": "Campbell Powershell", "purple": "#881798", "red": "#C50F1F", "selectionBackground": "#FFFFFF", "white": "#CCCCCC", "yellow": "#C19C00" }, { "background": "#282C34", "black": "#282C34", "blue": "#61AFEF", "brightBlack": "#5A6374", "brightBlue": "#61AFEF", "brightCyan": "#56B6C2", "brightGreen": "#98C379", "brightPurple": "#C678DD", "brightRed": "#E06C75", "brightWhite": "#DCDFE4", "brightYellow": "#E5C07B", "cursorColor": "#FFFFFF", "cyan": "#56B6C2", "foreground": "#DCDFE4", "green": "#98C379", "name": "One Half Dark", "purple": "#C678DD", "red": "#E06C75", "selectionBackground": "#FFFFFF", "white": "#DCDFE4", "yellow": "#E5C07B" }, { "background": "#FAFAFA", "black": "#383A42", "blue": "#0184BC", "brightBlack": "#4F525D", "brightBlue": "#61AFEF", "brightCyan": "#56B5C1", "brightGreen": "#98C379", "brightPurple": "#C577DD", "brightRed": "#DF6C75", "brightWhite": "#FFFFFF", "brightYellow": "#E4C07A", "cursorColor": "#4F525D", "cyan": "#0997B3", "foreground": "#383A42", "green": "#50A14F", "name": "One Half Light", "purple": "#A626A4", "red": "#E45649", "selectionBackground": "#4F525D", "white": "#FAFAFA", "yellow": "#C18301" }, { "background": "#002B36", "black": "#002B36", "blue": "#268BD2", "brightBlack": "#073642", "brightBlue": "#839496", "brightCyan": "#93A1A1", "brightGreen": "#586E75", "brightPurple": "#6C71C4", "brightRed": "#CB4B16", "brightWhite": "#FDF6E3", "brightYellow": "#657B83", "cursorColor": "#FFFFFF", "cyan": "#2AA198", "foreground": "#839496", "green": "#859900", "name": "Solarized Dark", "purple": "#D33682", "red": "#DC322F", "selectionBackground": "#FFFFFF", "white": "#EEE8D5", "yellow": "#B58900" }, { "background": "#FDF6E3", "black": "#002B36", "blue": "#268BD2", "brightBlack": "#073642", "brightBlue": "#839496", "brightCyan": "#93A1A1", "brightGreen": "#586E75", "brightPurple": "#6C71C4", "brightRed": "#CB4B16", "brightWhite": "#FDF6E3", "brightYellow": "#657B83", "cursorColor": "#002B36", "cyan": "#2AA198", "foreground": "#657B83", "green": "#859900", "name": "Solarized Light", "purple": "#D33682", "red": "#DC322F", "selectionBackground": "#073642", "white": "#EEE8D5", "yellow": "#B58900" }, { "background": "#000000", "black": "#000000", "blue": "#3465A4", "brightBlack": "#555753", "brightBlue": "#729FCF", "brightCyan": "#34E2E2", "brightGreen": "#8AE234", "brightPurple": "#AD7FA8", "brightRed": "#EF2929", "brightWhite": "#EEEEEC", "brightYellow": "#FCE94F", "cursorColor": "#FFFFFF", "cyan": "#06989A", "foreground": "#D3D7CF", "green": "#4E9A06", "name": "Tango Dark", "purple": "#75507B", "red": "#CC0000", "selectionBackground": "#FFFFFF", "white": "#D3D7CF", "yellow": "#C4A000" }, { "background": "#FFFFFF", "black": "#000000", "blue": "#3465A4", "brightBlack": "#555753", "brightBlue": "#729FCF", "brightCyan": "#34E2E2", "brightGreen": "#8AE234", "brightPurple": "#AD7FA8", "brightRed": "#EF2929", "brightWhite": "#EEEEEC", "brightYellow": "#FCE94F", "cursorColor": "#000000", "cyan": "#06989A", "foreground": "#555753", "green": "#4E9A06", "name": "Tango Light", "purple": "#75507B", "red": "#CC0000", "selectionBackground": "#555753", "white": "#D3D7CF", "yellow": "#C4A000" }, { "background": "#000000", "black": "#000000", "blue": "#000080", "brightBlack": "#808080", "brightBlue": "#0000FF", "brightCyan": "#00FFFF", "brightGreen": "#00FF00", "brightPurple": "#FF00FF", "brightRed": "#FF0000", "brightWhite": "#FFFFFF", "brightYellow": "#FFFF00", "cursorColor": "#FFFFFF", "cyan": "#008080", "foreground": "#C0C0C0", "green": "#008000", "name": "Vintage", "purple": "#800080", "red": "#800000", "selectionBackground": "#FFFFFF", "white": "#C0C0C0", "yellow": "#808000" } ], "themes": [] } 1 个帖子 - 1 位参与者 阅读完整话题

LinuxDo 最新话题 · 2026-05-29 19:34:19+08:00 · tech

Mac Book Pro 8.1 主要还是太老,十多年前的机器了。 现在主要做 Spring Web 开发,基本够用,装完系统后就默认可用,不必太多的其他操作。 输入法默认自带的拼音输入法基本完美使用。本来五笔的,但装了几个都或多或少有点问题,后来就默认拼音。 软件直接软件商店安装,常用的开发软件都有,IDEA、DataGrip、WebStorm、PyCharm、VSCode等。 AI工具基本用 Claude Code Cli 或在线页面版 微信有 linux 版本,比较完美,办公软件用 Libre Office,基本没有啥问题。 3 个帖子 - 3 位参与者 阅读完整话题

LinuxDo 最新话题 · 2026-05-25 09:29:08+08:00 · tech

看了两三天的agent教程,目前打算还是java+springAI为主 ,下载了springAI+alibaba阿里的项目,想看看成熟的项目架构和背后逻辑, 看的时候就在想,会不会agent后面也成了工具类一样的存在,那这样的话,是不是还要向上学习,请问已经在岗的agent佬,或者ai架构师佬,如果要自学转行ai, 有java基础的情况下,学agent是不是目前性价比最高的,以后的发展趋势会是怎么样的 6 个帖子 - 5 位参与者 阅读完整话题

LinuxDo 最新话题 · 2026-05-24 20:09:20+08:00 · tech

本帖使用社区开源推广,符合推广要求。我申明并遵循社区要求的以下内容: 我的帖子已经打上 开源推广 标签: 是 我的开源项目完整开源,无未开源部分: 是 我的开源项目已链接认可 LINUX DO 社区: 是 我帖子内的项目介绍,AI生成、润色内容部分已截图发出: 是 以上选择我承诺是永久有效的,接受社区和佬友监督: 是 以下为项目介绍正文内容,AI生成、润色内容已使用截图方式发出 找了几天没有找到idea上能用的hoppscotch插件,我造了个(我只是提了几个需求,ai帮我写的),自用是够了。 分享给有需要的朋友吧。 有什么问题可以fork自行解决;或我试着解决,但不要报太大希望,因为我也不懂kotlin和idea插件怎么开发 。 github.com GitHub - luyanfeng/hoppscotch-plugin: 用于在idea上向hoppscotch同步spring 的接口 用于在idea上向hoppscotch同步spring 的接口 用法: 用浏览器先登录hoppscotch,然后F12,找到access_token. 只取一次,配置到插件上。插件会自行获取refresh_token,并会 不定时 更新token确保token不过期。但你不能长时间不打开idea,否则插件也没法办刷新token(也可以到hoppscotch管理后台把jwt token时间设时长些试试)。 其它自行探索吧 1 个帖子 - 1 位参与者 阅读完整话题

LinuxDo 最新话题 · 2026-05-24 12:29:00+08:00 · tech

各位大佬,我在使用spring ai时,流式功能总是实现不了,想问问是为什么 sse中的内容,都是隔一段时间后一起返回的: apifox\curl直接向后端发送请求,也是同样的效果【都是一段时间后,将所有内容一起返回】: 协议使用的是sse 具体代码【整个后端就这一个Controller】: pom文件: spring boot 3.2.5 spring-boot-starter-webflux spring-ai-starter-model-openai spring-retry yaml文件: 3 个帖子 - 3 位参与者 阅读完整话题

cnBeta全文版 · 2026-05-24 07:05:11+08:00 · tech

一项在美国加州北区联邦地区法院提起的集体诉讼指控,多家硬盘悬臂组件供应商在长达十余年的时间里进行价格垄断,其中核心被告包括日本电子巨头TDK以及NHK Spring。诉状称,这些企业生产的悬臂组件被广泛用于全球约97%的机械硬盘中,使得案件事实上牵连到整个硬盘行业供应链。 悬臂组件是传统机械硬盘内部一个极少被普通用户注意到、却至关重要的精密部件,它是一根细小的机械“手臂”,负责以极高精度定位读写磁头,使其在高速旋转的碟片上方以极小间隙悬停并完成读写操作。随着硬盘存储密度不断提升,容错空间持续收紧,这一部件在制造工艺、工程公差和量产难度方面的技术门槛也显著提高,形成了供应商数量有限、市场高度集中的格局。 起诉书指称,在2003年1月1日至2016年12月31日期间,相关悬臂组件供应商通过协调定价等方式从事价格操纵行为,推高了硬盘生产环节的成本。这些增加的成本并未止步于零部件制造端,而是沿着供应链向下传导,最终反映在品牌硬盘厂商的采购价格以及消费者购买独立硬盘或预装硬盘电脑时所支付的终端价格中。 根据指控,涉案悬臂组件广泛供应于希捷(Seagate)、西部数据(Western Digital)、东芝(Toshiba)等主流硬盘品牌,但这些整机品牌本身并未被列为本次诉讼的被告。原告认为,正是由于核心零部件掌握在少数几家供应商手中,使得产业链上游具备通过合谋影响整个市场价格水平的能力,这也是案件在反垄断角度受到关注的原因。 这并非类似指控首次进入司法程序。早在2019年,加拿大就已有一宗围绕同一行业和同类行为的集体诉讼获法院受理,并于2022年在上诉被驳回后继续推进。目前美国新案在指控内容上与加拿大案件高度相似,同样聚焦于硬盘悬臂组件领域的价格垄断问题。 截至目前,美国这起集体诉讼尚未确定审判日期,法院也尚未就责任或赔偿作出任何裁决。不过,如果未来原告获得胜诉,2003年至2016年间购买过受影响硬盘产品的企业用户和个人消费者,都有可能被纳入潜在获赔范围。 根据目前公开的信息,符合条件的美国境内企业和个人用户默认将自动纳入集体诉讼范围,除非他们主动选择退出。案件相关方已经设立专门网站供公众查询信息和办理退出手续,当前公布的退伙(opt-out)截止日期为2026年8月23日。 查看评论

V2EX - 技术 · 2026-05-22 22:29:19+08:00 · tech

Spring Boot 3.x 循环依赖实战:从 allow-circular-references 到纯 DAG ,一个支付系统的重构之旅 项目背景:Jeepay 计全支付,Spring Boot 3.3.7 + MyBatis-Plus + Vue 3 ,多模块 Maven 项目。 前端集成引发的连锁反应 原本前后端分离部署( Nginx + 独立前端容器),想把前端 dist 直接打进 JAR 简化部署。几个坑: Vue SPA 路由 fallback:Spring Boot 3.x 默认用 PathPatternParser ,addViewControllers 不支持 {spring:\w+} 正则。最终用 @Order(HIGHEST_PRECEDENCE) 的 Filter 拦截无后缀路径 forward 到 index.html 。 Spring Security 6 ignoring() 不生效:日志明确警告 You are asking Spring Security to ignore... This is not recommended 。改为 authorizeHttpRequests().permitAll() 才生效。 字体文件 401:Security 的静态资源豁免模式漏了 .woff/.woff2/.ttf/.eot 。 前端构建 API baseURL 双层 /api/api/:VITE_API_BASE_URL=/api 拼接 url: '/api/xxx' → /api/api/xxx 。改为空值。 发行包瘦身:260MB → 120MB 三个模块的 fat JAR 共 288MB ,其中 130 个公共依赖(72MB) 重复存储 3 次。方案: 去掉未用依赖:jaxb-api(零 import)、mysql-connector-j(纯配置模块不需要)、activemq(仅编译,运行时用 RabbitMQ) 共享 lib:maven-dependency-plugin 收集所有传递依赖到 lib/(自动去重 182 个),antrun 解压 fat JAR 提取 BOOT-INF/classes/ 打包为 flat thin JAR(1.7-5MB) 启动方式:从 java -jar fat.jar 改为 java -cp "lib/*:apps/app.jar" MainClass 循环依赖根治 去掉 allow-circular-references: true 后直接启动,Spring Boot 3.x 严格检测报出完整依赖链: ┌─────┐ │ SysConfigService 自引用 (删 @ Autowired self ,直接用 this) ↑ ↓ │ IsvInfoService 自引用 (同上) 修复策略: 自引用:删字段,改用 this.xxx () 三角循环( PayInterfaceConfigService ↔ MchAppService/MchInfoService ):PayInterfaceConfigService.selectAllPayIfConfigListByAppId() 内部反向调用了 mchAppService.getById() 和 mchInfoService.getById()——这些只是 MyBatis-Plus 的简单 CRUD 委托。将这两个查询上移到 Controller 层,Service 方法改为接收 MchInfo 参数,依赖方向恢复。 两两循环:MchInfoService 注入 IsvInfoService 只是为了 getById(),IsvInfoService 注入 MchInfoService 只是为了 count()。直接替换为对应的 Mapper 注入,因为 MyBatis-Plus 的 ServiceImpl.getById() 底层就是 BaseMapper.selectById()。 关键认知: 依赖只能单向流动。找到"谁在反向调用"就是断环点。 大多数循环依赖是 CRUD 委托导致的。ServiceImpl 包装 BaseMapper ,循环往往是因为 A 需要 B 的 getById(),B 需要 A 的 count()——直接用 Mapper 替代 Service 注入,不改任何业务逻辑。 不要用 @ Lazy 、不要用 allow-circular-references ,这些都是掩耳盗铃。Spring Boot 3.x 默认禁止循环是为了逼你写出正确的分层。 最终效果 ┌───────────────────────────┬────────┬───────────────┐ │ 指标 │ 修复前 │ 修复后 │ ├───────────────────────────┼────────┼───────────────┤ │ 发行包大小 │ 260 MB │ 120 MB (-54%) │ ├───────────────────────────┼────────┼───────────────┤ │ 循环依赖 │ 5 个 │ 0 │ ├───────────────────────────┼────────┼───────────────┤ │ allow-circular-references │ true │ 已移除 │ ├───────────────────────────┼────────┼───────────────┤ │ @ Lazy │ 2 处 │ 0 │ ├───────────────────────────┼────────┼───────────────┤ │ 启动时间 │ ~8s │ ~4s │ └───────────────────────────┴────────┴───────────────┘

V2EX - 技术 · 2026-05-22 22:29:19+08:00 · tech

Spring Boot 3.x 循环依赖实战:从 allow-circular-references 到纯 DAG ,一个支付系统的重构之旅 项目背景:Jeepay 计全支付,Spring Boot 3.3.7 + MyBatis-Plus + Vue 3 ,多模块 Maven 项目。 前端集成引发的连锁反应 原本前后端分离部署( Nginx + 独立前端容器),想把前端 dist 直接打进 JAR 简化部署。几个坑: Vue SPA 路由 fallback:Spring Boot 3.x 默认用 PathPatternParser ,addViewControllers 不支持 {spring:\w+} 正则。最终用 @Order(HIGHEST_PRECEDENCE) 的 Filter 拦截无后缀路径 forward 到 index.html 。 Spring Security 6 ignoring() 不生效:日志明确警告 You are asking Spring Security to ignore... This is not recommended 。改为 authorizeHttpRequests().permitAll() 才生效。 字体文件 401:Security 的静态资源豁免模式漏了 .woff/.woff2/.ttf/.eot 。 前端构建 API baseURL 双层 /api/api/:VITE_API_BASE_URL=/api 拼接 url: '/api/xxx' → /api/api/xxx 。改为空值。 发行包瘦身:260MB → 120MB 三个模块的 fat JAR 共 288MB ,其中 130 个公共依赖(72MB) 重复存储 3 次。方案: 去掉未用依赖:jaxb-api(零 import)、mysql-connector-j(纯配置模块不需要)、activemq(仅编译,运行时用 RabbitMQ) 共享 lib:maven-dependency-plugin 收集所有传递依赖到 lib/(自动去重 182 个),antrun 解压 fat JAR 提取 BOOT-INF/classes/ 打包为 flat thin JAR(1.7-5MB) 启动方式:从 java -jar fat.jar 改为 java -cp "lib/*:apps/app.jar" MainClass 循环依赖根治 去掉 allow-circular-references: true 后直接启动,Spring Boot 3.x 严格检测报出完整依赖链: ┌─────┐ │ SysConfigService 自引用 (删 @ Autowired self ,直接用 this) ↑ ↓ │ IsvInfoService 自引用 (同上) 修复策略: 自引用:删字段,改用 this.xxx () 三角循环( PayInterfaceConfigService ↔ MchAppService/MchInfoService ):PayInterfaceConfigService.selectAllPayIfConfigListByAppId() 内部反向调用了 mchAppService.getById() 和 mchInfoService.getById()——这些只是 MyBatis-Plus 的简单 CRUD 委托。将这两个查询上移到 Controller 层,Service 方法改为接收 MchInfo 参数,依赖方向恢复。 两两循环:MchInfoService 注入 IsvInfoService 只是为了 getById(),IsvInfoService 注入 MchInfoService 只是为了 count()。直接替换为对应的 Mapper 注入,因为 MyBatis-Plus 的 ServiceImpl.getById() 底层就是 BaseMapper.selectById()。 关键认知: 依赖只能单向流动。找到"谁在反向调用"就是断环点。 大多数循环依赖是 CRUD 委托导致的。ServiceImpl 包装 BaseMapper ,循环往往是因为 A 需要 B 的 getById(),B 需要 A 的 count()——直接用 Mapper 替代 Service 注入,不改任何业务逻辑。 不要用 @ Lazy 、不要用 allow-circular-references ,这些都是掩耳盗铃。Spring Boot 3.x 默认禁止循环是为了逼你写出正确的分层。 最终效果 ┌───────────────────────────┬────────┬───────────────┐ │ 指标 │ 修复前 │ 修复后 │ ├───────────────────────────┼────────┼───────────────┤ │ 发行包大小 │ 260 MB │ 120 MB (-54%) │ ├───────────────────────────┼────────┼───────────────┤ │ 循环依赖 │ 5 个 │ 0 │ ├───────────────────────────┼────────┼───────────────┤ │ allow-circular-references │ true │ 已移除 │ ├───────────────────────────┼────────┼───────────────┤ │ @ Lazy │ 2 处 │ 0 │ ├───────────────────────────┼────────┼───────────────┤ │ 启动时间 │ ~8s │ ~4s │ └───────────────────────────┴────────┴───────────────┘

V2EX - 技术 · 2026-05-22 21:49:51+08:00 · tech

Spring Boot 3.x 循环依赖实战:从 allow-circular-references 到纯 DAG ,一个支付系统的重构之旅 项目背景:Jeepay 计全支付,Spring Boot 3.3.7 + MyBatis-Plus + Vue 3 ,多模块 Maven 项目。 前端集成引发的连锁反应 原本前后端分离部署( Nginx + 独立前端容器),想把前端 dist 直接打进 JAR 简化部署。几个坑: Vue SPA 路由 fallback:Spring Boot 3.x 默认用 PathPatternParser ,addViewControllers 不支持 {spring:\w+} 正则。最终用 @Order(HIGHEST_PRECEDENCE) 的 Filter 拦截无后缀路径 forward 到 index.html 。 Spring Security 6 ignoring() 不生效:日志明确警告 You are asking Spring Security to ignore... This is not recommended 。改为 authorizeHttpRequests().permitAll() 才生效。 字体文件 401:Security 的静态资源豁免模式漏了 .woff/.woff2/.ttf/.eot 。 前端构建 API baseURL 双层 /api/api/:VITE_API_BASE_URL=/api 拼接 url: '/api/xxx' → /api/api/xxx 。改为空值。 发行包瘦身:260MB → 120MB 三个模块的 fat JAR 共 288MB ,其中 130 个公共依赖(72MB) 重复存储 3 次。方案: 去掉未用依赖:jaxb-api(零 import)、mysql-connector-j(纯配置模块不需要)、activemq(仅编译,运行时用 RabbitMQ) 共享 lib:maven-dependency-plugin 收集所有传递依赖到 lib/(自动去重 182 个),antrun 解压 fat JAR 提取 BOOT-INF/classes/ 打包为 flat thin JAR(1.7-5MB) 启动方式:从 java -jar fat.jar 改为 java -cp "lib/*:apps/app.jar" MainClass 循环依赖根治 去掉 allow-circular-references: true 后直接启动,Spring Boot 3.x 严格检测报出完整依赖链: ┌─────┐ │ SysConfigService 自引用 (删 @ Autowired self ,直接用 this) ↑ ↓ │ IsvInfoService 自引用 (同上) 修复策略: 自引用:删字段,改用 this.xxx () 三角循环( PayInterfaceConfigService ↔ MchAppService/MchInfoService ):PayInterfaceConfigService.selectAllPayIfConfigListByAppId() 内部反向调用了 mchAppService.getById() 和 mchInfoService.getById()——这些只是 MyBatis-Plus 的简单 CRUD 委托。将这两个查询上移到 Controller 层,Service 方法改为接收 MchInfo 参数,依赖方向恢复。 两两循环:MchInfoService 注入 IsvInfoService 只是为了 getById(),IsvInfoService 注入 MchInfoService 只是为了 count()。直接替换为对应的 Mapper 注入,因为 MyBatis-Plus 的 ServiceImpl.getById() 底层就是 BaseMapper.selectById()。 关键认知: 依赖只能单向流动。找到"谁在反向调用"就是断环点。 大多数循环依赖是 CRUD 委托导致的。ServiceImpl 包装 BaseMapper ,循环往往是因为 A 需要 B 的 getById(),B 需要 A 的 count()——直接用 Mapper 替代 Service 注入,不改任何业务逻辑。 不要用 @ Lazy 、不要用 allow-circular-references ,这些都是掩耳盗铃。Spring Boot 3.x 默认禁止循环是为了逼你写出正确的分层。 最终效果 ┌───────────────────────────┬────────┬───────────────┐ │ 指标 │ 修复前 │ 修复后 │ ├───────────────────────────┼────────┼───────────────┤ │ 发行包大小 │ 260 MB │ 120 MB (-54%) │ ├───────────────────────────┼────────┼───────────────┤ │ 循环依赖 │ 5 个 │ 0 │ ├───────────────────────────┼────────┼───────────────┤ │ allow-circular-references │ true │ 已移除 │ ├───────────────────────────┼────────┼───────────────┤ │ @ Lazy │ 2 处 │ 0 │ ├───────────────────────────┼────────┼───────────────┤ │ 启动时间 │ ~8s │ ~4s │ └───────────────────────────┴────────┴───────────────┘

v2ex · 2026-05-22 21:49:51+08:00 · tech

Spring Boot 3.x 循环依赖实战:从 allow-circular-references 到纯 DAG ,一个支付系统的重构之旅 项目背景:Jeepay 计全支付,Spring Boot 3.3.7 + MyBatis-Plus + Vue 3 ,多模块 Maven 项目。 前端集成引发的连锁反应 原本前后端分离部署( Nginx + 独立前端容器),想把前端 dist 直接打进 JAR 简化部署。几个坑: Vue SPA 路由 fallback:Spring Boot 3.x 默认用 PathPatternParser ,addViewControllers 不支持 {spring:\w+} 正则。最终用 @Order(HIGHEST_PRECEDENCE) 的 Filter 拦截无后缀路径 forward 到 index.html 。 Spring Security 6 ignoring() 不生效:日志明确警告 You are asking Spring Security to ignore... This is not recommended 。改为 authorizeHttpRequests().permitAll() 才生效。 字体文件 401:Security 的静态资源豁免模式漏了 .woff/.woff2/.ttf/.eot 。 前端构建 API baseURL 双层 /api/api/:VITE_API_BASE_URL=/api 拼接 url: '/api/xxx' → /api/api/xxx 。改为空值。 发行包瘦身:260MB → 120MB 三个模块的 fat JAR 共 288MB ,其中 130 个公共依赖(72MB) 重复存储 3 次。方案: 去掉未用依赖:jaxb-api(零 import)、mysql-connector-j(纯配置模块不需要)、activemq(仅编译,运行时用 RabbitMQ) 共享 lib:maven-dependency-plugin 收集所有传递依赖到 lib/(自动去重 182 个),antrun 解压 fat JAR 提取 BOOT-INF/classes/ 打包为 flat thin JAR(1.7-5MB) 启动方式:从 java -jar fat.jar 改为 java -cp "lib/*:apps/app.jar" MainClass 循环依赖根治 去掉 allow-circular-references: true 后直接启动,Spring Boot 3.x 严格检测报出完整依赖链: ┌─────┐ │ SysConfigService 自引用 (删 @ Autowired self ,直接用 this) ↑ ↓ │ IsvInfoService 自引用 (同上) 修复策略: 自引用:删字段,改用 this.xxx () 三角循环( PayInterfaceConfigService ↔ MchAppService/MchInfoService ):PayInterfaceConfigService.selectAllPayIfConfigListByAppId() 内部反向调用了 mchAppService.getById() 和 mchInfoService.getById()——这些只是 MyBatis-Plus 的简单 CRUD 委托。将这两个查询上移到 Controller 层,Service 方法改为接收 MchInfo 参数,依赖方向恢复。 两两循环:MchInfoService 注入 IsvInfoService 只是为了 getById(),IsvInfoService 注入 MchInfoService 只是为了 count()。直接替换为对应的 Mapper 注入,因为 MyBatis-Plus 的 ServiceImpl.getById() 底层就是 BaseMapper.selectById()。 关键认知: 依赖只能单向流动。找到"谁在反向调用"就是断环点。 大多数循环依赖是 CRUD 委托导致的。ServiceImpl 包装 BaseMapper ,循环往往是因为 A 需要 B 的 getById(),B 需要 A 的 count()——直接用 Mapper 替代 Service 注入,不改任何业务逻辑。 不要用 @ Lazy 、不要用 allow-circular-references ,这些都是掩耳盗铃。Spring Boot 3.x 默认禁止循环是为了逼你写出正确的分层。 最终效果 ┌───────────────────────────┬────────┬───────────────┐ │ 指标 │ 修复前 │ 修复后 │ ├───────────────────────────┼────────┼───────────────┤ │ 发行包大小 │ 260 MB │ 120 MB (-54%) │ ├───────────────────────────┼────────┼───────────────┤ │ 循环依赖 │ 5 个 │ 0 │ ├───────────────────────────┼────────┼───────────────┤ │ allow-circular-references │ true │ 已移除 │ ├───────────────────────────┼────────┼───────────────┤ │ @ Lazy │ 2 处 │ 0 │ ├───────────────────────────┼────────┼───────────────┤ │ 启动时间 │ ~8s │ ~4s │ └───────────────────────────┴────────┴───────────────┘

V2EX - 技术 · 2026-05-22 21:49:51+08:00 · tech

Spring Boot 3.x 循环依赖实战:从 allow-circular-references 到纯 DAG ,一个支付系统的重构之旅 项目背景:Jeepay 计全支付,Spring Boot 3.3.7 + MyBatis-Plus + Vue 3 ,多模块 Maven 项目。 前端集成引发的连锁反应 原本前后端分离部署( Nginx + 独立前端容器),想把前端 dist 直接打进 JAR 简化部署。几个坑: Vue SPA 路由 fallback:Spring Boot 3.x 默认用 PathPatternParser ,addViewControllers 不支持 {spring:\w+} 正则。最终用 @Order(HIGHEST_PRECEDENCE) 的 Filter 拦截无后缀路径 forward 到 index.html 。 Spring Security 6 ignoring() 不生效:日志明确警告 You are asking Spring Security to ignore... This is not recommended 。改为 authorizeHttpRequests().permitAll() 才生效。 字体文件 401:Security 的静态资源豁免模式漏了 .woff/.woff2/.ttf/.eot 。 前端构建 API baseURL 双层 /api/api/:VITE_API_BASE_URL=/api 拼接 url: '/api/xxx' → /api/api/xxx 。改为空值。 发行包瘦身:260MB → 120MB 三个模块的 fat JAR 共 288MB ,其中 130 个公共依赖(72MB) 重复存储 3 次。方案: 去掉未用依赖:jaxb-api(零 import)、mysql-connector-j(纯配置模块不需要)、activemq(仅编译,运行时用 RabbitMQ) 共享 lib:maven-dependency-plugin 收集所有传递依赖到 lib/(自动去重 182 个),antrun 解压 fat JAR 提取 BOOT-INF/classes/ 打包为 flat thin JAR(1.7-5MB) 启动方式:从 java -jar fat.jar 改为 java -cp "lib/*:apps/app.jar" MainClass 循环依赖根治 去掉 allow-circular-references: true 后直接启动,Spring Boot 3.x 严格检测报出完整依赖链: ┌─────┐ │ SysConfigService 自引用 (删 @ Autowired self ,直接用 this) ↑ ↓ │ IsvInfoService 自引用 (同上) 修复策略: 自引用:删字段,改用 this.xxx () 三角循环( PayInterfaceConfigService ↔ MchAppService/MchInfoService ):PayInterfaceConfigService.selectAllPayIfConfigListByAppId() 内部反向调用了 mchAppService.getById() 和 mchInfoService.getById()——这些只是 MyBatis-Plus 的简单 CRUD 委托。将这两个查询上移到 Controller 层,Service 方法改为接收 MchInfo 参数,依赖方向恢复。 两两循环:MchInfoService 注入 IsvInfoService 只是为了 getById(),IsvInfoService 注入 MchInfoService 只是为了 count()。直接替换为对应的 Mapper 注入,因为 MyBatis-Plus 的 ServiceImpl.getById() 底层就是 BaseMapper.selectById()。 关键认知: 依赖只能单向流动。找到"谁在反向调用"就是断环点。 大多数循环依赖是 CRUD 委托导致的。ServiceImpl 包装 BaseMapper ,循环往往是因为 A 需要 B 的 getById(),B 需要 A 的 count()——直接用 Mapper 替代 Service 注入,不改任何业务逻辑。 不要用 @ Lazy 、不要用 allow-circular-references ,这些都是掩耳盗铃。Spring Boot 3.x 默认禁止循环是为了逼你写出正确的分层。 最终效果 ┌───────────────────────────┬────────┬───────────────┐ │ 指标 │ 修复前 │ 修复后 │ ├───────────────────────────┼────────┼───────────────┤ │ 发行包大小 │ 260 MB │ 120 MB (-54%) │ ├───────────────────────────┼────────┼───────────────┤ │ 循环依赖 │ 5 个 │ 0 │ ├───────────────────────────┼────────┼───────────────┤ │ allow-circular-references │ true │ 已移除 │ ├───────────────────────────┼────────┼───────────────┤ │ @ Lazy │ 2 处 │ 0 │ ├───────────────────────────┼────────┼───────────────┤ │ 启动时间 │ ~8s │ ~4s │ └───────────────────────────┴────────┴───────────────┘

LinuxDo 最新话题 · 2026-05-22 21:33:16+08:00 · tech

五个月之前用Trae搞了一个智旅云的SpringBoot + Vue的前后端分离项目,然后最近几天把这个项目重构成SpringCloud的微服务项目了。项目定位就是一个一站式衣食住行系统,所以集成的内容很多。 系统的整体架构: 系统首页 航班详情(MOCK数据) 酒店页面: 景区: 打车服务 餐厅: 社区: 会员: AI客服: 购物车: 订单: 乘客信息: 地图: 在此特别感谢Linux.do的各位佬,尤其是 huaibao中转站和windhub中转站的两位佬,一个Codex帮我重构,一个doubao作为AI客服。当然这个项目只是一个玩具项目,还没有经过压测(因为我还不会压测),所以,也想要得到一些其他佬的指点,比如前端要防抖呀,后端要怎么怎么做,希望各位佬狠狠拷打我,让我学到一些新知识。 5 个帖子 - 3 位参与者 阅读完整话题

LinuxDo 最新话题 · 2026-05-22 11:18:20+08:00 · tech

后端springMVC,前端html套layui。 公司领导不懂技术,但是领导想把前端界面搞好看点,觉得太老气了。 项目倒是不复杂,就是crud吧,sql倒是又臭又长,但是这种老项目耦合度都特别高,后端有一些控制前端的逻辑,也有常见的返回json数据接口。 接手这个老项目一个多月了,佬们有没有什么好建议。我基本要负责设计加开发了。 4 个帖子 - 3 位参与者 阅读完整话题