切入点表达式:@Pointcut()括号内表达式的作用
package com.cy.pj.common.aspect;@Slf4j@Aspect@Componentpublic 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; } }~~~~