Java 转大模型开发:代码跑通了,权限却漏了?

聊《我用Java经验做了次 AI 项目,最先失效的是旧方法》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。

摘要

从 Spring Boot 到 LangChain4j/Spring AI,技术栈迁移只是第一步。本文复盘了一次将传统后端逻辑重构为 Agent 应用的真实过程:当 Prompt 调优不再是瓶颈时,生产环境的“生死线”转移到了权限隔离、全链路日志和可观测性上。对于 Java 开发者而言,补齐工程化短板比单纯学习 LLM API 调用更为紧迫。

目录

  • 为什么你的 Agent Demo 能跑,上线就崩?
  • Java 开发者的优势与陷阱
  • 补齐 AI 技能:从 API 调用到 Spring AI
  • 项目实战:权限与日志的工程化改造
  • 面试准备:展示你的工程思维
  • 总结

为什么你的 Agent Demo 能跑,上线就崩?

做 Java 开发多年,我们习惯了确定性:输入 A,经过 B 处理,必定得到 C,或者抛出明确的异常。但大模型应用(LLM App)打破了这种确定性。

最近我在带团队做一个内部知识库问答系统,初期用 Python 快速搭了个 Demo,RAG 流程跑得飞起,Prompt 稍微调优一下,准确率就不错。但当我们尝试将其重构为高并发的 Spring Boot 服务,并接入企业级权限体系时,问题暴露无遗。

最直观的感受是:代码逻辑没变,但“控制流”变了。

在传统 CRUD 里,权限校验在 Controller 层统一拦截;但在 Agent 工作流中,模型可能会自主决定调用几个外部工具(Tool Call),甚至产生幻觉去查询不该查的数据。如果继续沿用旧的“接口级权限”思维,就会出现严重的越权漏洞。这就是为什么现在很多公司招大模型工程师,不只看你会不会写 Prompt,更看重你能否解决“权限黑洞”和“日志盲区”。

Java 开发者的优势与陷阱

别妄自菲薄,Java 背景在大模型工程化落地中有天然优势,但也存在思维惯性陷阱。

优势在于:
1. 类型安全与架构能力:大模型应用本质上还是软件系统,需要良好的分层设计。Java 的强类型约束能帮你更好地定义 Tool 的参数结构,避免 JSON 解析灾难。
2. 生态整合能力:企业级应用离不开数据库连接池、缓存、消息队列。Spring 生态对这些基础设施的支持远超 Python 快糙猛的脚本风格。

陷阱在于:
1. 过度依赖同步阻塞:LLM 推理是高延迟操作,传统 Java 线程模型容易打满资源。
2. 忽视非确定性输出:旧代码喜欢if-else明确分支,而 Agent 的输出可能是概率性的,需要引入重试机制、熔断器和结果校验层。

补齐 AI 技能:从 API 调用到 Spring AI

如果你已经会调 OpenAI 或国内的通义千问 API,那只是入门。真正的门槛在于如何将这些能力无缝嵌入现有的后端架构。

目前业界主要有两个方向:Python 系的 LangChain/LangGraph 和 Java 系的 LangChain4j/Spring AI。作为 Java 程序员,我建议直接拥抱 Spring AI。它不仅仅是封装了 LLM 客户端,更重要的是它将 LLM 作为 Spring Bean 的一部分,你可以像注入 Service 一样注入模型,像配置数据源一样配置 Embedding 向量库。

核心配置示例

application.yml中配置 Spring AI 的 ChatClient 和工具调用:

spring: ai: openai: api-key: ${OPENAI_API_KEY} chat: options: model: gpt-4o temperature: 0.7 vectorstore: qdrant: url: http://localhost:6333

在 Java 代码中,通过声明式方式绑定工具,这才是工程化的起点:

