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 blockString 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"})@ResponseBodypublic 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 blockString message=methodName+" "+loggable.module()+"异常!";logger.info(message);messageJson=AppResult.getFaileMsg(message);e.printStackTrace();}return messageJson;}}
参考:https://blog.csdn.net/kawnj/article/details/84639159
https://docs.spring.io/spring-framework/docs/5.1.3.RELEASE/spring-framework-reference/core.html#aop-introduction-proxies