//AOP切面 :多个切面时,@Order(i)注解来标识切面的优先级。i的值越小,优先级越高
@Order(6)
@Aspect
@Component
public class ControllerAspect {
@Autowired
private AmqpTemplate template;
@Pointcut("execution(public * com.vanrui.controller.*.*(..))")
public void log(){}
//统计请求的处理时间
ThreadLocal<Long> startTime = new ThreadLocal<>();
ThreadLocal<String> url = new ThreadLocal<>();
ThreadLocal<String> reqType = new ThreadLocal<>();
ThreadLocal<String> reqIp = new ThreadLocal<>();
@Before("log()")
public void doBefore(JoinPoint joinPoint) throws Throwable{
startTime.set(System.currentTimeMillis());
//接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
url.set(request.getRequestURL().toString());
reqType.set(request.getMethod());
reqIp.set(getIpAddr(request));
}
@AfterReturning(returning = "ret" , pointcut = "log()")
public void doAfterReturning(Object ret){
//处理完请求后,返回内容
Long time = System.currentTimeMillis()-startTime.get();
RxRequestLog rxRequestLog = new RxRequestLog();
rxRequestLog.setUrl(url.get().split("/api/")[1]);
rxRequestLog.setReqType(reqType.get());
rxRequestLog.setExeTime(time.intValue());
rxRequestLog.setReqTime(new Date(startTime.get()));
rxRequestLog.setReqIp(reqIp.get());
if (ret instanceof ResponseDTO) {
ResponseDTO responseDTO = (ResponseDTO)ret;
rxRequestLog.setResult(responseDTO.getCode());
}
template.convertAndSend(ConstantUtil.REQ_LOG_QUEUE, rxRequestLog);
}
/**
* 获取目标主机的ip
*
* @param request
* @return
*/
private String getRemoteHost(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
//多次反向代理后会有多个ip值,第一个ip才是真实ip
int index = ip.indexOf(",");
if(index != -1){
return ip.substring(0,index);
}else{
return ip;
}
}
ip = request.getHeader("X-Real-IP");
if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){
return ip;
}
ip = request.getRemoteAddr();
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
}
/**
* 获取用户真实IP地址,不使用request.getRemoteAddr()的原因是有可能用户使用了代理软件方式避免真实IP地址,
* 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值
*
* @return ip
*/
private String getIpAddr(HttpServletRequest request) {
String[] ipHeaderArray = new String[]{"x-forwarded-for","Proxy-Client-IP","WL-Proxy-Client-IP","HTTP_CLIENT_IP","HTTP_X_FORWARDED_FOR","X-Real-IP"};
String ip = null;
for (String ipHeader : ipHeaderArray) {
ip = request.getHeader(ipHeader);
if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
return ip.split(",")[0];
}
}
ip = request.getRemoteAddr();
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
}
}
辅助类:
@Data
@ApiModel
public class RxRequestLog implements Serializable {
/**
* 系统id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@ApiParam(value="系统id")
private Integer id;
/**
* 请求IP
*/
@ApiParam(value="请求IP")
private String reqIp;
/**
* 请求地址
*/
@ApiParam(value="请求地址")
private String url;
/**
* 请求时间
*/
@ApiParam(value="请求时间")
private Date reqTime;
/**
* 请求方式
*/
@ApiParam(value="请求方式")
private String reqType;
/**
* 执行时长(毫秒)
*/
@ApiParam(value="执行时长(毫秒)")
private Integer exeTime;
/**
* 请求结果(0-成功, 1-失败)
*/
@ApiParam(value="请求结果(0-成功, 1-失败)")
private Integer result;
private static final long serialVersionUID = 1L;
}
本文介绍了如何在SpringBoot应用中记录请求URL的日志,并通过辅助类实现实时推送到RabbitMQ的消息队列,以实现日志的集中管理和分析。
3910

被折叠的 条评论
为什么被折叠?