@Service public class DocumentAgentService { private final ChatClient chatClient; public DocumentAgentService(ChatClient.Builder chatClientBuilder) { this.chatClient = chatClientBuilder.build(); } /** * 核心业务方法:结合 RAG 和工具调用 */ public String queryKnowledge(String question) { return chatClient.prompt() .user(question) .system("你是一名资深技术支持,请基于提供的上下文回答用户问题。如果上下文中没有答案,请诚实告知。") .functions("searchDocuments", "getSystemStatus") // 声明可用工具 .call() .content(); } }

这里的关键不是chatClient怎么创建,而是.functions()这一行。它将你的 Java 方法暴露给 LLM,LLM 会根据用户意图动态选择调用哪个方法。这就引出了下一个更关键的问题:谁有权限调用这些方法?

项目实战:权限与日志的工程化改造

Demo 阶段,我们可以随便写个searchDocuments方法,返回所有文档。但在生产环境,这会导致严重的信息泄露。

1. 权限隔离:在工具层面做校验

不要指望 LLM 自觉遵守规则。必须在工具方法的入口处,结合当前的 SecurityContext 进行二次校验。

假设我们要实现一个“仅能查看自己部门文档”的功能:

@Tool(description = "搜索公司内部文档") public List<String> searchDocuments(@Param(description = "搜索关键词") String keyword) { // 1. 获取当前登录用户的部门ID String currentDeptId = SecurityContextHolder.getContext().getAuthentication().getDetails(); // 2. 权限校验:如果用户尝试搜索其他部门的敏感数据,直接拒绝或过滤 if (!isAuthorizedToAccess(keyword, currentDeptId)) { log.warn("Permission denied for user {} searching {}", currentDeptId, keyword); throw new AccessDeniedException("无权访问该部门文档"); } // 3. 执行实际查询 return documentRepository.search(keyword, currentDeptId); }

注意点:Spring AI 默认会将工具参数序列化为 JSON 传给模型。你需要确保你的@Tool方法签名清晰,并且返回值结构稳定,否则模型容易“猜错”参数格式。

2. 全链路日志:可观测性是调试的唯一依据

LLM 应用的调试极其困难,因为输入输出是非确定的。传统的System.out.println毫无用处。你需要的是结构化日志和Trace ID 贯穿。

我推荐集成 Micrometer Tracing 和 SLF4J MDC(Mapped Diagnostic Context)。在每次请求进入时,生成唯一的traceId,并将其注入到后续的 LLM 调用链中。

// 自定义过滤器,注入 Trace ID @Component public class AiTraceFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) { String traceId = UUID.randomUUID().toString(); MDC.put("traceId", traceId); try { filterChain.doFilter(request, response); } finally { MDC.remove("traceId"); } } }

在记录 LLM 响应时,务必记录:

  • Prompt 模板:实际发送给模型的完整文本。
  • Token 消耗:输入和输出的 token 数,用于成本核算。
  • 耗时分布:LLM 生成时间 vs 工具调用时间 vs 网络传输时间。

只有看到详细的 Trace,你才能知道是 Prompt 写得烂,还是模型反应慢,亦或是某个 Tool 查询数据库超时导致整个流程卡死。

面试准备:展示你的工程思维

当面试官问你“如何评估大模型应用的效果”时,不要只回答“准确率”和“召回率”。作为一个有 Java 背景的候选人,你应该强调以下三点:

1. 稳定性与容错:你是如何处理 LLM 超时、幻觉和不稳定输出的?(例如:引入重排序模型、设置重试上限、 fallback 策略)。
2. 成本控制:如何通过缓存 Embeddings、量化模型、或者优化 Prompt 长度来降低 Token 消耗?
3. 安全性:你如何实现输入过滤(防止 Prompt 注入)和输出合规性检查?

在简历项目中,建议这样描述:
> “基于 Spring AI 重构知识问答系统,引入全链路 Trace 监控与基于角色的工具权限校验,解决了 Demo 阶段存在的越权访问风险,并将平均响应延迟从 3s 优化至 800ms。”

总结

Java 转大模型开发,核心不在于学习新的语法,而在于思维模式的转换:从确定性的流程控制,转向概率性的意图理解与动态规划。

现在的行业趋势非常明确:单纯的 Prompt 工程师红利正在消退,企业更需要的是懂权限、懂日志、懂架构的 AI 工程师。你的 Java 经验在构建稳健、安全、可维护的大模型应用基础设施时,依然是巨大的护城河。

别急着写下一个 Hello World,先去检查一下你的工具类里,有没有留下权限的后门。

资料展示

下面是我整理的AI大模型学习资料和工具包预览,适合收藏后按主题逐步学习。

如果你想看完整资料目录,可以在评论区留言「资料」;也欢迎告诉我你更关注AI大模型里的哪类内容。