全局异常

我们知道在web开发中,我们要处理全局异常。全局异常在web又分为:已知异常,未知异常。

已知异常:就是我们能处理的,俗称BUG。

未知异常:就是开发者不能处理的异常,要用日志记录下来。

而在SpringBoot中异常处理,SpringBoot已经提供了

就是@ControllerAdivce 这个注解

我们来看下这个注解的源码

  

package org.springframework.web.bind.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<?>[] assignableTypes() default {};

    Class<? extends Annotation>[] annotations() default {};
}

这个注解只能作用类上

@ControllerAdvice是一个特殊的@Component,用于标识一个类,这个类中被以下三种注解标识的方法:@ExceptionHandler@InitBinder@ModelAttribute,将作用于所有的@Controller类的接口上

@InitBinder的作用
  作用:注册属性编辑器,对HTTP请求参数进行处理,再绑定到对应的接口,比如格式化的时间转换等。应用于单个@Controller类的方法上时,仅对该类里的接口有效。与@ControllerAdvice组合使用可全局生效
@ControllerAdvice
public class ActionAdvice {
    
    @InitBinder
    public void handleException(WebDataBinder binder) {
        binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss"));
    }
}

作者:空夜
链接:https://juejin.im/post/6844903826412011533
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

@ModelAttribute

  作用:绑定数据

@ControllerAdvice
public class ActionAdvice {
    
    @ModelAttribute
    public void handleException(Model model) {
        model.addAttribute("user", "zfh");
    }
}

作者:空夜
链接:https://juejin.im/post/6844903826412011533
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在接口中获取前面绑定的参数:

@RestController
public class BasicController {
    
    @GetMapping(value = "index")
    public Map index(@ModelAttribute("user") String user) {
        //...
    }
}

作者:空夜
链接:https://juejin.im/post/6844903826412011533
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

@ExceptionHandler

作用:统一异常处理,也可以指定要处理的异常类型

来看一下源码

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {

    /**
     * Exceptions handled by the annotated method. If empty, will default to any
     * exceptions listed in the method argument list.
     */
    Class<? extends Throwable>[] value() default {};

}
Class<? extends Throwable>[] value() default {};  是泛型类数组 继承 Throwable 
现在让我们回到java中的异常

 Error表示严重的错误,程序对此一般无能为力,出现Error异常程序都不能运行了,还处理个毛。

所以在SpringBoot中全局处理异常Exception。

Exception 分为 checkedException 和 RuntimeException

Checked Exception: 指的是不能恢复,必须要被使用者来处理的一类异常,如果不捕获,那么编译会报错。例如,IOException。

Unchecked Exception: 指的是在运行时才会导致程序奔溃的异常,编译时候并不会报错。例如,Runtime Exception

所以在web中已知异常HttpException 通常继承RuntimeException异常。

package com.lin.missyou.core;


import com.lin.missyou.core.configuration.ExceptionCodeConfiguration;
import com.lin.missyou.exception.http.HttpException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;

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

    @Autowired
    private ExceptionCodeConfiguration codeConfiguration;
    
    //未知异常处理
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    @ResponseStatus
    public UnifyResponse handleException(HttpServletRequest request,Exception e){
        String errorUrl =request.getMethod()+ " " +request.getRequestURL();
        UnifyResponse unifyResponse = new UnifyResponse(9999,"服务器未知错误",errorUrl);
        return unifyResponse;
    }
    
    //已知异常处理
    @ExceptionHandler(value = {HttpException.class,})
    public ResponseEntity<UnifyResponse> handleHttpException(HttpServletRequest request, HttpException e){

        String errorUrl =request.getMethod()+ " " +request.getRequestURI();

        String message = codeConfiguration.getMessage(e.getCode());

        UnifyResponse unifyResponse = new UnifyResponse(e.getCode(),message,errorUrl);
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        HttpStatus status = HttpStatus.resolve(e.getHttpStatusCode());

        ResponseEntity<UnifyResponse> responseEntity = new ResponseEntity<>(unifyResponse,httpHeaders,status);

        return responseEntity;
    }

}
package com.lin.missyou.core;

/**
 * 统一错误返回
 */
public class UnifyResponse {
    private int code;
    private String message;
    private String request;

    public UnifyResponse(String request) {
        this.request = request;
    }

    public UnifyResponse(int code, String message, String request) {
        this.code = code;
        this.message = message;
        this.request = request;

    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getRequest() {
        return request;
    }

    public void setRequest(String request) {
        this.request = request;
    }
}

在上面代码中要解释的注解@ResponseStatus

这里主要就是改变响应体的状态码 例如:500 服务器错误

这里的HttpException 是自定义的继承RuntimeException

package com.lin.missyou.exception.http;


public class HttpException extends RuntimeException {
    protected int code;
    protected int httpStatusCode=500;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public int getHttpStatusCode() {
        return httpStatusCode;
    }

    public void setHttpStatusCode(int httpStatusCode) {
        this.httpStatusCode = httpStatusCode;
    }
}
原文地址:https://www.cnblogs.com/wuheng-123/p/13885726.html