SpringBoot 使用@ControllerAdvice1:@ExceptionHandler异常统一处理类

原创
2020/05/05 22:57
阅读数 1.7K

@ControllerAdvice 是一种作用于控制层的切面通知(Advice),该注解能够将通用的@ExceptionHandler、@InitBinder和@ModelAttributes方法收集到一个类型,并应用到所有控制器上。

 

一、代码示例

 

1、自定义全局异常类

import com.example.demo.util.R;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 全局异常处理类
 */
@ControllerAdvice
public class CommonExceptionHandler {

    /**
     * 通用异常处理
     * @param ex
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public R exceptionHandler(Exception ex) {
        //输出异常信息
        ex.printStackTrace();
        //处理校验注解异常信息
        if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException mex = (MethodArgumentNotValidException) ex;
            List<FieldError> errorList = mex.getBindingResult().getFieldErrors();
            StringBuffer strBuffer = new StringBuffer();
            for(FieldError err: errorList){
                strBuffer.append(err.getDefaultMessage()).append(",");
            }
            return R.failed(strBuffer.substring(0, strBuffer.length() - 1));
        } else {
            return R.failed(ex.getMessage());
        }
    }

    /**
     * 单独针对某个异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public R error(NullPointerException e) {
        //输出异常信息
        e.printStackTrace();
        return R.failed("空指针异常");
    }
}

这就是主要核心的代码。

 

2、Controller 代码:

import com.example.demo.model.User;
import com.example.demo.util.R;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

/**
 * 用户登录控制器
 */
@RestController
@RequestMapping(value = "/user")
public class UserController {

    /**
     * 用户登录
     * @param user
     * @return
     */
    @PostMapping(value = "/login")
    public R login(@Valid @RequestBody User user){
        System.out.println("登录成功!");
        return R.ok(user);
    }

}

 

3、User 实体类

import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

/**
 * 用户登录实体类
 */
@Data
public class User {

    @NotBlank(message = "用户名不能为空")
    private String username;

    @NotBlank(message = "密码不能为空")
    @Size(max = 20, min = 6, message = "密码长度在6-20字符之间")
    private String password;

}

 

4、ApiCode 枚举

/**
 * api枚举器
 */
public enum ApiCode {

    FAILED(-1L, "操作失败"),
    SUCCESS(0L, "执行成功");

    private final long code;
    private final String msg;

    private ApiCode(long code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public long getCode() {
        return this.code;
    }

    public String getMsg() {
        return this.msg;
    }

}

 

5、返回对象 R 参考了 MyBatis-Plus 中 R 对象的设计

import com.example.demo.myenum.ApiCode;
import lombok.Data;

/**
 * 返回对象
 */
@Data
public class R<T> {

    private long code;
    private String msg;
    private T data;

    public R() {
    }

    public static <T> R<T> ok(T data) {
        ApiCode aec = ApiCode.SUCCESS;
        if(data instanceof Boolean && Boolean.FALSE.equals(data)) {
            aec = ApiCode.FAILED;
        }

        return restResult(data, aec.getCode(), aec.getMsg());
    }

    public static <T> R<T> failed(String msg) {
        return restResult(null, ApiCode.FAILED.getCode(), msg);
    }

    private static <T> R<T> restResult(T data, long code, String msg) {
        R<T> apiResult = new R();
        apiResult.setCode(code);
        apiResult.setData(data);
        apiResult.setMsg(msg);
        return apiResult;
    }

}

 

二、PostMan请求测试

看到这个结果我们的全局统一处理注解校验异常就成功了。

 

更多阅读

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部