SpringBoot搭建全局异常拦截

1.异常拦截类的创建

package com.liqi.web.core.exception;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import com.liqi.common.base.Constants;
import com.liqi.common.base.ResultBean;
import com.liqi.common.exception.BusinessInterfaceException;
import com.liqi.common.exception.bean.ErrorBean;

import lombok.extern.slf4j.Slf4j;

/**
 * 自定义异常处理器
 *
 * @author ieflex
 */
@RestControllerAdvice
@Slf4j
public class InterfaceExceptionHandler {

	/**
	 * 接口 业务异常
	 */
	@ResponseBody
	@ExceptionHandler(BusinessInterfaceException.class)
	public String businessInterfaceException(BusinessInterfaceException e) {
		log.error(e.getMessage(), e);
		ErrorBean error = e.getError();
		ResultBean resultBean = new ResultBean(error.hashCode(), error.getErrorMsg());
		return resultBean.toString();
	}

	/**
	 * 拦截所有运行时的全局异常   
	 */
	@ExceptionHandler(RuntimeException.class)
	@ResponseBody
	public String runtimeException(RuntimeException e) {
		log.error(e.getMessage(), e);
		// 返回 JOSN
		ResultBean resultBean = new ResultBean(Constants.INTERFACE_MSG_301, Constants.INTERFACE_MSG_301_TEXT);
		return resultBean.toString();
	}

	/**
	 * 系统异常捕获处理
	 */
	@ExceptionHandler(Exception.class)
	@ResponseBody
	public String exception(Exception e) {
		log.error(e.getMessage(), e);
		ResultBean resultBean = new ResultBean(Constants.INTERFACE_MSG_301, Constants.INTERFACE_MSG_301_TEXT);
		// 返回 JOSN
		return resultBean.toString();
	}
}

2.controller 测试

package com.springboot_Error.ErrorController;
        
        import org.springframework.stereotype.Controller;
        import org.springframework.web.bind.annotation.RequestMapping;
        
        @Controller
        public class ErrorControllerTest {
            //全局异常拦截 测试
            @RequestMapping("/ErrorTest")
            public String index2(){
                System.err.println("请求成功!");
                int i = 1/0; //这里会有一个运算异常
                return "index";
            }
            
        }

3.启动 springboot 工程

package com.springboot_Error.ErrorRun;
        
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

        
        //扫描 com.springboot_Error.ErrorController 包下 controller 注解过的类
        @ComponentScan(basePackages={"com.springboot_Error.ErrorController"})
        @EnableAutoConfiguration
        public class ErrorRun {
            
            public static void main(String[] args) {
                SpringApplication.run(ErrorRun.class, args);
            }
            
        }

4.测试

/**
 * 功能描述: 模拟自定义异常
 * @return
 */
@RequestMapping(value = "/api/test")
public Object myext() {
    throw new BusinessInterfaceException("500", "my ext异常");
}

经过测试发现可以捕获到Controller层的异常,当前前提是Controller层没有对异常进行catch处理,如果Controller层对异常进行了catch处理,那么在这里就不会捕获到Controller层的异常了,所以这一点要注意。

5.基于Springboot自身的全局异常统一处理

主要是实现ErrorController接口或者继承AbstractErrorController抽象类或者继承BasicErrorController类

以下是网上一位博主给出的示例代码,博客地址为:https://blog.csdn.net/king_is_everyone/article/details/53080851


@Controller
@RequestMapping(value = "error")
@EnableConfigurationProperties({ServerProperties.class})
public class ExceptionController implements ErrorController {

    private ErrorAttributes errorAttributes;

    @Autowired
    private ServerProperties serverProperties;

    /**
     * 初始化ExceptionController
     * @param errorAttributes
     */
    @Autowired
    public ExceptionController(ErrorAttributes errorAttributes) {
        Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
        this.errorAttributes = errorAttributes;
    }

