标题:从电商推荐到AI RAG:一场互联网大厂 Java 面试全程复盘


一、面试故事背景

一家头部互联网大厂在招 电商推荐与内容社区方向的 Java 工程师

面试官:L 老师(风格严肃、专业)
候选人:小 Y(自称“全栈”,实际上有点水,但会的地方答得还不错)

业务场景主要围绕:

  • 电商场景:商品下单、库存、支付、订单状态链路
  • 内容社区与 UGC:商品评价、短内容推荐
  • 大数据与 AI 服务:基于 RAG 的智能客服 / 问答,辅助用户选品

面试分为 3 轮,每轮 3~5 个问题,由浅入深,技术栈覆盖题目中列出的 Java/微服务/缓存/消息队列/AI 等核心能力。


二、第一轮:基础服务与接口设计(电商下单场景)

场景:用户在电商 App 上浏览商品,下单、支付、查看订单。你负责订单服务与部分商品服务。

问题 1:接口与项目结构

面试官:

我们日常后端主要用 Spring Boot 写 REST 接口。假设你要实现一个下单接口 /api/orders,用 POST 创建订单,请简要说说:

  1. Spring Boot 项目用 Maven 怎么组织模块?
  2. Controller 层典型代码结构会怎么写?

小 Y:

嗯……一般就是一个 spring-boot-starter-web 依赖,然后写个 Controller……@RestController,写个方法 createOrder,入参用 @RequestBody,返回就 ResponseEntity 呀。Maven 就一个模块呗,写在 src/main/java 里面就好了。

面试官(点头):

Controller 层回答还行,不过模块化可以再想想,电商系统一般不会只用一个模块。


问题 2:数据库与 ORM 选择

面试官:

订单信息会落 MySQL。我们内部既有用 Hibernate 的项目,也有用 MyBatis 的项目。你在设计订单表和 Java 实体时,会怎么选择 ORM 技术?为什么?

小 Y:

这个嘛……Hibernate 和 JPA 比较自动化,MyBatis 就更灵活一点,我觉得看心情用吧……

面试官(皱眉):

看心情可不行,后面我们再详细聊聊优缺点和适用场景。


问题 3:连接池与性能

面试官:

高并发场景下,数据库连接池很关键。你在 Spring Boot 里一般用什么连接池?简单说说怎么配置最大连接数等参数。

小 Y:

现在基本都是 HikariCP 啊,Spring Boot 默认就用它。我一般就用默认配置,最多改个最大连接数,比如 20 或者 50……

面试官:

基本方向对,不过生产环境要结合 QPS 和数据库能力综合考虑,不是随便写一个数。


问题 4:接口文档与 Swagger/OpenAPI

面试官:

你的下单接口要给前端、移动端用,还要给外部合作方打通。你会如何使用 Swagger / OpenAPI 来管理和暴露接口文档?

小 Y:

以前项目里用 springdoc-openapi,加个依赖,然后访问 /swagger-ui.html 就能看了。写 Controller 的时候加注释就行。

面试官:

还可以,知道工具和大致用法。


问题 5:单元测试与 Mock

面试官:

下单流程涉及库存检查、价格计算、优惠券校验等逻辑。你打算用 JUnit5 + Mockito 写单元测试。请说说:

  1. 如何对 Service 层做单元测试?
  2. 外部依赖(比如库存服务的客户端)怎么 Mock?

小 Y:

嗯……就 @ExtendWith(SpringExtension.class),然后 @SpringBootTest 写测试类,用 Mockito @Mock 一下依赖,when().thenReturn() 弄一下返回……

面试官:

还行,基本思路正确,不过单元测试不一定要起完整 Spring 容器,后面我们答案里会展开。


三、第二轮:微服务、缓存与消息队列(订单与库存联动)

场景扩展:订单服务拆分为多个微服务:订单服务、库存服务、支付服务。需要保证订单创建、库存预扣、支付结果通知的正确性和性能。

问题 1:微服务拆分与 Spring Cloud

面试官:

假如你用 Spring Cloud 做微服务,订单、库存、支付分别是独立服务:

  1. 服务发现你会用什么组件?
  2. 服务间调用怎么做负载均衡?

小 Y:

以前用过 Eureka,还有 Consul 吧,服务注册到上面,别的服务就能发现。负载均衡用 Ribbon 啊,或者 Spring Cloud LoadBalancer,现在好像推荐用 OpenFeign 调用,然后就自动负载均衡了。

