Blame view

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

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

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

/**
 * Api调用日志记录处理
周鸿 authored
41
 *
周峰 authored
42
43
44
45
 * @author huaheng
 */
@Aspect
@Component
周鸿 authored
46
@EnableAsync
47
48
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
57
    public void setApiLogService(IApiLogService apiLogService){
周峰 authored
58
59
60
61
        ApiLogAspect.apiLogService = apiLogService;
    }

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

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

    @Around("logPointCut()  && @annotation(apiLogger)")
73
74
75
76
77
    public Object around(ProceedingJoinPoint point, ApiLogger apiLogger) throws Throwable
    {
        if("WMS".equalsIgnoreCase(apiLogger.from()))
        //实际上静态方法上的Aop注解无法拦截到
        {
周峰 authored
78
            return aroundWms2XXX(point, apiLogger);
79
        } else {
周峰 authored
80
            return aroundXXX2Wms(point, apiLogger);
81
        }
周峰 authored
82
83
    }
84
85
    /**处理xxx调用wms接口的日志**/
    private Object aroundXXX2Wms(ProceedingJoinPoint point, ApiLogger apiLogger){
周峰 authored
86
87
        Object ret = null;
        ApiLog log = initApiLog(apiLogger, point);
88
        try{
周峰 authored
89
            ret = point.proceed();
90
        }catch (Exception e){
周峰 authored
91
            setApiLogException(log, e);
周鸿 authored
92
            ret = AjaxResult.error(e.getMessage());
93
        }finally{
周峰 authored
94
95
96
97
98
            finishApiLog(log, ret);
            return ret;
        }
    }
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
112
            initApiLog(connection, body);
        }catch (Exception e){
周峰 authored
113
114
115

        }
116
        try{
周峰 authored
117
            ret = point.proceed();
118
        }catch (Exception e){
周峰 authored
119
120
            setApiLogException(log, e);
            throw e;
121
122
        }finally{
            if(ret != null) {
游杰 authored
123
124
                finishApiLog(log, connection, ret.toString());
            }
周峰 authored
125
126
127
128
            return ret;
        }
    }
周鸿 authored
129
    /**
130
     * 记录响应头信息
周鸿 authored
131
     **/
132
    public static void finishApiLog(ApiLog log, HttpURLConnection connection, String body) {
周峰 authored
133
        try {
134
135
136
137
138
            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()));
周峰 authored
139
140
141
            //响应头
            Set<String> keyset = connection.getHeaderFields().keySet();
周峰 authored
142
            ArrayList<String> headerList = new ArrayList<>();
143
            Iterator<String> it = keyset.iterator();
周峰 authored
144
145
            while (it.hasNext()) {
                String name = it.next();
146
147
148
149
150
151
152
                String header = connection.getHeaderField(name);
                if (name == null || "".equals(name))
                    //第一行没有name
                    //HTTP/1.1 200 OK
                    headerList.add(header);
                else
                    headerList.add(name + ": " + header);
周峰 authored
153
            }
154
155
156
            log.setResponseHeader(org.apache.commons.lang3.StringUtils.join(headerList, "\n"));
            AjaxResult json = JSON.parseObject(body, AjaxResult.class);
            log.setRetCode(String.valueOf(json.getCode()));
周鸿 authored
157
158
        } catch (Exception e) {
            e.printStackTrace();
159
160
        } finally {
            SpringUtils.getBean(ApiLogAspect.class).saveApiLog(log);
周鸿 authored
161
        }
162
    }
周鸿 authored
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
    /**
     * 根据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();
        }
周鸿 authored
181
182
    }
183
周鸿 authored
184
185
186
187
    /**
     * 记录WMS调用外接口的请求信息
     * HttpUtils.bodypost方法中直接调用本类static方法
     **/
188
    public static ApiLog  initApiLog(String Method, String url, String body, HttpHeaders headers, String warehouseCode) {
周鸿 authored
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
        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) {
周峰 authored
210
211
212
213
214
215
            e.printStackTrace();
        }

        return log;
    }
216
217
218
219
    /**记录WMS调用外接口的请求信息
     * HttpUtils.bodypost方法中直接调用本类static方法**/
    public static  ApiLog initApiLog(HttpURLConnection connection, String body){
        ApiLog log = new ApiLog();
周峰 authored
220
        try {
221
222
223
224
            log.setApiMethod(connection.getRequestMethod());
            log.setUrl(connection.getURL().toString());
            log.setRequestTime(new Date());
            parseUrl(log, connection.getURL());
周峰 authored
225
226
227
228
229
230
231
232
233
234
235
236
237
238
            //请求头
            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){
周峰 authored
239
240
            e.printStackTrace();
        }
241
242

        return log;
周峰 authored
243
244
    }
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
    /**记录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;
    }

    /**记录响应头信息**/
    public static void finishApiLog(ApiLog log, Response response, String body){
周峰 authored
264
265
266
267
268
        try {
            log.setResponseBody(body);
            log.setResponseTime(new Date());
            Long duration = log.getResponseTime().getTime() - log.getRequestTime().getTime();
            log.setDuration(duration.intValue());
269
            log.setHttpCode(String.valueOf(response.code()));
周峰 authored
270
271

            //响应头
272
273
274
275
276
277
278
            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);
周峰 authored
279
            }
