利用spring AOP注解实现日志管理
最近刚接手一个项目,在项目的开始阶段,我们的架构师分配了个任务给我,让我利用spring的切面技术做一个日志管理的案例。要求很简单,就是需要记录:谁在什么时候对谁做了什么操作,同时在日志的描述中还要有修改前后内容的对比。话说两句话是挺简单的,但是对于对spring只有初学者水平的我还是有点难度的,于是各种百度,各种谷歌,各种想。终于在这篇http://kaowww153.iteye.com/blog/603891博客中得到启发,但是里面的内容写的还是不够完整,和我的需求也有些不一样。经过多次的修改和测试,终于成功通过。今天闲来无事,写个博文,以备下次需要做好笔记。话不多说,把过程写下:
1.首先创建一个自定义注解
package com.cstp.custom.interfaces;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RecordLog {
}
2.写一个过滤方法,这个方法是实现MethodIntherceptor接口的。
package com.cstp.custom.interfaces;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import com.cstp.jdbc.dao.systemLogDao;
import com.cstp.jdbc.dao.impl.systemLogDaoImpl;
import com.cstp.jdbc.vo.SystemLog;
import com.cstp.jdbc.vo.User;
public class LogAroundInterceptor implements MethodInterceptor {
private systemLogDao systemLogDao = new systemLogDaoImpl();
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// TODO Auto-generated method stub
Object returnObject;
Object newObj = null;
Object operatObj = null;
HttpServletRequest request = null;
Method method = invocation.getMethod();
if (method.isAnnotationPresent(RecordLog.class)) {
Object[] arguments = invocation.getArguments();
if (null != arguments) {
newObj = arguments[0];//新对象
operatObj = arguments[1];//操作人
if (arguments[2] instanceof HttpServletRequest) {
request = (HttpServletRequest)arguments[2]; //通过session把旧对象传过来作为新旧对象的比较
}
SystemLog systemLog = getSysLog(getOperaType(method.getName()), newObj, operatObj, request);
System.out.println(systemLog);
systemLogDao.addLog(systemLog);
}
returnObject = invocation.proceed(); // 执行被拦截的方法
} else {
returnObject = invocation.proceed(); // 执行被拦截的方法
}
return returnObject;
}
public int getOperaType(String methodName) {
int type = 0;
if (methodName.startsWith("save") || methodName.startsWith("add") || methodName.startsWith("insert")) {
type = 1;//增
} else if (methodName.startsWith("delete") || methodName.startsWith("del")) {
type = 2;//删
} else if (methodName.startsWith("update")){
type = 3;//改
}
return type;
}
public SystemLog getSysLog(int type, Object newObj, Object operator,HttpServletRequest request) {
StringBuffer sysContent = new StringBuffer();
SystemLog systemLog = new SystemLog();
Object oldObject = request.getSession().getAttribute("oldUser");
if (type != 1 && type != 2 && type != 3) {
System.out.println("此方法不能被记录日志");
return null;
}
if (newObj instanceof User) {
User user = (User) newObj;
sysContent.append("用户:");
if (type == 1) {
sysContent.append(user.getName()).append("被保存.");
} else if (type == 2) {
// sysContent.append(user.getDeleteUser()).append(
// "删除了用户:" + user.getUniqueUserName());
}
}
return systemLog;
}
}
3.applicationContext.xml里配置
<bean id="common" class="com.cstp.jdbc.test.Common">
</bean>
<aop:config>
<aop:pointcut id="logPointCuts"
expression="execution(* com.cstp.jdbc.test.*.*(..))" />
<aop:advisor pointcut-ref="logPointCuts" advice-ref="springMethodInterceptor" />
</aop:config>
<bean id="springMethodInterceptor" class="com.cstp.custom.interfaces.LogAroundInterceptor">
</bean>
</beans>
4.我的实体类common
@RecordLog
public void update(User user, User opeartor, HttpServletRequest request) {
UserDao userDao = new UserDaoImpl();
userDao.updateUser(user);
System.out.println("修改成功");
}
5.在servlet测试
UserDao userDao = new UserDaoImpl();
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
Common c = (Common) factory.getBean("common");
User user = new User();
user.setId(2);
user.setName("杰");
user.setPassword("123456");
user.setAge(18);
user.setSex("女");
User opeartor = userDao.findAllUserById(3);
User oldUser = userDao.findAllUserById(2);
HttpSession session = request.getSession();
session.setAttribute("oldUser", oldUser);
c.update(user, opeartor, request);
测试通过,我所需要的新旧对象,以及操作人,时间,描述等都可以在getSysLog()方法中获取,至于如何添加就简单啦,就不写上了。
6.使用方法很简单了:在需要添加日志的方法上加上我们的注解@RecordLog就可以了(就像我common类里的update方法一样)。
1.首先创建一个自定义注解
package com.cstp.custom.interfaces;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RecordLog {
}
2.写一个过滤方法,这个方法是实现MethodIntherceptor接口的。
package com.cstp.custom.interfaces;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import com.cstp.jdbc.dao.systemLogDao;
import com.cstp.jdbc.dao.impl.systemLogDaoImpl;
import com.cstp.jdbc.vo.SystemLog;
import com.cstp.jdbc.vo.User;
public class LogAroundInterceptor implements MethodInterceptor {
private systemLogDao systemLogDao = new systemLogDaoImpl();
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// TODO Auto-generated method stub
Object returnObject;
Object newObj = null;
Object operatObj = null;
HttpServletRequest request = null;
Method method = invocation.getMethod();
if (method.isAnnotationPresent(RecordLog.class)) {
Object[] arguments = invocation.getArguments();
if (null != arguments) {
newObj = arguments[0];//新对象
operatObj = arguments[1];//操作人
if (arguments[2] instanceof HttpServletRequest) {
request = (HttpServletRequest)arguments[2]; //通过session把旧对象传过来作为新旧对象的比较
}
SystemLog systemLog = getSysLog(getOperaType(method.getName()), newObj, operatObj, request);
System.out.println(systemLog);
systemLogDao.addLog(systemLog);
}
returnObject = invocation.proceed(); // 执行被拦截的方法
} else {
returnObject = invocation.proceed(); // 执行被拦截的方法
}
return returnObject;
}
public int getOperaType(String methodName) {
int type = 0;
if (methodName.startsWith("save") || methodName.startsWith("add") || methodName.startsWith("insert")) {
type = 1;//增
} else if (methodName.startsWith("delete") || methodName.startsWith("del")) {
type = 2;//删
} else if (methodName.startsWith("update")){
type = 3;//改
}
return type;
}
public SystemLog getSysLog(int type, Object newObj, Object operator,HttpServletRequest request) {
StringBuffer sysContent = new StringBuffer();
SystemLog systemLog = new SystemLog();
Object oldObject = request.getSession().getAttribute("oldUser");
if (type != 1 && type != 2 && type != 3) {
System.out.println("此方法不能被记录日志");
return null;
}
if (newObj instanceof User) {
User user = (User) newObj;
sysContent.append("用户:");
if (type == 1) {
sysContent.append(user.getName()).append("被保存.");
} else if (type == 2) {
// sysContent.append(user.getDeleteUser()).append(
// "删除了用户:" + user.getUniqueUserName());
}
}
return systemLog;
}
}
3.applicationContext.xml里配置
<bean id="common" class="com.cstp.jdbc.test.Common">
</bean>
<aop:config>
<aop:pointcut id="logPointCuts"
expression="execution(* com.cstp.jdbc.test.*.*(..))" />
<aop:advisor pointcut-ref="logPointCuts" advice-ref="springMethodInterceptor" />
</aop:config>
<bean id="springMethodInterceptor" class="com.cstp.custom.interfaces.LogAroundInterceptor">
</bean>
</beans>
4.我的实体类common
@RecordLog
public void update(User user, User opeartor, HttpServletRequest request) {
UserDao userDao = new UserDaoImpl();
userDao.updateUser(user);
System.out.println("修改成功");
}
5.在servlet测试
UserDao userDao = new UserDaoImpl();
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
Common c = (Common) factory.getBean("common");
User user = new User();
user.setId(2);
user.setName("杰");
user.setPassword("123456");
user.setAge(18);
user.setSex("女");
User opeartor = userDao.findAllUserById(3);
User oldUser = userDao.findAllUserById(2);
HttpSession session = request.getSession();
session.setAttribute("oldUser", oldUser);
c.update(user, opeartor, request);
测试通过,我所需要的新旧对象,以及操作人,时间,描述等都可以在getSysLog()方法中获取,至于如何添加就简单啦,就不写上了。
6.使用方法很简单了:在需要添加日志的方法上加上我们的注解@RecordLog就可以了(就像我common类里的update方法一样)。
如果你喜欢本文, 请长按二维码,关注公众号 分布式编程.
作者:分布式编程
出处:https://zthinker.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。