news 2026/4/27 1:35:20

#2026山东大学软件学院项目实训(四)——AI应用生成模块完整实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
#2026山东大学软件学院项目实训(四)——AI应用生成模块完整实现

文章标签:#Java #SpringBoot #SSE #AI编程 #LangChain4j

一、模块整体设计思路

AI应用生成模块是AI零代码应用生成平台的核心功能,负责将单机版AI代码生成能力与应用管理系统深度集成,实现用户-应用-代码的绑定关联。

本模块遵循核心设计原则:

  1. 应用绑定:代码生成与应用ID强关联,文件按应用ID规范存储
  2. 流式响应:采用SSE服务器推送技术,实现代码实时流式输出
  3. 权限校验:仅应用创建者可触发代码生成,保障数据安全
  4. 文件规范:统一文件目录命名规则,避免存储混乱
  5. 异常统一:全局捕获异常,返回友好错误提示

二、AI应用生成服务开发

1. 业务流程设计

平台化代码生成核心流程:

  1. 用户在主页输入提示词创建应用,生成应用记录入库
  2. 获取应用ID后跳转至AI对话页面
  3. 前端调用SSE流式生成接口,后端校验权限并触发AI生成
  4. 代码按codeGenType_appId规则保存至文件系统
  5. 流式返回生成内容至前端,实时展示生成效果

2. 核心代码改造

(1)代码保存模板改造(CodeFileSaverTemplate)

重构代码保存逻辑,新增应用ID参数,实现文件与应用绑定:

