springboot进阶-使用aop实现接口监控和全局异常处理

AOP是什么

用过spring开发的程序员对AOP应该都不陌生,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
简而言之,AOP就是为了减少我们纵向编码的复杂度,让我们可以更加的注重于业务实现。

AOP实战

准备工作

1.环境准备:
jdk1.8+springboot2.1.5+idea(强烈推荐使用idea开发)

2.依赖配置:
pom.xml引入aop的配置

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

因为我配置了parent,所以无需再单独配置aop的版本,单独使用请配置对应版本的aop

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

AOP代码实现

新建一个ExceptionAspectController类用来实现接口监控和全局异常处理。

/**
 * [说明]
 *
 * @author xiaoama
 * @date 2019/12/16 20:20.
 */
@Component
@Aspect
public class ExceptionAspectController {

    @Autowired
    private ExceptionHandle exceptionHandle;//全局异常处理类

   private ExceptionHandleRecords records;

    public static final Logger logger = LoggerFactory.getLogger(ExceptionAspectController.class);

    @Pointcut("execution(* com.xiaoama.test.controller.*.*(..))")//此处基于自身项目的路径做具体的设置
    public void pointCut(){}

    @Around("pointCut()")
    public Object handleControllerMethod(ProceedingJoinPoint point) {
        Object result = null;
        long beginTime = System.currentTimeMillis();
        HttpServletRequest request = null;
        try {
            // 执行方法
            request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            result = point.proceed();
            MethodSignature methodSignature =(MethodSignature) point.getSignature();
            String[] parameterNames = methodSignature.getParameterNames();
            Object[] param =point.getArgs();
            StringBuffer str=new StringBuffer();
            if(parameterNames!=null){
                for(int i=0;i<parameterNames.length;i++){
                    if (null !=param[i]){
                        str.append(param[i].toString());
                    }
            }
        }
            records = new ExceptionHandleRecords();
            records.setUrl(request.getRequestURL().toString());
            records.setMethod(request.getMethod());
            records.setParams(str.toString());
            records.setTime(new Date().getTime());
            records.setResult(result.toString());

            logger.info("[接口监控服务]  : "+records.toString());
        } catch (Throwable e) {
            logger.error("请求: "+request.getRequestURI()+" 异常",e);
            return exceptionHandle.exceptionGet(e);
        }
        // 执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        logger.info("use time :"+time);
        return result;
    }

}

PoingCut:
@Pointcut(“execution(* com.xiaoama.test.controller..(…))”)
设置切面的位置,根据自身项目路径修改具体的配置

ExceptionHandleRecords:
全局接口监控PO类,提供需要记录日志的参数类型,可以根据自身的项目需要修改此类。

public class ExceptionHandleRecords {

    private String url;
    private String method;
    private long time;
    private String params;
    private String result;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }

    public String getParams() {
        return params;
    }

    public void setParams(String params) {
        this.params = params;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public ExceptionHandleRecords() { }

    public ExceptionHandleRecords(String url, String method, long time, String params, String result) {
        this.url = url;
        this.method = method;
        this.time = time;
        this.params = params;
        this.result = result;
    }

    @Override
    public String toString() {
        return "{" +
                "\"url\":\"" + url + '\"' +
                ", \"method\":\"" + method + '\"' +
                ", \"time\":" + time +
                ", \"params\":\"" + params + '\"' +
                ", \"result\":\"" + result + '\"' +
                '}';
    }
}

ExceptionHandle:
异常处理类,用于处理全局的异常,根据不同的异常类型可以分别做不同的处理模式。

@ControllerAdvice
public class ExceptionHandle {

    private final static Logger LOGGER = LoggerFactory.getLogger(ExceptionHandle.class);

    /**
     * 判断错误是否是已定义的已知错误,不是则由未知错误代替,同时记录在log中
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseData exceptionGet(Throwable e){
        if(e instanceof BusinessException){
            BusinessException exception = (BusinessException)e;
            return ResponseData.fail(exception.getMsg());
        }
        if(e instanceof Exception){
            Exception exception = (Exception)e;
            return ResponseData.fail(exception.getMessage());
        }

        return ResponseData.fail("unknown error");
    }

}

总结

AOP的使用在开发中很常见,除了接口监控,异常处理等,我们通常也会用于权限控制,token认证,自定义注解(Annotation)等,是java开发的一大利器。

你可能感兴趣的:(spring,boot,aop,java)