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;
}
}