AI+Java项目+Springboot项目+Vue3全栈旅游项目
AI+Java项目+Springboot项目+Vue3项目实战AI智能旅游推荐助手企业级项目,适合前后端转全栈项目实战
主要环境
node版本 v22.12.0
node.js https://nodejs.org/zh-cn/download
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组件先把页面实现即可







附带一下给的提示词

第一次对话出来的页面


对于ui细节要求还原度不高的,有一张图片能够很精确的给你还原大概,如果需要还原度高的那么就需要ui出设计图然后用对应的一些skill或者mcp来实现了,后面的页面就大致按照这种方式一个个实现
后端篇
一.基础
前置条件:jdk
后端这边我们先用idea来做,后期可以转为其他平台,idea对于java的支持是最好的
当然idea也支持一些ai插件,在设置里面找到插件即可以安装各种ai插件

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

然后是框架的版本和一些依赖的勾选,类似于packagejson,vuerouter等等
这里因为开发的是java web项目勾选两个后面说

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

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

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

这个页面就是启动成功

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


二.项目实现
2.1.get接口
那么如何来实现接口的编写
我们之前选择的mvc的架构那么就要按照mvc的规则来写,mvc就是model层,view层,controller层,也就是模型,视图,控制器,接口主要就是写在控制器里面
那么控制器写在哪里,我们刚才看到的主文件,java的主文件里面第一级就是包一个java文件里面可能会有多个包,每个包里面会有很多类
所以接下来我们就先创建一个包,包名注意不要写错合乎规范,然后在包里面创建一个java类文件



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

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

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


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

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


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

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

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

但是这里需要注意一点,我们这里定义的是私有属性,也就是在外面是没有办法去获取到这些属性的值的
比如你想这么做,在我们刚才写接口那里,你直接调用示例赋值这是不行的

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

此时你想打印的话就是
你想赋值就是
当然这种方法是可以通过快速引入依赖来解决的不用去设置getter和set
这样就行了

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


这个时候再去调用接口

2.3 自定义异常返回格式
当然前端朋友都知道最不能接收的返回就是null所以我们自己做接口也要避免这种,对于data的定义,我们其实可以在ok方法下面再来专门给data定义一个ok方法
注意这里与前端不同,重载:函数名相同,参数不同,这里并不会把上面的覆盖了,而是共同存在



当然不止有成功的方法,也得处理异常的方法
首先是失败的方法

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


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

定义好后去创建类定义这个响应里面的对象
根据之前的接口文档可以看到这个接口的响应大概有这些字段

先把简单的定义了

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

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

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


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

接口这边直接用

2.5 参数校验异常处理
这边我们可以看到这个接口是有入参的

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

但是这样校验还没完,我们需要去判断前端有没有传参数,以及参数合不合乎规范,这里我们用
后端技术
- 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仓库里面去找
直接搜索之后,可以把这一段复制到之前说过的管理依赖的文件里面

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

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

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

接口这边也要定义使用

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


那么这里需要用到一个固定写法全局异常处理
在工具包里面创建一个类,大概就是跟request的响应拦截器远离差不多

2.6 service业务处理层
service层在controller层下面,刚才在controller层写好了接口,Controller 层接收前端请求后,只负责参数校验和调用 Service 层方法,不写业务逻辑,Service 层处理完返回结果给 Controller
service层就是处理业务逻辑的
如何取用?同样的创建一个包,然后包里面创建一个类,先简单写好这个处理函数,会接受到外面传进来三个入参

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

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


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

2.8 llm工具类封装和请求接口
这里我们就准备去调用大模型,由于调用大模型也是属于一个单独的逻辑,所以这里我们抽离出来作为一个工具类来写
先把需要的参数拿进来

这里我们后期要去调用接口,也会用到一个依赖这个用来也可以在前面maven仓库里面搜然后加入进来
OkHttp 4.12.0:HTTP 客户端,用于调用 LLM API

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

接下来要调用一个方法,这个方法主要是去跟轨迹流动创建连接
基本是根据官方api示例来

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

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

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

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

这里需要看到的是我们如何将生成的java字符串里面的转义字符去掉
可以直接复制这段代码
另外在后面还加了一个模型的模糊度的参数

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

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

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

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


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

2.9 chat接口service层调用实现
现在准备开始调用之前定义的llm接口了,如图在service里面去调用llm刚才定义好的工具类实例,但是需要注意的是
不能直接就调用并且传入参数,因为我们的参数是通过@value拿到的,所以要在下面先加@postconstruct才能拿到参数

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

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

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

这个处理的过程实际上就是对字符串进行处理转成json处理之后
这里我们直接用这一串函数

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

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

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

一把成功,成功返回


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

首先一样现在控制器声明方法
dto定义参数规则

跟刚才的recommend放在一起

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

当然在service层之前,我们肯定要去封装接口层先把接口调用了
和之前不同的是一个是第三个参数我们需要一个回调函数,因为后面流式输出会用到然后stream改为true

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

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

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

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

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

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

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

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

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

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

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

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

先定义约束

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

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

最后返回contreller层调用

重新运行调用接口

2.12 接口联调解决跨域问题
现在调用接口会有跨域问题

前端不用多说通过代理来解决,这里说一下后端解决
后端要解决我们这里也是写在contreller层,基本是固定写法

第一个接口成功

第二个接口成功


浙公网安备 33010602011771号