package com.huaheng.framework.aspectj; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.huaheng.common.utils.ServletUtils; import com.huaheng.common.utils.StringUtils; import com.huaheng.common.utils.security.ShiroUtils; import com.huaheng.common.utils.spring.SpringUtils; import com.huaheng.framework.aspectj.lang.annotation.ApiLogger; import com.huaheng.framework.web.domain.AjaxResult; import com.huaheng.pc.config.address.domain.Address; import com.huaheng.pc.config.address.service.AddressService; import com.huaheng.pc.monitor.apilog.domain.ApiLog; import com.huaheng.pc.monitor.apilog.service.IApiLogService; import org.apache.commons.lang.exception.ExceptionUtils; 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.http.HttpHeaders; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.net.HttpURLConnection; import java.net.URL; import java.util.*; /** * Api调用日志记录处理 * * @author huaheng */ @Aspect @Component @EnableAsync public class ApiLogAspect { private static final Logger log = LoggerFactory.getLogger(ApiLogAspect.class); private static IApiLogService apiLogService; private static AddressService addressService; @Autowired public void setApiLogService(IApiLogService apiLogService) { ApiLogAspect.apiLogService = apiLogService; } @Autowired public void setAddressService(AddressService addressService) { ApiLogAspect.addressService = addressService; } // 配置织入点 @Pointcut("@annotation(com.huaheng.framework.aspectj.lang.annotation.ApiLogger)") public void logPointCut() { } @Around("logPointCut() && @annotation(apiLogger)") public Object around(ProceedingJoinPoint point, ApiLogger apiLogger) throws Throwable { if ("WMS".equalsIgnoreCase(apiLogger.from())) //实际上静态方法上的Aop注解无法拦截到 return aroundWms2XXX(point, apiLogger); else return aroundXXX2Wms(point, apiLogger); } /** * 处理xxx调用wms接口的日志 **/ private Object aroundXXX2Wms(ProceedingJoinPoint point, ApiLogger apiLogger) { Object ret = null; ApiLog log = initApiLog(apiLogger, point); try { ret = point.proceed(); } catch (Exception e) { setApiLogException(log, e); ret = AjaxResult.error(e.getMessage()); } finally { finishApiLog(log, ret); return ret; } } /** * 处理WMS调用xxx接口的日志 **/ private Object aroundWms2XXX(ProceedingJoinPoint point, ApiLogger apiLogger) { Object ret = null; ApiLog log = new ApiLog(); HttpURLConnection connection = null; String body = null; try { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); connection = (HttpURLConnection) point.getArgs()[0]; body = (String) point.getArgs()[1]; initApiLog(connection, body, ShiroUtils.getWarehouseCode()); } catch (Exception e) { } try { ret = point.proceed(); } catch (Exception e) { setApiLogException(log, e); throw e; } finally { if (ret != null) { finishApiLog(log, connection, ret.toString()); } return ret; } } /** * 记录WMS调用外接口的请求信息 * 在HttpUtils.bodypost方法中直接调用本类static方法 **/ public static ApiLog initApiLog(HttpURLConnection connection, String body, String warehouseCode) { ApiLog log = new ApiLog(); try { log.setApiMethod(connection.getRequestMethod()); log.setUrl(connection.getURL().toString()); log.setRequestTime(new Date()); parseUrl(log, connection.getURL(), warehouseCode); //请求头 Set<String> keySet = connection.getRequestProperties().keySet(); ArrayList<String> headerList = new ArrayList<>(); Iterator<String> it = keySet.iterator(); while (it.hasNext()) { String name = it.next(); String header = connection.getRequestProperty(name); headerList.add(name + ": " + header); } log.setRequestHeader(org.apache.commons.lang3.StringUtils.join(headerList, "\n")); log.setRequestBody(body); } catch (Exception e) { e.printStackTrace(); } return log; } /** * 记录WMS调用外接口的请求信息 * 在HttpUtils.bodypost方法中直接调用本类static方法 **/ public static ApiLog initApiLog(String Method, String url, String body, HttpHeaders headers, String warehouseCode) { ApiLog log = new ApiLog(); try { URL url1 = new URL(url); log.setApiMethod(Method); log.setUrl(url); log.setRequestTime(new Date()); parseUrl(log, url1, warehouseCode); //请求头 Set<String> keySet = headers.keySet(); ArrayList<String> headerList = new ArrayList<>(); Iterator<String> it = keySet.iterator(); while (it.hasNext()) { String name = it.next(); String header = String.valueOf(headers.getContentType()); headerList.add(name + ": " + header); } log.setRequestHeader(org.apache.commons.lang3.StringUtils.join(headerList, "\n")); log.setRequestBody(body); } catch (Exception e) { e.printStackTrace(); } return log; } /** * 根据url,从address表中判断调用的去向 **/ public static void parseUrl(ApiLog log, URL url, String warehouseCode) { try { String[] spList = url.toString().split("/"); String apiName = spList[spList.length - 1]; int index = url.toString().lastIndexOf(apiName); String addUrl = url.toString().substring(0, index); Address address = addressService.getAddressByUrl(url.toString(), warehouseCode); log.setApiName(apiName); log.setRequestFrom("WMS"); log.setResponseBy(address.getParam().toUpperCase()); } catch (Exception e) { e.printStackTrace(); } } /** * 记录响应头信息 **/ public static void finishApiLog(ApiLog log, HttpURLConnection connection, String body) { try { log.setResponseBody(body); log.setResponseTime(new Date()); Long duration = log.getResponseTime().getTime() - log.getRequestTime().getTime(); log.setDuration(duration.intValue()); log.setHttpCode(String.valueOf(connection.getResponseCode())); //响应头 Set<String> keyset = connection.getHeaderFields().keySet(); ArrayList<String> headerList = new ArrayList<>(); Iterator<String> it = keyset.iterator(); while (it.hasNext()) { String name = it.next(); String header = connection.getHeaderField(name); if (name == null || "".equals(name)) //第一行没有name //HTTP/1.1 200 OK headerList.add(header); else headerList.add(name + ": " + header); } log.setResponseHeader(org.apache.commons.lang3.StringUtils.join(headerList, "\n")); AjaxResult json = JSON.parseObject(body, AjaxResult.class); log.setRetCode(String.valueOf(json.getCode())); } catch (Exception e) { e.printStackTrace(); } finally { SpringUtils.getBean(ApiLogAspect.class).saveApiLog(log); } } /** * 记录响应头信息 **/ public static void finishApiLog(ApiLog log, HttpHeaders headers, String body) { try { log.setResponseBody(body); log.setResponseTime(new Date()); Long duration = log.getResponseTime().getTime() - log.getRequestTime().getTime(); log.setDuration(duration.intValue()); log.setHttpCode(String.valueOf(200)); //响应头 Set<String> keyset = headers.keySet(); ArrayList<String> headerList = new ArrayList<>(); Iterator<String> it = keyset.iterator(); while (it.hasNext()) { String name = it.next(); String header = String.valueOf(headers.getContentType()); if (name == null || "".equals(name)) //第一行没有name //HTTP/1.1 200 OK headerList.add(header); else headerList.add(name + ": " + header); } log.setResponseHeader(org.apache.commons.lang3.StringUtils.join(headerList, "\n")); AjaxResult json = JSON.parseObject(body, AjaxResult.class); log.setRetCode(String.valueOf(json.getCode())); } catch (Exception e) { e.printStackTrace(); } finally { SpringUtils.getBean(ApiLogAspect.class).saveApiLog(log); } } private ApiLog initApiLog(ApiLogger apiLogger, ProceedingJoinPoint point) { ApiLog log = new ApiLog(); try { log.setRequestTime(new Date()); log.setRequestFrom(apiLogger.from()); log.setResponseBy(apiLogger.to()); log.setApiName(apiLogger.apiName()); HttpServletRequest request = ServletUtils.getRequest(); String qryStr = request.getQueryString(); String url = request.getRequestURL().toString(); if (StringUtils.isNotEmpty(qryStr)) url = url + "?" + qryStr; log.setUrl(url); log.setApiMethod(request.getMethod()); log.setIp(request.getRemoteAddr()); rebuildRequestHeader(log); rebuildRequestBody(log, request); //如果reqeust中取不到post参数,就从接口方法参数中取json对象 if (StringUtils.isEmpty(log.getRequestBody())) rebuildRequestBody(log, point); } catch (Exception e) { e.printStackTrace(); } return log; } private void finishApiLog(ApiLog log, Object ret) { try { rebuildResponseHeader(log); rebuildResponseBody(log, ret); log.setResponseTime(new Date()); Long duration = log.getResponseTime().getTime() - log.getRequestTime().getTime(); log.setDuration(duration.intValue()); HttpServletResponse resp = ServletUtils.getResponse(); log.setHttpCode(String.valueOf(resp.getStatus())); if (ret instanceof AjaxResult) { int retCode = ((AjaxResult) ret).getCode(); log.setRetCode(String.valueOf(retCode)); } } catch (Exception e) { e.printStackTrace(); } finally { saveApiLog(log); } } public static void setApiLogException(ApiLog log, Exception e) { try { String exception = ExceptionUtils.getFullStackTrace(e); String shortExpInfo = e.getMessage() + "\n" + org.apache.commons.lang3.StringUtils.left(exception, 1000); log.setException(shortExpInfo); } catch (Exception ex) { ex.printStackTrace(); } } private void rebuildRequestHeader(ApiLog log) { try { HttpServletRequest req = ServletUtils.getRequest(); Enumeration names = req.getHeaderNames(); ArrayList<String> headerList = new ArrayList<>(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); String header = req.getHeader(name); headerList.add(name + ": " + header); } String headers = org.apache.commons.lang3.StringUtils.join(headerList, "\n"); log.setRequestHeader(headers); } catch (Exception e) { e.printStackTrace(); } } /** * 先从post参数中构造request body */ private void rebuildRequestBody(ApiLog log, HttpServletRequest request) { try { Set<String> keySet = request.getParameterMap().keySet(); Iterator<String> it = keySet.iterator(); StringBuffer sbf = new StringBuffer(); while (it.hasNext()) { String key = it.next(); String value = request.getParameter(key); sbf.append(key).append("=").append(value); if (it.hasNext()) sbf.append("&"); } log.setRequestBody(sbf.toString()); } catch (Exception e) { e.printStackTrace(); } } /** * 根据接口中的参数构造request body */ private void rebuildRequestBody(ApiLog log, ProceedingJoinPoint point) { try { if (point.getArgs().length == 1) { log.setRequestBody(JSONObject.toJSONString(point.getArgs()[0])); return; } MethodSignature m = (MethodSignature) point.getSignature(); HashMap<String, Object> map = new HashMap<>(); Object[] args = point.getArgs(); for (int i = 0; i < m.getParameterNames().length; i++) { String name = m.getParameterNames()[i]; // Class type = m.getParameterTypes()[i]; map.put(name, args[i]); } if (!map.isEmpty()) log.setRequestBody(JSONObject.toJSONString(map)); } catch (Exception e) { e.printStackTrace(); } } private void rebuildResponseHeader(ApiLog log) { try { HttpServletResponse resp = ServletUtils.getResponse(); Collection names = resp.getHeaderNames(); ArrayList<String> headerList = new ArrayList<>(); Iterator<String> it = names.iterator(); while (it.hasNext()) { String name = it.next(); String header = resp.getHeader(name); headerList.add(name + ": " + header); } String headers = org.apache.commons.lang3.StringUtils.join(headerList, "\n"); log.setResponseHeader(headers); } catch (Exception e) { e.printStackTrace(); } } private void rebuildResponseBody(ApiLog log, Object ret) { try { log.setResponseBody(JSONObject.toJSON(ret).toString()); } catch (Exception e) { e.printStackTrace(); } } @Async public void saveApiLog(ApiLog log) { try { apiLogService.saveOrUpdate(log); } catch (Exception e) { e.printStackTrace(); } } }