成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術(shù)文章
文章詳情頁

在spring中手寫全局異常攔截器

瀏覽:2日期:2023-08-02 13:16:22

為什么要重復(fù)造輪子

你可能會問,Spring已經(jīng)自帶了全局異常攔截,為什么還要重復(fù)造輪子呢?

這是個(gè)好問題,我覺得有以下幾個(gè)原因

裝逼 Spring的全局異常攔截只是針對于Spring MVC的接口,對于你的RPC接口就無能為力了 無法定制化 除了寫業(yè)務(wù)代碼,我們其實(shí)還能干點(diǎn)別的事

我覺得上述理由已經(jīng)比較充分的解答了為什么要重復(fù)造輪子,接下來就來看一下怎么造輪子

造個(gè)什么樣的輪子?

我覺得全局異常攔截應(yīng)該有如下特性

使用方便,最好和spring原生的使用方式一致,降低學(xué)習(xí)成本 能夠支持所有接口 調(diào)用異常處理器可預(yù)期,比如說定義了RuntimeException的處理器和Exception的處理器,如果這個(gè)時(shí)候拋出NullPointException,這時(shí)候要能沒有歧義的選擇預(yù)期的處理器

如何造輪子?

由于現(xiàn)在的應(yīng)用基本上都是基于spring的,因此我也是基于SpringAop來實(shí)現(xiàn)全局異常攔截

首先先定義幾個(gè)注解

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface ExceptionAdvice {}@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface ExceptionHandler { Class<? extends Throwable>[] value();}@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface ExceptionIntercept {}

@ExceptionAdvice 的作用是標(biāo)志定義異常處理器的類,方便找到異常處理器

@ExceptionHandler 的作用是標(biāo)記某個(gè)方法是處理異常的,里面的值是能夠處理的異常類型

@ExceptionIntercept 的作用是標(biāo)記需要異常攔截的方法

接下來定義統(tǒng)一返回格式,以便出現(xiàn)錯(cuò)誤的時(shí)候統(tǒng)一返回

@Datapublic class BaseResponse<T> { private Integer code; private String message; private T data; public BaseResponse(Integer code, String message) { this.code = code; this.message = message; }}

然后定義一個(gè)收集異常處理器的類

