日志拦截AOP,当执行抛异常时@AfterThrowing执行了没效果

使用Spring的AOP进行日志记录,对应的代码为

package cn.tiansu.eway.logAop;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.inject.Inject;

import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import cn.tiansu.eway.annotation.SystemLog;
import cn.tiansu.eway.entity.LogFormMap;
import cn.tiansu.eway.mapper.LogMapper;
import cn.tiansu.eway.util.Common;

/**
 * 切点类
 *
 * @author LJN
 * @since 2015-05-05 Pm 20:35
 * @version 1.0
 */
@Aspect
@Component
public class LogAopAction <span style="color:#ff0000;">implements Ordered</span>{
	// 本地异常日志记录对象
	private static final Logger logger = LoggerFactory.getLogger(LogAopAction.class);
	@Inject
	private LogMapper logMapper;

	// Controller层切点
	@Pointcut("@annotation(cn.tiansu.eway.annotation.SystemLog)")
	public void controllerAspect() {
	}

	/**
	 * 操作异常记录
	 *
	 * @descript
	 * @param point
	 * @param e
	 * @author LJN
	 * @date 2015年5月5日
	 * @version 1.0
	 */
	@AfterThrowing(pointcut = "controllerAspect()", throwing = "e")
	public void doAfterThrowing(JoinPoint point, Throwable e) {
		LogFormMap logForm = new LogFormMap();
		Map<String, Object> map = null;
		String user = null;
		String ip = null;
		Long start = 0L;
		Long end = 0L;
		Long time = 0L;
		try {
			ip = SecurityUtils.getSubject().getSession().getHost();
		} catch (Exception ee) {
			ip = "无法获取登录用户Ip";
		}
		try {
			map = getControllerMethodDescription(point);
			// 登录名
			user = SecurityUtils.getSubject().getPrincipal().toString();
			if (Common.isEmpty(user)) {
				user = "无法获取登录用户信息!";
			}
		} catch (Exception ee) {
			user = "无法获取登录用户信息!";
		}

		try {
			start = System.currentTimeMillis();
			end = System.currentTimeMillis();
			time = end - start;

			logForm.put("accountName", user);
			logForm.put("module", map.get("module"));
			logForm.put("methods", map.get("methods"));
			logForm.put("description", "执行失败,原因:" + e);
			logForm.put("actionTime", time);
			logForm.put("userIP", ip);
			logForm.put("type", map.get("type"));
			logMapper.addEntity(logForm);

		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}

	/**
	 * 前置通知 用于拦截Controller层记录用户的操作
	 *
	 * @param joinPoint
	 *            切点
	 */
	@Around("controllerAspect()")
	public Object doController(ProceedingJoinPoint point) {
		Object result = null;
		// 执行方法名
		String methodName = point.getSignature().getName();
		String className = point.getTarget().getClass().getSimpleName();
		LogFormMap logForm = new LogFormMap();
		Map<String, Object> map = null;
		String user = null;
		Long start = 0L;
		Long end = 0L;
		Long time = 0L;
		String ip = null;
		try {
			ip = SecurityUtils.getSubject().getSession().getHost();
		} catch (Exception e) {
			ip = "无法获取登录用户Ip";
		}
		try {
			// 登录名
			user = SecurityUtils.getSubject().getPrincipal().toString();
			if (Common.isEmpty(user)) {
				user = "无法获取登录用户信息!";
			}
		} catch (Exception e) {
			user = "无法获取登录用户信息!";
		}
		// 当前用户
		try {
			map = getControllerMethodDescription(point);
			// 执行方法所消耗的时间
			start = System.currentTimeMillis();
			result = point.proceed();
			end = System.currentTimeMillis();
			time = end - start;
		} catch (Throwable e) {
			throw new RuntimeException(e);
		}
		try {
			logForm.put("accountName", user);
			logForm.put("module", map.get("module"));
			logForm.put("methods", map.get("methods"));
			logForm.put("type", map.get("type"));
			logForm.put("description", map.get("description"));
			logForm.put("actionTime", time.toString());
			logForm.put("userIP", ip);
			logMapper.addEntity(logForm);
			// *========控制台输出=========*//
			System.out.println("=====通知开始=====");
			System.out.println("请求方法:" + className + "." + methodName + "()");
			System.out.println("方法描述:" + map);
			System.out.println("请求IP:" + ip);
			System.out.println("=====通知结束=====");
		} catch (Exception e) {
			// 记录本地异常日志
			logger.error("====通知异常====");
			logger.error("异常信息:{}", e.getMessage());
		}
		return result;
	}

	/**
	 * 获取注解中对方法的描述信息 用于Controller层注解
	 *
	 * @param joinPoint
	 *            切点
	 * @return 方法描述
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public Map<String, Object> getControllerMethodDescription(
			JoinPoint joinPoint) throws Exception {
		Map<String, Object> map = new HashMap<String, Object>();
		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();
		Class targetClass = Class.forName(targetName);
		Method[] methods = targetClass.getMethods();
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class[] clazzs = method.getParameterTypes();
				if (clazzs.length == arguments.length) {
					map.put("module", method.getAnnotation(SystemLog.class)
							.module());
					map.put("methods", method.getAnnotation(SystemLog.class)
							.methods());
					map.put("type", method.getAnnotation(SystemLog.class)
							.type());
					String de = method.getAnnotation(SystemLog.class)
							.description();
					if (Common.isEmpty(de))
						de = "执行成功!";
					map.put("description", de);
					break;
				}
			}
		}
		return map;
	}

	<span style="color:#ff0000;">@Override
	public int getOrder() {
		// TODO Auto-generated method stub
		return 1;
	}</span>
}
当执行正常时,走 @Around;当执行异常时,走@AfterThrowing。结果发现,执行异常时,@AfterThrowing方法正常执行完毕,但是异常日志并没有插入数据表中,插入日志的代码也没报任何错误,遂百度之(http://my.oschina.net/HuifengWang/blog/304188),发现问题所在:

Spring中的事务是通过aop来实现的,当我们自己写aop拦截的时候,会遇到跟spring的事务aop执行的先后顺序问题,比如说动态切换数据源的问题,如果事务在前,数据源切换在后,会导致数据源切换失效,所以就用到了Order(排序)这个关键字.我们可以通过在@AspectJ的方法中实现org.springframework.core.Ordered 这个接口来定义order的顺序,order 的值越小,说明越先被执行。

当实现Ordered 接口之后,我们自己写的aop在事务介入之前就执行了!



  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
AOP(面向切面编程)可以帮助我们在程序运行动态地添加一些额外的功能。在记录日志异常拦截方面,使用 AOP 可以让我们更方便地实现这些功能,而不需要在每个方法中都手动添加相应的代码。 记录日志方面,我们可以使用 AOP 将 LogAspect(日志切面)应用到需要记录日志的方法上。LogAspect 可以在方法执行前、执行后或抛出异常记录相关日志信息。 异常拦截方面,我们可以使用 AOP 将 ExceptionAspect(异常切面)应用到需要拦截异常的方法上。ExceptionAspect 可以捕获方法执行过程中出的异常,并进行相应的处理,如记录日志、提示用户等。 下面是一个使用 AOP 记录日志异常拦截的示例代码: ```java @Aspect @Component public class LogAspect { private final Logger logger = LoggerFactory.getLogger(LogAspect.class); @Before("execution(* com.example.demo.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { logger.info("Before method: " + joinPoint.getSignature().getName()); } @AfterReturning("execution(* com.example.demo.service.*.*(..))") public void logAfterReturning(JoinPoint joinPoint) { logger.info("After method: " + joinPoint.getSignature().getName()); } @AfterThrowing(pointcut = "execution(* com.example.demo.service.*.*(..))", throwing = "ex") public void logAfterThrowing(JoinPoint joinPoint, Exception ex) { logger.error("Exception in method: " + joinPoint.getSignature().getName(), ex); } } @Aspect @Component public class ExceptionAspect { private final Logger logger = LoggerFactory.getLogger(ExceptionAspect.class); @Around("execution(* com.example.demo.service.*.*(..))") public Object handleException(ProceedingJoinPoint joinPoint) throws Throwable { try { return joinPoint.proceed(); } catch (Exception ex) { logger.error("Exception in method: " + joinPoint.getSignature().getName(), ex); // 处理异常,如记录日志、提示用户等 throw ex; } } } ``` 在上面的代码中,LogAspect 和 ExceptionAspect 分别实现了记录日志异常拦截的功能。我们将它们添加到需要记录日志拦截异常的方法上即可。例如,我们可以在需要记录日志的 service 方法上添加 @Before、@AfterReturning 和 @AfterThrowing 注解,或在需要拦截异常的方法上添加 @Around 注解

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值