Spring MVC使用AOP实现审计日志
先定一个注解,用于在Controller方法上记录每个方法的用途。
- package com.zjf.spring.annotation;
- import java.lang.annotation.Documented;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- /**
- * 定义注解
- *
- @Target : 用来说明该注解可以被声明在那些元素之前。
- ElementType.TYPE:说明该注解只能被声明在一个类前。
- ElementType.FIELD:说明该注解只能被声明在一个类的字段前。
- ElementType.METHOD:说明该注解只能被声明在一个类的方法前。
- ElementType.PARAMETER:说明该注解只能被声明在一个方法参数前。
- ElementType.CONSTRUCTOR:说明该注解只能声明在一个类的构造方法前。
- ElementType.LOCAL_VARIABLE:说明该注解只能声明在一个局部变量前。
- ElementType.ANNOTATION_TYPE:说明该注解只能声明在一个注解类型前。
- ElementType.PACKAGE:说明该注解只能声明在一个包名前。
- */
- @Target({ElementType.METHOD})
- /**
- @Retention :用来说明该注解类的生命周期。它有以下三个参数:
- RetentionPolicy.SOURCE : 注解只保留在源文件中
- RetentionPolicy.CLASS : 注解保留在class文件中,在加载到JVM虚拟机时丢弃
- RetentionPolicy.RUNTIME : 注解保留在程序运行期间,此时可以通过反射获得定义在某个类上的所有注解。
- */
- @Retention(RetentionPolicy.RUNTIME)
- /**
- Annotation(注解)是JDK5.0及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。
- 注解是以'@注解名'在代码中存在的,根据注解参数的个数,我们可以将注解分为:标记注解、单值注解、完整注解三类。
- 它们都不会直接影响到程序的语义,只是作为注解(标识)存在,我们可以通过反射机制编程实现对这些元数据(用来描述数据的数据)的访问。
- 另外,你可以在编译时选择代码里的注解是否只存在于源代码级,或者它也能在class文件中出现。
- */
- /*
- * 注解名字 LogAnnotation
- */
- public @interface LogAnnotation {
- //为LogAnnotation定义了一个desc属性 用于描述方法的description 在记录甚至日志的时候获取
- String desc() default "无描述信息";
- }
定义切面:
- package com.zjf.spring.log;
- import java.lang.reflect.Method;
- import javax.servlet.http.HttpServletRequest;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.Signature;
- import org.aspectj.lang.annotation.AfterReturning;
- import org.aspectj.lang.annotation.AfterThrowing;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Component;
- import org.springframework.web.context.request.RequestContextHolder;
- import org.springframework.web.context.request.ServletRequestAttributes;
- import com.zjf.spring.annotation.LogAnnotation;
- /**
- *
- * @Aspect生命这个类是一个切面
- *
- */
- @Aspect
- @Component
- public class SystemLogAspect {
- // 注入Service用于把日志保存数据库
- // 本地异常日志记录对象
- private static final Logger logger = LoggerFactory
- .getLogger(SystemLogAspect.class);
- // Controller层切点 通过注解进行切点 凡是生命了LogAnnotation注解的方法都要进入这个切面
- @Pointcut("@annotation(com.zjf.spring.annotation.LogAnnotation)")
- public void controllerAspect() {
- }
- /**
- *
- * 方法操作成功 会进入@AfterReturning
- * @param joinPoint 代表会记录切点的信息 就是代码运行到切点是的变量环境
- * 可以从joinPoint获取使用的LogAnnotation信息
- * 切点
- */
- @AfterReturning(pointcut = "controllerAspect()")
- public void doBefore(JoinPoint joinPoint) {
- handleLog(joinPoint, null);
- }
- /**
- * 方法执行中出现了异常 会出现在@AfterThrowing中
- */
- @AfterThrowing(value = "controllerAspect()", throwing = "e")
- public void doAfter(JoinPoint joinPoint, Exception e) {
- handleLog(joinPoint, e);
- }
- private void handleLog(JoinPoint joinPoint,Exception e) {
- try {
- //从joinPoint获得LogAnnotation注解
- LogAnnotation controllerLog = giveController(joinPoint);
- if(controllerLog == null)
- {
- return;
- }
- //获取request
- HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
- //通过request获取session 然后获取用户信息
- //通过request获取ip
- //处理设置注解上的参数 也就是方法的描述
- String desc = controllerLog.desc();
- System.out.println(desc);
- //保存数据库
- } catch (Exception exp) {
- //记录本地异常日志
- logger.error("==前置通知异常==");
- logger.error("异常信息:{}", exp.getMessage());
- exp.printStackTrace();
- }
- }
- /**
- * 是否存在注解,如果存在就记录日志
- * @param joinPoint
- * @param controllerLog
- * @return
- * @throws Exception
- */
- private static LogAnnotation giveController(JoinPoint joinPoint) throws Exception
- {
- /*
- * JoinPoint可以获取什么:
- l java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
- l Signature getSignature() :获取连接点的方法签名对象;
- l java.lang.Object getTarget() :获取连接点所在的目标对象;
- l java.lang.Object getThis() :获取代理对象本身;
- */
- Signature signature = joinPoint.getSignature();
- /*
- * MethodSignature可以获取什么:
- Class getReturnType(); 获取方法的返回类型
- Method getMethod(); 获取方法本身
- */
- MethodSignature methodSignature = (MethodSignature) signature;
- /**
- * Method可以获取方法上的各种信息 比如方法名称 方法参数 注解 参数上的注解等。
- */
- Method method = methodSignature.getMethod();
- if(method != null)
- {
- return method.getAnnotation(LogAnnotation.class);
- }
- return null;
- }
- }
声明:aop:aspectj-autoproxy
关于aop:aspectj-autoproxy:
通过aop命名空间的<aop:aspectj-autoproxy />声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。当然,spring 在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被<aop:aspectj-autoproxy />隐藏起来了
<aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。
- <aop:aspectj-autoproxy />
在Controller方法中加入注解:
- @RequestMapping(value="/test1")
- @LogAnnotation(desc="test1方法")
- public String test1(HttpServletRequest request)
- {
- request.setAttribute("att1", "val1");
- return "test1";
- }
Spring MVC使用AOP实现审计日志的更多相关文章
- springMVC+MyBatis+Spring 整合(4) ---解决Spring MVC 对AOP不起作用的问题
解决Spring MVC 对AOP不起作用的问题 分类: SpringMVC3x+Spring3x+MyBatis3x myibaits spring J2EE2013-11-21 11:22 640 ...
- spring mvc+ELK从头开始搭建日志平台
最近由于之前协助前公司做了点力所能及的事情,居然收到了一份贵重的端午礼物,是给我女儿的一个乐高积木,整个有7大包物件,我花了接近一天的时间一砖一瓦的组织起来,虽然很辛苦但是能够从过程中体验到乐趣.这次 ...
- spring MVC 及 AOP 原理
SpringMVC工作原理https://www.cnblogs.com/xiaoxi/p/6164383.htmlspring MVC 原理https://blog.csdn.net/y199108 ...
- 解决Spring MVC 对AOP不起作用的问题
用的是 SSM3的框架 Spring MVC 3.1 + Spring 3.1 + Mybatis3.1 第一种情况: Spring MVC 和 Spring 整合的时候,SpringMVC的spri ...
- Spring MVC通过AOP切面编程 来拦截controller 实现日志的写入
首选需要参考的是:[参考]http://www.cnblogs.com/guokai870510826/p/5977948.html http://www.cnblogs.com/guokai8 ...
- spring AOP 之五:Spring MVC通过AOP切面编程来拦截controller
示例1:通过包路径及类名规则为应用增加切面 该示例是通过拦截所有com.dxz.web.aop包下的以Controller结尾的所有类的所有方法,在方法执行前后打印和记录日志到数据库. 新建一个spr ...
- spring+mybatis基于 AOP实现业务日志管理
最近在项目上用到了操作日志的相关,之前的解决方案就是自己写一个日志project,然后统一调用日志接口即可,这样方便自定义定制,因为有很多设备控制之类的都是需要确认一下的,但是,对数据的操作,比如,增 ...
- ABP(现代ASP.NET样板开发框架)系列之19、ABP应用层——审计日志
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之19.ABP应用层——审计日志 ABP是“ASP.NET Boilerplate Project (ASP.NET ...
- ABP应用层——审计日志
ABP应用层——审计日志 点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之19.ABP应用层——审计日志 ABP是“ASP.NET Boilerplate Pro ...
随机推荐
- opensatck误删除service项目
由于在清除资源时,未考虑到租户service,将其一并删除,于是有了下面的填坑之旅 1,需要找到删除的services-id,查看keytone的log, grep -r "DELETE&q ...
- docker(常见调试技巧):docker打包镜像调试技巧
写Dockerfile可以先不指定CMD.ENTRYPOINT等启动命令,只要拷贝就好了 如下: # Dockerfile for basic-app-client # Build with: # d ...
- ASP.NET MVC 开发随笔(二)
1.目前在局部视图中使用多个model时候,发现使用IEnumerable的时候,读取不了原来model的内容,所以采用List发现没问题 2. 如果想在JS中使用Razor,则需要在Razor添加& ...
- 文件分发服务器 AWS CloudFront(CDN)使用入门-以S3为例 Lebal:Research
引言 在互联网上随意右击一张图片,都可以发现复制图片地址这个选项,这说明他们都有自己的链接(直链),也就是说我们可以通过一个链接本身来访问图片.代码等文件,而不是打开一个网页再选择复制,这就和下载链接 ...
- java课堂疑问解答与思考2
问题一 编写一个方法,使用以上算法生成指定数目(比如1000个)的随机整数. 答:Xn+1=(7^5*Xn)mod(2^31-1) 程序源码: import java.util.Random; imp ...
- DSP28335 eCAP 测频
F28335共有6组eCAP模块,每个eCAP不但具有捕获功能,而且还可用作PWM输出功能.F28335捕获模块的主要特征如下: 1. 150MHz系统时钟的情况下,32位时基的时间分辨率为6.67n ...
- pandas的.columns和.index
可以通过.columns和.index着两个属性返回数据集的列索引和行索引 设data是pandas的一个DataFram类型的数据集. 则data.index返回一个index类型的行索引列表,da ...
- 【神经网络与深度学习】【Python开发】Caffe配置 windows下怎么安装protobuf for python
首先从google上下载protobuf-2.5.0.zip和protoc-2.5.0-win32.zip,然后把protoc-2.5.0-win32.zip里的protoc.exe放到protobu ...
- 【VS开发】【Qt开发】使用process explorer查看exe调用dll的情况
打开process explorer 选中想要查看句柄或者加载的dll的进程,比如下面截图红框中的 chrome.exe 菜单点击view / Lower Pane View,其下有DLLS和Hand ...
- cocos creator 3D | 拇指投篮 | 3D项目入门实战
你的命中率是多少呢?文章底部试玩! 效果预览 配置环境: Cocos Creator 3D v1.0.1 玩法说明: 触摸屏幕,向上滑动投篮!注意篮板是会移动的哦!看看你的命中率是多少! 实现原理 为 ...