在软件的使用过程当中,对用户的行为及用户的操作进行跟踪分析,这也是相当重要的一个模块,那么如何实现用户的日志管理呢?
首先用户的日志管理这个模块要很容易潜入当前的系统中,不能影响当前系统的正常运行。这样在技术方面当然有很多种实现方法。在spring2+struts2+hibernate3的系统架构中,实现用户日志管理功能,我们可以采用struts2拦截器,也可以采用spring的切面编程思路。下面我们采用spring aop来实现用户的日志功能。
1、首先定义一个切面类。bsrAfterReturningAdvice
在spring的配置文件中可以这样申明
- <aop:config proxy-target-class="true">
- <aop:pointcut id="actionPointcut" expression="execution(* com.liuxing..*.*Action.*()throws *Exception))"/>
- <aop:aspect id="goLogAspect" ref="liuxingAfterReturningAdvice">
- <aop:after-returning pointcut-ref="actionPointcut" method="writeLogInfo"/>
- </aop:aspect>
- </aop:config>
- <bean id="liuxingAfterReturningAdvice" class="com.liuxing.annotation.LiuxingAfterReturningAdvice" >
在这里我们定义了一个类LiuxingAfterReturningAdvice,这个类是一个切面类,同时我们定义了一个spring的拦截器,这个拦截器拦截符合条件的所有action的所有方法。将这些action拦截之后有我们定义好的切面类来处理。
2、切面类的实现如下。
- import java.lang.reflect.Method;
- import java.lang.reflect.Field;
- import java.net.InetAddress;
- import com.liuxing.annotation.UserLogInfoService;
- import com.liuxing.annotation.UserLogInfo;
- import com.liuxing.util.ApplicationContextFactory;
- import org.springframework.context.ApplicationContext;
- import org.apache.struts2.ServletActionContext;
- import org.aspectj.lang.JoinPoint;
- import com.liuxing.commons.Constants;
- import com.liuxing.domain.BaseObject;
- import com.liuxing.domain.sys.SysUser;
- import com.liuxing.util.TimeHelper;
- public class LiuxingAfterReturningAdvice {
- private UserLogInfoService userLogInfoService;
- private UserLogInfoAction userLogInfoAction;
- private UserLogInfo userLogInfo;
- public void writeLogInfo(JoinPoint joinPoint) throws Exception,IllegalAccessException{
- //try{
- SysUser sysUser = (SysUser)ServletActionContext.getRequest().getSession().getAttribute(Constants.SESSION_USER_KEY);
- System.out.println(joinPoint.getStaticPart().toShortString());
- String temp=joinPoint.getStaticPart().toShortString();
- String classType=joinPoint.getTarget().getClass().getName();
- String methodName=temp.substring(10, temp.length()-1);
- Class className=Class.forName(classType);
- Method method=className.getMethod(methodName, new Class[]{});
- Field field;
- if(method.isAnnotationPresent(GoaAnnotation.class)){
- GoaAnnotation goaAnnotation=method.getAnnotation(GoaAnnotation.class);
- String operateDescribe=goaAnnotation.operateDescribe();
- System.out.println("添加在方法前面的描述是:"+operateDescribe);
- System.out.println("用户"+sysUser.getUserName()+"进行了"+operateDescribe+"操作");
- userLogInfo=new UserLogInfo();
- {//为用户日志实体赋值
- userLogInfo.setSysUser(sysUser);
- userLogInfo.setUserIp(ServletActionContext.getRequest().getRemoteAddr());
- userLogInfo.setUserOperateContent(operateDescribe);
- userLogInfo.setUserOperateTime(TimeHelper.getCurrentTime());
- userLogInfoService=(UserLogInfoService)ApplicationContextFactory.getApplicationContext().getBean("userLogInfoService");
- userLogInfoService.save(userLogInfo);
- }
- }
- }
- public UserLogInfoService getUserLogInfoService() {
- return userLogInfoService;
- }
- public void setUserLogInfoService(UserLogInfoService userLogInfoService) {
- this.userLogInfoService = userLogInfoService;
- }
- public UserLogInfoAction getUserLogInfoAction() {
- return userLogInfoAction;
- }
- public void setUserLogInfoAction(UserLogInfoAction userLogInfoAction) {
- this.userLogInfoAction = userLogInfoAction;
- }
- }
当一个方法被拦截掉后,将在此类进行处理,将用户的操作信息写入UserLogInfo实体,存入数据库。同事我们要在被拦截的类中加一个自定义的annotation,这也是非常关键的。
3、自定义的annotaion
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.METHOD)
- public @interface GoaAnnotation {
- String operateDescribe();
- }
4、在每一个要被拦截的方法前面加上自定义的注释。
如:
- @GoaAnnotation(operateDescribe="保存基本信息")
- public String save() throws Exception {
这样,我们在切面处理类中能够获取到这个注释的类容,同事能够得到调用的方法名,这样我们可以知道当前用户调用的方法,即进行了什么样的业务操作。我们的日志工作基本完成。