java自定义注解,保存用户操作日志

关于注解,很多人都清楚它们的用途,像@Autowired,@Controller,@Service等等

而自定义注解,就是我们自己创建一个注解。

自定义注解的格式:

public @interface 注解名 {定义体}

本文使用自定义注解结合springAop,记录用户的操作日志。


说到Aop切面编程,这种官方词语,看着就慌。

举个例子,现在你要吃?(面包),但你喜欢吃有馅的食物,于是你用水果刀切开一道口,往里头加了点葡萄干,然后又切了道口,往里头挤了点奶油。这样一来,面包就变美味了,切面包 == 切面?

?同理,现在有个修改数据的方法A,因为不知道是谁修改了数据,所以你打算在程序执行方法A后,自动保存操作日志。

于是你开始操刀:

A(){
    /** 执行操作 **/
    saveLog();
}

saveLog(){
    Log log = new Log();
    log.setModule("用户管理");
    log.setAction("修改数据");
    log.setCreateTime(new Date());
    log.setCreateId(userName);
    dao.saveLog(log);
}

很完美?

这时,其他功能也要跟着使用?。虽说能把saveLog()抽成公共方法,但每个需要保存日志的方法,都需要在尾部加上saveLog()。假如又需要在方法执行前,做其他操作,难道又要改成:

A(){
    doSomething();
    /** 执行操作 **/
    saveLog();
}
B(){
    doSomething();
    /** 执行操作 **/
    saveLog();
}
C(){
    doSomething();
    /** 执行操作 **/
    saveLog();
}

这是不可取的?‍。

而切面编程,能在方法执行前后,或者抛出异常时,自动执行一系列方法,非常漂亮的解决了这种问题。


回归主题,来为用户添加操作日志。

在spring配置文件里开启aop:

<aop:aspectj-autoproxy proxy-target-class="true" />

创建自定义注解LogAnnotation,默认模块是用户管理,默认操作是登录。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface LogAnnotation {
	String module() default "用户管理";
	String action() default "登录";
}

创建切面程序:

@Aspect
@Component
public class LogAspect {
	private Logger logger = Logger.getLogger(LogAspect.class);
	@Autowired
	private SysUserLogMapper sysUserLogMapper;
	
	@Pointcut("@annotation(com.plan.LogAnnotation)")
	private void logPointCut() {}
	
	@After("logPointCut()")
	public void after(JoinPoint joinPoint) {
		try {
			SysUserLog log = new SysUserLog();
			setUserInfo(log);
			setLogInfo(joinPoint,log);
			sysUserLogMapper.insert(log);
		} catch (InvalidSessionException e) {
			logger.error(e.getMessage());
		}
	}
	/**
	 * 设置用户信息
	 * @param log
	 */
	public void setUserInfo(SysUserLog log) {
		Session session = SecurityUtils.getSubject().getSession();
		User user = (User) session.getAttribute("user");
		log.setUserId(user.getUserId());
		log.setUserName(user.getChineseName());
		log.setCreateDate(new Date());
	}
	/**
	 * 设置操作信息
	 * @param joinPoint
	 * @param log
	 */
	public void setLogInfo(JoinPoint joinPoint, SysUserLog log){
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
		log.setModule(annotation.module());
		log.setAction(annotation.action());
	}
}

切面编程还有@before,这里就不写出来了。而关于@AfterThrowing,必须是方法体抛出异常,才能捕获到。

在需要记录日志的功能方法上添加注解:

@LogAnnotation(module="用户管理",action="登录")
public String userLogin() {

}

@LogAnnotation 对应的,就是 public @interface LogAnnotation

如此一来,在执行userLogin()方法后,程序会自动执行LogAspect类的after方法,得以记录日志。

以上!!!

另需注意

如果没使用springMVC,而是struts,或许会出现@Autowired类为NULL的情况,此时需要在struts.xml 配置文件上,加上这句:

<constant name="struts.objectFactory.spring.autoWire.alwaysRespect" value="true" />

确保Spring的自动装配策略总是被考虑的。

发布了40 篇原创文章 · 获赞 26 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/guowujun321/article/details/90033946