Blame view

src/main/java/com/huaheng/framework/aspectj/ApiLogAspect.java 18.3 KB
周峰 authored
1
2
3
4
package com.huaheng.framework.aspectj;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
xcq authored
5
import com.huaheng.common.constant.QuantityConstant;
周峰 authored
6
7
import com.huaheng.common.utils.ServletUtils;
import com.huaheng.common.utils.StringUtils;
8
import com.huaheng.common.utils.security.ShiroUtils;
肖超群 authored
9
import com.huaheng.common.utils.spring.SpringUtils;
周峰 authored
10
11
12
13
14
15
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;
xcq authored
16
17
import okhttp3.Request;
import okhttp3.Response;
周峰 authored
18
19
import org.apache.commons.lang.exception.ExceptionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
肖超群 authored
20
21
22
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
周峰 authored
23
24
25
26
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
肖超群 authored
27
28
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.annotation.Async;
周峰 authored
29
30
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
31
32
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
周峰 authored
33
34
35
36
37
38
39
40
41

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 * Api调用日志记录处理
肖超群 authored
42
 *
周峰 authored
43
44
45
46
 * @author huaheng
 */
@Aspect
@Component
肖超群 authored
47
48
@EnableAsync
public class ApiLogAspect {
周峰 authored
49
50
51
52
53
54
55
56
    private static final Logger log = LoggerFactory.getLogger(ApiLogAspect.class);

    private static IApiLogService apiLogService;

    private static AddressService addressService;


    @Autowired
肖超群 authored
57
    public void setApiLogService(IApiLogService apiLogService) {
周峰 authored
58
59
60
61
        ApiLogAspect.apiLogService = apiLogService;
    }

    @Autowired
肖超群 authored
62
    public void setAddressService(AddressService addressService) {
周峰 authored
63
64
65
66
67
        ApiLogAspect.addressService = addressService;
    }

    // 配置织入点
    @Pointcut("@annotation(com.huaheng.framework.aspectj.lang.annotation.ApiLogger)")
肖超群 authored
68
    public void logPointCut() {
周峰 authored
69
70
71
    }

    @Around("logPointCut()  && @annotation(apiLogger)")
肖超群 authored
72
73
    public Object around(ProceedingJoinPoint point, ApiLogger apiLogger) throws Throwable {
        if ("WMS".equalsIgnoreCase(apiLogger.from()))
周峰 authored
74
            //实际上静态方法上的Aop注解无法拦截到
周峰 authored
75
76
77
78
79
            return aroundWms2XXX(point, apiLogger);
        else
            return aroundXXX2Wms(point, apiLogger);
    }
肖超群 authored
80
81
82
83
    /**
     * 处理xxx调用wms接口的日志
     **/
    private Object aroundXXX2Wms(ProceedingJoinPoint point, ApiLogger apiLogger) {
周峰 authored
84
85
        Object ret = null;
        ApiLog log = initApiLog(apiLogger, point);
肖超群 authored
86
        try {
周峰 authored
87
            ret = point.proceed();
肖超群 authored
88
        } catch (Exception e) {
周峰 authored
89
            setApiLogException(log, e);
肖超群 authored
90
91
            ret = AjaxResult.error(e.getMessage());
        } finally {
周峰 authored
92
93
94
95
96
            finishApiLog(log, ret);
            return ret;
        }
    }
肖超群 authored
97
98
99
100
    /**
     * 处理WMS调用xxx接口的日志
     **/
    private Object aroundWms2XXX(ProceedingJoinPoint point, ApiLogger apiLogger) {
周峰 authored
101
102
103
104
105
106
107
        Object ret = null;
        ApiLog log = new ApiLog();

        HttpURLConnection connection = null;
        String body = null;

        try {
108
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
周峰 authored
109
110
            connection = (HttpURLConnection) point.getArgs()[0];
            body = (String) point.getArgs()[1];
111
            initApiLog(connection, body, ShiroUtils.getWarehouseCode());
肖超群 authored
112
        } catch (Exception e) {
周峰 authored
113
114
115

        }
肖超群 authored
116
        try {
周峰 authored
117
            ret = point.proceed();
肖超群 authored
118
        } catch (Exception e) {
周峰 authored
119
120
            setApiLogException(log, e);
            throw e;
肖超群 authored
121
122
        } finally {
            if (ret != null) {
游杰 authored
123
124
                finishApiLog(log, connection, ret.toString());
            }
周峰 authored
125
126
127
128
            return ret;
        }
    }
xcq authored
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
    /**记录WMS调用外接口的请求信息
     * HttpUtils.bodypost方法中直接调用本类static方法**/
    public static ApiLog initApiLog(Request request, String body){
        ApiLog log = new ApiLog();
        try {
            log.setApiMethod(request.method());
            log.setUrl(request.url().toString());
            log.setRequestTime(new Date());
            parseUrl(log, request.url().url());
            log.setRequestHeader(request.headers().toString());
            log.setRequestBody(body);
        }catch (Exception e){
            e.printStackTrace();
        }
        return 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(), QuantityConstant.DEFAULT_WAREHOUSE);
            log.setApiName(apiName);
            log.setRequestFrom("WMS");
            log.setResponseBy(address.getParam().toUpperCase());
        }catch (Exception e){
            e.printStackTrace();
        }
    }
