Standardized API Response, Global Exception Handling, and Logback Configuration in Spring Boot

This article explains how to define a unified JSON response format for Spring Boot APIs, implement a reusable result class with chainable methods, set up global exception handling using @ControllerAdvice, and configure Logback for structured logging across development and production environments, including code examples.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Standardized API Response, Global Exception Handling, and Logback Configuration in Spring Boot

Unified Result Return

Most front‑end and back‑end communication in modern projects uses JSON, so defining a uniform response structure simplifies interaction and UI rendering.

General Form

Whether the response is successful

Response status code

Status description

Response data

Other identifiers

Result Enum

@Getter
public enum ResultCodeEnum {
    SUCCESS(true,20000,"成功"),
    UNKNOWN_ERROR(false,20001,"未知错误"),
    PARAM_ERROR(false,20002,"参数错误"),
    // ... other enums
    ;
    private Boolean success;
    private Integer code;
    private String message;
    ResultCodeEnum(boolean success, Integer code, String message) {
        this.success = success;
        this.code = code;
        this.message = message;
    }
}

Unified Result Class

The class R encapsulates the fields above, hides its constructor, and provides static factory methods ( ok(), error()) as well as chainable setters for data, message, code, and success.

@Data
public class R {
    private Boolean success;
    private Integer code;
    private String message;
    private Map<String,Object> data = new HashMap<>();
    private R() {}
    public static R ok() { /* set SUCCESS enum */ }
    public static R error() { /* set UNKNOWN_ERROR enum */ }
    public static R setResult(ResultCodeEnum result) { /* set from enum */ }
    public R data(Map<String,Object> map) { this.data = map; return this; }
    public R data(String key, Object value) { this.data.put(key,value); return this; }
    public R message(String msg) { this.message = msg; return this; }
    public R code(Integer code) { this.code = code; return this; }
    public R success(Boolean success) { this.success = success; return this; }
}

Controller Layer Usage

@RestController
@RequestMapping("/api/v1/users")
public class TeacherAdminController {
    @Autowired
    private UserService userService;
    @GetMapping
    public R list() {
        List<Teacher> list = teacherService.list(null);
        return R.ok().data("items", list).message("用户列表");
    }
}

Typical JSON output:

{
  "success": true,
  "code": 20000,
  "message": "查询用户列表",
  "data": { "items": [ {"id":"1","username":"admin","role":"ADMIN"}, … ] }
}

Unified Exception Handling

Runtime exceptions that bypass normal return flow are captured by a global exception handler.

@ControllerAdvice

The annotation aggregates @ExceptionHandler methods for all controllers.

Catch generic Exception and return R.error() Specific handlers for NullPointerException, HttpClientErrorException, and custom

CMSException
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public R error(Exception e) {
        log.error(ExceptionUtil.getMessage(e));
        return R.error();
    }
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public R error(NullPointerException e) {
        return R.setResult(ResultCodeEnum.NULL_POINT);
    }
    @ExceptionHandler(CMSException.class)
    @ResponseBody
    public R error(CMSException e) {
        return R.error().message(e.getMessage()).code(e.getCode());
    }
}

Custom Exception

@Data
public class CMSException extends RuntimeException {
    private Integer code;
    public CMSException(Integer code, String message) { super(message); this.code = code; }
    public CMSException(ResultCodeEnum result) { super(result.getMessage()); this.code = result.getCode(); }
}

Log Collection with Logback

Logback is the default logging framework for Spring Boot. The article provides a complete logback‑spring.xml configuration that separates logs by level (DEBUG, INFO, WARN, ERROR) and routes them to console (development) or files (production).

Key Configuration Highlights

Define property log.path for log file location.

Use conversionRule for colored console output.

Separate RollingFileAppender for each level with size‑and‑time based rolling policies.

Root logger level set to info for dev, warn for prod via <springProfile>.

Exception Logging Utility

@Slf4j
public class ExceptionUtil {
    public static String getMessage(Exception e) {
        try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
            e.printStackTrace(pw);
            return sw.toString();
        } catch (IOException ex) {
            log.error(ex.getMessage());
            return null;
        }
    }
}

By injecting this utility into the global handler, stack traces are written to the appropriate log files.

References

Juejin article: https://juejin.im/post/5cbc744a6fb9a0685a3f01a7

GitHub project: https://github.com/chetwhy/cloud-flow

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Spring BootAPI response
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

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.