springboot异常处理

异常处理

类似于springboot大部分的设计,当有异常发生时,springboot会在底层寻找所有的类型为HandlerExceptionResolver的组件来处理异常,核心源码:

// Check registered HandlerExceptionResolvers...
		ModelAndView exMv = null;
		if (this.handlerExceptionResolvers != null) {
			for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
				exMv = resolver.resolveException(request, response, handler, ex);
				if (exMv != null) {
					break;
				}
			}
		}
		if (exMv != null) {
			if (exMv.isEmpty()) {
				request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
				return null;
			}
			// We might still need view name translation for a plain error model...
			if (!exMv.hasView()) {
				String defaultViewName = getDefaultViewName(request);
				if (defaultViewName != null) {
					exMv.setViewName(defaultViewName);
				}
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Using resolved error view: " + exMv, ex);
			}
			else if (logger.isDebugEnabled()) {
				logger.debug("Using resolved error view: " + exMv);
			}
			WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
			return exMv;
		}

		throw ex;

springboot循环调用所有的handlerExceptionResolvers的resolveException方法,resolveException返回类型为ModelAndView对象,一旦有哪个resolver处理之后返回值不为null,则视为已经异常已被处理,默认有ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver、DefaultHandlerExceptionResolver三个处理器(并按照这个顺序循环调用)。

自定义错误显示页面

默认情况下,在浏览器发起一个text/html请求时发生错误,springboot会返回一个白页显示所有的错误信息,我们不想将这些错误信息暴露给前端,想定义一个异常页面,我们可以在视图文件夹,**新建对应错误状态码为名称的页面,如:404.html,500.html等等,当发生对应状态码的异常时,springboot会自动的跳转到对应的视图页面。或者也可以创建名为4xx和5xx的页面视图,当发生4开头的错误,就会跳转到4xx,发生5开头的错误就会跳转到5xx。**当然要在项目添加了视图解析的情况下。

自定义异常映射(springboot没有找到合适处理的异常处理器的情况下)

如果说springboot默认的三个处理器都无法处理异常,就会将请求转发到/error进行处理,springboot默认的定义了一个名为BasicErrorController来处理/error的映射,BasicErrorController在默认情况下如果浏览器发过来的请求发生错误就返回白页,机器客户端请求错误就返回一个json。如果我们想自定义一个全局的异常处理的话,可以实现一个名为ErrorController的接口并将其注册到容器中来替换默认的BasicErrorController,例如:

@RestController
public class TestErrorController implements ErrorController {

    @ResponseBody
    @RequestMapping("/error")
    public String test(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        return "error" + statusCode;
    }
}

springboot将异常的详细信息都存储在了request中,如果我们想拿到更详细的信息可以从request中取

使用@ControllerAdvice+@ExceptionHandler

对应ExceptionHandlerExceptionResolver处理器

ExceptionHandlerExceptionResolver默认在异常处理器第一个被调用,它会寻找所有的@ExceptionHandler注解声明的异常处理方法,根据异常类型匹配寻找合适的方法进行处理,

@Slf4j
@ControllerAdvice(basePackageClasses = TestController.class)
public class MyExceptionAdvice {

    @ResponseBody
    @ExceptionHandler(ArithmeticException.class)
    public String handlerArithmeticException(HttpServletRequest request, Throwable ex) {
        log.info("处理异常" + ex.getMessage());
        return ex.getMessage();
    }
}
使用@ResponseStatus

对应ResponseStatusExceptionResolver处理器

当发生的异常没有合适的@ExceptionHandler声明的方法处理(比如一些自定义异常),但根据异常的类型匹配到被@ResponseStatus声明的异常类,ResponseStatusExceptionResolver将会将定义在@ResponseStatus的信息添加到response中,最后在被转发到/error映射上

@ResponseStatus(code = HttpStatus.BAD_REQUEST,reason = "我的异常")
public class MyException  extends RuntimeException{
    public MyException(String message) {
        super(message);
    }
}
springboot底层注解的异常

对应DefaultHandlerExceptionResolver处理器

如果说抛出的异常属于springboot自己定义的异常,将会被DefaultHandlerExceptionResolver处理,默认时将错误信息添加到到response中,然后转发到/error映射中,如果在@ControllerAdvice+@ExceptionHandler中配置了处理方法,@ExceptionHandle将被优先执行。

自定义HandlerExceptionResolver

异常处理器是处理异常的基本单元,如果我们要自定义一些异常处理器,可以通过实现HandlerExceptionResolver接口并将其注册到容器中,需要注意的是,我们需要设置容器的优先级@Order确保我们自定义的处理器在springboot默认的处理器之前调用,否则可能异常被默认处理器处理而使得自定义处理器没有生效。

@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
public class MyExceptionHandler implements HandlerExceptionResolver {

    @SneakyThrows
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        response.setCharacterEncoding("UTF-8");
        PrintWriter writer = response.getWriter();
        writer.write("error:"+ex.getMessage());
        return new ModelAndView();
    }
}
SpringBoot提供了一套默认的异常处理机制。一旦程序出现异常SpringBoot会向/error的URL发送请求,并通过BasicErrorController来处理该请求。默认情况下,SpringBoot会跳转到默认显示异常信息的页面来展示异常信息。如果我们希望将所有的异常统一跳转到自定义的错误页面,可以在src/main/resources/templates目录下创建一个名为error.html的页面。通过覆盖默认的错误页面,我们可以实现自定义的异常处理。 除了使用SpringBoot的默认配置外,还可以通过自定义错误页面来处理异常。我们可以在src/main/resources/templates目录下创建error.html页面,并将其命名为error。通过这种方式,我们可以自定义错误页面的内容和样式来展示异常信息。 在处理异常的过程中,可以关注ErrorMvcAutoConfiguration中的三个关键点。通过对SpringBoot错误处理机制源码的跟踪,我们可以更深入地了解异常处理的实现细节。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SpringBoot异常处理](https://blog.youkuaiyun.com/Linging_24/article/details/126077782)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [SpringBoot 异常处理详解](https://blog.youkuaiyun.com/qq_42402854/article/details/91415966)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值