280
281
            log.setRetCode(String.valueOf(ajaxResult.getCode()));
        }catch (Exception e){
周峰 authored
282
            e.printStackTrace();
283
284
285
286
287
288
289
290
        }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){

            }
周鸿 authored
291
292
293
294
295
            SpringUtils.getBean(ApiLogAspect.class).saveApiLog(log);
        }
    }
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312

    /**根据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.WAREHOUSECODE);
            log.setApiName(apiName);
            log.setRequestFrom("WMS");
            log.setResponseBy(address.getParam().toUpperCase());
        }catch (Exception e){
            e.printStackTrace();
        }
    }
周鸿 authored
313
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
    /**
     * 记录响应头信息
     **/
    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);
周峰 authored
345
346
347
        }
    }
周鸿 authored
348
349
    private ApiLog initApiLog(ApiLogger apiLogger, ProceedingJoinPoint point){
周峰 authored
350
        ApiLog log = new ApiLog();
351
        try{
周峰 authored
352
353
354
355
356
357
358
359
360
            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();
361
            if(StringUtils.isNotEmpty(qryStr)) {
周峰 authored
362
                url = url + "?" + qryStr;
363
            }
周峰 authored
364
365
366
367
368
369
370
371
372
373
            log.setUrl(url);

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

            rebuildRequestHeader(log);

            rebuildRequestBody(log, request);

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

        return log;
    }
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));
            }
401
        }catch (Exception e){
周峰 authored
402
            e.printStackTrace();
403
        }finally {
周峰 authored
404
405
406
407
            saveApiLog(log);
        }
    }
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);
413
        }catch (Exception ex){
周峰 authored
414
415
416
417
            ex.printStackTrace();
        }
    }
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<>();
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);
430
        }catch (Exception e){
周峰 authored
431
432
433
434
            e.printStackTrace();
        }
    }
435
436
437
    /**先从post参数中构造request body*/
    private void rebuildRequestBody(ApiLog log, HttpServletRequest request){
        try{
周峰 authored
438
439
440
            Set<String> keySet = request.getParameterMap().keySet();
            Iterator<String> it = keySet.iterator();
            StringBuffer sbf = new StringBuffer();
441
            while(it.hasNext()){
周峰 authored
442
443
444
                String key = it.next();
                String value = request.getParameter(key);
                sbf.append(key).append("=").append(value);
445
                if(it.hasNext()) {
周峰 authored
446
                    sbf.append("&");
447
                }
周峰 authored
448
449
            }
            log.setRequestBody(sbf.toString());
450
        }catch (Exception e){
周峰 authored
451
452
453
454
455
456
457
            e.printStackTrace();
        }
    }

    /**
     * 根据接口中的参数构造request body
     */
458
459
    private void rebuildRequestBody(ApiLog log, ProceedingJoinPoint point)
    {
周峰 authored
460
461
462
463
464
        try {
            if (point.getArgs().length == 1) {
                log.setRequestBody(JSONObject.toJSONString(point.getArgs()[0]));
                return;
            }
465
周峰 authored
466
467
468
469
470
471
472
473
            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]);
            }
474
475

            if(!map.isEmpty()) {
周峰 authored
476
                log.setRequestBody(JSONObject.toJSONString(map));
477
478
            }
        }catch (Exception e){
周峰 authored
479
480
481
482
            e.printStackTrace();
        }
    }
483
    private void rebuildResponseHeader(ApiLog log){
周峰 authored
484
485
486
487
488
        try {
            HttpServletResponse resp = ServletUtils.getResponse();
            Collection names = resp.getHeaderNames();
            ArrayList<String> headerList = new ArrayList<>();
            Iterator<String> it = names.iterator();
489
            while(it.hasNext()){
周峰 authored
490
491
492
493
494
495
                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);
496
        }catch (Exception e){
周峰 authored
497
498
499
500
            e.printStackTrace();
        }
    }
501
    private void rebuildResponseBody(ApiLog log, Object ret){
周峰 authored
502
503
        try {
            log.setResponseBody(JSONObject.toJSON(ret).toString());
504
        }catch (Exception e){
周峰 authored
505
506
507
508
            e.printStackTrace();
        }
    }
周鸿 authored
509
    @Async
510
511
    public void saveApiLog(ApiLog log){
        try{
周峰 authored
512
            apiLogService.saveOrUpdate(log);
513
        }catch (Exception e){
周峰 authored
514
515
516
517
            e.printStackTrace();
        }
    }
}