Răsfoiți Sursa

feat: 请求日志入库

weijianghai 11 luni în urmă
părinte
comite
a63f739bb9

+ 20 - 18
pom.xml

@@ -75,42 +75,44 @@
             <artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
             <version>4.3.0</version>
         </dependency>
-        <!-- https://mvnrepository.com/artifact/io.minio/minio -->
-        <dependency>
-            <groupId>io.minio</groupId>
-            <artifactId>minio</artifactId>
-            <version>8.5.6</version>
-        </dependency>
         <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
         <dependency>
             <groupId>com.github.pagehelper</groupId>
             <artifactId>pagehelper</artifactId>
             <version>6.1.0</version>
         </dependency>
-        <dependency>
-            <groupId>com.itextpdf</groupId>
-            <artifactId>itext7-core</artifactId>
-            <version>7.1.4</version>
-            <type>pom</type>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>com.itextpdf</groupId>-->
+<!--            <artifactId>itext7-core</artifactId>-->
+<!--            <version>7.1.4</version>-->
+<!--            <type>pom</type>-->
+<!--        </dependency>-->
         <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
         <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>easyexcel</artifactId>
             <version>3.0.5</version>
         </dependency>
-        <!-- https://mvnrepository.com/artifact/org.json/json -->
-        <dependency>
-            <groupId>org.json</groupId>
-            <artifactId>json</artifactId>
-            <version>20180130</version>
-        </dependency>
         <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
         <dependency>
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
             <version>2.15.1</version>
         </dependency>
+        <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-generator -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-generator</artifactId>
+            <version>3.5.5</version>
+            <scope>test</scope>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-freemarker -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-freemarker</artifactId>
+            <version>3.2.3</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <dependencyManagement>

+ 15 - 1
src/main/java/com/example/config/ApiDocConfig.java

@@ -2,12 +2,13 @@ package com.example.config;
 
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.parameters.Parameter;
+import org.springdoc.core.customizers.OpenApiCustomiser;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
 /**
  * api文档配置
- *
  */
 @Configuration
 public class ApiDocConfig {
@@ -15,4 +16,17 @@ public class ApiDocConfig {
     public OpenAPI openapi() {
         return new OpenAPI().info(new Info().title("财务接口").description("财务接口文档").version("1.0"));
     }
+
+    @Bean
+    public OpenApiCustomiser openApiCustomiser() {
+        return openApi -> openApi.getPaths().values().forEach(pathItem -> pathItem.readOperations().forEach(operation -> {
+            Parameter headerParam = new Parameter()
+                    .required(true)
+                    .in("header")
+                    .name("token")
+                    .description("访问令牌")
+                    .example("zoQtYlmhk/add/mBUBZD5mFJB1IXEwaLRS97Uf9z9Hlqdh/UHio66b35GOo/eEziALCI90sLNBn3WM7k1/FVGgGiDUO84mJ2JUgw5zHx8fvcO/OxqUB83JYaeV6eJIWkvJpp");
+            operation.addParametersItem(headerParam);
+        }));
+    }
 }

+ 0 - 62
src/main/java/com/example/config/HttpClientConfig.java

@@ -1,62 +0,0 @@
-package com.example.config;
-
-import okhttp3.OkHttpClient;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
-
-/**
- * OKHttpClient配置
- */
-@Configuration
-public class HttpClientConfig {
-    @Bean
-    public OkHttpClient myHttpClient() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
-        return new OkHttpClient.Builder()
-                .hostnameVerifier((hostname, session) -> true)
-                .retryOnConnectionFailure(true)
-                .sslSocketFactory(getSslSocketFactory(), getX509TrustManager())
-                .build();
-    }
-
-    private SSLSocketFactory getSslSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
-        SSLContext sslContext = SSLContext.getInstance("SSL");
-        sslContext.init(null, new TrustManager[]{
-                new X509TrustManager() {
-                    @Override
-                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
-                        // 不检查证书
-                    }
-
-                    @Override
-                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
-                        // 不检查证书
-                    }
-
-                    @Override
-                    public X509Certificate[] getAcceptedIssuers() {
-                        return new X509Certificate[]{};
-                    }
-                }
-        }, new SecureRandom());
-        return sslContext.getSocketFactory();
-    }
-
-    private X509TrustManager getX509TrustManager() throws NoSuchAlgorithmException, KeyStoreException {
-        TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
-        factory.init((KeyStore) null);
-        TrustManager[] managers = factory.getTrustManagers();
-        return (X509TrustManager) managers[0];
-    }
-}

