惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

有赞技术团队
有赞技术团队
MyScale Blog
MyScale Blog
Cyberwarzone
Cyberwarzone
Schneier on Security
Schneier on Security
I
Intezer
Cisco Talos Blog
Cisco Talos Blog
Cloudbric
Cloudbric
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
NISL@THU
NISL@THU
博客园 - Franky
F
Fortinet All Blogs
Google DeepMind News
Google DeepMind News
Jina AI
Jina AI
T
The Exploit Database - CXSecurity.com
P
Proofpoint News Feed
N
News and Events Feed by Topic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
F
Full Disclosure
T
Troy Hunt's Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Project Zero
Project Zero
P
Palo Alto Networks Blog
Recorded Future
Recorded Future
美团技术团队
D
Docker
PCI Perspectives
PCI Perspectives
Microsoft Azure Blog
Microsoft Azure Blog
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 最新话题
Recent Announcements
Recent Announcements
Hacker News: Ask HN
Hacker News: Ask HN
人人都是产品经理
人人都是产品经理
月光博客
月光博客
D
DataBreaches.Net
The Hacker News
The Hacker News
爱范儿
爱范儿
V
Visual Studio Blog
Engineering at Meta
Engineering at Meta
SecWiki News
SecWiki News
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
A
About on SuperTechFans
Latest news
Latest news
GbyAI
GbyAI
T
Tor Project blog
L
LINUX DO - 热门话题
Security Latest
Security Latest
博客园 - 聂微东
Y
Y Combinator Blog
AI
AI
M
MIT News - Artificial intelligence

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解 【002】HTTPS 粗解:证书、TLS 握手与对后端配置的影响 Hermes Agent 一周暴涨五万 Star,但我劝你别急着追 明明连接的是Redis的DB0,为什么能查到DB3的数据? 【从0到1构建一个ClaudeAgent】协作-Agent团队 熟悉电子元器件之后,电子小白下一步该怎么走? MAF快速入门(23)通过C#类定义Skills .NET 高级开发 | 手写一个对象映射框架 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 mysqldump 参数拾遗:在遗忘与铭记之间 C# .NET 周刊|2026年3月5期 Claude code入门 - 陈彦斌 一文学习入门 ThingsBoard 开源物联网平台 GitHub 热门项目 | 2026年04月16日 如何为GIT设置全局勾子,为每次提交追加信息 Number.isFinite和isFinite与isNaN()和Number.isNaN的区别 PortSwigger SQL注入LAB2 推荐一个测试人必备的Skills,从功能到性能全搞定(附详细实操和安装下载方式) 筑基期:掌握Odoo基础核心知识点02(Odoo XML 开发方式详解) GLM模型这么火,咱们用vllm也咧一个呗! 深入理解 AbortController:从底层原理到跨语言设计哲学 字符串学习笔记 多租户系统框架的基础模块设计和分析设计 Apache SeaTunnel Zeta 为什么能做到“又快又稳”? AI开发-python-LangGraph框架(3-26-LangGraph基本概念及第一个简单样例) Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 ElasticSearch7.X版本配置密码 用Manim实现动态交点计算--从一个动点问题说起 团结引擎+Addressable+Instant Game打包抖音小游戏 function call 实战:让 LLM 自动判断 pod 异常、调用日志工具并完成故障分析 bubseek —— 让 Agent 的足迹,变成团队的洞察 通过 C# 读取并导出 PDF 书签 如何用 GitHub Actions 实现 Steam 自动化发布 【从0到1构建一个ClaudeAgent】并发-后台任务 .NET 高级开发 | 定制 ASP.NET Core 框架 电子小白:什么是运算放大器(运放) zero2Agent:面向大厂面试的 Agent 工程教程,从概念到生产的完整学习路线 堆上的ORW HC32F460 USB CDC通信异常:非对齐访问异常排查 20260413-Hyperbridge 攻击事件:发生在默克尔山上的验证绕过 那些喊着AI 要淘汰你的人,正在靠你的焦虑赚大钱! 深度学习进阶(八)Swin Transformer 最小二乘问题详解19:带先验约束的增量式SFM优化与实现 SnapTranslate 3.0 正式发布:全局划词翻译 + 完整英语学习闭环,一站式搞定查词、记词、复习 工作的意义、工作的困难认知再思考 .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 开了 TUN 模式还是直连?90% 的人都踩过这个坑 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术
AI+Java项目+Springboot项目+Vue3全栈旅游项目
Heymar-10 · 2026-06-27 · via 博客园_首页

