Browse Source

feat: 使用请求拦截器替换aop打印请求日志

weijianghai 2 years ago
parent
commit
4d8bb88191

+ 6 - 0
sms_blk_api/build-dir/rollback.sh

@@ -0,0 +1,6 @@
+#!/bin/bash
+
+sh stop.sh
+rm -rf sms_blk_api-exec.jar
+mv sms_blk_api-exec.jar.bak sms_blk_api-exec.jar
+sh run.sh

+ 7 - 0
sms_blk_api/build-dir/update.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+rm -rf sms_blk_api-exec.jar.bak
+sh stop.sh
+mv sms_blk_api-exec.jar sms_blk_api-exec.jar.bak
+mv sms_blk_api-exec.jar.new sms_blk_api-exec.jar
+sh run.sh

+ 2 - 1
sms_blk_api/src/main/java/com/nokia/common/http/R.java

@@ -1,6 +1,7 @@
 package com.nokia.common.http;
 
 import lombok.Data;
+import org.slf4j.MDC;
 
 /**
  * 返回值的统一包装
@@ -41,7 +42,7 @@ public class R {
         R r = new R();
         r.setSuccess(false);
         r.setCode(500);
-        r.setMessage("失败");
+        r.setMessage("失败" + MDC.get("traceId"));
         return r;
     }
 

+ 0 - 70
sms_blk_api/src/main/java/com/nokia/sms/config/ControllerExceptionHandler.java

@@ -1,70 +0,0 @@
-package com.nokia.sms.config;
-
-import com.nokia.common.http.R;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.converter.HttpMessageNotReadableException;
-import org.springframework.validation.BindException;
-import org.springframework.validation.FieldError;
-import org.springframework.web.bind.MethodArgumentNotValidException;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.RestControllerAdvice;
-
-import javax.validation.ConstraintViolationException;
-
-/**
- * 请求异常处理
- */
-@Slf4j
-@RestControllerAdvice
-public class ControllerExceptionHandler
-{
-    @ExceptionHandler(HttpMessageNotReadableException.class)
-    public ResponseEntity<Object> httpMessageNotReadableExceptionValidatorHandler(HttpMessageNotReadableException e)
-    {
-        log.warn("╭( ′• o •′ )╭☞ 请求参数校验未通过: {}", e.getMessage());
-        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(R.error().message(e.getMessage()));
-    }
-
-    @ExceptionHandler(BindException.class)
-    public ResponseEntity<Object> bindExceptionValidatorHandler(BindException e)
-    {
-        FieldError fieldError = e.getBindingResult().getFieldError();
-        String message = "";
-        if (fieldError != null)
-        {
-            message = fieldError.getDefaultMessage();
-            log.warn("╭( ′• o •′ )╭☞ 请求参数校验未通过: {}", message);
-        }
-        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(R.error().message(message));
-    }
-
-    @ExceptionHandler(ConstraintViolationException.class)
-    public ResponseEntity<Object> constraintViolationExceptionValidatorHandler(ConstraintViolationException e)
-    {
-        String message = e.getConstraintViolations().iterator().next().getMessage();
-        log.warn("╭( ′• o •′ )╭☞ 请求参数校验未通过: {}", message);
-        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(R.error().message(message));
-    }
-
-    @ExceptionHandler(MethodArgumentNotValidException.class)
-    public ResponseEntity<Object> methodArgumentNotValidExceptionValidatorHandler(MethodArgumentNotValidException e)
-    {
-        FieldError fieldError = e.getBindingResult().getFieldError();
-        String message = "";
-        if (fieldError != null)
-        {
-            message = fieldError.getDefaultMessage();
-            log.warn("╭( ′• o •′ )╭☞ 请求参数校验未通过: {}", message);
-        }
-        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(R.error().message(message));
-    }
-    
-    @ExceptionHandler({Exception.class})
-    public ResponseEntity<Object> exceptionHandler(Exception e)
-    {
-        log.error("╭( ′• o •′ )╭☞ 发生错误了 {}", e.getMessage(), e);
-        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(R.error());
-    }
-}

+ 0 - 107
sms_blk_api/src/main/java/com/nokia/sms/config/LogAspectConfig.java

