SpringAOP自定义注解日志
1.在SpringMVC.xml开启aop注解
<!-- aop面向切面编程 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
2. 新建一个annotation类
package com.yc.util;
import java.lang.annotation.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* AOP自定义注解
* @author lam
* 2018年11月7日
*/
@Target({ElementType.METHOD})//方法
@Retention(RetentionPolicy.RUNTIME)//在运行时有效(即运行时保留)
@Documented
public @interface SystemControllerLog {
/**
* 日志描述
* @return
*/
String description() default "";
}
3.新建一个SystemLogAspect类---可以实现对具体参数的记录(例子只是获取单个字段,因为项目关系,查集合就不需要记录到具体参数,查询单个就可以记录到具体参数),还可以实现对不加(@SystemControllerLog)注解的不记录
package com.yc.action;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.yc.model.Log;
import com.yc.service.LogService;
import com.yc.util.SystemControllerLog;
import java.lang.reflect.Method;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Date;
import java.util.Enumeration;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
* 日志切面
*
* @author lam
* @create 2018年11月7日
**/
@Aspect
@Component
public class SystemLogAspect {
@Resource
private LogService logService;
//Controller层切点(AspectJ的execution表达式)
@Pointcut("execution(* com.yc.action..*.*(..))")
public void controllerAspect() {}
@After("controllerAspect()")
public void controllerAspect(JoinPoint joinPoint) throws Exception{
HttpServletRequest request =
((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// 请求的IP
String ip = request.getHeader("x-forwarded-for");
if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
// 多次反向代理后会有多个ip值,第一个ip才是真实ip
if (ip.indexOf(",") != -1) {
ip = ip.split(",")[0];
}
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
// 获取本地ip地址
if (ip.equals("127.0.0.1")) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
@SuppressWarnings("rawtypes")
Enumeration allNetInterfaces = null;
try {
allNetInterfaces = NetworkInterface.getNetworkInterfaces();
} catch (java.net.SocketException e) {
e.printStackTrace();
}
while (allNetInterfaces.hasMoreElements()) {
NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
@SuppressWarnings("rawtypes")
Enumeration addresses = netInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
inet = (InetAddress) addresses.nextElement();
if (inet != null && inet instanceof Inet4Address) {
if (inet.getHostAddress().equals("127.0.0.1")) {
continue;
}
ip = inet.getHostAddress();
}
}
}
}
//日志
Log log =new Log();
log.setIp(ip);
log.setDate(new Date());
//log.setName("test");//获取用户id
//log.setCompanyId(99);//获取用户公司id
//获取参数
Object[] arguments = joinPoint.getArgs();
String params = JSON.toJSONString(arguments);
JSONArray json = JSONArray.parseArray(params);//转换为json数组,可获取具体的字段
String isNull= null;
if(params.indexOf("companyName") != -1) {
for(int i=0;i < json.size();i++) {
isNull= json.getJSONObject(i).getString("companyName");
break;
}
}else {
}
//判断是否记录单个参数
if (isNull !=null) {
//判断是否切面(是否加SystemControllerLog注解)
if(getControllerMethodDescription(joinPoint) !=null) {
log.setOperation(getControllerMethodDescription(joinPoint)+"--"+isNull);//带参数(对单个参数增删改生效)
}else {
return;
}
}else {
//判断是否切面(是否加SystemControllerLog注解)
if(getControllerMethodDescription(joinPoint) !=null) {
log.setOperation(getControllerMethodDescription(joinPoint));//不带参(查询等等)
}else {
return;
}
}
int len =logService.insert(log);
}
//获取方法
@SuppressWarnings("rawtypes")
public static String getControllerMethodDescription(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[] methods = targetClass.getMethods(); // 获取类对象的所有方法
String description = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) { // 比较方法名相同
Class[] clazzs = method.getParameterTypes();
// 参数长度
if (clazzs.length == arguments.length) {
//判断是否切面(是否加SystemControllerLog注解)
if(method.getAnnotation(SystemControllerLog.class) !=null) {
description = method.getAnnotation(SystemControllerLog.class).description();
break;
}else {
return null;
}
}
}
}
return description;
}
}
4.新建测试类(不加注解没有记录)
/**
* 测试带参数
* @param company
* @return
*/
@ResponseBody
@RequestMapping("test.do")
@SystemControllerLog(description="测试带参数")
public JSONObject test(CustomerCompany company) {
JSONObject jsonObject =new JSONObject();
return jsonObject;
}
/**
* 测试不带参数
* @return
*/
@ResponseBody
@RequestMapping("test1.do")
@SystemControllerLog(description="测试不带参数")
public JSONObject test1() {
JSONObject jsonObject =new JSONObject();
return jsonObject;
}
5.运行效果
