Spring、Mybatis和Logback集成,用面向切面AOP方式打印异常Exception信息,
Step 1:
首先定义文件CommonLogger.java:
public class CommonLogger {
Logger logger = LoggerFactory.getLogger(CommonLogger.class);
public static String strLog = null;
/**
* 前置通知:在某连接点之前执行的通知,但这个通知不能阻止连接点前的执行
*
* @param jp
* 连接点:程序执行过程中的某一行为,例如,AServiceImpl.barA()的调用或者抛出的异常行为
*/
public void doBefore(JoinPoint jp) {
strLog = "doBefore Begining method: " + jp.getTarget().getClass().getName()
+ "." + jp.getSignature().getName();
logger.warn(strLog);
}
/**
* 环绕通知:包围一个连接点的通知,可以在方法的调用前后完成自定义的行为,也可以选择不执行
* 类似Web中Servlet规范中的Filter的doFilter方法。
*
* @param pjp
* 当前进程中的连接点
* @return
* @throws Throwable
*/
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
long time = System.currentTimeMillis();
Object retVal = pjp.proceed();
time = System.currentTimeMillis() - time;
System.out.println("process time: " + time + " ms");
strLog = "doAround processing method: "
+ pjp.getTarget().getClass().getName() + "."
+ pjp.getSignature().getName() + " process time: " + time + " ms";
logger.warn(strLog);
return retVal;
}
/**
* 抛出异常后通知 : 在方法抛出异常退出时执行的通知。
*
* @param jp
* 连接点:程序执行过程中的某一行为,例如,AServiceImpl.barA()的调用或者抛出的异常行为
*/
public void doAfter(JoinPoint jp) {
// org.apache.ibatis.logging.LogFactory.useLog4JLogging();
strLog = "doAfter:log Ending method: "
+ jp.getTarget().getClass().getName() + "."
+ jp.getSignature().getName();
logger.warn(strLog);
}
/**
* 捕获异常
* @param jp
* @param e
* @throws Throwable
*/
public void doAfterThrowing(JoinPoint jp, Exception e) throws Throwable {
String strLog = "doAfterThrowing Begining method: " + jp.getTarget().getClass().getName()
+ "." + jp.getSignature().getName();
logger.error("异常抛出exception " + strLog, e);
// logger.error(Level.ERROR, "异常抛出exception", e);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
Step 2:
然后在spring.xml文件中配置日志AOP处理:
<!-- 配置日志 使用Aop 记录日志注意:
1). 此处proxy-target-class="true" 否则Service内的参数会被拦截掉,导致Service内无法获得前台传递的参数
2). Service需交给spring容器去管理 -->
<aop:config expose-proxy="true" proxy-target-class="true">
<aop:aspect id="teslaLogAspect" ref="teslaLog">
<!-- 对哪些方法进行日志记录, 此处屏蔽action内的set get方法 -->
<aop:pointcut id="teslaLogAOP"
expression="execution(* com.xxx.service.impl.*.*(..))"/>
<aop:before pointcut-ref="teslaLogAOP" method="doBefore"/>
<aop:after pointcut-ref="teslaLogAOP" method="doAfter"/>
<aop:around pointcut-ref="teslaLogAOP" method="doAround"/>
<aop:after-throwing pointcut-ref="teslaLogAOP"
method="doAfterThrowing" throwing="e"/>
</aop:aspect>
</aop:config>
<!-- Aop日志类 -->
<bean id="teslaLog" class="com.xxx.log.CommonLogger"/>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
上述配置基本上可以满足打印日志需要,但是如果出现try catch语句,然后用e.printStackTrace()这种方法打印出来的日志,就无法被logback捕获,于是针对这种问题,有两种解决方案:
Way 1:
删掉所有try catch,直接在方法后面throw异常;
Way 2:
try {
int a = 1/0;
}
catch (Exception e){
e.printStackTrace();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
修改为:
try {
int a = 1/0;
}
catch (Exception e){
logger.error("异常抛出exception ", e);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
通过上面的方式,就可以解决了!
如果想了解Spring、Mybatis和Logback系统配置,替换原来的log4j并打印sql日志的方案,请参考:
Spring、Mybatis和Logback系统配置,替换原来的log4j并打印sql日志