【SPRING / GlobalExceptionHandler】使用拦截器统一处理异常

背景

业务开发,经常要处理各种各样的异常,然后一层处理,确实也不太舒服,也不够规整。
只管抛异常,不用每个地方都去判断catch 一下,会舒服得多。

但项目上还没有统一去做这个事情,虽然知道是好事,但没做就是没做,

业务来了

最近添加了一个全局异常处理类,是因为近来有一个业务,大概是根据当前登录人,判断这个请求是否在登录人的权限范围内,嗯,就是防跨权访问。

做法是这样子的,对于所有的 controller 做一个切面,然后在进入 controller 方法之前, doBefore() 获取当前登录人的权限信息,解析请求信息,然后做一下匹配判断,
如果请求在权限范围内,就通过
但如果不在请求范围内,就得报错返回,返回400.

问题来了

嗯,然后,问题来了,
切面的doBefore()是没有返回值的,所以怎样返回这个response 呢?没办法做呀?

机智如我,不过是想要拦截返回而已,doBefore() 做不了返回值, @Around 可以呀!
太TM机智了,二话不说,马上把 doBefore 整改成 Around,

しかし (然而.......)

报了一个类型转换的错误,
当然了,Around 返回值当然要遵循原来接口的返回类型了,不然不就乱套了么。

人家接口明明是一个 List 返回类型,现在返回一个 JSON, 那肯定是不行的,它会给你报一个500 的内部错误。
emmmm


难道就没有好办法了么

怎么可能,当然有,
那就是:

抛异常 + 全局异常处理

\

二者要配合使用,缺一不可。
只抛异常,它还是500的,达不到预期的效果。


两样都整上,就齐活了。

至于,怎样写一个全局拦截器,

比较简单,

public class GlobalExceptionHandler {

    @ExceptionHandler(BusinessException.class)
    public BaseResponse bizExceptionHandler(Exception e, HttpServletRequest request, HttpServletResponse response) {
        log.error(e.getMessage(), e);
        BaseResponse resp = new BaseResponse();
        resp.failed(e.getMessage());
        resp.setStatus(((BusinessException) e).errorCode);
        return resp;
    }

    @ExceptionHandler(Exception.class)
    public BaseResponse exceptionHandler(Exception e, HttpServletRequest request, HttpServletResponse response) {
        log.error(e.getMessage(), e);
        BaseResponse resp = new BaseResponse();
        resp.failed(e.getMessage());
        return resp;
    }
}

定义一下就好了。
(当然,这个类要被扫描到,能够被 spring 管理到就好了)


再记录一下:
不是所有的 exception 都能被区分出来。。。
有一次是使用了一个 IllegalAccessException, 这个就会被 exception 吞掉。。。

不是很清楚为什么。。。。

posted @ 2023-03-28 19:57  aaacarrot  阅读(347)  评论(0编辑  收藏  举报