@ControllerAdvice自定义异常统一处理

Posted nijunyang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@ControllerAdvice自定义异常统一处理相关的知识,希望对你有一定的参考价值。

正常来说一个系统肯定有很多业务异常。而这些业务异常的信息如何返回给前台呈现给用户。比如用户的某些操作不被允许,需要给用户提示。

Spring 提供了@ControllerAdvice这个注解,这个注解可以实现全局异常处理,全局数据绑定,全局数据预处理,这里主要说下使用这个注解实现全局异常处理。

1.定义我们自己的业务异常ErrorCodeException

package com.nijunyang.exception.exception;

/**
 * Description: 
 * Created by nijunyang on 2019/12/20 9:36
 */
public class ErrorCodeException extends RuntimeException {

    private int code;
    /**
     * 用于填充资源文件中占位符
     */
    private Object[] args;

    public ErrorCodeException(int code, Object... args) {
        this.code = code;
        this.args = args;
    }

    public int getCode() {
        return code;
    }

    public Object[] getArgs() {
        return args;
    }

}

 

2.编写统一异常处理器RestExceptionHandler,使用@ControllerAdvice注解修饰,在异常处理器编写针对某个异常的处理方法,使用@ExceptionHandler注解指向某个指定异常。当代码中抛了该异常就会进入此方法执行,从而返回我们处理后的信息给请求者。

3.资源文件放置提示信息,根据错误码去匹配提示信息。

 

package com.nijunyang.exception.handler;

import com.nijunyang.exception.exception.ErrorCodeException;
import com.nijunyang.exception.model.RestErrorResponse;
import com.nijunyang.exception.model.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Locale;

/**
 * Description: 控制层统一异常处理
 * Created by nijunyang on 2019/12/20 9:33
 */
@ControllerAdvice
public class RestExceptionHandler {

    @Autowired
    private MessageSource messageSource;

    //locale可以处理国际化资源文件,不同的语言
    @ExceptionHandler(value = ErrorCodeException.class)
    public final ResponseEntity<RestErrorResponse> handleBadRequestException(ErrorCodeException errorCodeException, Locale locale) {
        String message = messageSource.getMessage(String.valueOf(errorCodeException.getCode()), errorCodeException.getArgs(), locale);
        RestErrorResponse restErrorResponse = new RestErrorResponse(Status.FAILED, errorCodeException.getCode(), message);
        return new ResponseEntity<>(restErrorResponse, HttpStatus.OK);
    }
}

 

 

 

4.配置文件指向资源文件位置(spring.messages.basename=xxx

技术图片

 

 

 技术图片

 

 

 spring.messages.basename指向资源的前缀名字就行了,后面的国家语言标志不需要,Locale会根据系统的语言去识别,资源文件需要配置一个默认的(messages.properties),不然启动的时候可能无法正常注入资源,因为默认的是去加载不带国家语言标志的文件。

当然前缀随便配置什么都可以 只要再springboot的配置文件spring.messages.basename的路径配置正确就行,就像这样子也是可以的

技术图片 技术图片

 

 

 

5.控制层模拟异常抛出:

package com.nijunyang.exception.controller;

import com.nijunyang.exception.exception.ErrorCodeException;
import com.nijunyang.exception.model.ErrorCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Description: 
 * Created by nijunyang on 2019/12/20 9:58
 */
@RestController
@RequestMapping("/error")
public class Controller {

    @GetMapping("/file")
    public ResponseEntity test() {
        //模拟文件不存在
        String path = "a/b/c/d.txt";
        throw new ErrorCodeException(ErrorCode.FILE_DOES_NOT_EXIST_51001, path);
    }
}

6.前台调用结果

技术图片

 

z/b/c/d.txt就去填充了资源文件中的占位符

 

错误码:

package com.nijunyang.exception.model;

/**
 * Description:
 * Created by nijunyang on 2020/1/20 20:28
 */
public final class ErrorCode {
    public static int FILE_DOES_NOT_EXIST_51001 = 51001;
}

结果状态:

package com.nijunyang.exception.model;

/**
 * Description: 
 * Created by nijunyang on 2019/12/20 10:21
 */
public enum Status {
    SUCCESS,
    FAILED
}

异常统一结果返回对象

package com.nijunyang.exception.model;

/**
 * Description: 
 * Created by nijunyang on 2019/12/20 9:38
 */
public class RestErrorResponse {

    private Status status;
    /**
     * 错误码
     */
    private Integer errorCode;
    /**
     * 错误信息
     */
    private String errorMsg;

    public RestErrorResponse(Status status, Integer errorCode, String errorMsg) {
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
        this.status = status;
    }

    public Integer getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(Integer errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public Status getStatus() {
        return status;
    }

}

pom文件依赖:springBoot版本是2.1.7.RELEASE

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>
    </dependencies>

完整代码:https://github.com/bluedarkni/study.git  ---->springboot--->exception项目

以上是关于@ControllerAdvice自定义异常统一处理的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot异常统一处理方法:@ControllerAdvice注解的使用全局异常捕获自定义异常捕获

@ControllerAdvice 拦截异常并统一处理

@ControllerAdvice 拦截异常并统一处理

Java项目构建基础之统一异常

自定义异常

Spring Boot @ControllerAdvice 拦截异常并统一处理