Spring Boot升级后Spring Data Rest Delete响应码变更原因及自定义方案咨询
一、响应码变更的官方依据
Spring Boot 3.x 对应的 Spring Data Rest 版本为 4.x(适配 Spring Framework 6.x),在 Spring Data Rest 4.0 的发布变更中,将配置项 returnBodyOnDelete 的默认值从 false 修改为 true。
在 Spring Boot 2.7.x(对应 Spring Data Rest 3.6.x)中,该配置默认关闭,因此 Delete 接口执行成功后直接返回 204 No Content(无响应体);升级到 Spring Boot 3.1.8 后,默认开启该配置,Delete 接口会尝试返回被删除的实体数据,因此响应码变为 200 OK。这就是导致会话关闭后关联实体不可用问题的核心原因——框架试图序列化已脱离会话的关联实体,引发异常。
二、统一将 Delete 请求响应码改为 204 的解决方案
提供三种可行方案,按需选择:
1. 全局配置(最简单)
在 application.properties 或 application.yml 中添加配置,全局关闭 Delete 后返回实体的行为:
# application.properties spring.data.rest.return-body-on-delete=false
# application.yml spring: data: rest: return-body-on-delete: false
配置生效后,所有通过 Spring Data Rest 自动生成的 Delete 接口都会返回 204 No Content。
2. 单个仓库精准配置
如果不需要全局修改,可针对特定仓库接口单独设置:
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; @RepositoryRestResource(returnBodyOnDelete = false) public interface YourEntityRepository extends JpaRepository<YourEntity, Long> { // 仓库方法定义 }
仅该仓库生成的 Delete 接口会返回 204,其他仓库保持默认行为。
3. 自定义响应拦截(最灵活)
如果需要更复杂的响应逻辑(比如根据条件动态调整响应码),可以通过 @RestControllerAdvice 拦截并修改响应:
import org.springframework.core.MethodParameter; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import java.lang.reflect.Method; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import java.util.Arrays; @RestControllerAdvice(basePackages = "org.springframework.data.rest.webmvc") public class DeleteResponseHandler implements ResponseBodyAdvice<Object> { @Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { Method method = returnType.getMethod(); if (method == null) return false; RequestMapping mapping = method.getAnnotation(RequestMapping.class); return mapping != null && Arrays.asList(mapping.method()).contains(RequestMethod.DELETE); } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { response.setStatusCode(HttpStatus.NO_CONTENT); return null; // 清空响应体 } }
该方式会拦截所有 Spring Data Rest 处理的 Delete 请求,强制返回 204 No Content。
内容的提问来源于stack exchange,提问作者user09

