欢迎光临
我们一直在努力

利用controlleradvice实现全局的异常处理和一些共有属性的注入

对于个人站长的后端服务(通常运行在VPS或公有云虚拟机上),提供稳定且友好的API接口至关重要。当服务发生错误时,如果不进行统一处理,客户端可能会收到各种不规范的错误页面或堆栈信息,这既影响用户体验,也存在安全隐患。

Spring Framework提供了强大的@ControllerAdvice注解,允许我们集中处理跨越所有@Controller@RestController的逻辑,最主要的应用就是全局异常处理和模型数据注入。

1. 什么是@ControllerAdvice?

@ControllerAdvice(或@RestControllerAdvice,后者默认包含了@ResponseBody,常用于RESTful API)是一个特殊的Spring组件。它允许你在应用层面上拦截请求,对所有Controller进行统一的配置和处理。

2. 实现全局异常处理

我们将定义一个标准的错误响应体,并创建一个全局异常处理器来捕获并格式化所有抛出的异常。

步骤 2.1:定义统一响应结构

首先,我们创建一个通用的返回对象Result,用于封装成功和失败的响应。

public class Result<T> {
    private int code; // 业务状态码
    private String message; // 错误或成功信息
    private T data;

    public Result(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static <T> Result<T> success(T data) {
        return new Result<>(200, "操作成功", data);
    }

    public static Result<?> failure(int code, String message) {
        return new Result<>(code, message, null);
    }

    // Getters and Setters omitted for brevity
}

步骤 2.2:创建全局异常处理器

使用@RestControllerAdvice注解标记该类,并使用@ExceptionHandler来指定该方法需要处理的异常类型。

package com.example.vpsdemo.advice;

import com.example.vpsdemo.dto.Result;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局统一异常处理器
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    // 1. 处理自定义业务异常(例如:用户不存在、参数错误)
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST) // 设置HTTP状态码为400
    public Result<?> handleIllegalArgumentException(IllegalArgumentException e) {
        System.err.println("捕获到参数非法异常: " + e.getMessage());
        return Result.failure(40001, e.getMessage());
    }

    // 2. 处理Spring框架的参数校验异常(@Valid或@Validated失败时抛出)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result<?> handleValidationException(MethodArgumentNotValidException e) {
        String defaultMessage = e.getBindingResult().getFieldError().getDefaultMessage();
        System.err.println("捕获到参数校验异常: " + defaultMessage);
        return Result.failure(40002, "参数校验失败: " + defaultMessage);
    }

    // 3. 处理所有未捕获的通用异常(兜底处理)
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) // 设置HTTP状态码为500
    public Result<?> handleGeneralException(Exception e) {
        e.printStackTrace(); // 记录详细堆栈信息
        return Result.failure(50000, "服务器内部错误,请联系管理员。错误信息: " + e.getMessage());
    }
}

步骤 2.3:测试异常处理

创建一个简单的Controller来触发异常:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @GetMapping("/test/error")
    public Result<String> triggerError(@RequestParam String id) {
        if (id.length() < 5) {
            // 抛出将被全局捕获的异常
            throw new IllegalArgumentException("ID长度不足5位");
        }
        return Result.success("验证成功");
    }
}

访问 /test/error?id=123 后,全局异常处理器会捕获 IllegalArgumentException,并返回统一的JSON格式响应。

3. 利用@ControllerAdvice注入共有属性(Model属性)

除了异常处理,@ControllerAdvice还可以配合@ModelAttribute在所有Controller的方法执行前,向Model中注入公共属性。这在需要为所有视图模板(如Thymeleaf或JSP)提供相同的全局配置或用户信息时非常有用。

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;

@ControllerAdvice
public class CommonAttributeAdvice {

    /**
     * 在所有Controller方法执行前,将属性注入到Model中
     */
    @ModelAttribute("globalConfig")
    public String addGlobalConfig() {
        // 假设这里获取了站点的版本号或ICP备案信息
        return "Version 1.0.0 | Powered by VPS Tech Blog";
    }
}

这样,在任何视图模板中,你都可以直接通过 globalConfig 访问到这个值。

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » 利用controlleradvice实现全局的异常处理和一些共有属性的注入
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址