自定義註解,使用切面(Aspect)記錄操作日誌

1、註解的生命週期

註解的生命週期有 3 種策略,定義在 RetentionPolicy 枚舉中。

1)SOURCE:在源文件中有效,被編譯器丟棄。

2)CLASS:在編譯器生成的字節碼文件中有效,但在運行時會被處理類文件的 JVM 丟棄。

3)RUNTIME:在運行時有效。這也是註解生命週期中最常用的一種策略,它允許程序通過反射的方式訪問註解,並根據註解的定義執行相應的代碼。

2、註解裝飾的目標

註解的目標定義了註解將適用於哪一種級別的 Java 代碼上,有些註解只適用於方法,有些只適用於成員變量,有些只適用於類,有些則都適用。

截止到 Java 9,註解的類型一共有 11 種,定義在 ElementType 枚舉中。

1)TYPE:用於類、接口、註解、枚舉

2)FIELD:用於字段(類的成員變量),或者枚舉常量

3)METHOD:用於方法

4)PARAMETER:用於普通方法或者構造方法的參數

5)CONSTRUCTOR:用於構造方法

6)LOCAL_VARIABLE:用於變量

7)ANNOTATION_TYPE:用於註解

8)PACKAGE:用於包

9)TYPE_PARAMETER:用於泛型參數

10)TYPE_USE:用於聲明語句、泛型或者強制轉換語句中的類型

11)MODULE:用於模塊

import java.lang.annotation.*;

/**
 * 操作日誌註解
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MethodLog {

    /**
     * 記錄操作描述
     *
     * @return
     */
    String remark() default "";

    /**
     * LogTypeFinal中定義的常量
     *
     * @return
     */
    String openType() default "";

    String mkbh() default "";

    String qqurl() default "";
}

 切面編程:

import com.alibaba.fastjson.JSONObject;
import com.sky.common.util.UserUtil;
import com.sky.service.log.LogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.*;


@Aspect
@Component
public class SystemLogAspect {

    private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);

    @Pointcut("@annotation(com.sky.rxyWeb.log.MethodLog)")
    public void logAspect() {
    }


    @Autowired
    HttpServletRequest request;

    @Autowired
    LogService logService;

    /**
     * 前置通知
     *
     * @param joinPoint
     */
    @Before("logAspect()")
    public void doBefore(JoinPoint joinPoint) {
    }

    /**
     * 後置通知
     *
     * @param joinPoint
     */
    @After("logAspect()")
    public void doAfter(JoinPoint joinPoint) {
    }

    /**
     * 後置返回通知
     *
     * @param joinPoint
     */
    @AfterReturning(value = "logAspect()", returning = "result")
    public void doAfterReturn(JoinPoint joinPoint, Object result) {

        try {
            //result 結果返回的內容
            if (null == result ) {
                return;
            }
//            String signature = joinPoint.getSignature().toString();  // 獲取方法簽名
//            if (signature.contains("ExampleForLogs.selectYQLists")) {
//
//            }
            //保存日誌信息
            if (result instanceof JSONObject) {
                JSONObject jsonObject = (JSONObject) result;
                logService.insertLog(jsonObject.getJSONObject("loginfo"));
            }else{
                JSONObject jsonObject=new JSONObject();
                MethodLog methodLog = this.getMethodRemark(joinPoint);
                jsonObject.put("ywlx",methodLog.openType());
                jsonObject.put("mkbh",methodLog.mkbh());
                jsonObject.put("rzbt",methodLog.remark());
                jsonObject.put("qqurl",methodLog.qqurl());
                jsonObject.put("czipdz",this.getRequestIP(request));
                jsonObject.put("czrbh",UserUtil.getUserInfo("YHBH"));
                logService.insertLog(jsonObject);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 異常通知 用於攔截service層記錄異常日誌
     *
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(pointcut = "logAspect()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {

    }
    /**
     * 獲取方法的中文備註____用於記錄用戶的操作日誌描述
     *
     * @param joinPoint
     * @return
     * @throws Exception
     */
    private MethodLog getMethodRemark(JoinPoint joinPoint) throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();

        Class targetClass = Class.forName(targetName);
        Method[] method = targetClass.getMethods();
        for (Method m : method) {
            if (m.getName().equals(methodName)) {
                Class[] tmpCs = m.getParameterTypes();
                if (tmpCs.length == arguments.length) {
                    MethodLog methodCache = m.getAnnotation(MethodLog.class);
                    if (methodCache != null && !("").equals(methodCache.remark())) {
                        return methodCache;
                    }
                    break;
                }
            }
        }
        return null;
    }
    /**
     * 獲取參數request
     *
     * @param point
     * @return
     */
    private HttpServletRequest getRequest(JoinPoint point) {
        Object[] args = point.getArgs();
        for (Object obj : args) {
            if (obj instanceof HttpServletRequest)
                return (HttpServletRequest) obj;
        }
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        return request;
    }

    /**
     *      * 獲取IP
     *      * @param request
     *      * @return
     *     
     */
    private String getRequestIP(HttpServletRequest request) {
        String ip = null;
        if (request.getHeader("x-forwarded-for") == null) {
            ip = request.getRemoteAddr();
        } else {
            ip = request.getHeader("x-forwarded-for");
        }
        return ip;
    }

    /**
     * 獲取前臺傳過來的參數
     *
     * @param request
     * @return
     */
    private Map getParam(HttpServletRequest request) {
        Map properties = request.getParameterMap();
        Map returnMap = new HashMap();
        Iterator entries = properties.entrySet().iterator();
        Map.Entry entry;
        String name = "";
        String value = "";
        while (entries.hasNext()) {
            entry = (Map.Entry) entries.next();
            name = (String) entry.getKey();
            Object valueObj = entry.getValue();
            value = null;
            if (null == valueObj) {
                value = "";
            } else if (valueObj instanceof String[]) {
                String[] values = (String[]) valueObj;
                for (int i = 0; i < values.length; i++) {
                    if (value == null)
                        value = (values[i] == null ? "" : values[i]);
                    else
                        value += "," + (values[i] == null ? "" : values[i]);
                }
            } else {
                value = valueObj.toString();
            }
            returnMap.put(name, value);
        }
        return returnMap;
    }
}

調用示例:

import com.alibaba.fastjson.JSONObject;
import com.sky.common.entity.base.ResultMap;
import com.sky.rxyWeb.log.MethodLog;
import com.sky.service.zdsj.XtzdsjService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/test")
public class ExampleForLogs {

    @Autowired
    private XtzdsjService xtzdsjService;

    /**
     * 查詢所有
     * @return
     */
    @GetMapping("/selectYQList")
    @MethodLog(remark = "XX信息查詢",openType = "")
    public JSONObject selectYQLists() {
        JSONObject result = new JSONObject();

        result.put("result", ResultMap.getResultMap(xtzdsjService.selectYQList()));

        //在result中存放日誌業務類型、模塊編號、日誌標題等信息可在切面中獲取
        JSONObject loginfo = new JSONObject();
        loginfo.put("rzbh", System.currentTimeMillis());//日誌編號
        loginfo.put("ywlx", "1");//業務類型
        loginfo.put("mkbh", "D13");//模塊編號
        loginfo.put("rzbt", "XXX查詢");//日誌標題
        loginfo.put("qqurl", "selectYQList");//請求url
        loginfo.put("czipdz", "XXXXXX");//操作IP地址
        loginfo.put("czrbh", "XXXXXX");//操作人編號
        result.put("loginfo", loginfo);
        return result;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章