    /**
     * 定义404的ModelAndView
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(produces = "text/html",value = "404")
    public ModelAndView errorHtml404(HttpServletRequest request,
                                  HttpServletResponse response) {
        response.setStatus(getStatus(request).value());
        Map<String, Object> model = getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.TEXT_HTML));
        return new ModelAndView("error/404", model);
    }

    /**
     * 定义404的JSON数据
     * @param request
     * @return
     */
    @RequestMapping(value = "404")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> error404(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.TEXT_HTML));
        HttpStatus status = getStatus(request);
        return new ResponseEntity<Map<String, Object>>(body, status);
    }

    /**
     * 定义500的ModelAndView
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(produces = "text/html",value = "500")
    public ModelAndView errorHtml500(HttpServletRequest request,
                                  HttpServletResponse response) {
        response.setStatus(getStatus(request).value());
        Map<String, Object> model = getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.TEXT_HTML));
        return new ModelAndView("error/500", model);
    }

    /**
     * 定义500的错误JSON信息
     * @param request
     * @return
     */
    @RequestMapping(value = "500")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> error500(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.TEXT_HTML));
        HttpStatus status = getStatus(request);
        return new ResponseEntity<Map<String, Object>>(body, status);
    }

    /**
     * Determine if the stacktrace attribute should be included.
     * @param request the source request
     * @param produces the media type produced (or {@code MediaType.ALL})
     * @return if the stacktrace attribute should be included
     */
    protected boolean isIncludeStackTrace(HttpServletRequest request,
                                          MediaType produces) {
        ErrorProperties.IncludeStacktrace include = this.serverProperties.getError().getIncludeStacktrace();
        if (include == ErrorProperties.IncludeStacktrace.ALWAYS) {
            return true;
        }
        if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM) {
            return getTraceParameter(request);
        }
        return false;
    }

    /**
     * 获取错误的信息
     * @param request
     * @param includeStackTrace
     * @return
     */
    private Map<String, Object> getErrorAttributes(HttpServletRequest request,
                                                   boolean includeStackTrace) {
        RequestAttributes requestAttributes = new ServletRequestAttributes(request);
        return this.errorAttributes.getErrorAttributes(requestAttributes,
                includeStackTrace);
    }

    /**
     * 是否包含trace
     * @param request
     * @return
     */
    private boolean getTraceParameter(HttpServletRequest request) {
        String parameter = request.getParameter("trace");
        if (parameter == null) {
            return false;
        }
        return !"false".equals(parameter.toLowerCase());
    }

    /**
     * 获取错误编码
     * @param request
     * @return
     */
    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request
                .getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        try {
            return HttpStatus.valueOf(statusCode);
        }
        catch (Exception ex) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
    }

    /**
     * 实现错误路径,暂时无用
     * @see ExceptionMvcAutoConfiguration#containerCustomizer()
     * @return
     */
    @Override
    public String getErrorPath() {
        return "";
    }

}

6.AOP也可以实现异常的全局处理

@Component
@Aspect
public class ExceptionAspectController {
    public static final Logger logger = LoggerFactory.getLogger(ExceptionAspectController.class);

    @Pointcut("execution(* com.test.test.*.*(..))")//此处基于自身项目的路径做具体的设置
    public void pointCut(){}

    @Around("pointCut()")
    public Object handleControllerMethod(ProceedingJoinPoint pjp) {
        Stopwatch stopwatch = Stopwatch.createStarted();

        APIResponse<?> apiResponse;
        try {
            logger.info("执行Controller开始: " + pjp.getSignature() + " 参数:" + Lists.newArrayList(pjp.getArgs()).toString());
            apiResponse = (APIResponse<?>) pjp.proceed(pjp.getArgs());
            logger.info("执行Controller结束: " + pjp.getSignature() + ", 返回值:" + apiResponse.toString());
            logger.info("耗时:" + stopwatch.stop().elapsed(TimeUnit.MILLISECONDS) + "(毫秒).");
        } catch (Throwable throwable) {
            apiResponse = handlerException(pjp, throwable);
        }

        return apiResponse;
    }