@@ -1,107 +0,0 @@
-package com.nokia.sms.config;
-
-import com.alibaba.fastjson.JSON;
-import lombok.extern.slf4j.Slf4j;
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Before;
-import org.aspectj.lang.annotation.Pointcut;
-import org.slf4j.MDC;
-import org.springframework.stereotype.Component;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.StopWatch;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * 日志配置
- *
- */
-@Aspect
-@Component
-@Slf4j
-public class LogAspectConfig
-{
-    @Pointcut("execution(* com.nokia..ControllerExceptionHandler.*ValidatorHandler(..))")
-    public void validatorExceptionHandlerPointcut()
-    {
-        // Pointcut
-    }
-
-    @Pointcut("execution(public * com.nokia..*Controller.*(..))")
-    public void controllerPointcut()
-    {
-        // Pointcut
-    }
-
-    @Pointcut("execution(* com.nokia..ControllerExceptionHandler.*(..))")
-    public void controllerExceptionHandlerPointcut()
-    {
-        // Pointcut
-    }
-
-    @Pointcut("controllerPointcut() || validatorExceptionHandlerPointcut()")
-    public void beforePointCut()
-    {
-        // Pointcut
-    }
-
-    @Pointcut("controllerPointcut() || controllerExceptionHandlerPointcut()")
-    public void afterPointCut()
-    {
-        // Pointcut
-    }
-
-    @Before("beforePointCut()")
-    public void doBefore(JoinPoint joinPoint)
-    {
-        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
-        if (attributes == null)
-        {
-            return;
-        }
-        HttpServletRequest request = attributes.getRequest();
-        // 打印请求信息
-        log.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
-        // 打印请求参数
-        Object[] args = joinPoint.getArgs();
-        List<Object> list = new ArrayList<>();
-        for (Object arg : args) {
-            if (arg instanceof ServletRequest
-                    || arg instanceof ServletResponse
-                    || arg instanceof MultipartFile
-                    || arg instanceof Exception
-            ) {
-                continue;
-            }
-            list.add(arg);
-        }
-        if (CollectionUtils.isEmpty(list)) {
-            return;
-        }
-        log.info("请求参数: {}", JSON.toJSONString(list));
-    }
-
-    @Around("afterPointCut()")
-    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
-    {
-        StopWatch stopWatch = new StopWatch();
-        stopWatch.start();
-        MDC.put("traceId", UUID.randomUUID().toString().replace("-", ""));
-        Object result = proceedingJoinPoint.proceed();
-        stopWatch.stop();
-        log.info("返回: {}", JSON.toJSONString(result));
-        log.info("耗时:{} ms", stopWatch.getTotalTimeMillis());
-        return result;
-    }
-}

+ 79 - 0
sms_blk_api/src/main/java/com/nokia/sms/config/web/ControllerExceptionHandler.java

@@ -0,0 +1,79 @@
+package com.nokia.sms.config.web;
+
+import com.nokia.common.http.R;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.TypeMismatchException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.converter.HttpMessageConversionException;
+import org.springframework.validation.BindException;
+import org.springframework.validation.FieldError;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MissingRequestValueException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import javax.validation.ValidationException;
+
+/**
+ * 请求异常处理
+ */
+@Slf4j
+@RestControllerAdvice
+public class ControllerExceptionHandler
+{
+    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+    public ResponseEntity<Object> httpRequestMethodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException e)
+    {
+        log.warn(e.getMessage());
+        return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).body(R.error().message(e.getMessage()));
+    }
+
+    @ExceptionHandler(MissingRequestValueException.class)
+    public ResponseEntity<Object> missingRequestValueExceptionHandler(MissingRequestValueException e)
+    {
+        log.warn(e.getMessage());
+        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(R.error().message(e.getMessage()));
+    }
+
+    @ExceptionHandler(HttpMessageConversionException.class)
+    public ResponseEntity<Object> httpMessageConversionExceptionHandler(HttpMessageConversionException e)
+    {
+        log.warn(e.getMessage());
+        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(R.error().message(e.getMessage()));
+    }
+
+    @ExceptionHandler(TypeMismatchException.class)
+    public ResponseEntity<Object> typeMismatchExceptionHandler(TypeMismatchException e)
+    {
+        log.warn(e.getMessage());
+        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(R.error().message(e.getMessage()));
+    }
+
+    @ExceptionHandler(BindException.class)
+    public ResponseEntity<Object> bindExceptionHandler(BindException e)
+    {
+        FieldError fieldError = e.getBindingResult().getFieldError();
+        String message = "";
+        if (fieldError != null)
+        {
+            message = fieldError.getDefaultMessage();
+        }
+        log.warn(message);
+        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(R.error().message(message));
+    }
+
+    @ExceptionHandler(ValidationException.class)
+    public ResponseEntity<Object> validationExceptionHandler(ValidationException e)
+    {
+        log.warn(e.getMessage());
+        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(R.error().message(e.getMessage()));
+    }
+
+    @ExceptionHandler(Exception.class)
+    public ResponseEntity<Object> exceptionHandler(Exception e)
+    {
+        log.error("╭( ′• o •′ )╭☞ 发生错误了 {}", e.getMessage(), e);
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(R.error());
+    }
+}

