pringoot实现拦截的几种姿势腾讯云开发者社区

本文已收录至我的GitHub

AOP(面向切面编程)常用于解决系统中的一些耦合问题,是一种编程的模式 通过将一些通用逻辑抽取为公共模块,由容器来进行调用,以达到模块间隔离的效果。

AOP常用于...

日志记录

你需要为你的Web应用程序实现访问日志记录,却又不想在所有接口中一个个进行打点。

安全控制

为URL 实现访问权限控制,自动拦截一些非法访问。

事务

某些业务流程需要在一个事务中串行

异常处理

系统发生处理异常,根据不同的异常返回定制的消息体。

在笔者刚开始接触编程之时,AOP还是个新事物,当时曾认为AOP会大行其道。 果不其然,目前流行的Spring 框架中,AOP已经成为其关键的核心能力。

接下来,我们要看看在SpringBoot 框架中,怎么实现常用的一些拦截操作。

先看看下面的一个Controller方法:

示例

在上述代码的 body 方法中,会接受一个MsgBody请求消息体,最终简单的输出content字段。

下面,我们将介绍如何为这个方法实现拦截动作。算起来,共有五种姿势。

其中 CustomerFilter 实现了Filter接口,如下:

为Filter的实现类添加 @WebFilter注解,由SpringBoot 框架扫描后注入

@WebFilter的启用需要配合@ServletComponentScan才能生效

使用注解是最简单的,但其缺点是仍然无法支持 order属性(用于控制Filter的排序)。

而通常的@Order注解只能用于定义Bean的加载顺序,却真正无法控制Filter排序。这是一个已知问题,参考这里

推荐指数

Filter 定义属于J2EE规范,由Servlet容器调度执行。

由于独立于框架之外,无法使用 Spring 框架的便捷特性, 目前一些第三方组件集成时会使用该方式。

方法

说明

preHandle

Controller方法执行前调用

preHandle

Controller方法后,视图渲染前调用

afterCompletion

整个方法执行后(包括异常抛出捕获)

基于 HandlerInterceptor接口 实现的样例:

除了上面的代码实现,还不要忘了将 Interceptor 实现进行注册:

推荐指数

HandlerInterceptor 来自SpringMVC框架,基本可代替 Filter 接口使用。

除了可以方便的进行异常处理之外,通过接口参数能获得Controller方法实例,还可以实现更灵活的定制。

@ExceptionHandler 的用途是捕获方法执行时抛出的异常, 通常可用于捕获全局异常,并输出自定义的结果。

如下面的实例:

需要注意的是,@ExceptionHandler 需要与 @ControllerAdvice配合使用 其中 @ControllerAdvice的 assignableTypes 属性指定了所拦截类的名称。 除此之外,该注解还支持指定包扫描范围、注解范围等等。

推荐指数

@ExceptionHandler 使用非常方便,在异常处理的机制上是首选; 目前也是SpringBoot 框架最为推荐使用的方法。

RequestBodyAdvice、ResponseBodyAdvice 相对于读者可能比较陌生, 而这俩接口也是 Spring 4.x 才开始出现的。

我们都知道,SpringBoot 中可以利用@RequestBody这样的注解完成请求内容体与对象的转换。

而RequestBodyAdvice *则可用于在请求内容对象转换的前后时刻*进行拦截处理,其定义了几个方法:

方法

说明

supports

判断是否支持

handleEmptyBody

当请求体为空时调用

beforeBodyRead

在请求体未读取(转换)时调用

afterBodyRead

在请求体完成读取后调用

实现代码如下:

上述代码实现中,针对前面提到的 MsgBody对象类型进行了拦截处理。

在beforeBodyRead 中,返回一个BodyInputMessage对象,而这个对象便负责源数据流解析转换

代码说明

完成数据流的转换,包括以下步骤:

ResponseBodyAdvice 的用途在于对返回内容做拦截处理,如下面的示例:

看,还是容易理解的,我们在返回的字符串中添加了一个前缀!

推荐指数

这是两个非常冷门的接口,目前的使用场景也相对有限; 一般在需要对输入输出流进行特殊处理(比如加解密)的场景下使用。

简单说明

@Pointcut 用于定义切面点,而使用target关键字可以定位到具体的类。@Around 定义了一个切面处理方法,通过注入ProceedingJoinPoint对象达到控制的目的。

一些常用的切面注解:

注解

说明

@Before

方法执行之前

@After

方法执行之后

@Around

方法执行前后

@AfterThrowing

抛出异常后

@AfterReturing

正常返回后

深入一点

aop的能力来自于spring-boot-starter-aop,进一步依赖于aspectjweaver组件。有兴趣可以进一步了解。

推荐指数

aspectj 与 SpringBoot 可以无缝集成,这是一个经典的AOP框架, 可以实现任何你想要的功能,笔者之前曾在多个项目中使用,效果是十分不错的。

注解的支持及自动包扫描大大简化了开发,然而,你仍然需要先对 Pointcut 的定义有充分的了解。

到这里,读者可能想知道,这些实现拦截器的接口之间有什么关系呢? 答案是,没有什么关系! 每一种接口都会在不同的时机被调用,

我们基于上面的代码示例做了日志输出:

可以看到,各种拦截器接口的执行顺序如下图:

AOP 是实现拦截器的基本思路,本文介绍了SpringBoot 项目中实现拦截功能的五种常用姿势。

对于每一种方法都给出了真实的代码样例,读者可以根据需要选择自己适用的方案。

THE END
0.29个A股行业指数,基于lightGBM的排序学习(代码+数据)之前分享过系列的代码: 行业指数轮动:一个可实盘策略的“魔改”历程,十年年化15%(策略+代码+数据**) 我们下载29个A股主要行业指数。 下面是etf与指数的对应关系: etfs_indexes = { '159870.SZ':'000813.CSI', '512400.SH':'000819.SH', '515220.SH':'399998.SZ', jvzq<84yyy4489iqe0ipo8hqpvkov8761272986316;8;9<36a723:8697640|mvon
1.以列车为主要场景的10部佳作,中韩电影力压《子弹列车》!(子弹列车《源代码》(2011)好片指数:82分军人科特被送进一个模拟程序,能够还原列车在爆炸前8分钟发生的一切。科特必须在有限时间内找出真凶,否则更严重的恐怖袭击就会发生。可他慢慢发现,恐袭的真凶变得无关紧要,这个“源代码”程序本身就隐藏着让人头皮发麻的秘密。邓肯·琼斯在石破天惊的处女作《月球》之后,导演了《源代码jvzquC41oq|jg7iqwdgo0lto1tkwkn|136<87>::1
2.恒生指数的代码是什么?您好,恒生指数的代码是999999。1、恒生指数,香港股市价格的重要指标,指数由若干只成份股(即蓝筹股)jvzquC41nkibk7hqhqum0lto1cyl1zfa36665@3jvor
3.SRISWAPDWAAIEDI等气象资料计算干旱指数的方法SPI是一种基于月降水的指数,而SPEI则考虑了温度因素。SRI利用月径流数据,DWAAI关注旱涝急转事件。SWAP通过日尺度降水数据进行干旱监测。文章探讨了各指数的优缺点、计算方法和代码实现,并比较了SPI与SWAP的差异,强调了不同尺度下干旱指数的适用性和分级阈值的重要性。jvzquC41dnuh0lxfp0tfv8vsa6:36?;3:1gsvrhng1jfvjnnu1729B8377?