spring+aop+自定义注解实现操作日志记录

1,spring配置文件

<bean class="com.able.aop.LogAspect" id="logAspect"/>

    <aop:config>
        <aop:aspect id="serviceMonitor" ref="logAspect">
            <aop:pointcut expression="execution(* com.able.controller.*.*(..))" id="servicePointcut" />
            <aop:around method="doAroundMethodLog" pointcut-ref="servicePointcut"/>
        </aop:aspect>
    </aop:config>

2,日志拦截类

public class LogAspect {
    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private UserOperatLogService userOperatLogService;
    @Autowired
    private TokenService tokenService;
    /**
     * 标注该方法体为环绕通知,当目标方法执行时执行该方法体
     */
    public Object doAroundMethodLog(ProceedingJoinPoint jp) throws Throwable{
        StopWatch stopWatch = new StopWatch(); //记录方法执行耗时
        stopWatch.start();
        Object retVal = null;
        try{
            retVal = jp.proceed();
        }catch (Throwable e){
            e.printStackTrace();
            logger.error(e.getMessage());
            retVal = new ResponseEntity(new RestResult(e.getMessage(),false), HttpStatus.OK);
        }finally {
            stopWatch.stop();
            insertOpertLog(jp, stopWatch);
        }
        return retVal;
    }
	private void insertOpertLog(ProceedingJoinPoint jp, StopWatch stopWatch) {
		Class<? extends Object> classD=jp.getTarget().getClass();
		String className = classD.getName();
		MethodSignature joinPointObject = (MethodSignature) jp.getSignature();
		Method method = joinPointObject.getMethod();
		String methodName = method.getName();
		if(!jp.getTarget().getClass().isAnnotationPresent(NoLog.class)&&!method.isAnnotationPresent(NoLog.class)){
			String params = parseParames(jp.getArgs()); //解析目标方法体的参数
			UserOperatLog userOperatLog=new UserOperatLog();
			userOperatLog.setIpAddr(request.getRemoteAddr());
			userOperatLog.setActionUrl(request.getRequestURI());
			userOperatLog.setTimeLong(stopWatch.getTotalTimeMillis()+"");
			ShiroUser shiroUser = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
			if(shiroUser!=null){
				userOperatLog.setUserId(shiroUser.getZhsId());
				userOperatLog.setUserName(shiroUser.getRealName());
			}else{
				String tokenCode=request.getParameter("tokenCode")==null?"":request.getParameter("tokenCode");
				if(tokenCode!=null && !"".equals(tokenCode)){
					Token token = new Token();
					token.setTokenCode(tokenCode);
					List<Token> list =tokenService.selectBySelective(token);
					if(list != null && list.size() > 0){
						token=list.get(0);
						userOperatLog.setUserId(token.getUserId());
						userOperatLog.setUserName(token.getRealName());
					}
				}
			}
			Function fd = null;
			Operate md = null;
			if(classD.isAnnotationPresent(Function.class)){
			    fd = classD.getAnnotation(Function.class);
			}
			if(method.isAnnotationPresent(Operate.class)){
			    md =method.getAnnotation(Operate.class);
			}
			if(fd!=null){
				userOperatLog.setMean(fd.value());
				userOperatLog.setModule(fd.moduleName());
				userOperatLog.setSubModule(fd.subModuleName());
			}
			if(md!=null){
				userOperatLog.setFunction(md.value());
			}
			userOperatLog.setParamData(params);
			userOperatLog.setCreateTime(DateUtil.getTimeStamp());
			logger.info("业务处理"+",模块:["+(fd!=null?fd.moduleName():"")+"],操作:["+(md!=null?md.value():"")+"],调用类名称:["+className+"],调用方法名称:["+methodName+"],参数为:" + params + ";耗时" + stopWatch.getTotalTimeMillis() + "毫秒");
			userOperatLogService.insertBySelective(userOperatLog);
			//userOperatLogService.testasy();
			logger.info("执行完毕=======");
		}
	}

3,自定义注解三个

    功能模块注解

/**
 * 每个类的功能描述
 * @author zhangqh
 * @date 2016-8-2 下午01:03:59
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface Function {
    String value() default "";
    String moduleName() default "";
    String subModuleName() default "";
}

操作方法注解

/**
 * 方法描述
 * @author zhangqh
 * @date 2016-8-2 下午12:55:25
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Operate {
    String value() default "";
}

不需要记录日志的注解

/**
 * 免记录日志注解标识
 * @author wjhu
 * @date 2016-8-2 下午01:03:59
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
public @interface NoLog {

}

 4,controller中记录操作日志的使用

/**
 * @Function注解为对应的操作日志模块
 * @author zhangqh
 *
 */
@Controller
@RequestMapping("/test")
@Function(value ="测试模块",moduleName = "测试模块",subModuleName = "")
public class test {
	/**
	 * 会记录对应的操作说明
	 */
	@Operate(value="操作")
	public void aa(){
		
	}
	/**
	 * 使用@NoLog注解就不是记录该方法的操作日志了
	 */
	@NoLog
	public void bb(){
		
	}
}

 提示:如果记录日志要持久化到数据库的话,建议入库操作加上异步操作这样对性能会提升不少

spring对异步调用方法支持也比较好 配置也比较简单,只需要要在配置文件中加入

<!-- 支持异步加载 -->
 <task:annotation-driven/>

 就可以了,然后使用的方法上加上@Async就可以了

猜你喜欢

转载自840327220.iteye.com/blog/2316017