Spring boot集中异常处理

集中异常处理

方式一:ExceptionHandle

定义自己的异常类型,根据不同类型做不同处理,比如我定义的MyException:

public class MyException extends RuntimeException {
    public MyException(String msg) {
        super(msg);
    }
}

然后通过MyExceptionHandle处理该异常,需要注意的是异常不能在filter中抛出,抛出也没法捕获

@RestControllerAdvice
public class MyExceptionHandle {

    @ExceptionHandler(MyException.class)
    public Result exceptionHandle(MyException e) {
        return Result.getFailed( "system error:MyException" + e.getMessage());
    }
}

在controller、service以及拦截器的预处理方法中都可以完美捕获,这里特殊说下拦截器:

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //throw new MyException("拦截器错误:MyInterceptor");
        // 这里的异常会完美捕获,并返回
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        throw new MyException("拦截器错误:MyInterceptor");
        /** 能捕获异常信息并返回给客户端,但并不会覆盖已经请求成功的返回结果,但会包含在返回结果中,比如我的返回结果:
         {"code":1,"success":true,"msg":"请求成功","result":true}{"code":0,"success":false,"msg":"system error:MyException拦截器错误:MyInterceptor","result":null}
         */
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        throw new MyException("拦截器错误:MyInterceptor");
        // 这里抛出的异常并不能被捕获,会直接在后台抛出,相当于回掉函数,请求结果已经返回
    }
}

上面的解释已经够清楚了,就不做过多说明了。刚刚我们说了,上面的这种方式,对于filter是不起作用的,下面我们说的这种方式,主要就是针对filter来说的

方式二:ExceptionFilter

定义一个controller,请求路径可以自己指定,比如/error/exthrow:

@Controller
public class ExceptionController {

    @RequestMapping("/error/exthrow")
    public void rethrow(HttpServletRequest request) throws Exception {
        throw ((Exception) request.getAttribute("filter.error"));
    }
}

再定义一个异常拦截器,在需要抛出异常的拦截器中直接抛出异常,然后在异常拦截器中try-catch,发生异常时直接转发至前面定义的异常controller,这里需要注意的是,如果你的filter是实现Filter或者继承OncePerRequestFilter,那你不需要任何处理,直接request.setAttribute("filter.error", e)就可以了。

由于我把自己的filter交给shiro管理,而且是继承BasicHttpAuthenticationFilter的,不知到什么原因,直接catch到的异常类型是ServletException,为了拿到真正的异常信息,我需要通过getCause()方法获取filter中抛出的异常。因为controller抛出的异常最后还是会交给我们定义的MyExceptionHandle去处理,如果获取到的异常不是我们自定义的异常或者他的子类的话,就会返回500错误(在这个示例前,我以为所有的filter都是这样的,后来实践后发现并不是这样??)。

@Component
public class ExceptionFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            chain.doFilter(request, response);
        } catch (Exception e) {
            request.setAttribute("filter.error", e);
            //将异常分发到/error/exthrow控制器
            request.getRequestDispatcher("/error/exthrow").forward(request, response);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {

    }
}

我的filter:

实现Filter接口:

public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        throw new MyException("MyFilter过滤器抛出异常");
        //filterChain.doFilter(servletRequest, servletResponse);
    }

}

filter2继承OncePerRequestFilter:

public class MyFilter2 extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        throw new MyException("MyFilter2异常");
    }
}

filter配置类:

 @Bean
    public FilterRegistrationBean myFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new MyFilter());
        registration.setName("myFilter");
        registration.addUrlPatterns("/*");
        //此处尽量小,要比其他Filter靠前
        registration.setOrder(1);
        return registration;
    }

    @Bean
    public FilterRegistrationBean myFilter2Registration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new MyFilter2());
        registration.setName("myFilter2");
        registration.addUrlPatterns("/*");
        //此处尽量小,要比其他Filter靠前
        registration.setOrder(2);
        return registration;
    }

    /**
     * 配置拦截器
     * @return
     */
    @Bean
    public FilterRegistrationBean exceptionFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new ExceptionFilter());
        registration.setName("exceptionFilter");
        //此处尽量小,要比其他Filter靠前
        registration.setOrder(-1);
        return registration;
    }

方式三:BasicErrorController

其实spring boot原生提供了异常集中处理,我们经常会看到:

但是这种方式不够友好,而且大部分情况不满足我们的需求,我们可以通过继承这个controller,然后重写error方法或者errorHtml方法,或者两个都重写,区别是errorHtml是处理请求头为text/html的请求发生的异常,而error是除了这个之外的其他异常。

下面是我定义的baseController,error部分返回的结果是空,还需要进一步的研究:

@RestController
@RequestMapping(value = "error")
public class MyBaseErrorController extends BasicErrorController {