+ 14 - 0
sms_blk_api/src/main/java/com/nokia/sms/config/web/MyDispatcherServlet.java

@@ -0,0 +1,14 @@
+package com.nokia.sms.config.web;
+
+import org.springframework.web.servlet.DispatcherServlet;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class MyDispatcherServlet extends DispatcherServlet {
+    @Override
+    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
+        // 替换request和response
+        super.doDispatch(new MyHttpServletRequestWrapper(request), new MyHttpServletResponseWrapper(response));
+    }
+}

+ 54 - 0
sms_blk_api/src/main/java/com/nokia/sms/config/web/MyHttpServletRequestWrapper.java

@@ -0,0 +1,54 @@
+package com.nokia.sms.config.web;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.StreamUtils;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.*;
+
+/**
+ * 解决流只能读取一次问题
+ */
+@Slf4j
+public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {
+    private byte[] bytes;
+
+    public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
+        super(request);
+        bytes = StreamUtils.copyToByteArray(request.getInputStream());
+    }
+
+    @Override
+    public ServletInputStream getInputStream() {
+        ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
+        return new ServletInputStream() {
+            @Override
+            public boolean isFinished() {
+                return false;
+            }
+
+            @Override
+            public boolean isReady() {
+                return false;
+            }
+
+            @Override
+            public void setReadListener(ReadListener readListener) {
+                //
+            }
+
+            @Override
+            public int read() {
+                return stream.read();
+            }
+        };
+    }
+
+    @Override
+    public BufferedReader getReader() throws UnsupportedEncodingException {
+        return new BufferedReader(new InputStreamReader(getInputStream(), super.getCharacterEncoding()));
+    }
+}

+ 47 - 0
sms_blk_api/src/main/java/com/nokia/sms/config/web/MyHttpServletResponseWrapper.java

@@ -0,0 +1,47 @@
+package com.nokia.sms.config.web;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * 解决流只能读取一次问题
+ */
+public class MyHttpServletResponseWrapper extends HttpServletResponseWrapper {
+    private ByteArrayOutputStream byteArrayOutputStream;
+    private ServletOutputStream servletOutputStream;
+
+    public MyHttpServletResponseWrapper(HttpServletResponse response) {
+        super(response);
+        byteArrayOutputStream = new ByteArrayOutputStream();
+        servletOutputStream = new ServletOutputStream() {
+            @Override
+            public boolean isReady() {
+                return false;
+            }
+
+            @Override
+            public void setWriteListener(WriteListener writeListener) {
+                //
+            }
+
+            @Override
+            public void write(int b) throws IOException {
+                response.getOutputStream().write(b);
+                byteArrayOutputStream.write(b);
+            }
+        };
+    }
+
+    @Override
+    public ServletOutputStream getOutputStream() {
+        return servletOutputStream;
+    }
+
+    public byte[] toByteArray() {
+        return byteArrayOutputStream.toByteArray();
+    }
+}

+ 52 - 0
sms_blk_api/src/main/java/com/nokia/sms/config/web/MyWebMvcConfigurer.java