AI+Java项目+Springboot项目+Vue3项目实战AI智能旅游推荐助手企业级项目,适合前后端转全栈项目实战

主要环境

node版本 v22.12.0

node.js https://nodejs.org/zh-cn/download

nvm https://nvm.uihtm.com/

jdk https://www.oracle.com/java/technologies/downloads/

Vant(Vue3版本) https://vant.pro/vant/#/zh-CN

硅基流动 https://www.siliconflow.cn/

DeepSeek https://www.deepseek.com/

前端编辑器(cursor)

后端编辑器(IntelliJ IDEA)https://www.jetbrains.com.cn/idea/

vite https://vitejs.cn/vite6-cn/guide/

apifox https://apifox.com/index.html

接口文档 https://l3tn86ysds.apifox.cn/

maven仓库搜索 https://search.maven.org/

前端篇

前端这边不做过多赘述,页面图给出来,大概是一个h5页面配合vant组件先把页面实现即可

01

02

03

04

05

06

07

附带一下给的提示词

image-20260615165727445

第一次对话出来的页面

image-20260615170135941

image-20260615170146214

对于ui细节要求还原度不高的,有一张图片能够很精确的给你还原大概,如果需要还原度高的那么就需要ui出设计图然后用对应的一些skill或者mcp来实现了,后面的页面就大致按照这种方式一个个实现

后端篇

一.基础

前置条件:jdk

后端这边我们先用idea来做,后期可以转为其他平台,idea对于java的支持是最好的

当然idea也支持一些ai插件,在设置里面找到插件即可以安装各种ai插件

image-20260615172255580

直接在idea创建一个项目位置跟前端放在一起,这里我们选择springboot,springboot是java的一个框架,类似于vue,react能够快速去写一些功能,语言选择java,类型是语言依赖的关系,选择主流的maven,jdk选择主流的17版本,其他默认即可

image-20260615172654911

然后是框架的版本和一些依赖的勾选,类似于packagejson,vuerouter等等

这里因为开发的是java web项目勾选两个后面说

image-20260615172848830

创建好项目后主要看到两个文件,一个是pom它类似于package.json就是看这个java项目有哪些依赖的

image-20260615173130567

然后是这个文件夹里面,java代码都在里面,而且里面已经常见好了一个java文件,类似于app.vue是一个主启动文件那么要启动java项目就可以点击旁边的三角符号

image-20260615173344206

然后可以在启动日志里面找到端口号并且查看

image-20260615174101487

这个页面就是启动成功

image-20260615174146485

如果想要修改端口号,可以在resources文件夹里面修改,里面的application可以将后缀名改为yml,然后点击右上角实现刷新重新运行

image-20260615174536593

image-20260615174755117

二.项目实现

2.1.get接口

那么如何来实现接口的编写

我们之前选择的mvc的架构那么就要按照mvc的规则来写,mvc就是model层,view层,controller层,也就是模型,视图,控制器,接口主要就是写在控制器里面

那么控制器写在哪里,我们刚才看到的主文件,java的主文件里面第一级就是包一个java文件里面可能会有多个包,每个包里面会有很多类

所以接下来我们就先创建一个包,包名注意不要写错合乎规范,然后在包里面创建一个java类文件

image-20260616141029791

image-20260616141038363

image-20260616141108229

开始定义接口,那么首先是定义公共部分也就是接口前缀

image-20260616144203310

然后比如我们定义一个get接口,那么就要@getmapping,下面些函数,string是定义输出类型,比如定义了字符串,就必须输出字符串

image-20260616144455520

此时我们去访问这个get接口会发现还是报错,那是因为我们的输出类型也要定义image-20260616144849445

image-20260616144935214

image-20260616144949585

2.2 apifox使用

