Backend Development 10 min read

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.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Unified Response and Global Exception Handling in Spring Boot 3

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.

backendJavaAPISpringBootExceptionHandlingUnifiedResponse
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.