You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot GET接口返回重复响应体问题排查求助

排查Spring Boot GET接口返回重复响应体的问题

根据你提供的代码和响应示例,以下是逐步排查和解决思路:


1. 先确认控制器方法是否被执行两次

在getUserById和existByEmail方法中添加日志,直接打印调用记录:

@GetMapping("/{id}")
public ResponseEntity<?> getUserById(@PathVariable("id") String userId) {
    System.out.println("GET /v0/api/user/" + userId + " 执行");
    UserResponse user = this.userApplication.findById(userId);
    EntityModel<UserResponse> entityModel = this.requestResponseAssembler.toEntityModel(user);
    return ResponseEntity.ok(entityModel);
}

@RequestMapping(value = "/{email}", method = RequestMethod.HEAD)
public ResponseEntity<?> existByEmail(@PathVariable("email") String email) {
    System.out.println("HEAD /v0/api/user/" + email + " 执行");
    if (userApplication.checkIfUserExistByEmail(email)) return ResponseEntity.status(HttpStatus.FOUND).build();
    return ResponseEntity.notFound().build();
}

调用接口后查看控制台:

  • 如果两个方法的日志都出现,说明路径匹配冲突:/{id}和/{email}都是通用路径变量,当请求的ID格式类似邮箱时,可能触发HEAD接口的匹配(虽然指定了HEAD方法,但某些客户端可能同时发送GET+HEAD请求)。
  • 如果只有getUserById的日志出现两次,说明方法被重复执行,问题出在AOP、拦截器或请求重复发送上。

2. 排查请求是否被重复发送

用curl或Postman单独调用一次接口,观察请求次数:

curl -v http://localhost:8080/v0/api/user/8db4c6ab-0872-4688-8cc2-26ea93019f78
  • 如果响应仍然重复,说明问题在服务端;
  • 如果响应正常,说明客户端(浏览器/前端代码)发送了两次请求。

3. 检查过滤器/拦截器是否重复写入响应

查看项目中自定义的Filter或Interceptor,比如继承OncePerRequestFilter的类,检查是否存在以下问题:

  • 重复调用chain.doFilter(request, response);
  • 在过滤器中额外写入响应内容,导致和控制器的输出叠加。

比如这类错误代码:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    filterChain.doFilter(request, response);
    // 额外写入响应,导致重复输出
    response.getWriter().write("冗余内容");
}

4. 排查Spring HATEOAS序列化问题

因为你返回的是EntityModel(Spring HATEOAS类型),可能存在序列化重复的情况:

  • 暂时修改接口返回普通UserResponse,看是否还会重复:
@GetMapping("/{id}")
public ResponseEntity<?> getUserById(@PathVariable("id") String userId) {
    UserResponse user = this.userApplication.findById(userId);
    return ResponseEntity.ok(user);
}

如果此时响应正常,说明问题出在HATEOAS的序列化环节:

  • 检查Spring Boot和Spring HATEOAS的版本兼容性(Java 17需要Spring Boot 3.x + Spring HATEOAS 2.x);
  • 查看是否自定义了HttpMessageConverter,导致JSON序列化被执行两次。

5. 检查AOP切面是否重复调用方法

如果项目中有AOP环绕通知,确认是否重复调用了proceed():

@Around("execution(* com.example.controller.UserResource.getUserById(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    // 错误:调用了两次proceed(),导致方法执行两次
    joinPoint.proceed();
    return joinPoint.proceed();
}

常见修复方案

  1. 路径冲突:修改HEAD接口的路径,比如改为/exists/{email},避免和GET接口的/{id}重叠;
  2. 过滤器问题:修正过滤器逻辑,确保只处理一次响应;
  3. AOP问题:保证proceed()只调用一次;
  4. HATEOAS版本问题:升级或降级依赖,确保版本兼容。

内容的提问来源于stack exchange,提问作者eynoc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 14:37:37