当然一般要测试接口我们都用专业的软件来进行,包括post接口你用浏览器就不好测试了,这个时候我们在apifox创建一个项目

image-20260616145327452

可以去新建一个接口然后配置好开发环境地址就行了

image-20260616145455891

image-20260616145506111

但是我们都知道正常后端返回应该是类似于如下这么一个json格式不只是一个单字符串

image-20260616150617113

所以这里我们需要将返回内容进行一个包装,这里我们直接创建一个类,先创建一个包VO一般都会将实体类放进VO里面然后创建一个类

这里创建类之后然后在类里面声明了四个私有属性,前三个不用多说主要是第四个,我们可以看到前面返回的数据data里面的内容是不定的有字符串也有对象等等,所以我们这里给data定义一个泛型,也就是外部在调用result的时候通过《》可以来声明data是一个什么类型

image-20260616151744164

定义完属性就是定义输出成功的方法,直接定义一个ok的方法,然后去调用这个类并给到result,输出result,那么这个result里面就带有success,message等这些属性了

image-20260616152325213

但是这里需要注意一点,我们这里定义的是私有属性,也就是在外面是没有办法去获取到这些属性的值的

比如你想这么做,在我们刚才写接口那里,你直接调用示例赋值这是不行的

image-20260616152732129

如果你想正常访问以及赋值,原理就是在刚才定义约束那里设置getter和setter方法

image-20260616152928390

此时你想打印的话就是image-20260616153003633

你想赋值就是image-20260616153034455

当然这种方法是可以通过快速引入依赖来解决的不用去设置getter和set

这样就行了

image-20260616153202939

言归正传,那么此时我就可以去先把无参的类型定义好,然后这边接口直接调用,注意现在返回类型是一个对象,所以之前定义的string方法也要改为一个支持传入的对象类型

image-20260616153413204

image-20260616153455590

这个时候再去调用接口

image-20260616153525330

2.3 自定义异常返回格式

当然前端朋友都知道最不能接收的返回就是null所以我们自己做接口也要避免这种,对于data的定义,我们其实可以在ok方法下面再来专门给data定义一个ok方法

注意这里与前端不同,重载:函数名相同,参数不同,这里并不会把上面的覆盖了,而是共同存在

image-20260616154144031

image-20260616155131217

image-20260616155139945

当然不止有成功的方法,也得处理异常的方法

首先是失败的方法

image-20260616160142202

还有一个就是错误的方法,错误的方法就不需要再去传什么错误码之类的了,直接定义两个属性错误和错误信息

image-20260616160550987

image-20260616160624349

2.4 旅游推荐接口

旅游推荐接口我们采用post,post跟get差不多,然后响应里面有很多内容所以我们要定义一下响应参数

image-20260616162623729

定义好后去创建类定义这个响应里面的对象

根据之前的接口文档可以看到这个接口的响应大概有这些字段

image-20260616162910988

先把简单的定义了

image-20260616163126090

然后是下面这个比较复杂的数组

image-20260616163119111

由于这个数组里面是一个个对象所以先定一个数组list,然后去定义里面的对象类型

下面三个对象字段都差不多所以可以定义为一样的,注意由于对象里面还有对象所以我们在定义对象的时候套娃式的在下面继续定义这个对象里面的对象

image-20260616163837134

再然后下面又是一个对象,我们就直接定义约束,double浮点型,支持小数

image-20260616164103693

image-20260616164108785

最后两个是数组里面放着字符串这个可以直接定义

image-20260616164200060

接口这边直接用

image-20260616165032610

2.5 参数校验异常处理

这边我们可以看到这个接口是有入参的

image-20260616165233011

那么对于入参我们也要去进行参数定义

image-20260616165438680

但是这样校验还没完,我们需要去判断前端有没有传参数,以及参数合不合乎规范,这里我们用

后端技术

  • Spring Boot 3.2.5:核心框架
  • Spring Web:Web 层框架
  • Spring Validation:参数校验
  • Java 17:开发语言
  • OkHttp 4.12.0:HTTP 客户端,用于调用 LLM API
  • Jackson:JSON 序列化和反序列化
  • Lombok:简化代码开发
  • 大模型接口:硅基流动、DeepSeek
  • 流式响应:Server-Sent Events (SSE) 技术
  • Maven:项目构建工具https://search.maven.org/

