源码地址

异常的捕获方式

方式一 HandlerExceptionResolver接口

实现该接口,注册到spring容器中,当controller中产生异常的时候会调用该接口来处理,注意,当返回值指定视图时会自动跳转至指定的视图中去,如果返回null,会继续调用下一个异常处理器去执行。  springboot中可以通过以下方式去注册进容器。

@Component
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyException implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse,
                                         Object o, Exception e) {
        log.error("错误信息:",e);
        return null;
    }
}

这里可以直接返回ModelAndView对象,跳转到页面。如果返回null,则跳转到/error

方式二 @ControllerAdvice以及@ExceptionHandler

spring 中还可以通过@ControllerAdvice以及@ExceptionHandler(ApplicationException.class)注解对指定的异常做全局处理

@ControllerAdvice
@Slf4j
public class GlobalExceptionController {
    @ExceptionHandler(Exception.class)
    public String handlerException(Exception e) {
        log.error("控制器增强处理异常");
        return "error2";//返回templates/error2.html
    }
}

执行完之后会返回一个ModelAndView对象,所以不会再执行我们自己注册的异常解析器了,要想生效,我们只需在注册时调整注册顺序即可

全局的异常处理

以上2种方式只能处理Controller层之内的异常,对于渲染层及其他的异常是无能为力的,如果我们要做全局的异常处理就需要结合容器来做处理了。

例如:404错误

以tomcat为例,容器在处理请求时,遇到异常情况,首先会去找错误页面,如果没有配置错误页面,会HttpStatus默认转发到/error路径,所以我们可以写一个controller类来处理/error 请求,而springboot中默认有一个处理/error 请求的controller类

@Controller
@RequestMapping("${server.error.path:/error}")
public class GlobalErrorController implements ErrorController {

    /**
     * 错误信息的构建工具.
     */
    @Autowired
    private ErrorInfoBuilder errorInfoBuilder;

    /**
     * 错误信息页的路径
     */
    private final static String DEFAULT_ERROR_VIEW = "error";

    /**
     * 获取错误控制器的映射路径.
     */
    @Override
    public String getErrorPath() {
        return errorInfoBuilder.getErrorProperties().getPath();
    }

    /**
     * 情况1:若预期返回类型为text/html,s则返回错误信息页(View).
     */
    @RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
    @ResponseBody
    public ModelAndView errorHtml(HttpServletRequest request) {
        return new ModelAndView(DEFAULT_ERROR_VIEW,
                "errorInfo", errorInfoBuilder.getErrorInfo(request));
    }

    /**
     * 情况2:其它预期类型 则返回详细的错误信息(JSON).
     */
    @RequestMapping
    @ResponseBody
    public ErrorInfo error(HttpServletRequest request) {
        return errorInfoBuilder.getErrorInfo(request);
    }
}

样例测试访问地址:http://127.0.0.1:8080/exception

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