面试官:

这部分不错,知道技术演进。


问题 2:缓存设计与 Redis

面试官:

现在订单详情查询很频繁,订单信息主要存 MySQL,但每次查库压力会很大。你打算用 Redis 做缓存:

  1. 缓存 Key 怎么设计?
  2. 如何避免缓存穿透和雪崩?

小 Y:

Key 就 order:detail:orderId 吧,避免冲突。穿透的话可以缓存空值,雪崩就加点随机过期时间……

面试官:

这个回答不错,思路清晰,有实践经验的感觉。


问题 3:消息队列与最终一致性

面试官:

用户下单后,库存服务要异步扣减,还要发消息给推荐系统做统计。我们用 Kafka 或 RabbitMQ:

  1. 你如何保证订单状态和消息发送的 最终一致性
  2. Kafka 消费端如何做到 幂等

小 Y:

嗯……就是事务嘛……可以用事务消息,或者先写数据库再发消息……Kafka 幂等的话,可以靠消费位点吧?

面试官(略显严肃):

事务这块不能太含糊,等会我们在解析部分会详细说。


问题 4:监控与链路追踪

面试官:

订单调用库存、库存再调消息队列,如果某个环节变慢或者报错,我们要快速定位问题。请说说:

  1. 你会怎么用 Prometheus + Grafana 做指标监控?
  2. 链路追踪你熟悉 Jaeger 或 Zipkin 吗?大概怎么接入?

小 Y:

指标就用 Micrometer 暴露,然后 Prometheus 抓数据,Grafana 画图。链路追踪以前项目里加过 Sleuth,配置一下就能看到 traceId 了,Jaeger、Zipkin 就类似……

面试官:

至少知道常用栈,这块可以。


问题 5:日志与 ELK

面试官:

系统日志我们会统一打到 ELK(Elasticsearch + Logstash + Kibana)。你在使用 Logback 或 Log4j2 时:

  1. 日志级别如何划分?
  2. 如何设计日志字段,方便后续检索和分析?

小 Y:

日志级别就 debug、info、warn、error……字段就随便打点吧,比如用户 ID、订单 ID 啥的。

面试官:

随便打点不行,要有统一规范,不过核心字段你说到了。


四、第三轮:AI 智能客服与安全风控(RAG + 风控拦截)

场景再升级:公司新做一个 智能客服系统,帮助用户查询订单状态、物流进度、推荐商品。后台基于 RAG(检索增强生成),利用公司订单、物流、商品文档构建知识库,并在 Web/App、企业协同 SaaS 中统一接入。

问题 1:AI 智能客服总体架构

面试官:

我们打算用 Spring Boot + Spring AI 搭一个智能客服服务:

  1. 整体架构上,你会怎么拆分模块?(例如:对话管理、向量检索、工具调用等)
  2. RAG 的核心步骤你能简要说一下吗?

小 Y:

呃……RAG 就是先检索再生成嘛,先搜文档再喂给大模型。模块就拆成几个 Service,向量库啥的……具体就……嗯,大概是这样吧。

面试官(表情严肃):

概念知道一点,但缺少细节,我们等会在答案中会展开完整流程。


问题 2:向量数据库与语义检索

面试官:

我们考虑用 Milvus 或 Redis 作为向量数据库,结合 OpenAI 或本地 Ollama 的 Embedding 模型:

  1. 向量化的大致流程是什么?
  2. 语义检索和传统关键词检索有什么差别?

小 Y:

向量化就是把文本丢给 embedding 模型,变成一串数字,然后存向量库,查的时候也是算相似度。语义检索就更智能,能按意思搜,关键词就只能按词匹配……

面试官:

这部分理解还不错。


问题 3:Agent 与工具调用

面试官:

我们希望智能客服不仅能回答知识库问题,还能调用 订单查询、退款状态、物流跟踪等后端接口。现在很多框架支持 Agent + 工具调用:

  1. 你理解的 Agent 是什么?
  2. 工具调用标准化一般包括哪些信息?

小 Y:

Agent 就是……一个智能体?能自动帮你调接口……标准化就,呃,有个名字,有个参数,啥的……

面试官(摇头):

概念过于抽象,缺细节,后面我们会给一个比较标准的表述。


