1.首先是用注解方式捕捉Controller 层异常:
首先是引入aop 依赖的jar
<!-- Spring AOP 日志管理需要导入的包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
其次是在applicationg.xml spring 容器中加入 aop 配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" ....
xsi:schemaLocation="
...
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
在application 添加spring配置代理
<!-- proxy-target-class="true"配置使Spring采用CGLIB代理 proxy-target-class="false" 配置使Spring采用JDK代理--><!-- 开启@aspectJ切面注解器 默认是flase -->
<aop:aspectj-autoproxy />
添加自定义注解:
package com.buDun.test.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
//@Target({ElementType.METHOD,ElementType.FIELD})
@Target(ElementType.METHOD)
@Documented
public @interface Loggable {
/**Insert,Update,Delete,Select */
String optType() default "";
/** 描述*/
String describe() default "";
/**模块 */
String module() default "";
}
参考:http://mini.eastday.com/bdmip/180411141722960.html
定义一个切面:
注意:@AfterReturning 注解args参数中一定有,returning="retVal" 并且注解参数名称 和方法参数名称相同
@AfterThrowing 注解也是:注解args参数一定有throwing="ex" 并且注解参数名称和方法参数名称相同
捕捉异常处理:可以使用@around 获取 ptpJoinPoint.proceed(); 捕捉异常处理在返回给前端;
package com.BaDun.test.aop;
import java.lang.reflect.Method;
import java.util.Objects;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
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.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.BaDun.test.annotation.Loggable;
import com.BaDun.test.common.AppResult;
/**
* Aop接收打印日志.
* <p>主要用来截取controller的日志处理和异常捕获</p>
* @author jhon07
* @version 1.11
*
*/
@Aspect
@Component("loggerAspect")
public class LoggerAspect {
private Logger logger=LoggerFactory.getLogger(LoggerAspect.class);
@Pointcut("@annotation(com.BaDun.test.annotation.Loggable)")
public void log(){};
/**
*
* @param joinPoint
* @param retVal
* @return JSONObject
* @author qienay
* @since 1.11
*
*/
@AfterReturning(value="log()",returning="retVal")
public JSONObject log(JoinPoint joinPoint,JSONObject retVal){
//获取参数值
Object[] args = joinPoint.getArgs();
//获取方法名称
String methodName=joinPoint.getSignature().getName();
//获取相应的类
Class<?> targetClass=joinPoint.getTarget().getClass();
Method method=null;
for(Method mt:targetClass.getMethods()){
if(methodName.equals(mt.getName())){
method=mt;
break;
}
}
Loggable loggable = method.getAnnotation(Loggable.class);
if(Objects.isNull(loggable)){
return retVal ;
}
logger.info("loggable desc:{} ,opType:{},module:{}",loggable.describe(),loggable.optType(),loggable.module(),args);
return retVal;
};
/**
* 方法处理后异常打印.
* @deprecated
* @param joinPoint
* @param ex
* @return void
*/
@AfterThrowing(value="log()",throwing="ex")
public void log(JoinPoint joinPoint,Exception ex){
//获取参数值
Object[] args = joinPoint.getArgs();
//获取方法名称
String methodName = joinPoint.getSignature().getName();
//获取相应类
Class<?> targetClass = joinPoint.getTarget().getClass();
Method method=null;
for(Method mt:targetClass.getMethods()){
if(methodName.equals(mt.getName())){
method=mt;
break;
}
}
Loggable loggable = method.getAnnotation(Loggable.class);
if(Objects.isNull(loggable)){
return ;
}
logger.info("loggable desc:{},opType:{},module:[],exception:{},params{}",loggable.describe(),loggable.optType(),loggable.module(),ex.getMessage(),args);
}
/**
* 环绕通知主要用来处理Controller层 异常.
* <p>controller 层类{@link com.BaDun.test.controller.testController}<p>
* @param joinPoint
* @return JSONObject
* @author jhon07
* @since 1.11
*/
@Around(value="log()")
public JSONObject authorSessionAfter(ProceedingJoinPoint ptpJoinPoint){
JSONObject messageJson=null;
String methodName=null;
Loggable loggable=null;
try {
//Object proceed = joinPoint.proceed();
//获取方法名
methodName= ptpJoinPoint.getSignature().getName();
//获取类型名称
Class<?> targetClass = ptpJoinPoint.getTarget().getClass();
Method method=null;
for(Method mt:targetClass.getMethods()){
if(methodName.equals(mt.getName())){
method=mt;
break;
}
}
loggable = method.getAnnotation(Loggable.class);
//获取controller传递的值
Object proceed = ptpJoinPoint.proceed();
messageJson=JSON.parseObject(proceed.toString());
} catch (Throwable e) {
// TODO Auto-generated catch block
String message=methodName+" "+loggable.module()+"异常!";
logger.info(message);
messageJson=AppResult.getFaileMsg(message);
e.printStackTrace();
}
return messageJson;
}
}
注意:controller 层 方法为public 不管是CGlib 还是JDK 创建代理类,首先得能访问这个类.方法;
@Loggable(describe="查询Jhon07信息", module = "查询", optType = "POST")
@RequestMapping(value = { "/queryUserInfo" }, method = { RequestMethod.POST }, produces={"application/json;charset=UTF-8"})
@ResponseBody
public void queryUserInfo(....){}
2.使用注解方式实现:
首先是在appliction.xml spring 容器中加入:aop配置
需要注意的是:mehod 不能像注解一样,使用重载方式,这里的method 的名字都不同的
<!-- AOP配置 -->
<aop:config>
<aop:aspect id="controllerAspect" ref="loggerAspects">
<aop:pointcut expression="execution(* com.buDun.test.controller.*.*(..))" id="controllPoincut" />
<aop:around pointcut-ref="controllPoincut" method="aroundLog" />
<aop:after-returning pointcut-ref="controllPoincut" method="afterReturningLog" returning="retVal" />
<!-- <aop:after-throwing pointcut-ref="controllPoincut" method="AfterThrowingLog" throwing="ex"/> -->
</aop:aspect>
</aop:config>
定义切面类:
package com.buDun.test.aop;
import java.lang.reflect.Method;
import java.util.Objects;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
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.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.buDun.test.annotation.Loggable;
import com.buDun.test.common.AppResult;
/**
* Aop接收打印日志.
* <p>主要用来截取controller的日志处理和异常捕获</p>
* @author jhon07
* @version 1.11
*
*/
@Component("loggerAspects")
public class LoggerAspects {
private Logger logger=LoggerFactory.getLogger(LoggerAspect.class);
public void log(){};
/**
*
* @param joinPoint
* @param retVal
* @return JSONObject
* @author qienay
* @since 1.11
*
*/
public JSONObject afterReturningLog(JoinPoint joinPoint,JSONObject retVal){
//获取参数值
Object[] args = joinPoint.getArgs();
//获取方法名称
String methodName=joinPoint.getSignature().getName();
//获取相应的类
Class<?> targetClass=joinPoint.getTarget().getClass();
Method method=null;
for(Method mt:targetClass.getMethods()){
if(methodName.equals(mt.getName())){
method=mt;
break;
}
}
Loggable loggable = method.getAnnotation(Loggable.class);
if(Objects.isNull(loggable)){
return retVal ;
}
logger.info("loggable desc:{} ,opType:{},module:{}",loggable.describe(),loggable.optType(),loggable.module(),args);
return retVal;
};
/**
* 方法处理后异常打印.
* @deprecated
* @param joinPoint
* @param ex
* @return void
*/
public void AfterThrowingLog(JoinPoint joinPoint,Exception ex){
//获取参数值
Object[] args = joinPoint.getArgs();
//获取方法名称
String methodName = joinPoint.getSignature().getName();
//获取相应类
Class<?> targetClass = joinPoint.getTarget().getClass();
Method method=null;
for(Method mt:targetClass.getMethods()){
if(methodName.equals(mt.getName())){
method=mt;
break;
}
}
Loggable loggable = method.getAnnotation(Loggable.class);
if(Objects.isNull(loggable)){
return ;
}
logger.info("loggable desc:{},opType:{},module:[],exception:{},params{}",loggable.describe(),loggable.optType(),loggable.module(),ex.getMessage(),args);
}
/**
* 环绕通知主要用来处理Controller层 异常.
* <p>controller 层类{@link com.buDun.test.controller.testController}<p>
* @param joinPoint
* @return JSONObject
* @author jhon07
* @since 1.11
*/
public JSONObject aroundLog(ProceedingJoinPoint ptpJoinPoint){
JSONObject messageJson=null;
String methodName=null;
Loggable loggable=null;
try {
//Object proceed = joinPoint.proceed();
//获取方法名
methodName= ptpJoinPoint.getSignature().getName();
//获取类型名称
Class<?> targetClass = ptpJoinPoint.getTarget().getClass();
Method method=null;
for(Method mt:targetClass.getMethods()){
if(methodName.equals(mt.getName())){
method=mt;
break;
}
}
loggable = method.getAnnotation(Loggable.class);
//获取controller传递的值
Object proceed = ptpJoinPoint.proceed();
messageJson=JSON.parseObject(proceed.toString());
} catch (Throwable e) {
// TODO Auto-generated catch block
String message=methodName+" "+loggable.module()+"异常!";
logger.info(message);
messageJson=AppResult.getFaileMsg(message);
e.printStackTrace();
}
return messageJson;
}
}