肖超群 authored
163
164
165
166
167
    /**
     * 记录WMS调用外接口的请求信息
     * HttpUtils.bodypost方法中直接调用本类static方法
     **/
    public static ApiLog initApiLog(HttpURLConnection connection, String body, String warehouseCode) {
周峰 authored
168
169
170
171
172
        ApiLog log = new ApiLog();
        try {
            log.setApiMethod(connection.getRequestMethod());
            log.setUrl(connection.getURL().toString());
            log.setRequestTime(new Date());
173
            parseUrl(log, connection.getURL(), warehouseCode);
周峰 authored
174
175
176
177
178
179
180
181
182
183
184

            //请求头
            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);
            }
周峰 authored
185
            log.setRequestHeader(org.apache.commons.lang3.StringUtils.join(headerList, "\n"));
周峰 authored
186
            log.setRequestBody(body);
肖超群 authored
187
        } catch (Exception e) {
周峰 authored
188
189
190
191
192
193
            e.printStackTrace();
        }

        return log;
    }
肖超群 authored
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
    /**
     * 记录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) {
周峰 authored
231
232
233
234
235
236
        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);
237
            Address address = addressService.getAddressByUrl(url.toString(), warehouseCode);
周峰 authored
238
239
240
            log.setApiName(apiName);
            log.setRequestFrom("WMS");
            log.setResponseBy(address.getParam().toUpperCase());
肖超群 authored
241
        } catch (Exception e) {
周峰 authored
242
243
244
245
            e.printStackTrace();
        }
    }
xcq authored
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
    /**记录响应头信息**/
    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);
        }
    }
肖超群 authored
279
280
281
282
    /**
     * 记录响应头信息
     **/
    public static void finishApiLog(ApiLog log, HttpURLConnection connection, String body) {
周峰 authored
283
284
285
286
287
288
289
290
291
292
293
        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();
肖超群 authored
294
            while (it.hasNext()) {
周峰 authored
295
296
                String name = it.next();
                String header = connection.getHeaderField(name);
肖超群 authored
297
                if (name == null || "".equals(name))
周峰 authored
298
299
300
301
302
                    //第一行没有name
                    //HTTP/1.1 200 OK
                    headerList.add(header);
                else
                    headerList.add(name + ": " + header);
周峰 authored
303
304
305
            }
            log.setResponseHeader(org.apache.commons.lang3.StringUtils.join(headerList, "\n"));
            AjaxResult json = JSON.parseObject(body, AjaxResult.class);
周峰 authored
306
            log.setRetCode(String.valueOf(json.getCode()));
肖超群 authored
307
        } catch (Exception e) {
周峰 authored
308
            e.printStackTrace();
肖超群 authored
309
310
        } finally {
            SpringUtils.getBean(ApiLogAspect.class).saveApiLog(log);
周峰 authored
311
312
313
        }
    }
肖超群 authored
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351

    /**
     * 记录响应头信息
     **/
    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) {
周峰 authored
352
        ApiLog log = new ApiLog();
肖超群 authored
353
        try {
周峰 authored
354
355
356
357
358
359
360
361
362
            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();
肖超群 authored
363
            if (StringUtils.isNotEmpty(qryStr))
周峰 authored
364
365
366
367
368
369
370
371
372
373
374
                url = url + "?" + qryStr;
            log.setUrl(url);

            log.setApiMethod(request.getMethod());
            log.setIp(request.getRemoteAddr());

            rebuildRequestHeader(log);

            rebuildRequestBody(log, request);

            //如果reqeust中取不到post参数,就从接口方法参数中取json对象
肖超群 authored
375
            if (StringUtils.isEmpty(log.getRequestBody()))
周峰 authored
376
377
                rebuildRequestBody(log, point);
肖超群 authored
378
        } catch (Exception e) {
周峰 authored
379
380
381
382
383
384
            e.printStackTrace();
        }

        return log;
    }