问题 4:AI 幻觉与企业文档问答

面试官:

大模型会产生幻觉(Hallucination),在企业场景,尤其是订单和支付相关问题上,不能乱编:

  1. 你觉得如何降低幻觉?
  2. 企业文档问答系统中,如何保证回答可追溯?

小 Y:

嗯……就多检索一点文档吧,让它别瞎编?可追溯就,把来源返回给用户……差不多这样。

面试官:

思路有一点,但不系统。


问题 5:安全与风控

面试官:

智能客服毕竟要查用户订单,涉及权限与风控:

  1. 你会如何用 Spring Security + JWT 做用户鉴权?
  2. 风控上,对于频繁查询订单、尝试越权访问的请求,你有何简单策略?

小 Y:

鉴权的话就登录发个 JWT,里面带用户 ID,后面请求带 token,后端用 Spring Security 解析。风控就……比如限流、黑名单?

面试官:

基本点答到了。


五、面试结束语

面试官:

好,今天就问到这里。你在基础服务和常规微服务方面还可以,但在事务一致性、AI 架构、Agent 工具调用等方面还比较薄弱。

回去之后可以重点补一下我们聊到的几个点,尤其是分布式事务、消息一致性、RAG 流程的细节。后续结果我们会通过邮件或电话通知你。

小 Y:

好的好的,我回去一定好好学习!


六、面试题详细解析(小白向)

下面是对上述所有问题的系统解析,按照业务场景串联,适合小白和初中级工程师系统学习。

1. Spring Boot 项目结构与 REST 接口设计

1.1 项目模块化(Maven/Gradle)

在大厂电商项目中,很少是单一模块:

常见拆分方式:

  • order-service:订单服务
  • product-service:商品服务
  • inventory-service:库存服务
  • common-lib:通用工具(DTO、异常、公共配置等)

Maven 父子结构示例:

<project>
  <groupId>com.company.mall</groupId>
  <artifactId>mall-parent</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>

  <modules>
    <module>common-lib</module>
    <module>order-service</module>
    <module>inventory-service</module>
  </modules>
</project>

1.2 Controller 层典型写法

@RestController
@RequestMapping("/api/orders")
public class OrderController {