Spring Validation这个东西来进行参数校验位置,可以再上面的maven仓库里面去找

直接搜索之后,可以把这一段复制到之前说过的管理依赖的文件里面

image-20260616165658249

加完后可以点击右边的按钮去进行更新下载

image-20260616165747630

你如果想去找的话就可以在根目录的这个文件夹里面去找

image-20260616165855431

如何去用?相信看到后面的message能看懂

image-20260616170123338

接口这边也要定义使用

image-20260616170315005

此时规则是生效的,但是你会发现如果你真没有传的话

image-20260616170653646

image-20260616170706331

那么这里需要用到一个固定写法全局异常处理

在工具包里面创建一个类,大概就是跟request的响应拦截器远离差不多

image-20260617101427937

2.6 service业务处理层

service层在controller层下面,刚才在controller层写好了接口,Controller 层接收前端请求后,只负责参数校验和调用 Service 层方法,不写业务逻辑,Service 层处理完返回结果给 Controller

service层就是处理业务逻辑的

如何取用?同样的创建一个包,然后包里面创建一个类,先简单写好这个处理函数,会接受到外面传进来三个入参

image-20260617103210401

我们现在controller层去给到service处理函数参数,调用之前要先声明,然后下面调用的时候,把定义好的约束三个入参分别获取过来

image-20260617103802409

2.7 接入ai处理数据

那么接下来拿到参数之后如何去进行业务逻辑处理,这里我们接入硅基流动 https://www.siliconflow.cn/ ,先去创建一个密钥,参考api文档

image-20260617105238109

image-20260617105405148

定义好之后就要逻辑层去拿到这三个参数等会调用,注意这里怎么拿的,可以用一个依赖直接拿过来

image-20260617110603797

2.8 llm工具类封装和请求接口

这里我们就准备去调用大模型,由于调用大模型也是属于一个单独的逻辑,所以这里我们抽离出来作为一个工具类来写

先把需要的参数拿进来

image-20260617113638325

这里我们后期要去调用接口,也会用到一个依赖这个用来也可以在前面maven仓库里面搜然后加入进来

OkHttp 4.12.0:HTTP 客户端,用于调用 LLM API

image-20260617113829737

创建连接

设置连接时间,读取时间,写入时间超时然后连接

image-20260617114533990

接下来要调用一个方法,这个方法主要是去跟轨迹流动创建连接

基本是根据官方api示例来

image-20260617114821294

可以看到他的接口的url以及一些请求头,这里我们调用这个接口并且把请求头给上,然后调用post请求,下面的-d是请求需要携带的一些参数,先把post写上然后单独写个函数来处理参数

image-20260625112549085

参数都是根据之前我们所看到的他要求的拼接出来的

image-20260625115318533

会接受两个入参,一个系统输入,一个用户输入,除此之外我们在这里还新增了一个配置stream表示是否流式输出,判断了一下是否有系统输入,有责拼接,没有直接拼接用户输入

image-20260625115327054

关于user输入这里需要注意我们这里本来就是输入三个关键字然后给你出来推荐页面,所以部分描述已经在后台创建好了,我们只需要把用户输入的三个参数传进来,大概文字描述是这样

image-20260625174433354

这里需要看到的是我们如何将生成的java字符串里面的转义字符去掉

可以直接复制这段代码

另外在后面还加了一个模型的模糊度的参数

image-20260625175018565

入参整理好了,就可以回到之前调用接口那里去调用,media是固定写法

image-20260625175729256

注意这里我们只是创建了一个post请求,还没有调用,调用这里使用trycatch去调用,并且引用了一个IOE捕捉错误的模块,然后没有错误的情况下返回判断接口是否成功,成功return body

image-20260625181404879

然后我们可以看看成功的一个响应,主要是choice里面的,里面是一个json字符串

image-20260625181531941

所以这里我们有一段处理这个json字符串的方法,这一段主要是mapper方法他也是一个依赖,用来java专门处理序列号json字符串的

image-20260625181715612

image-20260625181818802

