Mastering Unified Response and Global Exception Handling in Spring Boot 3
This tutorial explains how to implement a standardized response format and a global exception handling mechanism in Spring Boot 3, providing reusable code examples, status enums, controller advice, and best‑practice guidelines to improve code consistency, readability, and maintainability across backend projects.
Environment: SpringBoot 3.2.5
1. Introduction
Unified result return and unified exception handling standardize code, improve team collaboration, reduce maintenance difficulty, and make code easier to understand and extend.
2. Practical Example
2.1 Unified Response
Define a generic response object that contains a status code, message, and data. Using generics provides type safety and readability.
<code>public class ResultResponse<T> {
private Integer code;
private String msg;
private T data;
// getters, setters
}</code>Define common status codes, usually HTTP codes, and optionally custom application‑specific codes.
200 OK : request succeeded
201 Created : resource created
204 No Content : request succeeded with no content
400 Bad Request : client error
401 Unauthorized : unauthorized access
404 Not Found : resource not found
500 Internal Server Error : server error
Custom status enum:
<code>public enum StatusEnum {
SUCCESS(200, "Request processed successfully"),
UNAUTHORIZED(401, "Authentication failed"),
FORBIDDEN(403, "Access denied"),
SERVICE_ERROR(500, "Service exception"),
PARAM_INVALID(1000, "Invalid parameter");
public final Integer code;
public final String message;
StatusEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}</code>Utility methods for success and error responses:
<code>public class R {
public static <T> ResultResponse<T> success(T data) {
ResultResponse<T> response = new ResultResponse<>();
response.setData(data);
response.setCode(StatusEnum.SUCCESS.code);
return response;
}
public static <T> ResultResponse<T> error(StatusEnum statusEnum) {
return error(statusEnum, statusEnum.message);
}
public static <T> ResultResponse<T> error(StatusEnum statusEnum, String errorMsg) {
ResultResponse<T> response = new ResultResponse<>();
response.setCode(statusEnum.code);
response.setMsg(errorMsg);
return response;
}
}</code>Controller example:
<code>@RestController
@RequestMapping("/users")
@Validated
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping("")
public ResultResponse<Void> createUser(@Validated @RequestBody UserVO userVO) {
userService.createUser(userVO);
return ResultResponse.success(null);
}
@GetMapping("/{id}")
public ResultResponse<UserVO> getUser(@NotNull(message = "Missing user ID") Long id) {
UserVO userVO = userService.getUserById(id);
return ResultResponse.success(userVO);
}
}</code>Sample JSON responses for POST and GET requests are shown.
2.2 Unified Exception Handling
Define a custom business exception extending RuntimeException:
<code>public class BusinessException extends RuntimeException {
private final StatusEnum status;
public BusinessException(StatusEnum status, String message) {
super(message);
this.status = status;
}
public BusinessException(StatusEnum status) {
this(status, status.message);
}
// getters, setters
}</code>Global exception handler using @ControllerAdvice (or @RestControllerAdvice) and @ExceptionHandler:
<code>@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
@ResponseBody
public ResultResponse<Void> handleBusinessException(BusinessException ex, HttpServletRequest request) {
return ResultResponse.error(ex.getStatus(), ex.getMessage());
}
@ExceptionHandler(Exception.class)
@ResponseBody
public ResultResponse<Void> handleException(Exception ex, HttpServletRequest request) {
return ResultResponse.error(StatusEnum.SERVICE_ERROR);
}
}</code>Service layer can throw BusinessException when business rules are violated, and the client receives a consistent error JSON.
When using @ControllerAdvice, add @ResponseBody to the handler methods; @RestControllerAdvice does not require it.
Best practices for exception handling include avoiding misuse of exceptions for flow control, not ignoring exceptions, not leaving empty catch blocks, throwing exceptions only for genuine error conditions, and covering exception scenarios in unit tests.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.