    private final OrderService orderService;

    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }

    @PostMapping
    public ResponseEntity<OrderDTO> createOrder(@RequestBody CreateOrderRequest request) {
        OrderDTO order = orderService.createOrder(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(order);
    }

    @GetMapping("/{orderId}")
    public ResponseEntity<OrderDTO> getOrder(@PathVariable Long orderId) {
        return ResponseEntity.ok(orderService.getOrder(orderId));
    }
}
  • 使用 @RestController@RequestMapping 定义 REST 接口
  • 入参用 DTO 对象,而不是直接实体
  • 返回统一的响应结构(可封装 CommonResponse

2. Hibernate / JPA 与 MyBatis 选型

2.1 核心差异

  • Hibernate / JPA

    • 优点:
      • 面向对象,实体与表映射自动化
      • 有缓存、延迟加载等能力
      • 对简单 CRUD 开发效率高
    • 缺点:
      • 性能调优复杂(N+1、延迟加载等问题)
      • 复杂 SQL 控制力不如 MyBatis
  • MyBatis

    • 优点:
      • SQL 可控,适合复杂查询
      • 易于阅读、与 DBA 协作
    • 缺点:
      • 需要编写大量 SQL
      • 对象关系映射需要手工维护

2.2 常见实践

  • 后台管理、通用 CRUD:可以用 JPA + Spring Data JPA
  • 关键业务(订单、支付、风控):更多使用 MyBatis 或 MyBatis-Plus,方便精细控制 SQL 和性能

3. 数据库连接池(HikariCP)的配置

Spring Boot 2+ 默认使用 HikariCP:

spring:
  datasource:
    url: jdbc:mysql://.../mall
    username: xxx
    password: xxx
    hikari:
      maximum-pool-size: 30
      minimum-idle: 10
      connection-timeout: 30000
      max-lifetime: 1800000
  • 最大连接数要结合:
    • 单实例最大 QPS
    • 单机/集群连接上限
    • 业务峰值等

4. Swagger/OpenAPI 与接口管理

常用方案:

  • springdoc-openapi(替代传统 Swagger2)
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.0.0</version>
</dependency>

配置后访问:

  • /swagger-ui.html/swagger-ui/index.html

好处:

  • 接口自描述
  • 前后端协作方便
  • 对外开放 API 时可生成 OpenAPI Spec 文档

5. 单元测试与 Mock(JUnit5 + Mockito)

5.1 不一定要 @SpringBootTest

对 Service 做“真·单元测试”时,可以:

@ExtendWith(MockitoExtension.class)
class OrderServiceTest {

    @Mock
    private InventoryClient inventoryClient;

    @InjectMocks
    private OrderServiceImpl orderService;

    @Test
    void testCreateOrder() {
        when(inventoryClient.checkStock(anyLong())).thenReturn(true);
        OrderDTO order = orderService.createOrder(...);
        assertNotNull(order);
    }
}
  • 只测试业务逻辑,不依赖 Spring 容器
  • 外部调用用 Mockito Mock 掉

6. 微服务与 Spring Cloud 生态

6.1 服务发现

常用组件:

  • Eureka:Netflix OSS,Spring Cloud 早期默认
  • Consul:支持服务发现 + 配置
  • Nacos:国内常用,整合注册 + 配置

6.2 服务调用与负载均衡

  • 早期用 Ribbon
  • 现在使用:
    • Spring Cloud LoadBalancer
    • OpenFeign + LoadBalancer

调用示例:

@FeignClient(name = "inventory-service")
public interface InventoryClient {

    @PostMapping("/api/inventory/reserve")
    ReserveResponse reserve(@RequestBody ReserveRequest request);
}

7. Redis 缓存设计(防穿透、防雪崩)

7.1 Key 设计

  • 模式:业务:模块:主键
    • 示例:order:detail:12345
  • 好处:
    • 可读性好
    • 易于做整体清理和统计

7.2 缓存穿透

  • 问题:频繁查询不存在的数据,直接打到数据库
  • 解决:
    • 对不存在的数据缓存一个短期空值(如 60s)
    • 或使用布隆过滤器拦截非法 ID

7.3 缓存雪崩

  • 问题:大量 Key 在同一时间过期,瞬时打爆数据库
  • 解决:
    • 过期时间加随机偏移:baseTTL + random(0, 300s)
    • 做多级缓存(本地 Caffeine + Redis)

8. 消息队列与最终一致性(Kafka / RabbitMQ)

8.1 典型模式:本地消息表(Outbox Pattern)

  • 步骤:
    1. 订单服务在一个本地事务中:
      • 写订单表
      • 写本地消息表(order_created
    2. 后台任务(或中间件)异步扫描本地消息表,发送到 Kafka
    3. 发送成功后,标记消息已投递

这样即使订单创建成功但消息发送失败,也不会丢失消息。

8.2 Kafka 消费幂等

  • 常用方式:
    • 基于业务主键做幂等(如订单号)
      • 在消费端建立处理记录表,记录已经处理过的业务 ID
    • 或利用 Kafka 幂等生产者 + idempotent 业务逻辑(例如使用 INSERT IGNOREON DUPLICATE KEY UPDATE

9. 监控与链路追踪

9.1 指标监控:Micrometer + Prometheus + Grafana

  • 在 Spring Boot 中引入 micrometer-registry-prometheus
  • 默认会暴露 /actuator/prometheus 指标
  • Prometheus 抓取 -> Grafana 画图(QPS、RT、错误率等)

9.2 链路追踪:Sleuth + Jaeger/Zipkin

  • Sleuth 自动给请求加 traceIdspanId
  • 通过 exporter 将数据发送到 Jaeger/Zipkin
  • 在可视化界面查看完整调用链:订单 -> 库存 -> MQ

10. 日志与 ELK

10.1 日志级别

  • DEBUG:开发调试
  • INFO:重要业务日志(下单成功、支付成功)
  • WARN:非预期但可继续
  • ERROR:严重错误

10.2 日志字段设计

  • 统一的 JSON 日志:
    • traceId
    • userId
    • orderId
    • serviceName
    • method
    • level
    • message

方便在 Kibana 中根据字段过滤和聚合分析。


11. 智能客服与 RAG 架构

11.1 RAG(Retrieval-Augmented Generation)流程

  1. 文档加载
    • 从 MySQL、Elasticsearch、OSS 等加载订单 FAQ、物流规则、商品说明
  2. 切分 Chunk
    • 文本分成小段(如 200~500 字)
  3. 向量化(Embedding)
    • 使用 OpenAI / 本地 Ollama 的 Embedding 模型,将文本变成向量
  4. 向量入库
    • 存入 Milvus / Chroma / Redis 向量索引
  5. 查询阶段
    • 用户提问 -> 将问题向量化 -> 在向量库中做语义检索,取 Top-K 文档
  6. 提示填充(Prompting)
    • 将检索到的文档作为上下文拼接进 Prompt
  7. 生成回答
    • 调用大模型生成答案

11.2 模块拆分

  • 对话管理模块:Session 管理、聊天会话内存
  • 检索模块:向量检索、语义检索
  • 工具执行模块:订单查询、物流查询工具
  • 日志与监控模块:记录每次调用链路

12. 向量化与语义检索

12.1 向量化流程

  • 输入:文本(如“如何查询订单物流?”)
  • 模型:Embedding 模型(OpenAI text-embedding-3-small 等)
  • 输出:高维向量(如 1536 维浮点数)
  • 存储:
    • Milvus:专门的向量数据库,支持大规模向量检索
    • Redis:Redis Vector / 模拟向量存储

12.2 语义检索 vs 关键词检索

  • 关键词:依赖词匹配(如 Elasticsearch 的 term/match 查询)
  • 语义:通过向量相似度,支持同义词、语序变化、口语化表达

实际项目中常做 混合检索:先用关键词筛一轮,再用向量排序。


13. Agent 与工具调用标准化

13.1 Agent 概念

  • Agent 是一个“具备状态与目标”的智能体:
    • 能读理解用户意图
    • 能决定何时调用哪些工具(API)
    • 能组合多个步骤完成复杂任务(如“帮我查最近三个月订单并退款未发货的”)

13.2 工具调用标准化

工具描述通常包括:

  • name:工具名,例如 get_order_detail
  • description:用途说明
  • parameters:参数结构(JSON Schema)
    • orderId(Long, required)
    • userId(Long, required)

框架(如 Spring AI、LangChain 等)会:

  1. 将工具描述提供给模型
  2. 模型按标准格式返回工具调用请求
  3. 框架执行工具并返回结果

14. AI 幻觉控制与企业文档问答

14.1 降低幻觉

  • 严格控制模型输出范围:
    • 强调“仅根据提供的上下文回答”
  • 检索质量优化:
    • 提高向量检索质量(更多样本、合适的 chunk 大小)
  • 引入 答案校验
    • 对金额、订单号等敏感字段做后端验证

14.2 可追溯性

  • 在回答中附上:
    • 文档标题
    • 文档 ID 或链接
    • 文档片段内容
  • 方便客服或用户核对答案来源

15. 安全与风控(Spring Security + JWT)

15.1 JWT 鉴权基本流程

  1. 用户登录,后端校验账号密码
  2. 生成 JWT:
    • 包含 sub(用户 ID)、过期时间、角色信息
  3. 前端存储 token(Header 或 Cookie)
  4. 后续请求在 Authorization: Bearer xxx 中携带
  5. Spring Security 通过过滤器解析 JWT,构造 Authentication

15.2 简单风控策略

  • 限流(如基于 Redis + Lua):
    • 单用户单位时间内查询订单次数限制
  • 黑名单:
    • 连续触发风控规则的 IP / 用户加入黑名单
  • 审计日志:
    • 记录异常访问行为,用于后续分析和模型训练

七、总结

通过这场“电商 + 智能客服”场景的大厂 Java 面试,我们串联了:

  • Spring Boot、Spring MVC 的 REST 服务基础
  • Hibernate / MyBatis 等 ORM 选型
  • HikariCP、Redis 缓存、Kafka 消息队列
  • Spring Cloud 微服务与监控、链路追踪
  • ELK 日志体系
  • 基于 Spring AI 的 RAG 架构、向量数据库与语义检索
  • Agent 工具调用、AI 幻觉控制
  • Spring Security + JWT 的安全与风控

对于刚入门或准备跳槽大厂的 Java 开发者,可以把这篇文章当作一个 场景驱动的知识图谱:一边回顾面试问答,一边对照解析部分查缺补漏,逐步构建起从传统电商到 AI 智能客服的一整套后端技术体系。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