除了在URL接口上加之外,还有比如在拦截器上加
@ExceptionHandler(SystemException.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public BaseResponse handleSystemException(SystemException ex) {
return BaseResponse.newFailResponse()
.errorCode(ex.getCode())
.errorMsg(ex.getMessage())
.build();
}
@ResponseBody
public BaseResponse<Boolean> addToCart(@RequestBody @Validated AddToCartRequest request) {
return BaseResponse.success(cartService.addToCart(request)).build();
}
在 @ExceptionHandler 方法中添加 @ResponseBody 注解是为了明确告诉 Spring 将方法的返回值直接序列化为 HTTP 响应体(如 JSON/XML),而不是尝试解析为视图名称(如 Thymeleaf/JSP)。以下是详细解释:
1. @ResponseBody 的作用
- 功能 :将方法的返回值(这里是
BaseResponse对象)通过HttpMessageConverter(如Jackson)转换为 JSON/XML,并直接写入 HTTP 响应体。 - 适用场景:RESTful API 或需要直接返回数据的场景(而非跳转页面)。
- 对比
@RestController:- 如果类标注了
@RestController(相当于@Controller+@ResponseBody),则所有方法默认返回数据,无需单独加@ResponseBody。 - 如果类是普通
@Controller,则需显式添加@ResponseBody才能返回 JSON/XML。
- 如果类标注了
2. 为什么这里需要 @ResponseBody?
情况 1:类标注了 @Controller 但没有 @RestController
java
`@Controller
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(SystemException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody // 必须加,否则 Spring 会尝试解析为视图名称
public BaseResponse handleSystemException(SystemException ex) {
return BaseResponse.newFailResponse()...;
}
}`
- 不加
@ResponseBody:Spring 会认为返回值是视图名称(如"BaseResponse"),然后尝试查找对应的模板文件(如BaseResponse.jsp),导致404或错误。 - 加
@ResponseBody:Spring 会将BaseResponse对象转换为 JSON,直接作为响应体返回。
情况 2:类标注了 @RestControllerAdvice
java
`@RestControllerAdvice // 等价于 @ControllerAdvice + @ResponseBody
public class GlobalExceptionHandler {
@ExceptionHandler(SystemException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public BaseResponse handleSystemException(SystemException ex) { // 无需 @ResponseBody
return BaseResponse.newFailResponse()...;
}
}`
- 如果使用
@RestControllerAdvice,所有方法的返回值默认视为响应体,无需单独加@ResponseBody。
3. 为什么 @ExceptionHandler 通常需要 @ResponseBody?
- RESTful API 场景:异常处理通常返回结构化数据(如错误码、消息),而非视图。
- Spring 的默认行为 :
- 没有
@ResponseBody时,Spring 会尝试将返回值解析为视图名称。 - 加上
@ResponseBody后,Spring 会跳过视图解析,直接序列化对象。
- 没有
4. 其他相关注解
-
@ResponseStatus:设置 HTTP 状态码(如500),与响应体内容无关。 -
@ResponseBody:控制响应体的生成方式(对象 → JSON/XML)。 -
组合使用 :
java`@ExceptionHandler(SystemException.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) // 设置状态码 @ResponseBody // 确保返回的是 JSON 而非视图 public BaseResponse handleSystemException(SystemException ex) { ... }`
5. 实际代码中的必要性
在你的代码中:
java
`@ExceptionHandler(SystemException.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody // 必须加,除非类是 @RestControllerAdvice
public BaseResponse handleSystemException(SystemException ex) {
return BaseResponse.newFailResponse()...;
}`
- 如果去掉
@ResponseBody:- 方法返回的
BaseResponse会被当作视图名称,导致 Spring 抛出Could not resolve view with name 'BaseResponse'。
- 方法返回的
- 加上
@ResponseBody:BaseResponse对象会被正确转换为 JSON,并附带500状态码。
6. 最佳实践
-
推荐使用
@RestControllerAdvice:java`@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(SystemException.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public BaseResponse handleSystemException(SystemException ex) { ... } }`- 更简洁,避免遗漏
@ResponseBody。
- 更简洁,避免遗漏
-
如果必须用
@ControllerAdvice:- 确保每个返回数据的方法都加上
@ResponseBody。
- 确保每个返回数据的方法都加上
总结
@ResponseBody的作用:将方法返回值序列化为 HTTP 响应体(如 JSON)。- 在
@ExceptionHandler中的必要性:防止 Spring 将返回值误认为视图名称。 - 简化方案 :使用
@RestControllerAdvice替代@ControllerAdvice+@ResponseBody。
你的代码中 @ResponseBody 是必要的,除非你明确使用了 @RestControllerAdvice!