public class ExceptionMethodPool { private List<ExceptionMethod> methods; private Object excutor; public ExceptionMethodPool(Object excutor) { this.methods = new ArrayList<ExceptionMethod>(); this.excutor = excutor; } public Object getExcutor() { return excutor; } public void add(Class<? extends Throwable> clazz, Method method) { methods.add(new ExceptionMethod(clazz, method)); } //按序查找能夠處理該異常的處理器 public Method obtainMethod(Throwable throwable) { return methods.stream().filter(e -> e.getClazz().isAssignableFrom(throwable.getClass())).findFirst().orElseThrow(() ->new RuntimeException('沒有找到對應(yīng)的異常處理器')).getMethod(); } @AllArgsConstructor @Getter class ExceptionMethod { private Class<? extends Throwable> clazz; private Method method; }}

ExceptionMethod 里面有兩個(gè)屬性

clazz:這個(gè)代表著能夠處理的異常 method:代表著處理異常調(diào)用的方法

ExceptionMethodPool 里面按序存放所有異常處理器,excutor是執(zhí)行這些異常處理器的對象

接下來把所有定義的異常處理器收集起來

@Componentpublic class ExceptionBeanPostProcessor implements BeanPostProcessor { private ExceptionMethodPool exceptionMethodPool; @Autowired private ConfigurableApplicationContext context; @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { Class<?> clazz = bean.getClass(); ExceptionAdvice advice = clazz.getAnnotation(ExceptionAdvice.class); if (advice == null) return bean; if (exceptionMethodPool != null) throw new RuntimeException('不允許有兩個(gè)異常定義類'); exceptionMethodPool = new ExceptionMethodPool(bean); //保持處理異常方法順序 Arrays.stream(clazz.getDeclaredMethods()).filter(method -> method.getAnnotation(ExceptionHandler.class) != null).forEach(method -> { ExceptionHandler exceptionHandler = method.getAnnotation(ExceptionHandler.class); Arrays.stream(exceptionHandler.value()).forEach(c -> exceptionMethodPool.add(c,method));}); //注冊進(jìn)spring容器 context.getBeanFactory().registerSingleton('exceptionMethodPool',exceptionMethodPool); return bean; }}

ExceptionBeanPostProcessor 通過實(shí)現(xiàn)BeanPostProcessor 接口,在bean初始化之前,把所有異常處理器塞進(jìn) ExceptionMethodPool,并把其注冊進(jìn)Spring容器

然后定義異常處理器

@Componentpublic class ExceptionProcessor { @Autowired private ExceptionMethodPool exceptionMethodPool; public BaseResponse process(Throwable e) { return (BaseResponse) FunctionUtil.computeOrGetDefault(() ->{ Method method = exceptionMethodPool.obtainMethod(e); method.setAccessible(true); return method.invoke(exceptionMethodPool.getExcutor(),e); },new BaseResponse(0,'未知錯(cuò)誤')); }}

這里應(yīng)用了我自己通過函數(shù)式編程封裝的一些語法糖,有興趣的可以看下

最后通過AOP進(jìn)行攔截

@Aspect@Componentpublic class ExceptionInterceptAop { @Autowired private ExceptionProcessor exceptionProcessor; @Pointcut('@annotation(com.example.exception.intercept.ExceptionIntercept)') public void pointcut() { } @Around('pointcut()') public Object around(ProceedingJoinPoint point) { return computeAndDealException(() -> point.proceed(),e -> exceptionProcessor.process(e)); } public static <R> R computeAndDealException(ThrowExceptionSupplier<R> supplier, Function<Throwable, R> dealFunc) { try { return supplier.get(); } catch (Throwable e) { return dealFunc.apply(e); } } @FunctionalInterface public interface ThrowExceptionSupplier<T> { T get() throws Throwable; }}

到這里代碼部分就已經(jīng)完成了,我們來看下如何使用

@ExceptionAdvicepublic class ExceptionConfig { @ExceptionHandler(value = NullPointerException.class) public BaseResponse process(NullPointerException e){ return new BaseResponse(0,'NPE'); } @ExceptionHandler(value = Exception.class) public BaseResponse process(Exception e){ return new BaseResponse(0,'Ex'); } }@RestControllerpublic class TestControler { @RequestMapping('/test') @ExceptionIntercept public BaseResponse test(@RequestParam('a') Integer a){ if (a == 1){ return new BaseResponse(1,a+''); } else if (a == 2){ throw new NullPointerException(); } else throw new RuntimeException(); }}

我們通過@ExceptionAdvice標(biāo)志定義異常處理器的類,然后通過@ExceptionHandler標(biāo)注處理異常的方法,方便收集

最后在需要異常攔截的方法上面通過@ExceptionIntercept進(jìn)行異常攔截

我沒有使用Spring那種匹配最近父類的方式尋找匹配的異常處理器,我覺得這種設(shè)計(jì)是一個(gè)敗筆,理由如下

代碼復(fù)雜 不能一眼看出要去調(diào)用哪個(gè)異常處理器,尤其是定義的異常處理器非常多的時(shí)候,要是弄多個(gè)定義類就更不好找了,可能要把所有的處理器看完才知道應(yīng)該調(diào)用哪個(gè)

出于以上考慮,我只保留了一個(gè)異常處理器定義類,并且匹配順序和方法定義順序一致,從上到下依次匹配,這樣只要找到一個(gè)能夠處理的處理器,那么就知道了會如何調(diào)用

原創(chuàng)不易,如果覺得對你有幫助,麻煩點(diǎn)個(gè)贊!

我會不定期分享一些有意思的技術(shù),點(diǎn)個(gè)關(guān)注不迷路-。 -

以上就是在spring中手寫全局異常攔截器的詳細(xì)內(nèi)容,更多關(guān)于spring 全局異常攔截的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Spring
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
亚洲色欲色欲www在线观看| 国产在线看一区| 韩国中文字幕2020精品| 蜜桃av综合| 亚洲欧美日韩国产一区二区三区| 国产精品乱子久久久久| av成人老司机| 日韩视频在线永久播放| 国产美女av一区二区三区| 欧美在线观看18| 三级一区在线视频先锋| 蜜桃久久av| 午夜久久久久久电影| 中文一区二区| 亚洲裸体xxx| 狠狠色狠狠色综合人人| 国产性色一区二区| 99在线热播精品免费| 久久视频一区二区| 不卡的av中国片| www日韩大片| 99精品视频在线播放观看| 91精品欧美综合在线观看最新 | 国产精品免费看片| 欧美另类亚洲| 国产精品天天看| 激情欧美丁香| 国产精品成人一区二区三区夜夜夜 | 欧美国产视频在线| 狠狠爱www人成狠狠爱综合网 | 激情丁香综合| 亚洲色图丝袜美腿| 一色屋精品视频在线观看网站| 正在播放亚洲一区| 国产精品白丝av| 日韩欧美一二三区| 成人开心网精品视频| 久久久久国产精品麻豆ai换脸| 狠狠色2019综合网| 欧美浪妇xxxx高跟鞋交| 国产成人精品一区二区三区四区 | 久久只有精品| 日韩精品三区四区| 欧美性猛片xxxx免费看久爱| 狠狠色狠狠色合久久伊人| 日韩一卡二卡三卡四卡| av午夜一区麻豆| 欧美国产日产图区| 亚洲精选久久| 日韩主播视频在线| 在线不卡中文字幕播放| 99在线精品观看| 亚洲欧洲精品成人久久奇米网| 成人免费视频国产在线观看| 日韩精品一区二区三区在线播放| 毛片av一区二区三区| 欧美精品久久久久久久多人混战 | 国产精品啊啊啊| 一片黄亚洲嫩模| 欧美亚洲一区二区在线| 国产一二三精品| 国产欧美视频在线观看| 中文有码久久| 另类人妖一区二区av| 日韩午夜在线观看| eeuss影院一区二区三区| 久久久国际精品| 亚洲国产一区二区精品专区| 天天综合日日夜夜精品| 欧美一区二区在线视频| 国产精品国码视频| 午夜私人影院久久久久| 日韩三级精品电影久久久| 国产尤物精品| 日韩国产精品久久久久久亚洲| 久久资源在线| 国产精品综合一区二区三区| 国产欧美一区二区精品久导航 | 337p粉嫩大胆噜噜噜噜噜91av | 亚洲国产另类av| 91麻豆精品国产91久久久久久久久| 蜜桃视频一区二区| 欧美一级生活片| 亚洲成色最大综合在线| 美国毛片一区二区| 久久久久青草大香线综合精品| 91丨九色丨蝌蚪丨老版| 亚洲国产精品一区二区久久| 在线电影一区二区三区| 国产精品igao视频网网址不卡日韩| 欧美激情中文不卡| 男女精品网站| 成人性生交大片免费看中文 | 久久99精品一区二区三区| 久久免费精品国产久精品久久久久| 成人污视频在线观看| 中文字幕视频一区二区三区久| 亚洲一级一区| 激情文学综合网| 亚洲色图另类专区| 在线成人av网站| 99re热精品| 大陆成人av片| 偷拍日韩校园综合在线| 精品毛片乱码1区2区3区| 99精品国产一区二区青青牛奶| 午夜欧美电影在线观看| 日韩精品中文字幕在线不卡尤物| 成人午夜av电影| 亚洲地区一二三色| 精品免费视频.| 久久久国产精品一区二区中文 | 欧美国产禁国产网站cc| 色94色欧美sute亚洲线路二| 欧美一区二区三区在线播放| 一片黄亚洲嫩模| 26uuu欧美| 欧美伊人久久大香线蕉综合69 | 色综合天天天天做夜夜夜夜做| 国产精品国产精品国产专区不蜜| 99在线观看免费视频精品观看| 亚洲h精品动漫在线观看| 久久久国际精品| 91精品福利视频| 韩国一区二区三区在线观看| 激情五月婷婷综合| 性感美女极品91精品| 亚洲国产精品成人综合色在线婷婷| 在线不卡欧美| 成人午夜av电影| 老司机午夜精品| 亚洲国产精品久久久久秋霞影院| 欧美日韩高清影院| 亚洲激情一区| 91免费在线看| 国产成人av网站| 午夜不卡av免费| 亚洲麻豆国产自偷在线| 国产日韩欧美在线一区| 91精品福利在线一区二区三区| 欧美日韩三级电影在线| 国产一区二区三区久久悠悠色av| 久久亚洲免费视频| 老司机免费视频久久| 亚洲三级色网| 99久久er热在这里只有精品66| 亚洲人成小说网站色在线| 久久一留热品黄| 欧美一区二区三区免费在线看| 精品不卡一区| 粉嫩久久99精品久久久久久夜| 亚洲欧美偷拍卡通变态| 久久人人97超碰com| 欧美日韩亚洲综合一区| 一本到一区二区三区| 国产亚洲在线| 亚洲国产精品久久久久久女王| 蜜臀91精品一区二区三区 | 欧美精品黑人性xxxx| 在线观看三级视频欧美| 久久网站免费| 羞羞答答国产精品www一本 | 亚洲美女一区| 91蜜桃网址入口| 成人黄色在线看| 国产传媒久久文化传媒| 久久精品国产亚洲5555| 日本不卡视频在线| 日产精品久久久久久久性色| 亚洲国产精品麻豆| 樱花影视一区二区| 亚洲丝袜精品丝袜在线| 中文字幕在线免费不卡| 中文字幕一区二区三区在线观看 | 欧美精品三级日韩久久| 欧美日韩高清在线| 欧美日韩不卡一区二区| 欧美性大战久久久久久久蜜臀| 国内激情久久| 91在线播放网址| 91亚洲精品久久久蜜桃| 99久久免费国产| 91麻豆精东视频| 欧美日韩国产一区精品一区| 欧美日韩一区综合| 国产精品扒开腿做爽爽爽软件| 国产一区二区在线观看视频| 久久精品国产**网站演员| 久久99这里只有精品| 九色综合国产一区二区三区| 麻豆高清免费国产一区| 日韩av电影天堂| 麻豆视频一区二区| 国内偷窥港台综合视频在线播放| 亚洲一二三四在线| 亚洲曰韩产成在线| 亚洲国产欧美在线人成| 亚洲在线观看免费视频| 亚洲与欧洲av电影| 日韩国产在线观看一区|