aop:aspect oriented programming 面向切面编程
aop关注不是某一个类或某些方法;控制大量资源,关注的是大量的类和方法。
2.aop应用场景以及常用术语
权限控制、缓存控制、事务控制、分布式追踪、异常处理等
target:目标类,即需要被代理的类。例如:userservice
joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法
pointcut 切入点:已经被增强的连接点。例如:adduser()
advice 通知/增强,增强代码。例如:after、before
weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程.
aspect(切面): 是切入点pointcut和通知advice的结合
3.aop的特点
1)降低模块与模块之间的耦合度,提高业务代码的聚合度。(高内聚低耦合)
2)提高了代码的复用性
3)提高系统的扩展性。(高版本兼容低版本)
4)可以在不影响原有的功能基础上添加新的功能
二、springboot 使用 aop 实现流程1.引入依赖
<!-- spring aop --> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-aop</artifactid></dependency>
2.封装记录日志实体类
@getter@setter@apimodel(value = "systemlog对象", description = "")public class systemlog implements serializable { private static final long serialversionuid = 1l; @apimodelproperty("id") @tableid(value = "id", type = idtype.auto) private integer id; @apimodelproperty("用户名") private string username; @apimodelproperty("用户id") private integer userid; @apimodelproperty("操作描述") private string operate; @apimodelproperty("模块") private string module; @apimodelproperty("创建日志时间") @datetimeformat(pattern = "yyyy-mm-dd hh:mm:ss") private date createtime; @apimodelproperty("操作结果") private string result;}
3.编写注解类(自定义日志注解类)
/** * controller层切面日志注解 * @author hsq */@target(elementtype.method)@retention(retentionpolicy.runtime)public @interface systemcontrollerlog { // 操作描述 string operate(); // 模块 string module();}
4.编写操作日志的切面类
** * @author hsq */@aspect@componentpublic class systemlogaspect { private static final logger logger = loggerfactory.getlogger(systemlogaspect.class); @autowired private isystemlogservice isystemlogservice; @autowired private userservice userservice; /** * controller层切点 */ @pointcut("@annotation(com.hsq.demo.config.systemcontrollerlog)") public void systemcontrollerlog(){ } /** * 前置通知 用于拦截controller层记录用户的操作的开始时间 * @param joinpoint 切点 * @throws interruptedexception */ @before("systemcontrollerlog()") public void dobefore(joinpoint joinpoint) throws interruptedexception{ logger.info("进入日志切面前置通知!"); } @after("systemcontrollerlog()") public void doafter(joinpoint joinpoint) { logger.info("进入日志切面后置通知!"); } /**value切入点位置 * returning 自定义的变量,标识目标方法的返回值,自定义变量名必须和通知方法的形参一样 * 特点:在目标方法之后执行的,能够获取到目标方法的返回值,可以根据这个返回值做不同的处理 */ @afterreturning(value = "systemcontrollerlog()", returning = "ret") public void doafterreturning(object ret) throws throwable { } /*** * 异常通知 记录操作报错日志 * * @param joinpoint * * @param e * */ @afterthrowing(pointcut = "systemcontrollerlog()", throwing = "e") public void doafterthrowing(joinpoint joinpoint, throwable e) { logger.info("进入日志切面异常通知!!"); logger.info("异常信息:" + e.getmessage()); } //使用这个方法先注释前面三个方法,留before方法就行 /** * 通知包裹了目标方法,在目标方法调用之前和之后执行自定义的行为 * proceedingjoinpoint切入点可以获取切入点方法上的名字、参数、注解和对象 * @param joinpoint */ @around("systemcontrollerlog() && @annotation(systemcontrollerlog)") public result doafterreturning(proceedingjoinpoint joinpoint, systemcontrollerlog systemcontrollerlog) throws throwable { logger.info("设置日志信息存储到表中!"); //joinpoint.proceed() 结果集 //参数数组 object[] args = joinpoint.getargs(); //请求参数数据 string requestjson = jsonutil.tojsonstr(args); //方法名 string methodname = joinpoint.getsignature().getname(); //得到request httpservletrequest request = ((servletrequestattributes) requestcontextholder.getrequestattributes()).getrequest(); //得到token string token = request.getheader("token"); string userid = jwt.decode(token).getaudience().get(0); user user = userservice.getbyid(userid); logger.info("得到用户信息:"+user.tostring()); //写入数据库操作日志 systemlog systemlog = new systemlog(); systemlog.setuserid(user.getuid()); systemlog.setusername(user.getuname()); systemlog.setoperate(systemcontrollerlog.operate()); systemlog.setmodule(systemcontrollerlog.module()); systemlog.setcreatetime(new date()); //存入返回的结果集 joinpoint.proceed() result proceed = (result) joinpoint.proceed(); systemlog.setresult(jsonutil.tojsonstr(joinpoint.proceed())); //保存 savesystemlog(systemlog); return proceed; }}
5.controller使用
@getmapping("/userlistpage") @systemcontrollerlog(operate = "用户查询",module = "用户管理") public result finduserlist( @requestparam integer pagenum, @requestparam integer pagesize, @requestparam string username, @requestparam string lovevalue, @requestparam string address) {} @postmapping("/addorupdate") @systemcontrollerlog(operate = "用户修改或者添加",module = "用户管理") public result addorupdateuser(@requestbody user user){}
6.数据库记录
以上就是springboot怎么使用aop记录接口操作日志的详细内容。