/** * 模板方法:保存代码的标准流程(使用appId) * @param result 代码结果对象 * @param appId 应用ID * @return 保存的目录 */publicfinalFilesaveCode(Tresult,LongappId){// 1.验证输入validateInput(result);// 2.构建基于appId的目录StringbaseDirPath=buildUniqueDir(appId);// 3.保存文件(具体实现由子类提供)saveFiles(result,baseDirPath);// 4.返回目录文件对象returnnewFile(baseDirPath);}/** * 构建基于appId的目录路径 * @param appId 应用ID * @return 目录路径 */protectedfinalStringbuildUniqueDir(LongappId){if(appId==null){thrownewBusinessException(ErrorCode.PARAMS_ERROR,"应用ID不能为空");}StringcodeType=getCodeType().getValue();StringuniqueDirName=StrUtil.format("{}_{}",codeType,appId);StringdirPath=FILE_SAVE_ROOT_DIR+File.separator+uniqueDirName;FileUtil.mkdir(dirPath);returndirPath;}
(2)代码保存执行器改造(CodeFileSaverExecutor)

修改执行方法,补充appId参数,适配新的保存逻辑:

/** * 执行代码保存(使用appId) * @param codeResult 代码结果对象 * @param codeGenType 代码生成类型 * @param appId 应用ID * @return 保存的目录 */publicstaticFileexecuteSaver(ObjectcodeResult,CodeGenTypeEnumcodeGenType,LongappId){returnswitch(codeGenType){caseHTML->htmlCodeFileSaver.saveCode((HtmlCodeResult)codeResult,appId);caseMULTI_FILE->multiFileCodeFileSaver.saveCode((MultiFileCodeResult)codeResult,appId);default->thrownewBusinessException(ErrorCode.SYSTEM_ERROR,"不支持的代码生成类型:"+codeGenType);};}
(3)AI代码生成门面改造(AiCodeGeneratorFacade)

所有生成方法新增appId参数,同步适配流式生成:

/** * 统一入口:根据类型生成并保存代码(流式, 使用appId) * @param userMessage 用户提示词 * @param codeGenTypeEnum 生成类型 * @param appId 应用ID * @return 流式响应 */publicFlux<String>generateAndSaveCodeStream(StringuserMessage,CodeGenTypeEnumcodeGenTypeEnum,LongappId){if(codeGenTypeEnum==null){thrownewBusinessException(ErrorCode.SYSTEM_ERROR,"生成类型为空");}returnswitch(codeGenTypeEnum){caseHTML->{Flux<String>codeStream=aiCodeGeneratorService.generateHtmlCodeStream(userMessage);yieldprocessCodeStream(codeStream,CodeGenTypeEnum.HTML,appId);}caseMULTI_FILE->{Flux<String>codeStream=aiCodeGeneratorService.generateMultiFileCodeStream(userMessage);yieldprocessCodeStream(codeStream,CodeGenTypeEnum.MULTI_FILE,appId);}default->{StringerrorMessage="不支持的生成类型:"+codeGenTypeEnum.getValue();thrownewBusinessException(ErrorCode.SYSTEM_ERROR,errorMessage);}};}
(4)应用服务生成方法(AppService#chatToGenCode)

实现权限校验、应用查询、AI生成调用的核心逻辑:

@OverridepublicFlux<String>chatToGenCode(LongappId,Stringmessage,UserloginUser){// 1.参数校验ThrowUtils.throwIf(appId==null||appId<=0,ErrorCode.PARAMS_ERROR,"应用ID不能为空");ThrowUtils.throwIf(StrUtil.isBlank(message),ErrorCode.PARAMS_ERROR,"用户消息不能为空");// 2.查询应用信息Appapp=this.getById(appId);ThrowUtils.throwIf(app==null,ErrorCode.NOT_FOUND_ERROR,"应用不存在");// 3.验证权限:仅本人可生成代码if(!app.getUserId().equals(loginUser.getId())){thrownewBusinessException(ErrorCode.NO_AUTH_ERROR,"无权限访问该应用");}// 4.获取代码生成类型StringcodeGenTypeStr=app.getCodeGenType();CodeGenTypeEnumcodeGenTypeEnum=CodeGenTypeEnum.getEnumByValue(codeGenTypeStr);if(codeGenTypeEnum==null){thrownewBusinessException(ErrorCode.SYSTEM_ERROR,"不支持的代码生成类型");}// 5.调用AI生成代码returnaiCodeGeneratorFacade.generateAndSaveCodeStream(message,codeGenTypeEnum,appId);}

三、SSE流式接口开发

1. 接口设计

采用SSE(Server-Sent Events)实现流式响应,使用GET请求便于前端EventSource对接,声明响应类型为text/event-stream

2. 核心接口代码(AppController)

/** * 应用聊天生成代码(流式SSE) * @param appId 应用ID * @param message 用户消息 * @param request 请求对象 * @return 生成结果流 */@GetMapping(value="/chat/gen/code",produces=MediaType.TEXT_EVENT_STREAM_VALUE)publicFlux<String>chatToGenCode(@RequestParamLongappId,@RequestParamStringmessage,HttpServletRequestrequest){// 参数校验ThrowUtils.throwIf(appId==null||appId<=0,ErrorCode.PARAMS_ERROR,"应用ID无效");ThrowUtils.throwIf(StrUtil.isBlank(message),ErrorCode.PARAMS_ERROR,"用户消息不能为空");// 获取当前登录用户UserloginUser=userService.getLoginUser(request);// 调用服务生成代码(流式)returnappService.chatToGenCode(appId,message,loginUser);}

四、SSE流式接口优化

原生SSE接口存在空格丢失无法区分正常结束/异常中断两大问题,需针对性优化。

1. 优化1:解决前端空格丢失问题

问题原因

前端EventSource解析纯文本流式数据时,空格/换行符会被异常过滤,导致代码格式错乱。

解决方案

将流式数据封装为ServerSentEvent,数据转为JSON格式传输,保留原始格式。

2. 优化2:添加生成完成标识

问题原因

SSE默认通过关闭连接标识传输结束,无法区分正常完成网络异常中断

解决方案

追加done事件,前端通过监听事件类型判断生成状态。

3. 优化后完整接口代码

/** * 应用聊天生成代码(优化版SSE) * @param appId 应用ID * @param message 用户消息 * @param request 请求对象 * @return 优化后流式响应 */@GetMapping(value="/chat/gen/code",produces=MediaType.TEXT_EVENT_STREAM_VALUE)publicFlux<ServerSentEvent<String>>chatToGenCode(@RequestParamLongappId,@RequestParamStringmessage,HttpServletRequestrequest){// 参数校验ThrowUtils.throwIf(appId==null||appId<=0,ErrorCode.PARAMS_ERROR,"应用ID无效");ThrowUtils.throwIf(StrUtil.isBlank(message),ErrorCode.PARAMS_ERROR,"用户消息不能为空");// 获取当前登录用户UserloginUser=userService.getLoginUser(request);// 调用服务生成代码Flux<String>contentFlux=appService.chatToGenCode(appId,message,loginUser);// 封装数据+添加结束事件returncontentFlux.map(chunk->{// 封装为JSON,保留空格格式Map<String,String>wrapper=Map.of("d",chunk);StringjsonData=JSONUtil.toJsonStr(wrapper);returnServerSentEvent.<String>builder().data(jsonData).build();}).concatWith(Mono.just(// 发送done事件标识生成完成ServerSentEvent.<String>builder().event("done").data("").build()));}

五、接口测试

1. 测试步骤

  1. 用户登录获取会话
  2. 调用SSE流式生成接口
  3. 查看实时输出结果

2. 测试命令(CURL)

# 1.用户登录,保存cookiecurl-XPOST"http://localhost:8123/api/user/login"\-H"Content-Type: application/json"\-d'{"userAccount":"yupi","userPassword":"12345678"}'\-ccookies.txt# 2.调用SSE流式生成接口curl-G"http://localhost:8123/api/app/chat/gen/code"\--data-urlencode"appId=303320512563961856"\--data-urlencode"message=我需要一个简单的任务记录工具网站"\-H"Accept: text/event-stream"\-H"Cache-Control: no-cache"\-bcookies.txt\--no-buffer

3. 测试效果

优化后接口可正常保留空格/换行,生成完成后触发done事件,前端可精准判断生成状态。

六、模块核心要点总结

  1. 应用绑定:通过appId关联代码文件,解决平台化存储混乱问题
  2. 流式响应:SSE技术实现代码实时输出,提升用户交互体验
  3. 双层优化:JSON封装解决空格丢失,done事件明确生成结束状态
  4. 权限管控:仅应用创建者可触发生成,保障平台数据安全
  5. 规范统一:文件目录、接口返回、异常处理全链路标准化
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/27 1:23:04

AGI时代智能体工厂:agno框架构建多智能体系统实战指南

1. 项目概述&#xff1a;AGI时代的新基建&#xff0c;从“智能体”到“智能体工厂”最近几年&#xff0c;AI领域最火的概念莫过于“智能体”了。从AutoGPT的横空出世&#xff0c;到各种基于大语言模型的自动化工具层出不穷&#xff0c;大家似乎都看到了一个未来&#xff1a;让A…

作者头像 李华
网站建设 2026/4/27 1:03:42

唐山正规的纤维水泥板制造厂名声

在建筑材料领域&#xff0c;纤维水泥板凭借其诸多优势得到了广泛应用。唐山作为一个有着深厚工业底蕴的城市&#xff0c;拥有不少正规的纤维水泥板制造厂&#xff0c;并且在业界享有良好的名声。下面我们就一同来探寻唐山纤维水泥板制造厂良好名声背后的秘密。一、产品质量过硬…

作者头像 李华
网站建设 2026/4/27 1:02:22

小白学习神经网络多分类问题在对应位置卡了好久!!

记录一下终于迈过去这个坎。是一个手写数字识别问题&#xff0c;我卡在为什么相应位置就是这个数字&#xff0c;对卡了很久。神经网络输出十个数字&#xff0c;经过softmax&#xff0c;输出十个概率&#xff0c;而我的问题是&#xff1a;怎么知道最大的那个概率对应的就是哪个数…

作者头像 李华
网站建设 2026/4/27 1:02:20

NVIDIA NeMo Retriever技术解析与应用实践

1. 企业数据智能化的挑战与机遇在数字化转型浪潮中&#xff0c;企业积累的数据量正呈指数级增长。根据IDC最新预测&#xff0c;2024年全球企业将产生11ZB&#xff08;1ZB10亿TB&#xff09;的独特数据&#xff0c;到2027年这一数字将激增至20ZB。更关键的是&#xff0c;这些数据…

作者头像 李华