@@ -0,0 +1,52 @@
+package com.nokia.sms.config.web;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.DispatcherServlet;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class MyWebMvcConfigurer implements WebMvcConfigurer {
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        // 添加请求日志拦截
+        registry.addInterceptor(new RequestLogHandlerInterceptor()).addPathPatterns("/**");
+    }
+
+    /**
+     * 使用自定义DispatcherServlet
+     */
+    @Bean
+    @Qualifier(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
+    public DispatcherServlet dispatcherServlet() {
+        return new MyDispatcherServlet();
+    }
+
+//    /**
+//     * 配置消息转换器
+//     *
+//     * @param converters 转换器
+//     */
+//    @Override
+//    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
+//        converters.add(mappingJackson2HttpMessageConverter());
+//    }
+//
+//    /**
+//     * 配置映射jackson2 http消息转换器
+//     *
+//     * @return {@link MappingJackson2HttpMessageConverter}
+//     */
+//    @Bean
+//    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
+//        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
+//        ObjectMapper mapper = new ObjectMapper();
+//        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+//        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
+//        converter.setObjectMapper(mapper);
+//        return converter;
+//    }
+}

+ 70 - 0
sms_blk_api/src/main/java/com/nokia/sms/config/web/RequestLogHandlerInterceptor.java

@@ -0,0 +1,70 @@
+package com.nokia.sms.config.web;
+
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+import org.springframework.lang.Nullable;
+import org.springframework.util.StopWatch;
+import org.springframework.util.StreamUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.nio.charset.Charset;
+import java.util.UUID;
+
+/**
+ * 请求日志拦截器
+ */
+@Slf4j
+public class RequestLogHandlerInterceptor implements HandlerInterceptor {
+    /**
+     * 计时器线程变量
+     */
+    private static final ThreadLocal<StopWatch> STOP_WATCH_THREAD_LOCAL = new ThreadLocal<>();
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        StopWatch stopWatch = new StopWatch();
+        stopWatch.start();
+        // 计时器放入线程变量
+        STOP_WATCH_THREAD_LOCAL.set(stopWatch);
+        // 日志添加跟踪id
+        MDC.put("traceId", UUID.randomUUID().toString().replace("-", ""));
+        log.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
+        // 请求头参数
+//        Map<String, String> headers = new HashMap<>();
+//        Enumeration<String> headerNames = request.getHeaderNames();
+//        while (headerNames.hasMoreElements()) {
+//            String k	= headerNames.nextElement();
+//            String v = request.getHeader(k);
+//            headers.put(k, v);
+//        }
+//        log.info("请求头参数: {}", JSON.toJSONString(headers));
+        // 查询参数
+//        Map<String, String> parameters = new HashMap<>();
+//        Enumeration<String> parameterNames = request.getParameterNames();
+//        while (parameterNames.hasMoreElements()) {
+//            String k	= parameterNames.nextElement();
+//            String v = request.getParameter(k);
+//            parameters.put(k, v);
+//        }
+//        log.info("查询参数: {}", JSON.toJSONString(parameters));
+        // 请求体参数
+        String body = StreamUtils.copyToString(request.getInputStream(), Charset.forName(request.getCharacterEncoding()));
+        log.info("请求参数: {}", StringUtils.trimAllWhitespace(body));
+        return true;
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
+                                @Nullable Exception ex) throws Exception {
+        MyHttpServletResponseWrapper wrapper = (MyHttpServletResponseWrapper) response;
+        String responseString = new String(wrapper.toByteArray());
+        log.info("返回 {}: {}", wrapper.getStatus(), responseString);
+        StopWatch stopWatch = STOP_WATCH_THREAD_LOCAL.get();
+        stopWatch.stop();
+        log.info("耗时 {} ms", stopWatch.getTotalTimeMillis());
+        STOP_WATCH_THREAD_LOCAL.remove();
+    }
+}

+ 1 - 0
sms_blk_api/src/main/java/com/nokia/sms/service/QueryService.java

@@ -24,6 +24,7 @@ public class QueryService {
         try {
             // 查询黑名单
             String responseString = restTemplate.postForObject(URL, new QueryBlackDTO(params.getPhone()), String.class);
+            log.info("查询黑名单响应: {}", responseString);
             if (responseString == null) {
                 log.error("查询黑名单接口响应为空");
                 return r;