SpringBoot 集成AOP 自定义注解

SpringBoot 集成Aop 完成自定义注解功能 前提是需要掌握一定的Spring Aop知识

第一步:引入jar

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

第二步: 开启自动代理功能@EnableAspectJAutoProxy

package com.zhangheng;

import java.util.Properties;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import com.github.pagehelper.PageHelper;

/**
 * 程序启动入口
 * 
 * @author zhangh
 * @date 2018年4月26日上午9:16:27
 */
@SpringBootApplication
@EnableAspectJAutoProxy
@MapperScan("com.zhangheng.dao")
public class Application {

    /**
     * @author zhangh
     * @date 2018年4月28日下午5:18:38
     * @param args
     */
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        // 下面的代码可以自定义banner 还可以控制banner的显示方式(log console off)
        // SpringApplication app = new SpringApplication(Application.class);
        // app.setBannerMode(Banner.Mode.OFF);
        // app.run(args);
    }
}

第三步: 编写自定义注解以及切面类

package com.zhangheng.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;

/**
 * 校验参数
 * 
 * @author zhangh
 * @date 2018年4月26日上午9:37:58
 */
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CheckParam {
}
package com.zhangheng.annotation;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.zhangheng.common.ResultEnum;
import com.zhangheng.exception.MyException;
import com.zhangheng.util.AnnotationUtil;

/**
 * 自定义校验参数切面
 * 
 * @author zhangh
 * @date 2018年4月26日上午10:03:32
 */
@Aspect
@Component
@Order(1)
public class CheckParamAspect {

    private static Logger logger = Logger.getLogger(CheckParamAspect.class);

    @Pointcut("@annotation(com.zhangheng.annotation.CheckParam)")
    public void pointCut() {}

    /**
     * 切面前置处理
     * 
     * @param joinPoint
     */
    @Before("pointCut()")
    public void before(JoinPoint joinPoint) {
        MethodSignature sign = (MethodSignature) joinPoint.getSignature();
        logger.info("打印:" + sign.getDeclaringTypeName() + " 前置日志");
    }

    /**
     * 切面回环处理 这个方法里不允许出现try catch 异常捕获 必须要往外抛
     * 
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     * @author zhangh
     */
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object[] params = proceedingJoinPoint.getArgs();
        boolean hasAuthor = params != null && params.length > 0 ? true : false;
        if (hasAuthor && !params[0].toString().equals("-1")) {// 模拟校验参数
            return proceedingJoinPoint.proceed();
        } else {
            logger.info("很抱歉  方法" + AnnotationUtil.getClassName(proceedingJoinPoint) + "."
                    + AnnotationUtil.getMethodName(proceedingJoinPoint) + "参数校验失败");
            throw new MyException(ResultEnum.PARAM_ERROR);
        }
    }

    /**
     * 切面后置处理
     * 
     * @param joinPoint
     */
    @After("pointCut()")
    public void after(JoinPoint joinPoint) {
        logger.info("调用aspect 方法结束");
    }
}

第四步:编写统一异常处理

package com.zhangheng.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.zhangheng.common.ResultEnum;
import com.zhangheng.common.ResultInfo;
import com.zhangheng.util.ResultUtil;

@ControllerAdvice
public class MyExceptionHandler {

    /**
     * 全局异常处理
     * 
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResultInfo<Object> handle(Exception e) {
        if (e instanceof MyException) {
            return ResultUtil.error(((MyException) e).getCode(), e.getMessage());
        }else {
            //String errorInfo = e.getCause().toString().substring(e.getCause().toString().lastIndexOf(":") + 1);
            return ResultUtil.error(ResultEnum.UNKOWN_ERROR,e.getMessage());
        }
    }

    /**
     * MyException 异常处理
     * 
     * @param e
     * @return
     */
    @ExceptionHandler(value = MyException.class)
    @ResponseBody
    public ResultInfo<Object> MyExceptionHandle(MyException e) {
        if (e instanceof MyException) {
            return ResultUtil.error(((MyException) e).getCode(), e.getMessage());
        } else {
            return ResultUtil.error(ResultEnum.UNKOWN_ERROR,e.getMessage());
        }
    }

}
package com.zhangheng.exception;

import com.zhangheng.common.ResultEnum;

public class MyException extends RuntimeException {

    /**
     * 
     */
    private static final long serialVersionUID = -5126369846766704829L;
    private Integer code;

    public MyException(ResultEnum resultEnum) {
        super(resultEnum.getMsg());
        this.code = resultEnum.getCode();
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

}

一些辅助工具类

package com.zhangheng.util;

import com.zhangheng.common.ResultEnum;
import com.zhangheng.common.ResultInfo;

/**
 * 接口统一返回标准数据格式
 * @author zhangh
 * @date 2018年4月27日上午9:13:36
 */
public class ResultUtil {

    /**
     * 调用成功
     * @param obj 返回的数据
     * @return
     */
    public static ResultInfo<Object> success(ResultEnum resultEnum,Object obj) {
        return new ResultInfo<Object>(true, resultEnum.getCode(), resultEnum.getMsg(), obj);
    }

    /**
     * 调用成功 不需要返回数据 只返回状态
     * @return
     */
    public static ResultInfo<Object> success(ResultEnum resultEnum) {
        return new ResultInfo<Object>(true, resultEnum.getCode(), resultEnum.getMsg(), null);
    }

    /**
     * 调用失败
     * @param code 错误码
     * @param msg 错误信息
     * @return
     */
    public static ResultInfo<Object> error(Integer code, String msg) {
        return new ResultInfo<Object>(false, code, msg, null);
    }

    /**
     * 从先定义好的枚举类中返回接口信息
     * @param resultEnum
     * @return
     */
    public static ResultInfo<Object> error(ResultEnum resultEnum) {
        return new ResultInfo<Object>(false, resultEnum.getCode(), resultEnum.getMsg(), null);
    }

    /**
     * 重写之前已经实例化的枚举信息 不懂的别随意用
     * @author zhangh
     * @date 2018/4/27 10:08:22
     * @param resultEnum
     * @return
     */
    public static ResultInfo<Object> error(ResultEnum resultEnum,String msg) {
        return new ResultInfo<Object>(false, resultEnum.getCode(), msg, null);
    }
}
package com.zhangheng.common;

/**
 * 封装接口返回状态结果集
 * 
 * @author zhangh
 * @date 2018年4月26日下午2:34:37
 */
public enum ResultEnum {
    SUCCESS(1, "成功"), 
    PARAM_ERROR(-1, "参数异常"), 
    AUTHORIZATION_ERROR(-2, "对不起,您的权限不够"), 
    DADABASE_ERROR(-3,"网络超时"), 
    UNKOWN_ERROR(-99, "未知错误");//这里的信息以程序捕获的具体异常信息为主

    private Integer code;
    private String msg;

    ResultEnum(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

}

以上就是SpringBoot 集成自定义注解的全部步骤了,如有不懂的请留言。

猜你喜欢

转载自blog.csdn.net/forever_insist/article/details/80305788