package com.huaheng.framework.aspectj; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.huaheng.common.constant.QuantityConstant; 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 okhttp3.Request; import okhttp3.Response; 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.json.JSONException; 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; } } /** * 记录响应头信息 **/ 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); } } /** * 根据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"); if(address!=null){ log.setResponseBy(address.getParam().toUpperCase()); }else { log.setResponseBy("XX"); } } catch (Exception e) { e.printStackTrace(); } } /** * 记录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; } /**记录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(Request request, String body,String warehouseCode){ ApiLog log = new ApiLog(); try { log.setApiMethod(request.method()); log.setUrl(request.url().toString()); log.setRequestTime(new Date()); parseUrl(log, request.url().url(),warehouseCode); log.setRequestHeader(request.headers().toString()); log.setRequestBody(body); }catch (Exception e){ e.printStackTrace(); } return log; } /**记录响应头信息**/ public static void finishApiLog(ApiLog log, Response response, 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(response.code())); //响应头 log.setResponseHeader(response.headers().toString()); AjaxResult ajaxResult = null; try{ ajaxResult = JSON.parseObject(body, AjaxResult.class); }catch(Exception ex){ body = JSON.parse(body).toString(); ajaxResult = JSON.parseObject(body, AjaxResult.class); } log.setRetCode(String.valueOf(ajaxResult.getCode())); }catch (Exception e){ e.printStackTrace(); }finally { try { if (StringUtils.isNotEmpty(log.getResponseBody()) && log.getResponseBody().length() > 2001) { log.setResponseBody(log.getResponseBody().substring(0, 2000) + "\n太长了...后面省略。\n" + log.getResponseBody().length()); } }catch (Exception e){ } SpringUtils.getBean(ApiLogAspect.class).saveApiLog(log); } } /**根据url,从address表中判断调用的去向**/ public static void parseUrl(ApiLog log, URL url){ 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(), "CS0001"); log.setApiName(apiName); log.setRequestFrom("WMS"); log.setResponseBy(address.getParam().toUpperCase()); }catch (Exception e){ e.printStackTrace(); } } /** * 记录响应头信息 **/ 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")); if(StringUtils.isNotEmpty(body)){ AjaxResult json = JSON.parseObject(body, AjaxResult.class); log.setRetCode(String.valueOf(json.getCode())); }else{ log.setRetCode("400"); } } 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) { String str=JSONObject.toJSONString(point.getArgs()[0]); log=parseJson(str,log); log.setRequestBody(str); 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(); } } /** * 解析json * @param str * @param log */ public ApiLog parseJson(String str,ApiLog log){ try { org.json.JSONObject object=new org.json.JSONObject(str); Iterator<String> it = object.keys(); while (it.hasNext()) { String json_key = it.next(); Object json_value = object.get(json_key); if(json_key.equals("warehouseCode")){ log.setWarehouseCode(json_value.toString()); break; } if(json_value.getClass().getSimpleName().equals("JSONObject")){ parseJson(json_value.toString(),log); } /*if (json_value!=null){ System.out.println("CCC"+"json_key:" + json_key + ",json_value:" + json_value + ",类型:" + json_value.getClass().getSimpleName()); }*/ } } catch (JSONException e) { String replaceAll = str.replaceAll("\\\\", ""); String replaceAll1=replaceAll.substring(1,replaceAll.length()-1); try{ List<String> list =JSON.parseArray(replaceAll1,String.class); String strnew=StringUtils.join(list,","); log=parseJson(strnew,log); }catch (Exception e1){ log=parseJson(replaceAll1,log); } } return log; } }