自定义RuntimeException抛出后,为何返回结果包含堆栈跟踪信息?
问题描述
在Spring Boot项目中实现了自定义异常InvalidEntryException(继承自RuntimeException),在EmployeeServiceImpl的updateEmployeeDto方法中,当传入无效员工ID时抛出该异常。目前异常消息已正常记录,但Postman返回结果中同时包含堆栈跟踪(trace)信息,相关代码及返回结果如下:
抛出异常的Service类代码
@Service public class EmployeeServiceImpl implements EmployeeService { // 输入无效员工ID时程序应抛出错误 public EmployeeDTO updateEmployeeDto(EmployeeDTO employeeDTO, Long employeeId){ Optional<Employees> employeeWithId = Optional.ofNullable(employeesRepo.findByEmployeeId(employeeId)); if(!employeeWithId.isEmpty()){ Employees employee=employeeWithId.get(); } else{ throw new InvalidEntryException("Entered employee id was not found"); } } }
自定义异常类代码
public class InvalidEntryException extends RuntimeException{ public InvalidEntryException(String message){ super(message); } }
Postman返回结果
{ "timestamp": "2022-12-19T05:33:03.854+00:00", "status": 500, "error": "Internal Server Error", "trace": "com.assetmanagementsystems.ams.exception.InvalidEntryException: Entered employee id was not found\r\n\tat com.assetmanagementsystems.ams.service.serviceImpl.EmployeeServiceImpl.getEmployeeById(EmployeeServiceImpl.java:64)\r\n\tat com.assetmanagementsystems.ams.controller.EmployeeController.retrieveEmpById(EmployeeController.java:60)java.base/java.lang.Thread.run(Thread.java:833)\r\n", "message": "Entered employee id was not found", "path": "/employees/employee/22" }
原因分析
这是Spring Boot默认异常处理机制的行为:在开发环境(默认启动环境)下,为方便开发者调试,DefaultErrorAttributes会返回完整的错误详情,其中就包含堆栈跟踪信息;而生产环境下默认不会返回trace内容。
解决方法
方法1:通过配置控制返回策略
直接修改配置文件,全局控制是否返回堆栈跟踪,适合不需要自定义响应结构的场景:
application.properties配置
# 无论环境,永远不返回堆栈跟踪 server.error.include-stacktrace=never # 或者保持默认逻辑:仅在请求参数带trace时返回,生产环境默认不返回 # server.error.include-stacktrace=on_trace_param
application.yml配置
server: error: include-stacktrace: never
方法2:自定义全局异常处理器
通过@RestControllerAdvice和@ExceptionHandler捕获自定义异常,返回完全自定义的响应体,彻底控制返回内容,同时还能修正HTTP状态码(比如把500改为更合理的404):
import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.context.request.ServletWebRequest; import java.time.LocalDateTime; import java.util.HashMap; import java.util.Map; @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(InvalidEntryException.class) public ResponseEntity<Map<String, Object>> handleInvalidEntryException(InvalidEntryException ex, ServletWebRequest request) { Map<String, Object> errorResponse = new HashMap<>(); errorResponse.put("timestamp", LocalDateTime.now().toString()); errorResponse.put("status", HttpStatus.NOT_FOUND.value()); errorResponse.put("error", "Not Found"); errorResponse.put("message", ex.getMessage()); errorResponse.put("path", request.getRequest().getRequestURI()); return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND); } }
配置后,抛出InvalidEntryException时,Postman会返回你定义的响应结构,不会包含堆栈跟踪信息。
内容的提问来源于stack exchange,提问作者Vibhanshu Jha
相关产品推荐
相关产品推荐