肖超群 authored
385
    private void finishApiLog(ApiLog log, Object ret) {
周峰 authored
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
        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));
            }
肖超群 authored
401
        } catch (Exception e) {
周峰 authored
402
            e.printStackTrace();
肖超群 authored
403
        } finally {
周峰 authored
404
405
406
407
            saveApiLog(log);
        }
    }
肖超群 authored
408
    public static void setApiLogException(ApiLog log, Exception e) {
周峰 authored
409
410
        try {
            String exception = ExceptionUtils.getFullStackTrace(e);
周峰 authored
411
            String shortExpInfo = e.getMessage() + "\n" + org.apache.commons.lang3.StringUtils.left(exception, 1000);
周峰 authored
412
            log.setException(shortExpInfo);
肖超群 authored
413
        } catch (Exception ex) {
周峰 authored
414
415
416
417
            ex.printStackTrace();
        }
    }
肖超群 authored
418
    private void rebuildRequestHeader(ApiLog log) {
周峰 authored
419
420
421
422
        try {
            HttpServletRequest req = ServletUtils.getRequest();
            Enumeration names = req.getHeaderNames();
            ArrayList<String> headerList = new ArrayList<>();
肖超群 authored
423
424
            while (names.hasMoreElements()) {
                String name = (String) names.nextElement();
周峰 authored
425
426
427
428
429
                String header = req.getHeader(name);
                headerList.add(name + ": " + header);
            }
            String headers = org.apache.commons.lang3.StringUtils.join(headerList, "\n");
            log.setRequestHeader(headers);
肖超群 authored
430
        } catch (Exception e) {
周峰 authored
431
432
433
434
            e.printStackTrace();
        }
    }
肖超群 authored
435
436
437
438
439
    /**
     * 先从post参数中构造request body
     */
    private void rebuildRequestBody(ApiLog log, HttpServletRequest request) {
        try {
周峰 authored
440
441
442
            Set<String> keySet = request.getParameterMap().keySet();
            Iterator<String> it = keySet.iterator();
            StringBuffer sbf = new StringBuffer();
肖超群 authored
443
            while (it.hasNext()) {
周峰 authored
444
445
446
                String key = it.next();
                String value = request.getParameter(key);
                sbf.append(key).append("=").append(value);
肖超群 authored
447
                if (it.hasNext())
周峰 authored
448
449
450
                    sbf.append("&");
            }
            log.setRequestBody(sbf.toString());
肖超群 authored
451
        } catch (Exception e) {
周峰 authored
452
453
454
455
456
457
458
            e.printStackTrace();
        }
    }

    /**
     * 根据接口中的参数构造request body
     */
肖超群 authored
459
    private void rebuildRequestBody(ApiLog log, ProceedingJoinPoint point) {
周峰 authored
460
461
462
463
464
465
466
467
468
469
470
471
472
        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]);
            }
肖超群 authored
473
            if (!map.isEmpty())
周峰 authored
474
                log.setRequestBody(JSONObject.toJSONString(map));
肖超群 authored
475
        } catch (Exception e) {
周峰 authored
476
477
478
479
            e.printStackTrace();
        }
    }
肖超群 authored
480
    private void rebuildResponseHeader(ApiLog log) {
周峰 authored
481
482
483
484
485
        try {
            HttpServletResponse resp = ServletUtils.getResponse();
            Collection names = resp.getHeaderNames();
            ArrayList<String> headerList = new ArrayList<>();
            Iterator<String> it = names.iterator();
肖超群 authored
486
            while (it.hasNext()) {
周峰 authored
487
488
489
490
491
492
                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);
肖超群 authored
493
        } catch (Exception e) {
周峰 authored
494
495
496
497
            e.printStackTrace();
        }
    }
肖超群 authored
498
    private void rebuildResponseBody(ApiLog log, Object ret) {
周峰 authored
499
500
        try {
            log.setResponseBody(JSONObject.toJSON(ret).toString());
肖超群 authored
501
        } catch (Exception e) {
周峰 authored
502
503
504
505
            e.printStackTrace();
        }
    }
肖超群 authored
506
507
508
    @Async
    public void saveApiLog(ApiLog log) {
        try {
周峰 authored
509
            apiLogService.saveOrUpdate(log);
肖超群 authored
510
        } catch (Exception e) {
周峰 authored
511
512
513
514
            e.printStackTrace();
        }
    }
}