    public MyBaseErrorController(ErrorAttributes errorAttributes) {
        super(errorAttributes, new ErrorProperties());
    }

    @Override
    @RequestMapping(produces = {MediaType.ALL_VALUE})
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {

        return new ResponseEntity<Map<String, Object>>(Result.failedResultMap(000, "未知错误"), HttpStatus.OK);
    }

    @RequestMapping(
            produces = {"text/html"}
    )
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = this.getStatus(request);
        response.setStatus(status.value());
        return null;
    }

}

原文地址:https://www.cnblogs.com/caoleiCoding/p/12701400.html

时间: 04-14

Spring boot集中异常处理的相关文章

Spring Boot? 统一异常处理

效果区:  代码区: package com.wls.integrateplugs.exception.dto; public class ErrorInfo<T> { public static final Integer OK = 200; public static final Integer ERROR = 500; private Integer code; private String message; private String url; private T data; pub

spring boot 全局异常处理

import cn.sisyphe.framework.web.exception.DataException; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.converter.HttpMessageConversionException; import org.springframework.validation.Bin

spring boot 1.5.4 统一异常处理(九)

上一篇:springboot 1.5.4 配置文件详解(八) 1      Spring Boot统一异常处理 Spring Boot中实现了默认的error映射,但是在实际应用中,上面你的错误页面对用户来说并不够友好,我们通常需要去实现我们自己的异常提示. 以springboot项目为例,进行处理! springboot项目源码: https://git.oschina.net/wyait/springboot1.5.4.git 1.1  创建全局异常处理类 通过使用@ControllerAd

面试那点小事,你从未见过的spring boot面试集锦(附详细答案)

一, 什么是spring boot? 多年来,随着新功能的增加,spring变得越来越复杂.只需访问页面https://spring.io/projects,我们将看到所有在应用程序中使用的不同功能的spring项目.如果必须启动一个新的spring项目,我们必须添加构建路径或maven依赖项,配置application server,添加spring配置.因此,启动一个新的spring项目需要大量的工作,因为我们目前必须从头开始做所有事情.Spring Boot是这个问题的解决方案.Sprin

Spring Boot 使用 Aop 实现日志全局拦截

前面的章节我们学习到 Spring Boot Log 日志使用教程 和 Spring Boot 异常处理与全局异常处理,本章我们结合 Aop 面向切面编程来实现全局拦截异常并记录日志. 在 Spring Boot 中 Aop 与 Ioc 可以说是 Spring 的灵魂,其功能也是非常强大. 1 新建 Spring Boot 项目 1)File > New > Project,如下图选择 Spring Initializr 然后点击 [Next]下一步 2)填写 GroupId(包名).Arti

Spring Boot Shiro 使用教程

Apache Shiro 已经大名鼎鼎,搞 Java 的没有不知道的,这类似于 .Net 中的身份验证 form 认证.跟 .net core 中的认证授权策略基本是一样的.当然都不知道也没有关系,因为所有的权限都是模拟的人或机构的社会行为. 本系列从简单的权限讲起,主要涉及到 Shiro.Spring Security.Jwt.OAuth2.0及其他自定义权限策略. 本章主要讲解 Shiro 的基本原理与如何使用,本章主要用到以下基础设施: jdk1.8+ spring boot 2.1.6

2019年Spring Boot面试都问了什么?快看看这22道面试题!

Spring Boot 面试题 1.什么是 Spring Boot? 2.Spring Boot 有哪些优点? 3.什么是 JavaConfig? 4.如何重新加载 Spring Boot 上的更改,而无需重新启动服务器? 5.Spring Boot 中的监视器是什么? 6.如何在 Spring Boot 中禁用 Actuator 端点安全性? 7.如何在自定义端口上运行 Spring Boot 应用程序? 8.什么是 YAML? 9.如何实现 Spring Boot 应用程序的安全性? 10.

spring-boot实战【07】【转】:Spring Boot中Web应用的统一异常处理

我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异常内容. 选择一个之前实现过的Web应用(Chapter3-1-2)为基础,启动该应用,访问一个不存在的URL,或是修改处理内容,直接抛出异常,如: 1 2 3 4 @RequestMapping("/hello") public String hello() throws Exce

Spring Boot异常处理详解

在Spring MVC异常处理详解中,介绍了Spring MVC的异常处理体系,本文将讲解在此基础上Spring Boot为我们做了哪些工作.下图列出了Spring Boot中跟MVC异常处理相关的类. Spring Boot在启动过程中会根据当前环境进行AutoConfiguration,其中跟MVC错误处理相关的配置内容,在ErrorMvcAutoConfiguration这个类中.以下会分块介绍这个类里面的配置. 在Servlet容器中添加了一个默认的错误页面 因为ErrorMvcAuto