SpringBoot 实现全局异常处理

描述

SpringBoot 提供了错误处理机制,默认情况下,Spring Boot 提供了一个/error以合理方式处理所有错误的映射,并在 servlet 容器中注册为“全局”错误页面。对于机器客户端,它会生成包含错误详细信息、HTTP 状态和异常消息的 JSON 响应,详细请看官网。

官网地址:Sprinboot错误处理

@ControllerAdvice以自定义 JSON 文档以针对特定控制器和/或异常类型返回

ControllerAdvice

ControllerAdvice 注解,我们来看看这个注解中有哪些属性:

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

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

    Class[] basePackageClasses() default {};

    Class[] assignableTypes() default {};

    Class[] annotations() default {};

大致就是处理的范围,可以指定包名,指定类等操作。

全局异常处理

首先创建一个 MyGlobalExceptionHandler 类,然后加上ControllerAdvice注解,指定处理的范围。

import com.example.springbootjpaintegrat.entity.Fault;
import com.example.springbootjpaintegrat.entity.FaultFault;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
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 org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.HashMap;
import java.util.Map;
@Slf4j
@ControllerAdvice(value = "com.example.springbootjpaintegrat.controller")
public class MyGlobalExceptionHandler {

    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public String  customException(RuntimeException e) {
        Map map = new HashMap<>();
        map.put("code", 400);
        map.put("msg", "全局异常测试");
        Gson gson = new Gson();
        return gson.toJson(map);
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public ResponseEntity handleFaultException(Exception fault) {
        log.error("Fault: {}, {}", fault.getMessage(), fault);
        ResponseEntity faultResponseEntity = new ResponseEntity<>(new Fault().fault(new FaultFault()), HttpStatus.INTERNAL_SERVER_ERROR);
        Gson gson = new Gson();
        String s = gson.toJson(faultResponseEntity);
        System.out.println(s);
        return faultResponseEntity;
    }

    @ExceptionHandler(NumberFormatException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public String handleNumberFaultException(NumberFormatException fault) {
        return fault.getMessage();
    }

    @ExceptionHandler(CharacterException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public String handleCharacterFaultException(CharacterException e) {
        return e.getMessage();
    }

}

@ControllerAdvice(value = “com.example.springbootjpaintegrat.controller”): 指定异常处理的范围,请注意,如果 当前项目有二个异常处理的时候,一定要指定范围,否则会导致springboot 只能处理一个异常类。另一个会失效。

这里我处理了三个异常 RuntimeException,Exception 已经自定义 异常 CharacterException,在不同的异常中,处理不同的操作,这里大家可以自行扩展,这里只是我的一个demo。如果大家是一个前后端分离项目的话,可以是把 ControllerAdvice 替换 为 RestControllerAdvice 这样的话,就不需要在分个方法上面加 ResponseBody注解了。

自定义错误页面

如果是spring mvc项目,没有做前后端分离的话,那么在全局异常中,可以捕获,然后跳转错误页面,这也是一种很好的处理方式:

@Configuration(proxyBeanMethods = false)
public class MyErrorPagesConfiguration {

    @Bean
    public ErrorPageRegistrar errorPageRegistrar() {
        return this::registerErrorPages;
    }

    private void registerErrorPages(ErrorPageRegistry registry) {
        registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
    }

}

跳转404页面:

src/
 +- main/
     +- java/
     |   + 
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- 

跳转 500页面:

src/
 +- main/
     +- java/
     |   + 
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.ftlh
             +- 

部署中的错误处理

当部署到 servlet 容器时,Spring Boot 使用其错误页面过滤器将具有错误状态的请求转发到相应的错误页面。这是必要的,因为 Servlet 规范没有提供用于注册错误页面的 API。根据您将 war 文件部署到的容器以及您的应用程序使用的技术,可能需要一些额外的配置。

如果响应尚未提交,错误页面过滤器只能将请求转发到正确的错误页面。默认情况下,WebSphere Application Server 8.0 及更高版本在成功完成 servlet 的服务方法后提交响应。您应该通过设置com.ibm.ws.webcontainer.invokeFlushAfterService为 来禁用此行为false

如果您正在使用 Spring Security 并希望访问错误页面中的主体,则必须配置 Spring Security 的过滤器以在错误分派时调用。为此,请将spring.security.filter.dispatcher-types属性设置为async, error, forward, request

其他方式同理。项目的代码已经上传到 github上面。

实例代码在github上面需要的请自行拉取:spring-boot-integrate 然后后续会集成更多的模块进去,需要请点个star。后续会集成更多的接口实现,有需要的请保存。
如果这篇文章,有帮助到大家的,请给作者一个一键三连,谢谢

你可能感兴趣的:(Springboot,spring,java,spring,boot)