切入点表达式:@Pointcut()括号内表达式的作用
package com.cy.pj.common.aspect;
@Slf4j
@Aspect
@Component
public class SysLogAspect {
//@Pointcut首先定义一个切点,bean(bean对象的名字)为一种切入点表达式(这个表达式定义了那个那些bean 对象的方法要进行功能扩展)"bean(sysUserServiceImpl)中的sysUserServiceImpl为交给bean创建对象的名"
//@Pointcut("bean(sysUserServiceImpl)")
//这是写了一个注解,以注解方式选择要操作的方法
@Pointcut("@annotation(com.cy.pj.common.annotation.RequiredLog)")
public void doLogPointCut() {}
//@Around注解描述的方法为一个通知方法(服务增益方法),jp为连接点
@Around("doLogPointCut()")
public Object doLogAround(ProceedingJoinPoint jp)throws Throwable {
//1.记录方法开始执行时间
try {
long t1=System.currentTimeMillis();
log.info("start:{}",t1);
//2.执行目标方法
Object result=jp.proceed();//最终(中间还可以调用本类其它通知或其它切面的通知)会调用目标方法
//3.记录方法结束执行时间
long t2=System.currentTimeMillis();
log.info("after:{}",t2);
//4.将正常行为日志信息写入到数据库
saveUserLog(jp,(t2-t1));
//5.返回目标方法执行结果
return result;//目标方法的返回结果
}catch(Throwable e) {
log.error("目标方法执行时出现了异常:{}",e.getMessage());
throw e;
}
@Autowired
private SysLogService sysLogService;
/**记录用户行为的正常信息*/
private void saveUserLog(ProceedingJoinPoint jp,long time)throws Exception {
//1.获取用户行为日志
String ip=IPUtils.getIpAddr();
String username="cgb2005";//将来是登录用户的用户名
Date createdTime=new Date();
//获取操作名
String operation=getOperation(jp);
String method=getTargetClassMethod(jp);
//String params=Arrays.toString(jp.getArgs());//普通格式字符串
String params=new ObjectMapper().writeValueAsString(jp.getArgs());//json格式的参数
//2.封装用户行为日志(在内容中通过对象去实现)
SysLog log=new SysLog();
log.setIp(ip);
log.setUsername(username);
log.setCreatedTime(createdTime);
log.setOperation(operation);
log.setMethod(method);
log.setParams(params);
log.setTime(time);
//3.将用户行为日志持久化(将内存中对象信息写入到数据库)
sysLogService.saveObject(log);
}
/**获取目标方法的全限定名(目标类全名+方法名)*/
private String getTargetClassMethod(ProceedingJoinPoint jp) {
//1.获取目标对象类型
Class<?> targetCls=jp.getTarget().getClass();
//2.获取目标对象类型的类全名
String targetClsName=targetCls.getName();
//3.获取目标方法名
//3.1获取方法签名(方法签名对象中封装了方法相关信息)
MethodSignature ms=(MethodSignature)jp.getSignature();
//3.2基于方法签名获取方法名
String methodName=ms.getName();
//4.构建方法的全限定名并返回
return targetClsName+"."+methodName;
}
/**获取目标方法上@ReqiredLog注解中定义的operation名字 获取注解value的值*/
private String getOperation(ProceedingJoinPoint jp)throws Exception {
//1.获取目标对象类型
Class<?> targetCls=jp.getTarget().getClass();
//2.获取目标方法对象
//2.1获取方法签名信息
MethodSignature ms=(MethodSignature)jp.getSignature();
//2.2获取方法对象
//假如希望无论是jdk代理还是cglib代理,我们让method变量指向的都是目标对象中的方法对象,那如何实现?
Method method=targetCls.getDeclaredMethod(ms.getName(), ms.getParameterTypes());
//3.获取方法上的reqiredLog注解对象
RequiredLog requiredLog=method.getAnnotation(RequiredLog.class);
//4.获取注解中的operation的值.
if(requiredLog==null)return "operation";
return requiredLog.operation();
}
}
获取IP地址的工具类
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
public class IPUtils {
private static Logger logger=LoggerFactory.getLogger(IPUtils.class);
public static String getIpAddr() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String ip = null;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} catch (Exception e) {
logger.error("IPUtils ERROR ", e);
}
return ip;
}
}~~~~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。