你不是说你会Aop吗?

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 你不是说你会Aop吗?

一大早,小王就急匆匆的跑过来找我,说:周哥,那个记录日志的功能我想请教一下。

因为公司某个项目要跟别的平台做对接,我们这边需要给他们提供一套接口。昨天,我就将记录接口日志的工作安排给了小王。

下面是我跟小王的主要对话。

我:说说怎么了?

小王:我将记录接口日志的功能放到了每个controller中,现在感觉有点繁琐,我这样做是不是不太合适?

我:为什么要去每个接口里记录日志?

小王:最开始我是用的拦截器,但是这样一个请求就记录了两条记录。

我:为什么是两条?

小王:在preHandle中记录一条请求数据,在postHandle中记录一条响应数据。

我:。。。你不是说你会Aop吗?

小王:Aop也是一样,在前置通知记录一条请求数据,后置通知记录一条响应数据。

小王:这个数据和以前记录操作日志的不太一样,以前只需要在前置通知记录一条操作日志就可以了,但是现在有响应,所以只能在controller中记录日志了。

我:那你知不知道有个环绕通知?你说一下Aop就几种通知类型。

小王:总共有五种,分别是:

  • 前置通知:在我们执行目标方法之前运行(@Before
  • 后置通知:在我们目标方法运行结束之后,不管有没有异常(@After
  • 返回通知:在我们的目标方法正常返回值后运行(@AfterReturning
  • 异常通知:在我们的目标方法出现异常后运行(@AfterThrowing
  • 环绕通知:目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,joinPoint.procced()就是执行目标方法的代码 。环绕通知可以控制返回对象(@Around)

接下来,我们一起来演示一下如何使用环绕通知来解决小王的问题。

第一步:提供接口用来接收参数和响应接口

@RestController
public class TestController {
    @GetMapping("/getName")
    public String getName(HttpServletRequest request) throw Exception {

        String result = "Java旅途";
        String age = request.getParameter("age");
        if("18".equals(age)){
            result = "无法识别";
        }
        return result;
    }
}

第二步:定义切点

execution()是比较常用的定义切点的表达式,execution()语法如下:

execution(修饰符  返回值  包.类.方法名(参数) throws异常)

其中:

修饰符和throws异常可以省略不写

根据这些解释,我们可以将第一步中的接口用execution()表达式来描述一下:

execution(String binzh.website.controller.TestController.GetName(HttpServletRequest))
  • *:匹配所有项
  • ..:匹配任意个方法参数
  • ..出现在类名中时,后面必须跟*,表示包、子孙包下的所有类;

现在我们优化一下上面的表达式,定义切面为controller包及controller下面所有包的所有方法

execution(* binzh.website.controller..*.*(..))

第三步:环绕通知记录日志

@Around("execution(* binzh.website.controller..*.*(..))")
public Object around(ProceedingJoinPoint joinPoint) {
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    String age = request.getParameter("age");
    Object proceed = "";
    try {
        proceed = joinPoint.proceed();
    } catch (Throwable e) {
        e.printStackTrace();
    }
    System.out.println("age==="+age);
    System.out.println("proceed ===="+proceed);
    return proceed;
}

运行结果如下:

age===19
proceed ====Java旅途

我们之所以可以用环绕通知来处理小王的问题。其中一个重要的原因就是,我们提供的所有接口都是经过统一加密的,最后请求的参数都是一个固定的名字。还需要注意的一点就是,环绕通知的返回值类型必须大于等于方法的返回值,即:加入你方法返回String类型,环绕通知不能写成void类型

小王看到这里后,恍然大悟,准备赶紧回去试一下。我急忙拉住他。

我:如果接口出现异常了怎么办?

小王:那我在异常通知里处理就可以了。

我:你再想一下?

小王:好像不行,异常通知里获取不到请求参数。

我:在环绕通知中捕获处理可以吗?

这时候,看见小王眼睛发光,惊讶的说了一句:环绕通知太牛批了,竟然可以完成前置通知、后置通知和异常通知的工作!

这篇文章戏有点多,别见怪。实战是提升技术最有效的途径!

相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
目录
相关文章
|
6月前
|
机器学习/深度学习 人工智能 前端开发
SWEET-RL:8B小模型暴打GPT-4?Meta开源强化学习黑科技,多轮任务成功率飙升6%
Meta最新开源的SWEET-RL框架通过优化多轮交互任务的信用分配机制,使Llama-3.1-8B模型在协作推理任务中的表现提升6%,性能达到顶尖大模型水平。
337 33
SWEET-RL:8B小模型暴打GPT-4?Meta开源强化学习黑科技,多轮任务成功率飙升6%
|
8月前
|
人工智能 监控 安全
Java智慧工地(源码):数字化管理提升施工安全与质量
随着科技的发展,智慧工地已成为建筑行业转型升级的重要手段。依托智能感知设备和云物互联技术,智慧工地为工程管理带来了革命性的变革,实现了项目管理的简单化、远程化和智能化。
207 5
|
12月前
|
供应链 安全 算法
Github 宣布在2023年底前必须使用双重验证
2FA(双因素身份验证)是一种增强在线账户安全性的方法,要求用户提供两种不同类型的验证信息才能登录。常见的验证因素包括密码、手机验证码、指纹等。启用2FA能显著提升账户安全性,防止因密码泄露导致的账户被盗。对于开发者而言,尤其是在使用如GitHub这样的平台时,启用2FA尤为重要,可有效抵御恶意攻击,保护代码和个人信息的安全。设置2FA通常通过安装TOTP应用(如Microsoft Authenticator)并按照平台指引完成相关配置。即使手机App被卸载,用户也可通过保存的恢复码登录账户。
603 3
Github 宣布在2023年底前必须使用双重验证
|
11月前
|
测试技术 开发者 UED
探索软件测试的深度:从单元测试到自动化测试
【10月更文挑战第30天】在软件开发的世界中,测试是确保产品质量和用户满意度的关键步骤。本文将深入探讨软件测试的不同层次,从基本的单元测试到复杂的自动化测试,揭示它们如何共同构建一个坚实的质量保证体系。我们将通过实际代码示例,展示如何在开发过程中实施有效的测试策略,以确保软件的稳定性和可靠性。无论你是新手还是经验丰富的开发者,这篇文章都将为你提供宝贵的见解和实用技巧。
|
TensorFlow 算法框架/工具 Python
【Mac 系统】解决VSCode用Conda成功安装TensorFlow但程序报错显示红色波浪线Unable to import ‘tensorflow‘ pylint(import-error)
本文解决在Mac系统上使用VSCode时遇到的TensorFlow无法导入问题,原因是Python解析器未正确设置为Conda环境下的版本。通过在VSCode左下角选择正确的Python解析器,即可解决import TensorFlow时报错和显示红色波浪线的问题。
648 9
|
机器学习/深度学习 人工智能 算法
人工智能伦理框架:构建AI的道德指南针
【7月更文挑战第16天】随着人工智能技术的快速发展,其对社会的深远影响引起了广泛关注。本文探讨了构建人工智能伦理框架的必要性,并提出了一套基于四大原则的伦理指导方针:透明度、公正性、责任归属和隐私保护。文章旨在为AI系统的设计与部署提供道德指南,确保技术进步与人类价值观相协调。
862 3
|
关系型数据库 Linux 应用服务中间件
在Linux中,什么是LAMP和LNMP堆栈?
在Linux中,什么是LAMP和LNMP堆栈?
|
iOS开发 MacOS
macOS10.13.6及以下版本不能自动升级到更高版本的解决方案
macOS10.13.6及以下版本不能自动升级到更高版本的解决方案
2268 1
N..
|
开发框架 前端开发 UED
Bootstrap弹出框与警告框
Bootstrap弹出框与警告框
N..
219 0
|
存储 Unix Linux
Linux下的NFS搭建配置
Linux下的NFS搭建配置
337 3