    private APIResponse<?> handlerException(ProceedingJoinPoint pjp, Throwable e) {
        APIResponse<?> apiResponse = null;
        if(e.getClass().isAssignableFrom(MessageCenterException.class) ){
            MessageCenterException messageCenterException = (MessageCenterException)e;
            logger.error("RuntimeException{方法:" + pjp.getSignature() + ", 参数:" + pjp.getArgs() + ",异常:" + messageCenterException.getException().getMessage() + "}", e);
            apiResponse = messageCenterException.getApiResponse();
        } else if (e instanceof RuntimeException) {
            logger.error("RuntimeException{方法:" + pjp.getSignature() + ", 参数:" + pjp.getArgs() + ",异常:" + e.getMessage() + "}", e);
            apiResponse = new APIResponse(APIResponse.FAIL,null,e.getMessage());
        } else {
            logger.error("异常{方法:" + pjp.getSignature() + ", 参数:" + pjp.getArgs() + ",异常:" + e.getMessage() + "}", e);
            apiResponse = new APIResponse(APIResponse.FAIL,null,e.getMessage());
        }

        return apiResponse;
    }
}

到此这篇关于SpringBoot搭建全局异常拦截的文章就介绍到这了,更多相关Springboot全局异常内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot学习之全局异常处理设置(返回JSON)

    SpringBoot学习--全局异常处理设置(返回JSON) 需求 现在习惯使用ajax的方式发起请求,所以经常需要服务端返回一个json或者字符串. 控制全局的异常处理. 如果在单个方法中使用try,catch把方法包裹起来,工作量大,而且会异常的抛出而导致@Transactional注解的方法事务不会回滚. 说明 使用@ControllerAdvice注解 使用@ExceptionHandler注解 @ControllerAdvice 该注解是spring2.3以后新增的一个注解,主要是用来

  • springboot springmvc抛出全局异常的解决方法

    springboot中抛出异常,springboot自带的是springmvc框架,这个就不多说了. springmvc统一异常解决方法这里要说明的是.只是结合了springboot的使用而已.直接上代码,有效有用的才是ok. 1.定义异常捕获 package com.example.rest.error; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.Exce

  • springboot全局异常处理详解

    一.单个controller范围的异常处理 package com.xxx.secondboot.web; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import

  • SpringBoot全局异常与数据校验的方法

    异常处理是每个项目中都绕不开的话题,那么如何优雅的处理异常,是本文的话题.本文将结合SpringBoot框架一起和大家探讨下. 要思考的问题 在现在的前后端交互中,通常都规范了接口返回方式,如返回的接口状态(成功|失败)以及要返回的数据在那个字段取,或者说失败了以后提示信息从接口哪里返回,因此,如果想做全局异常,并且异常发生后能准确的返回给前端解析,那么需要异常发生时返回给前端的格式与正常失败场景的格式一致. 项目建立 利用idea 工具,很容易的搭建一个SpringBoot项目,要引入的mav

  • SpringBoot配置系统全局异常映射处理

    目录 一.异常分类 1.业务异常 2.系统异常 二.解决应用启动后404界面 1.引入页面Jar包 2.自定义首页接口 3.首页界面 4.运行效果 三.SpringBoot2.0中异常处理 1.项目结构图 2.自定义业务异常类 3.自定义异常描述对象 4.统一异常处理格式 5.简单的测试接口 四.源代码地址 一.异常分类 这里的异常分类从系统处理异常的角度看,主要分类两类:业务异常和系统异常. 1.业务异常 业务异常主要是一些可预见性异常,处理业务异常,用来提示用户的操作,提高系统的可操作性.

  • SpringBoot搭建全局异常拦截

    1.异常拦截类的创建 package com.liqi.web.core.exception; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestControllerAdvice; import

  • 在spring中手写全局异常拦截器

    为什么要重复造轮子 你可能会问,Spring已经自带了全局异常拦截,为什么还要重复造轮子呢? 这是个好问题,我觉得有以下几个原因 装逼 Spring的全局异常拦截只是针对于Spring MVC的接口,对于你的RPC接口就无能为力了 无法定制化 除了写业务代码,我们其实还能干点别的事 我觉得上述理由已经比较充分的解答了为什么要重复造轮子,接下来就来看一下怎么造轮子 造个什么样的轮子? 我觉得全局异常拦截应该有如下特性 使用方便,最好和spring原生的使用方式一致,降低学习成本 能够支持所有接口

  • ASP.NET Core中实现全局异常拦截的完整步骤

    前言 异常是一种运行时错误,当异常没有得到适当的处理,很可能会导致你的程序意外终止,这篇就来讨论一下如何在 ASP.Net Core MVC 中实现全局异常处理,我会用一些 样例代码 和 截图 来说明这些概念. 全局异常处理 其实在 ASP.Net Core MVC 框架中已经有了全局异常处理的机制,你可以在一个中心化的地方使用 全局异常处理中间件 来进行异常拦截,如果不用这种中心化方式的话,你就只能在 Controller 或者 Action 作用域上单独处理,这会导致异常处理代码零散在项目各

  • Spring boot项目中异常拦截设计和处理详解

    背景: 项目运行过程中会出现各种各样的问题,常见的有以下几种情况: 业务流程分析疏漏,对业务流程的反向操作.边界分析设计不充分 调用外部服务.调用外部系统出现的超时.错误.返回值与预期不符 外部资源连通性问题,db等服务器出现的网络抖动或宕机 无论是分析设计.开发.测试.线上都需要能够准确定位问题并制定解决方案. 目的: 规范化异常的处理过程,避免异常被吞和到处都在捕获异常的情况 准确的反馈异常信息,为定位问题提供依据 通用性异常全局处理,降低业务开发关注度 对异常情况进行预警,以便能够及时响应

  • SpringBoot处理全局统一异常的实现

    在后端发生异常或者是请求出错时,前端通常显示如下 Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Fri Jun 07 15:38:07 CST 2019 There was an unexpected error (type=Not Found, status=404). No message available 对于

  • SpringBoot配置GlobalExceptionHandler全局异常处理器案例

    1. 创建全局异常处理器类GlobalExceptionHandler @ControllerAdvice: 定义统一的异常处理类,捕获 Controller 层抛出的异常.如果添加 @ResponseBody 返回信息则为JSON格式,这样就不必在每个Controller中逐个定义AOP去拦截处理异常. @RestControllerAdvice: 相当于 @ControllerAdvice 与 @ResponseBody 的结合体. @ExceptionHandler: 统一处理一种类的异常

  • 如何基于Springboot完成新增员工功能并设置全局异常处理器

    目录 1. 新增员工 1.1 需求分析 1.2 数据模型 1.3 程序执行流程 1.4 代码实现 2 全局异常处理 2.1 新增员工存在的问题 2.2 全局异常处理思路 2.3 全局异常处理器 2.4 全局异常处理器代码实现 2.5 测试 总结 1. 新增员工 1.1 需求分析 后台系统中可以管理员工信息,通过新增员工来添加后台系统用户.点击[添加员工]按钮跳转到新增页面,如下 当填写完表单信息, 点击"保存"按钮后, 会提交该表单的数据到服务端, 在服务端中需要接受数据, 然后将数据

  • SpringBoot如何优雅的处理全局异常

    前言 本篇文章主要介绍的是SpringBoot项目进行全局异常的处理. SpringBoot全局异常准备 说明:如果想直接获取工程那么可以直接跳到底部,通过链接下载工程代码. 开发准备 环境要求 JDK:1.8 SpringBoot:1.5.17.RELEASE 首先还是Maven的相关依赖: <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.

  • SpringBoot如何优雅地处理全局异常详解

    前言 之前用springboot的时候,只知道捕获异常使用try{}catch,一个接口一个try{}catch,这也是大多数开发人员异常处理的常用方式,虽然屡试不爽,但会造成一个问题,就是一个Controller下面,满屏幕的try{}catch,看着一点都不优雅,一点都不符合小明的气质,憋了这么久,小明今天终于决定对所有异常实施统一处理的方案. 开发准备 JDK8.正常的springboot项目 代码编写 通用异常处理 其实Spring系列的项目全局异常处理方式早已存在,只不过我们一直忙于搬

随机推荐