+ 7 - 3
src/main/java/com/example/config/web/MyWebMvcConfigurer.java

@@ -1,5 +1,6 @@
 package com.example.config.web;
 
+import com.example.service.common.RequestLogService;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
 import org.springframework.context.annotation.Bean;
@@ -10,13 +11,16 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 @Configuration
 public class MyWebMvcConfigurer implements WebMvcConfigurer {
+    private final RequestLogService requestLogService;
+
+    public MyWebMvcConfigurer(RequestLogService requestLogService) {
+        this.requestLogService = requestLogService;
+    }
 
     @Override
     public void addInterceptors(InterceptorRegistry registry) {
         // 添加请求日志拦截
-        registry.addInterceptor(new RequestLogHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/webjars/**", "/doc**", "/v3/**");
-        // 添加token拦截
-//        registry.addInterceptor(new TokenInterceptor()).addPathPatterns("/house-car/**");
+        registry.addInterceptor(new RequestLogHandlerInterceptor(requestLogService)).addPathPatterns("/**").excludePathPatterns("/webjars/**", "/doc**", "/v3/**");
     }
 
     /**

+ 35 - 9
src/main/java/com/example/config/web/RequestLogHandlerInterceptor.java

@@ -1,5 +1,7 @@
 package com.example.config.web;
 
+import com.example.entity.common.RequestLogPo;
+import com.example.service.common.RequestLogService;
 import com.example.utils.AESUtil;
 import com.example.utils.R;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -20,6 +22,7 @@ import java.net.URLDecoder;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Map;
@@ -34,6 +37,11 @@ public class RequestLogHandlerInterceptor implements HandlerInterceptor {
      * 计时器线程变量
      */
     private static final ThreadLocal<StopWatch> STOP_WATCH_THREAD_LOCAL = new ThreadLocal<>();
+    private RequestLogService requestLogService;
+
+    public RequestLogHandlerInterceptor(RequestLogService requestLogService) {
+        this.requestLogService = requestLogService;
+    }
 
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
@@ -69,7 +77,6 @@ public class RequestLogHandlerInterceptor implements HandlerInterceptor {
             body = StreamUtils.copyToString(request.getInputStream(), Charset.forName(request.getCharacterEncoding()));
             log.info("请求体参数: {}", StringUtils.trimAllWhitespace(body));
         }
-        // todo: 记录日志
         String token = request.getHeader("token");
         if (!StringUtils.hasText(token) || "undefined".equals(token)) {
             token = parameters.get("token");
@@ -89,20 +96,39 @@ public class RequestLogHandlerInterceptor implements HandlerInterceptor {
 //            if (!"FINANCE".equals(map.get("APP_ID")) || !StringUtils.hasText(map.get("LOGIN_ID"))) {
 //                return forbidden(response);
 //            }
-            map.put("api", request.getRequestURI());
-            map.put("body", body);
-            map.put("time", now.toString());
-            map.put("headers", gson.toJson(headers));
-            map.put("parameters", gson.toJson(parameters));
-            map.put("token", urlDecodeToken);
-            log.info("调用记录: {}", gson.toJson(map));
+            Map<String, String> requestParameters = new HashMap<>();
+            requestParameters.put("request_parameters", gson.toJson(parameters));
+            requestParameters.put("request_body", body);
+            RequestLogPo requestLogPo = new RequestLogPo();
+            requestLogPo.setRequestTime(now);
+            requestLogPo.setLoginId(map.get("LOGIN_ID"));
+            requestLogPo.setPageUrl(map.get("REQUEST_URL"));
+            requestLogPo.setApi(request.getRequestURI());
+            requestLogPo.setRequestParameters(gson.toJson(requestParameters));
+            requestLogPo.setHeaders(gson.toJson(headers));
+            requestLogPo.setAppId(map.get("APP_ID"));
+            setTimeStamp(map, requestLogPo);
+            requestLogPo.setToken(urlDecodeToken);
+            requestLogService.offer(requestLogPo);
         } catch (Exception e) {
-            log.warn("token解密失败: {}", token);
+            log.error("token解密失败: {} {}", token, e.getMessage(), e);
 //            return forbidden(response);
         }
         return true;
     }
 
+    private void setTimeStamp(Map<String, String> map, RequestLogPo requestLogPo) {
+        String timeStamp = map.get("TIME_STAMP");
+        if (StringUtils.hasText(timeStamp)) {
+            try {
+                requestLogPo.setTimeStamp(LocalDateTime.parse(map.get("TIME_STAMP"),
+                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+            } catch (Exception e) {
+                log.warn("时间戳解析失败: {}", timeStamp);
+            }
+        }
+    }
+
     @Override
     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                 @Nullable Exception ex) throws Exception {

+ 46 - 0
src/main/java/com/example/dao/common/RequestLogDao.java

@@ -0,0 +1,46 @@
+package com.example.dao.common;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.example.entity.common.RequestLogPo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.List;
+
+@Mapper
+public interface RequestLogDao extends BaseMapper<RequestLogPo> {
+    /**
+     * 批量插入
+     */
+    @Update("""
+<script>
+insert into common.request_log
+(
+request_time,
+login_id,
+page_url,
+api,
+request_parameters,
+headers,
+app_id,
+time_stamp,
+token
+)
+values
+<foreach collection="list" item="item" index="index" separator=",">
+(
+#{item.requestTime},
+#{item.loginId},
+#{item.pageUrl},
+#{item.api},
+#{item.requestParameters},
+#{item.headers},
+#{item.appId},
+#{item.timeStamp},
+#{item.token}
+)
+</foreach>
+</script>
+""")
+    int insertBatch(List<RequestLogPo> list);
+}

+ 57 - 0
src/main/java/com/example/entity/common/RequestLogPo.java

@@ -0,0 +1,57 @@
+package com.example.entity.common;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@NoArgsConstructor
+@Data
+@TableName("common.request_log")
+public class RequestLogPo {
+    /**
+     * 请求时间
+     */
+    private LocalDateTime requestTime;
+
+    /**
+     * 账号,从token解密
+     */
+    private String loginId;
+
+    /**
+     * 页面url,从token解密
+     */
+    private String pageUrl;
+
+    /**
+     * 接口url
+     */
+    private String api;
+
+    /**
+     * 请求参数
+     */
+    private String requestParameters;
+
+    /**
+     * 请求头
+     */
+    private String headers;
+
+    /**
+     * 应用id,从token解密
+     */
+    private String appId;
+
+    /**
+     * 时间戳,从token解密
+     */
+    private LocalDateTime timeStamp;
+
+    /**
+     * 访问令牌
+     */
+    private String token;
+}

+ 41 - 0
src/main/java/com/example/service/common/RequestLogService.java

@@ -0,0 +1,41 @@
+package com.example.service.common;
+
+import com.example.dao.common.RequestLogDao;
+import com.example.entity.common.RequestLogPo;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+@Slf4j
+@Service
+public class RequestLogService {
+    public static final ConcurrentLinkedQueue<RequestLogPo> QUEUE = new ConcurrentLinkedQueue<>();
+    private final RequestLogDao requestLogDao;
+
+    public RequestLogService(RequestLogDao requestLogDao) {
+        this.requestLogDao = requestLogDao;
+    }
+
+    public void offer(RequestLogPo requestLog) {
+        QUEUE.offer(requestLog);
+    }
+
+    @PostConstruct
+    public void consumer() {
+        CompletableFuture.runAsync(() -> {
+            while (true) {
+                try {
+                    RequestLogPo requestLogPo = QUEUE.poll();
+                    if (requestLogPo != null) {
+                        requestLogDao.insert(requestLogPo);
+                    }
+                } catch (Exception e) {
+                    log.error(e.getMessage(), e);
+                }
+            }
+        });
+    }
+}

+ 0 - 207
src/main/java/com/example/utils/excel/ExcelTool.java

@@ -1,207 +0,0 @@
-package com.example.utils.excel;
-
-import com.example.utils.RRException;
-import org.apache.commons.lang3.time.DateFormatUtils;
-import org.apache.poi.hssf.usermodel.HSSFDateUtil;
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
-import org.json.JSONObject;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 读取EXCEL表的信息
- * @author
- * @date 2020-05-04 13:10
- */
-public class ExcelTool {
-
-    /**
-     * 读取EXCEL表信息
-     *
-     * @param file
-     * @param title
-     * @return
-     */
-    @SuppressWarnings("unchecked")
-    public static List<String[]> readExcel(MultipartFile file, String[] title) throws RRException, IOException, InvalidFormatException {
-        return readExcel(file, title, 1);
-    }
-
-    /**
-     * 读取EXCEL表信息(从第几行开始)
-     *
-     * @param file
-     * @param title
-     * @param fromRow
-     * @return
-     */
-    @SuppressWarnings("unchecked")
-    public static List<String[]> readExcel(MultipartFile file, String[] title, int fromRow) throws RRException, IOException, InvalidFormatException {
-        Workbook wb;
-        List<String[]> list = new ArrayList();
-        InputStream is = file.getInputStream();
-        wb = WorkbookFactory.create(is);
-        Sheet sheet = wb.getSheetAt(0);
-        Row row;
-        for (int i = sheet.getFirstRowNum() + fromRow; i <= sheet.getLastRowNum(); i++) {
-            row = sheet.getRow(i);
-            System.out.println(i);
-            if (i >= 1 && row != null && row.getCell(0) != null && !row.getCell(0).toString().equals("")) {
-                String[] t = new String[title.length];
-                for (int m = 0; m < title.length; m++) {
-                    Cell cell = row.getCell(m);
-                    t[m] = getCellValue(cell);
-                }
-                list.add(t);
-            }
-        }
-        return list;
-    }
-
-    @SuppressWarnings("unchecked")
-    public static List<String[]> readExcel(MultipartFile file,int fromRow) throws RRException, IOException, InvalidFormatException {
-        Workbook wb;
-        List<String[]> list = new ArrayList();
-        InputStream is = file.getInputStream();
-        wb = WorkbookFactory.create(is);
-        Sheet sheet = wb.getSheetAt(0);
-        Row row;
-        //必须是连续的数据
-        for (int i = sheet.getFirstRowNum() + fromRow; i <= sheet.getLastRowNum(); i++) {
-            row = sheet.getRow(i);
-            if (i >= 1 && row != null && row.getCell(0) != null && !row.getCell(0).toString().equals("")) {
-                String[] t = new String[50];
-                for (int m = 0; m <50; m++) {
-                    Cell cell = row.getCell(m);
-                    t[m] = getCellValue(cell);
-                }
-                list.add(t);
-            }else{
-                break;
-            }
-        }
-        return list;
-    }
-
-
-    public static String getCellValue(Cell cell) {
-        String cellValue = "";
-        if (cell == null) {
-            return cellValue;
-        }
-        //判断数据的类型
-        switch (cell.getCellTypeEnum()) {
-            case NUMERIC: //数字
-                String a = "";
-                if (HSSFDateUtil.isCellDateFormatted(cell)) {
-                    Date date = cell.getDateCellValue();
-                    a = DateFormatUtils.format(date, "yyyy-MM-dd");
-                    cellValue = a;
-                } else {
-                    cell.setCellType(CellType.STRING);
-                    cellValue = String.valueOf(cell.getStringCellValue());                }
-                break;
-            case STRING: //字符串
-                cellValue = String.valueOf(cell.getStringCellValue());
-                break;
-            case BOOLEAN: //Boolean
-                cellValue = String.valueOf(cell.getBooleanCellValue());
-                break;
-            case FORMULA: //公式
-                cell.setCellType(CellType.STRING);
-                cellValue = String.valueOf(cell.getStringCellValue());
-                break;
-            case BLANK: //空值
-                cellValue = "";
-                break;
-            case ERROR: //故障
-                cellValue = "非法字符";
-                break;
-            default:
-                cellValue = "未知类型";
-                break;
-        }
-        return cellValue;
-    }
-
-    /**
-     * 读取导入Excel的表头数据
-     */
-    public static List<String> readExcelTitle(MultipartFile file) throws RRException, IOException, InvalidFormatException {
-        Workbook wb;
-        List list = new ArrayList();
-        InputStream is = file.getInputStream();
-        wb = WorkbookFactory.create(is);
-        Sheet sheet = wb.getSheetAt(0);
-        Row row = sheet.getRow(0);
-        int m=0;
-
-        while(true){
-            Cell cell = row.getCell(m);
-            String t=getCellValue(cell);
-            if(t!=null&&!t.equals("")){
-                list.add(t);
-                m++;
-            }else{
-                break;
-            }
-            if(m>100){
-                break;
-            }
-        }
-        return list;
-    }
-
-    public static List<JSONObject> readExcel(MultipartFile file, List<String> propertyList) throws RRException, IOException, InvalidFormatException {
-        Workbook wb;
-        List<JSONObject> list = new ArrayList();
-        InputStream is = file.getInputStream();
-        wb = WorkbookFactory.create(is);
-        Sheet sheet = wb.getSheetAt(0);
-        Row row;
-        for (int i = sheet.getFirstRowNum()+1 ; i <= sheet.getLastRowNum(); i++) {
-            row = sheet.getRow(i);
-            JSONObject jsonObject=new JSONObject();
-            if (i >= 1 && row != null && row.getCell(0) != null && !row.getCell(0).toString().equals("")) {
-                for (int m = 0; m < propertyList.size(); m++) {
-                    Cell cell = row.getCell(m);
-                    jsonObject.put(propertyList.get(m),getCellValue(cell));
-                }
-            }
-            list.add(jsonObject);
-        }
-        return list;
-    }
-
-    /**
-     * @param file
-     * @param title
-     * @return
-     */
-    @SuppressWarnings("unchecked")
-    public static List<String[]> readExcelMaxData(MultipartFile file, String[] title) throws RRException {
-        try {
-            String fileName = file.getOriginalFilename();
-            String prefix = fileName.substring(fileName.lastIndexOf("."));
-            File excelFile = File.createTempFile("itemAA", prefix);
-            file.transferTo(excelFile);
-            ExcelReaderUtil.list.clear();
-            ExcelReaderUtil.readExcel(excelFile.toString());
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return  ExcelReaderUtil.list;
-    }
-}

+ 8 - 5
src/main/resources/application-dev.yml

@@ -2,14 +2,17 @@ server:
   port: 39101
 spring:
   datasource:
+    driver-class-name: org.postgresql.Driver
     username: postgres
     password: Test!234
-    driver-class-name: org.postgresql.Driver
     url: jdbc:postgresql://192.168.65.128:5432/financialdb
+#    username: finance
+#    password: Finance@unicom23
+#    url: jdbc:postgresql://172.16.107.5:5432/financialdb
 logging:
   level:
     com:
-      nokia: debug
-mybatis-plus:
-  configuration:
-    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+      example: debug
+#mybatis-plus:
+#  configuration:
+#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

+ 1 - 1
src/main/resources/application-prod.yml

@@ -16,4 +16,4 @@ knife4j:
 logging:
   level:
     com:
-      nokia: info
+      example: info

+ 15 - 0
src/main/resources/application-test.yml

@@ -0,0 +1,15 @@
+server:
+  port: 39101
+spring:
+  datasource:
+    driver-class-name: org.postgresql.Driver
+    url: jdbc:postgresql://192.168.50.3:15432/financialdb
+    username: postgres
+    password: NFQCgBA6YhNvgAqG6THw
+logging:
+  level:
+    com:
+      example: debug
+#mybatis-plus:
+#  configuration:
+#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl