//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; }