1. 程式人生 > >SpringBoot 整合AOP 自定義註解

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 整合自定義註解的全部步驟了,如有不懂的請留言。