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