com.yanyun.log.aop.DealAopSendMsg Maven / Gradle / Ivy
package com.yanyun.log.aop;
import com.yanyun.auth.dto.ResultDto;
import com.yanyun.log.model.LogModel;
import com.yanyun.log.service.MQSendEventService;
import com.yanyun.log.utils.LogUtils;
import com.yanyun.log.websocket.LogSocketConfig;
import io.kubemq.sdk.basic.ServerAddressNotSuppliedException;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
/**
* 做AOP拦截,拦截带有Swagger注解的方法,统计用户行为
* 数据的组装在此处做处理
*/
@Aspect
public class DealAopSendMsg {
//日志
private static final Logger logger = LoggerFactory.getLogger(DealAopSendMsg.class);
//mq发送消息的组件
private MQSendEventService mqSendEventService;
//连接池组件
private ExecutorService senderThreadPool;
//远程调用组件
private RestTemplate restTemplate;
private String ip2RegionAddr;
public DealAopSendMsg(MQSendEventService mqSendEventService, ExecutorService senderThreadPool, RestTemplate restTemplate,String ip2RegionAddr) {
this.mqSendEventService = mqSendEventService;
this.senderThreadPool = senderThreadPool;
this.restTemplate = restTemplate;
this.ip2RegionAddr = ip2RegionAddr;
}
//拦截带有apiOperation注解的方法进行统计
@Pointcut("@annotation(io.swagger.annotations.ApiOperation)")
public void pointCut() {
}
/**
* 做环绕通知,处理拦截的用户行为
*
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("pointCut()")
public Object deal(ProceedingJoinPoint joinPoint) throws Throwable {
//执行结果
Object proceed = null;
//日志对象
LogModel logModel = new LogModel();
try {
proceed = joinPoint.proceed();
if (proceed instanceof ResultDto) {
Integer code = ((ResultDto) proceed).getCode();
if (code != null && code == 200) {
logModel.setOptionResult("成功");
} else {
logModel.setOptionResult("失败");
}
} else {
//如果不是固定的返回值,那么直接返回成功
logModel.setOptionResult("成功.");
}
} catch (Exception e) {
logModel.setOptionResult("异常");
}
//获取用户的登录信息
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (null == authentication || authentication instanceof AnonymousAuthenticationToken) {
//如果是匿名登录
logModel.setUsername("匿名用户");
} else {
//是登录的用户
logModel.setUsername((String) authentication.getPrincipal());
}
//获取请求对象
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//从请求中获取Ip
String ip = LogUtils.getIp(request);
logModel.setIp(ip);
//从请求中获取浏览器类型
String browser = LogUtils.getBrowser(request);
logModel.setBrowser(browser);
//用户操作时间
long optionTime = System.currentTimeMillis();
logModel.setOptionTime(optionTime);
//采集用户操作
if (joinPoint.getSignature() instanceof MethodSignature) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取操作路径
String path = joinPoint.getTarget().getClass().getName() + "." + signature.getName();
logModel.setClassPath(path);
ApiOperation annotation = signature.getMethod().getAnnotation(ApiOperation.class);
//如果标记了swagger注解说明了方法,那么进行采集数据
if (annotation != null && !StringUtils.isEmpty(annotation.value())) {
//获取操作类型
logModel.setOptionType(annotation.value());
}
if (annotation != null && !StringUtils.isEmpty(annotation.notes())) {
//获取详细操作
logModel.setOption(annotation.notes());
}
}
//异步线程执行 采集用户行为数据到MQ
senderThreadPool.submit(() -> {
//发送数据到MQ
try {
//获取ip对应的区域
String area = getArea(ip);
logModel.setArea(area);
//将日志消息发布到Channel中
mqSendEventService.sendLogInfoToMqEvent(logModel);
} catch (IOException e) {
e.printStackTrace();
} catch (ServerAddressNotSuppliedException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
});
return proceed;//返回执行结果
}
/**
* 获取Ip对应的地址区域
* @param ip
* @return
*/
private String getArea(String ip) {
if (!StringUtils.isEmpty(ip) && ip.equalsIgnoreCase("0:0:0:0:0:0:0:1")){
return "局域网";
}
//远程调用,并发送数据
try {
String ipAddre = restTemplate.getForObject(ip2RegionAddr+"?ip="+ip, String.class);
if (!StringUtils.isEmpty(ipAddre)) {
String[] split = ipAddre.split(",");
if (split.length > 1) {
//如果得到了正确的解析,那么地址为
String ipAddr = split[1];
//空行截取
String[] s = ipAddr.split(" ");
return s[0];
} else {
return null;
}
}
return null;
} catch (Exception e) {
e.printStackTrace();
logger.error("获取Ip对应的区域地址失败,请检查网络服务");
return null;
}
}
}