最近项目中有需求对用户重要操作行为进行记录,这也是开发中常见需求,记录下来。
首先,对于不同类型的需求,近项目中有需求对用户重要操作行为进行记录,这也是开发中常见需求。
首先,对于不同类型的需求,日志记录选项也不同,在这里采用的的springAop切面+自定义注解方法实现记录。
SpringAop 底层的原理就是动态代理,
但是运行时织入的,也就是在用到目标类或者方法的时候,生成一个代理类,然后将配好的通知织入
但就Aop而言的话它本身还有的方式就是,编译时织入,比如说是前置通知,当你编译了以后他就会织入到方法当中,所以你通过反射的方法去看的话会看到相应的生成代码
,还有就是在类加载期间织入的,
但是就性能而言的,SpringAop的这种动态代理的方式,是有着较高的效率的;
Spring提供了四种aop切面的支持
基于代理的经典的pringAop
纯POJO切面
@AspectJ注解驱动切面//底层也是Spring的动态代理 只是参考了AspectJ的一些形式
注入式Aspectj切面
而本此使用的就是@AspectJ注解驱动切面的方式。
下面,就是实现一个自定义的注解;
@Target({ElementType.PARAMETER,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemControllerLog {
/*对于引用注解方法的描述*/
String description() default "";
}
接下来就是定义一个切面类
@Aspect
@Component
引入两个注解一个是表明切面类,一个是让spring容器去管理;
接下来是考虑数据库中记录的信息是什么,一般来说,我们需要记录用户,角色,操作方法,操作时间,该方法说明,访问ip等,具体根据自己需求,设计字段。
@Resource
private ISysLogService sysLogService;
引入记录入数据库中
private static final Logger logger=LoggerFactory.getLogger(SystemLogAspect.class);
打印在控制台
@Pointcut("@annotation(net.dreamlu.utils.SystemControllerLog)")
public void controllerAspect() {
}
配置切点,在配置切点这里,对于切入表达式不同,切入点不同,我们需要的是使用该注解的方法对其进行行为记录,同样,我们也可以对整个Controller类或者其他所需进行切入,可自行搜索查看其他切入表达式。
接下来,就是对我们的切入点配置通知,在这进行前置通知,方法内主要是获取我们所需的字段信息,然后存入数据库之中,这里JoinPoint可以帮助我们获取很多切入方法信息;
@Before("controllerAspect()")
public void doBefore(JoinPoint joinPoint) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
String[] infoArr=null;
try {
infoArr = getControllerMethodDescription(joinPoint).split(";");
} catch (Exception e) {
e.printStackTrace();
}
String ip=request.getRemoteAddr();
SysLogEvent sysLog =new SysLogEvent();
sysLog.setUsername(SecurityUtils.getUserName());
sysLog.setOperation(infoArr.toString());
sysLog.setClassMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
sysLog.setClientIp(ip);
sysLogService.saveSysLog(sysLog);
}
获取注解内描述信息
public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();//目标方法名
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String infoStr = "";
for (Method method:methods) {
if (method.getName().equals(methodName)){
Class[] clazzs = method.getParameterTypes();
if (clazzs.length==arguments.length){
String description = method.getAnnotation(SystemControllerLog.class).description();
infoStr = description;
break;
}
}
}
return infoStr;
}