然后我们在刚才成功输出那里对成功的结果传进去即可

image-20260625182249917

2.9 chat接口service层调用实现

现在准备开始调用之前定义的llm接口了,如图在service里面去调用llm刚才定义好的工具类实例,但是需要注意的是

不能直接就调用并且传入参数,因为我们的参数是通过@value拿到的,所以要在下面先加@postconstruct才能拿到参数

image-20260626155544086

调用我们直接去调用之前封装好的chat方法,但是这里需要对第二个参数用户提示词优化一下

image-20260626160555206

然后接下来调用之后需要对返回的数据进行处理因为拿到的是这样的形式

image-20260626160724711

然后我们需要返回给页面需要处理成接口这样的形式

image-20260626160758344

这个处理的过程实际上就是对字符串进行处理转成json处理之后

这里我们直接用这一串函数

image-20260627092005569

然后就可以在我们之前定义好的调用controller去调用service层,并把返回结果对外暴露

image-20260627092111936

这个时候就可以去调用接口了,但是会发现接口出现了我们给的错误提示

image-20260627094209040

这里我们直接丢给ai去处理排错

image-20260627094553391

一把成功,成功返回

image-20260627094850890

image-20260627094832350

2.10 流式对话请求接口封装

接下来我们还有一个接口类似于一个ai对话流式输出的接口

image-20260627094959088

首先一样现在控制器声明方法

dto定义参数规则

image-20260627095534164

跟刚才的recommend放在一起

image-20260627095639859

然后流程就是再去service层处理逻辑

image-20260627100038839

当然在service层之前,我们肯定要去封装接口层先把接口调用了

和之前不同的是一个是第三个参数我们需要一个回调函数,因为后面流式输出会用到然后stream改为true

image-20260627100512875

调用接口区别,我们这里是读取流式输出,所以java也有一个专门对于流式的调用方法

image-20260627101057097

前端最终拿到的这种是后端处理过的

image-20260627101124321

正常后端拿到的是

data:“你好”

data:“你是”

类似于这种

所以这里后端主要处理逻辑去做一个循环,只要每次拿到响应是data开头就说明后面是我们想要的值,所以去截取,知道看到done就结束,然后每一个截取到的值我们也用一个方法去进行处理包装

image-20260627102024842

然后我们再在处理后的数据通过回到函数传递出去,后面service层会用到这个回调

image-20260627102245214

当然如果想给前端最后返回一个完整的字符串,也可以在这里去进行拼接

image-20260627102538194

2.11 chatstream接口service层调用

现在我们开始在service层来调用接口

注意sse接口的写法

这里我们先定义一个sse接口连接,设置超时时间,然后下面去调用llm的chat方法直接把用户输入,系统输入,还有拿到的每一次ai返回的data回到函数传给他

image-20260627104124853

但是我们可以看到我们需要给前端返回的是这样的对象,而实际上大模型返回的只是data里面的内容,我们还要包装一层

image-20260627104322902

去约束这两个参数,并且注意这里用到了一种写法,一般来说都是外面调用约束的规则,而这里直接调用对外暴露出需要的对象

image-20260627104746545

再回来这里可以直接通过streamchunkVO拿到对象,但是我们前面是需要一个字符串对象,所以还得用这个object方法处理一下,只要写入就要trycatch

image-20260627105037878

刚才都是在callback完成的事情,然后这个时候把回调传给llm接口参数

image-20260627105340826

还用通过之前创建的sse发送出去

image-20260627105908975

这是传递分片的数据,可以看到最后发送完成还有一个完成的

image-20260627105957507

先定义约束

image-20260627110247089

在分片发送完成后发送即可

image-20260627110548371

最后我们的new threa需要在后面start同时return emitter

image-20260627110708239

最后返回contreller层调用

image-20260627110832520

重新运行调用接口

image-20260627111329780

2.12 接口联调解决跨域问题

现在调用接口会有跨域问题

image-20260627112310876

前端不用多说通过代理来解决,这里说一下后端解决

后端要解决我们这里也是写在contreller层,基本是固定写法

image-20260627112452879

第一个接口成功

image-20260627112856230

第二个接口成功

image-20260627113048514