天天看點

Springboot+AOP實作系統日志子產品,請求參數、傳回結果。根據記錄生成ApiPost文檔一、引入AOP依賴二、生成必要枚舉類和接口三、建立注解類 OperationLog.java 四、建立切面處理類(重要!) SystemLogAspect.java五、資料庫SQL六、其他 

一、引入AOP依賴

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
           

二、生成必要枚舉類和接口

(1)OpType.java (操作類型)

package com.plat.sysLog.logEnum;

/**
 * @author xxs
 * @date 2022年08月10日 16:44
 */
public interface OpType {

    /**
     * 新增
     */
    public static final int ADD = 1;

    /**
     * 修改
     */
    public static final int UPDATE = 2;
    /**
     * 删除
     */
    public static final int DELETE = 3;
    /**
     * 查詢-分頁
     */
    public static final int QUERY_PAGE = 4;
    /**
     * 其他
     */
    public static final int OTHER = 5;
    /**
     * 登入
     */
    public static final int LOGIN = 6;
    /**
     * 登出
     */
    public static final int LOGOUT = 7;
    /**
     * 導出
     */
    public static final int EXPORT = 8;
    /**
     * 導入
     */
    public static final int IMPORT = 9;
    /**
     * 儲存
     */
    public static final int SAVE = 10;
    /**
     * 發送郵件
     */
    public static final int SEND_EMAIL = 11;
    /**
     * 發送短信
     */
    public static final int SMS = 12;
    /**
     * 查詢-不分頁
     */
    public static final int QUERY_NO_PAGE = 13;
    /**
     * 查詢明細
     */
    public static final int QUERY_DETAIL = 14;
    /**
     * 稽核
     */
    public static final int AUDIT = 15;
    /**
     * 反稽核
     */
    public static final int UN_AUDIT = 16;
    /**
     * 下載下傳
     */
    public static final int DOWNLOAD = 17;
    /**
     * 上傳
     */
    public static final int UPLOAD = 18;
    /**
     * 校驗
     */
    public static final int CHECK = 19;
    /**
     * 安裝
     */
    public static final int INSTALL = 20;
    /**
     * 解除安裝
     */
    public static final int UN_INSTALL = 21;
    /**
     * 啟動
     */
    public static final int START = 22;
    /**
     * 停止
     */
    public static final int STOP = 23;
    /**
     * 重新開機
     */
    public static final int RESTART = 24;
    /**
     * 暫停
     */
    public static final int PAUSE = 25;
    /**
     * 恢複
     */
    public static final int RESUME = 26;
    /**
     * 重新整理
     */
    public static final int REFRESH = 27;
    /**
     * 生成
     */
    public static final int GENERATE = 28;
    /**
     * 統計
     */
    public static final int STATISTICS = 29;

    /**
     * 同步
     */
    public static final int SYNC = 30;
    /**
     * 定時排程
     */
    public static final int SCHEDULE = 31;



}
           

(2)OpTypeEnum.java (操作類型枚舉)

package com.plat.sysLog.logEnum;

import java.util.ArrayList;
import java.util.List;

/**
 * @author hz
 */
public enum OpTypeEnum {
    /*
        1. 增加
        2. 删除
        3. 修改
        4. 查詢
        5. 其他
     */
    ADD(OpType.ADD, "新增"),

    UPDATE(OpType.UPDATE, "修改"),

    DELETE(OpType.DELETE, "删除"),

    QUERY_PAGE(OpType.QUERY_PAGE, "查詢-分頁", true),

    OTHER(OpType.OTHER, "其他"),

    LOGIN(OpType.LOGIN, "登入"),

    LOGOUT(OpType.LOGOUT, "登出"),

    EXPORT(OpType.EXPORT, "導出"),

    IMPORT(OpType.IMPORT, "導入"),

    SAVE(OpType.SAVE, "儲存"),

    SEND_EMAIL(OpType.SEND_EMAIL, "發送郵件"),

    SMS(OpType.SMS, "發送短信"),

    QUERY_NO_PAGE(OpType.QUERY_NO_PAGE, "查詢-不分頁", true),

    QUERY_DETAIL(OpType.QUERY_DETAIL, "查詢明細", true),

    AUDIT(OpType.AUDIT, "稽核"),

    UN_AUDIT(OpType.UN_AUDIT, "反稽核"),

    DOWNLOAD(OpType.DOWNLOAD, "下載下傳"),

    UPLOAD(OpType.UPLOAD, "上傳"),

    CHECK(OpType.CHECK, "校驗"),

    INSTALL(OpType.INSTALL, "安裝"),

    UN_INSTALL(OpType.UN_INSTALL, "解除安裝"),

    START(OpType.START, "啟動"),

    STOP(OpType.STOP, "停止"),

    RESTART(OpType.RESTART, "重新開機"),

    PAUSE(OpType.PAUSE, "暫停"),

    RESUME(OpType.RESUME, "恢複"),

    REFRESH(OpType.REFRESH, "重新整理"),

    GENERATE(OpType.GENERATE, "生成"),

    STATISTICS(OpType.STATISTICS, "統計"),

    SYNC(OpType.SYNC, "同步"),

    SCHEDULE(OpType.SCHEDULE, "定時排程"),

    last(0, "最後一個");
    final int key;
    final String desc;
    //是否忽略傳回結果
    final boolean ignoreResult;

    OpTypeEnum(int key, String desc) {
        this.key = key;
        this.desc = desc;
        this.ignoreResult = false;
    }

    OpTypeEnum(int key, String desc, boolean ignoreResult) {
        this.key = key;
        this.desc = desc;
        this.ignoreResult = ignoreResult;
    }

    /**
     * 根據key擷取desc
     */
    public static String getDesc(Integer key) {
        for (OpTypeEnum opTypeEnum : OpTypeEnum.values()) {
            if (opTypeEnum.getKey() == key) {
                return opTypeEnum.getDesc();
            }
        }
        return "";
    }

    /**
     * 擷取所有忽略傳回結果的Key集合
     */
    public static List<Integer> getIgnoreResultKeys() {
        List<Integer> keys = new ArrayList<>();
        for (OpTypeEnum opTypeEnum : OpTypeEnum.values()) {
            if (opTypeEnum.isIgnoreResult()) {
                keys.add(opTypeEnum.getKey());
            }
        }
        return keys;
    }

    public int getKey() {
        return key;
    }

    public String getDesc() {
        return desc;
    }

    public boolean isIgnoreResult() {
        return ignoreResult;
    }

}
           

(3)SysType.java (面向調用服務類型)

package com.plat.sysLog.logEnum;

/**
 * @author xxs
 * @date 2022年08月10日 16:50
 */
public interface SysType {
    /**
     * WEB服務
     */
    public static final int WEB = 1;
}
           

(4)SysLog.java(系統日志實體類)

package com.plat.sysLog.model;

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class SysLog {

    private static final long serialVersionUID = 1L;
    /**
     *
     */
    private Long id;

    /**
     * 操作人
     */
    private String operationUser;

    /**
     * 請求路徑
     */
    private String path;

    /**
     * 開始時間
     */
    private String startTime;
    /**
     * 結束時間
     */
    private String endTime;


    /**
     * 方法入參
     */
    private String parameter;

    /**
     * 傳回參數
     */
    private String result;

    /**
     * 操作方法
     */
    private String title;

    /**
     * 方法描述
     */
    private String action;

    /**
     * 系統類型
     */
    private Integer sysType;

    /**
     * 操作類型
     */
    private Integer opType;

    /**
     * 請求ip
     */
    private String sourceIp;

    /**
     * 方法名稱
     */
    private String method;

    /**
     * 請求方式
     */
    private String requestMethod;

    /**
     * 操作狀态(0正常 1異常)
     */
    private Integer status;

    /**
     * 錯誤資訊
     */
    private String errorMsg;


    public SysLog() {

    }
}
           

三、建立注解類 OperationLog.java

package com.plat.sysLog.config;

import com.plat.sysLog.logEnum.OpType;
import com.plat.sysLog.logEnum.SysType;

import java.lang.annotation.*;

/**
 * @author xxs
 * @date 2022年08月10日 16:01
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface OperationLog {
    //功能子產品
    String title() default "";
    //詳情
    String desc() default "";
    //操作類型
    int opType() default OpType.OTHER;
    //接口調用方系統類型
    int sysType() default SysType.WEB;
    //是否忽略傳回結果,0跟随預設,1忽略,2不忽略
    int ignoreResult() default 0;
    //是否忽略請求參數
    boolean ignoreParam() default false;
    //是否來源于定時任務
    boolean fromTask() default false;

}
           

 四、建立切面處理類(重要!) SystemLogAspect.java

package com.hz.plat.sysLog.logAspect;

import com.alibaba.fastjson.JSONObject;
import com.plat.common.util.DateUtil;
import com.plat.common.util.IpAddressUtil;
import com.plat.shiro.TokenManager;
import com.plat.sysLog.config.OperationLog;
import com.plat.sysLog.dao.SysLogMapper;
import com.plat.sysLog.logEnum.OpTypeEnum;
import com.plat.sysLog.model.SysLog;
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.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author xxs
 * @date 2022年08月10日 16:01
 * @description 記錄檔切面
 */
@Aspect
@Component
@EnableAsync
@Order(-1)
@Slf4j
public class SystemLogAspect {
    SysLog sysLog = null;
    //日志 mapper
    @Resource
    private SysLogMapper logMapper;
    //請求
    private HttpServletRequest request = null;
    //是否忽略傳回結果
    private int ignoreResult = 0;
    //是否來源定時任務
    private boolean isScheduledTask = false;

    /**
     * 注解的位置
     */
    @Pointcut("@annotation(com.plat.sysLog.config.OperationLog)")
    public void logPointCut() {
    }


    @Around(value = "logPointCut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        try {
            sysLog = new SysLog();
            sysLog.setStartTime(DateUtil.getCurrentDateString("yyyy-MM-dd HH:mm:ss.SSS"));
            //通過uuid關聯請求參數和傳回參數
//            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            String user = null;
            try {
                user = TokenManager.getNickname();
            } catch (Exception e) {
                user = "未登入使用者";
            }
//            sysLog.setId(uuid);
            sysLog.setOperationUser(user);
            methodBefore(pjp);

            Object proceed = pjp.proceed();
            methodAfter(proceed);
            sysLog.setStatus(0);
            return proceed;
        } catch (Exception e) {
            sysLog.setStatus(1);
            sysLog.setErrorMsg(sysLog.getErrorMsg() + "errMsg:" + e.getMessage() + "\n" + "errStackTrace:" + e.getStackTrace()[0].toString() + "\n");
            log.error("【AOP日志管理】=========》", e);
            throw e;
        } finally {
            sysLog.setEndTime(DateUtil.getCurrentDateString("yyyy-MM-dd HH:mm:ss.SSS"));
            if (isScheduledTask) {
                sysLog.setRequestMethod("定時任務");
                sysLog.setSourceIp("定時任務");
                sysLog.setPath("定時任務");
            } else {
                String requestMethod = null;
                String requestPath = null;
                String ipAddress = null;
                try {
                    request = getHttpServletRequest();
                    requestMethod = request.getMethod();
                    requestPath = request.getServletPath();
                    ipAddress = IpAddressUtil.getIpAddress(request);
                } catch (Exception e) {
                    sysLog.setErrorMsg(sysLog.getErrorMsg() + "errMsg:" + e.getMessage() + "\n" + "errStackTrace:" + e.getStackTrace()[0].toString() + "\n");
                    log.error("【AOP日志管理】=========》", e);
                }
                sysLog.setSourceIp(ipAddress);
                sysLog.setRequestMethod(requestMethod);
                sysLog.setPath(requestPath);
            }
            logMapper.insert(sysLog);
        }
    }

    /**
     * 處理傳回結果
     * @param proceed
     */
    private void methodAfter(Object proceed) {
        if (ObjectUtils.nullSafeEquals(ignoreResult, 0)) {
            if (proceed != null) {
                String resultParamJsonStr = JSONObject.toJSONString(proceed);
                if (OpTypeEnum.getIgnoreResultKeys().contains(sysLog.getOpType())) {
                    sysLog.setResult("忽略傳回結果");
                } else {
                    sysLog.setResult(resultParamJsonStr);
                }
            }
        } else if (ObjectUtils.nullSafeEquals(ignoreResult, 1)) {
            sysLog.setResult("忽略傳回結果");
        }else if (ObjectUtils.nullSafeEquals(ignoreResult, 2)) {
            if (proceed != null) {
                String resultParamJsonStr = JSONObject.toJSONString(proceed);
                sysLog.setResult(resultParamJsonStr);
            }
        }
    }

    public void methodBefore(JoinPoint joinPoint) {
        // 列印請求内容
        try {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            Class<?> targetClass = null;
            try {
                targetClass = Class.forName(targetName);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            Method[] methods = new Method[0];
            if (targetClass != null) {
                methods = targetClass.getMethods();
            }
            Class<?>[] clazzs;
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length && method.getAnnotation(OperationLog.class) != null) {
                        String title = method.getAnnotation(OperationLog.class).title();
                        int sysType = method.getAnnotation(OperationLog.class).sysType();
                        int opType = method.getAnnotation(OperationLog.class).opType();
                        String action = method.getAnnotation(OperationLog.class).desc();
                        ignoreResult = method.getAnnotation(OperationLog.class).ignoreResult();
                        isScheduledTask = method.getAnnotation(OperationLog.class).fromTask();
                        boolean ignoreParam = method.getAnnotation(OperationLog.class).ignoreParam();
                        if (!ignoreParam) {
                            Map<String, Object> nameAndValue = getNameAndValue(joinPoint);
                            String paramJsonStr = JSONObject.toJSONString(nameAndValue);
                            sysLog.setParameter(paramJsonStr);
                        } else {
                            sysLog.setParameter("忽略請求參數");
                        }
                        String thisMethodName = targetName + "." + methodName;
                        sysLog.setTitle(title);
                        sysLog.setSysType(sysType);
                        sysLog.setOpType(opType);
                        sysLog.setAction(action);
                        sysLog.setMethod(thisMethodName);
                    }
                }
            }
        } catch (Exception e) {
            sysLog.setErrorMsg(sysLog.getErrorMsg() + "errMsg:" + e.getMessage() + "\n" + "errStackTrace:" + e.getStackTrace()[0].toString() + "\n");
        }
    }

    /**
     * @param joinPoint
     * @return
     * @Description 擷取入參方法參數
     */
    public Map<String, Object> getNameAndValue(JoinPoint joinPoint) {
        Map<String, Object> param = new HashMap<>();
        Object[] paramValues = joinPoint.getArgs();
        String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
        for (int i = 0; i < paramNames.length; i++) {
            if (paramValues[i] instanceof MultipartFile || paramValues[i] instanceof HttpSession || paramValues[i] instanceof ServletRequest || paramValues[i] instanceof ServletResponse) {
                param.put(paramNames[i], "忽略請求參數:" + paramValues[i].getClass().getTypeName());
            } else {
                param.put(paramNames[i], paramValues[i]);
            }
        }
        return param;
    }


    /**
     * @Description: 擷取request
     */
    public HttpServletRequest getHttpServletRequest() {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = null;
        if (sra != null) {
            request = sra.getRequest();
        }
        return request;
    }


}
           

五、資料庫SQL

CREATE TABLE `plat_sys_log` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `title` varchar(50) DEFAULT NULL COMMENT '操作方法',

  `action` varchar(50) DEFAULT NULL COMMENT '方法描述',

  `opType` int(2) DEFAULT NULL COMMENT '操作類型',

  `operationUser` varchar(50) DEFAULT NULL COMMENT '操作人',

  `path` varchar(255) DEFAULT NULL COMMENT '請求路徑',

  `startTime` varchar(50) DEFAULT NULL COMMENT '方法執行耗時',

  `endTime` varchar(50) DEFAULT NULL COMMENT '操作時間',

  `parameter` varchar(2000) DEFAULT NULL COMMENT '方法入參',

  `result` text COMMENT '傳回參數',

  `status` int(1) DEFAULT NULL COMMENT '操作狀态(0正常 1異常)',

  `sourceIp` varchar(128) DEFAULT NULL COMMENT '請求ip',

  `errorMsg` varchar(2000) DEFAULT NULL COMMENT '錯誤資訊',

  `requestMethod` varchar(10) DEFAULT '' COMMENT '請求方式',

  `method` varchar(100) DEFAULT NULL COMMENT '方法名稱',

  `sysType` int(2) DEFAULT NULL COMMENT '系統類型',

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=170 DEFAULT CHARSET=utf8;

六、其他 

至于mapper和dao層代碼我就不贅述了。給大家看一下效果圖

調用方式:

@OperationLog(title = "看闆統計", opType = OpType.STATISTICS,desc = "擷取看闆統計資訊") 

效果展示

Springboot+AOP實作系統日志子產品,請求參數、傳回結果。根據記錄生成ApiPost文檔一、引入AOP依賴二、生成必要枚舉類和接口三、建立注解類 OperationLog.java 四、建立切面處理類(重要!) SystemLogAspect.java五、資料庫SQL六、其他 
Springboot+AOP實作系統日志子產品,請求參數、傳回結果。根據記錄生成ApiPost文檔一、引入AOP依賴二、生成必要枚舉類和接口三、建立注解類 OperationLog.java 四、建立切面處理類(重要!) SystemLogAspect.java五、資料庫SQL六、其他 
Springboot+AOP實作系統日志子產品,請求參數、傳回結果。根據記錄生成ApiPost文檔一、引入AOP依賴二、生成必要枚舉類和接口三、建立注解類 OperationLog.java 四、建立切面處理類(重要!) SystemLogAspect.java五、資料庫SQL六、其他 

 七、生成apiPost.json接口文檔

        1、因為項目接口基本使用的Map進行前後端傳參,是以無法适用Swagger等主流API文檔生成插件。是以另辟蹊徑...

import com.alibaba.fastjson.JSONObject;
import com.hz.MubanApplication;
import com.hz.plat.common.util.DateUtil;
import com.hz.plat.sysLog.dao.SysLogMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.stereotype.Component;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author xxs
 * @date 2022年11月04日 09:27
 */
@Component
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MubanApplication.class)
@Slf4j
public class PostApiTest {

    @Resource
    SysLogMapper sysLogMapper;

    @Test
    public void getJsonFile() {
        String path = "C:\\Users\\xxs\\Desktop\\test.json";
        try {
            creteJsonFile(path);
            // File file = new File(path);
            // creteJsonFile(file);
        } catch (IOException e) {
            log.error("生成檔案失敗", e);
        }
    }

    /**
     * 直接生成json檔案
     *
     * @throws IOException
     */
    public void creteJsonFile(String filePath) throws IOException {
        List<Map> mapList = sysLogMapper.listForJson(new HashMap());
        List<Map> allFolderList = extractApiJson(mapList, true);
        // 補全json
        Map jsonMap = new HashMap();
        jsonMap.put("project", new HashMap() {{
            put("name", "Api-" + DateUtil.getCurrentDateString("yyyyMMddHHmmss"));
            put("description", "");
            put("details", new HashMap() {{
                put("variable", new ArrayList() {
                    {
                        add(new HashMap() {{
                            put("key", "userName");
                            put("description", "使用者名");
                        }});
                        add(new HashMap() {{
                            put("key", "password");
                            put("description", "密碼");
                        }});
                        add(new HashMap() {{
                            put("key", "loginName");
                            put("description", "登入名");
                        }});
                    }
                });
                put("markList", new ArrayList() {
                    {
                        add(new HashMap() {{
                            put("key", "developing");
                            put("name", "開發中");
                            put("color", "#3A86FF");
                            put("is_default", true);
                        }});
                        add(new HashMap() {{
                            put("key", "POST");
                            put("name", "POST請求");
                            put("color", "#2BA58F");
                            put("is_default", true);
                        }});
                        add(new HashMap() {{
                            put("key", "GET");
                            put("name", "GET請求");
                            put("color", "#EC4646");
                            put("is_default", true);
                        }});
                    }
                });
                put("script", new HashMap() {{
                    put("pre_script", "");
                    put("test", "");
                }});
                put("request", new HashMap() {{
                    put("query", new ArrayList());
                    put("header", new ArrayList());
                    put("body", new ArrayList());
                }});
            }});
        }});
        jsonMap.put("apis", allFolderList);
        jsonMap.put("envs", new ArrayList() {{
            add(new HashMap() {{
                put("env_id", "f69e93ad-67bc-4bcf-82ac-d3ddc844ff21");
                put("list", new HashMap());
                put("name", "接口文檔");
                put("pre_url", "http://192.168.0.188:8082");
            }});
            add(new HashMap() {{
                put("env_id", "-1");
                put("list", new HashMap());
                put("name", "預設環境");
                put("pre_url", "");
            }});
            add(new HashMap() {{
                put("env_id", "-2");
                put("list", new HashMap());
                put("name", "Mock環境");
                put("pre_url", "");
            }});
        }});
        String json = JSONObject.toJSONString(jsonMap);
        FileUtils.writeStringToFile(new File(filePath), json, "UTF-8");
    }


    /**
     * 生成json檔案
     * 根據原json檔案生成新的json檔案
     *
     * @param jsonFile
     * @throws IOException
     */
    public void creteJsonFile(File jsonFile) throws IOException {
        // 讀取apiJson.json檔案
        String oldJsonString = FileUtils.readFileToString(jsonFile, "UTF-8");
        JSONObject oldJson = JSONObject.parseObject(oldJsonString);
        // 過濾掉已經存在的接口
        List<Map> allOldApiList = new ArrayList();
        List<Map> oldApiList = (List<Map>) oldJson.get("apis");
        // 遞歸擷取所有接口
        getAllApiList(oldApiList, allOldApiList);

        Set<String> oldApiNameList = new HashSet();
        for (Map oldApi : allOldApiList) {
            Map request = (Map) oldApi.get("request");
            oldApiNameList.add(request.get("url").toString());
        }
        log.info("oldApiNameList:{}", oldApiNameList);
        // 查詢資料庫
        // 已經包含的接口排除掉
        List<Map> newApiList = sysLogMapper.listForJson(new HashMap() {{
            put("pathList", oldApiNameList);
        }});
        List<Map> apiJson = extractApiJson(newApiList,true);
        // 合并json
        oldApiList.addAll(apiJson);
        // 寫入新檔案
        // 在源檔案名後面加上new
        String newFileName = jsonFile.getAbsolutePath().replace(".json", "-new.json");
        FileUtils.writeStringToFile(new File(newFileName), oldJson.toJSONString(), "UTF-8");
    }

    /**
     * 提取接口json
     *
     * @param mapList
     * @return
     */
    public static List<Map> extractApiJson(List<Map> mapList,boolean createRootFolder) {
        List<Map> allFolderList = new ArrayList();
        List<String> allFolderNameList = new ArrayList();
        List<String> allApiNameList = new ArrayList();
        for (int i = 0, mapListSize = mapList.size(); i < mapListSize; i++) {
            Map dbMap = mapList.get(i);
            List<Map> children = new ArrayList();
            String title = dbMap.get("title").toString();
            if (allFolderNameList.contains(title)) {
                children = (List<Map>) allFolderList.get(allFolderNameList.indexOf(title)).get("children");
            } else {
                Map folderMap = new HashMap();
                folderMap.put("target_type", "folder");
                folderMap.put("name", title);
                folderMap.put("mark", "developing");
                folderMap.put("sort", 2 + i);
                folderMap.put("request", new HashMap() {{
                    put("description", "");
                }});
                folderMap.put("children", children);
                allFolderList.add(folderMap);
                allFolderNameList.add(title);
            }
            String path = dbMap.getOrDefault("path","").toString();
            if (allApiNameList.contains(path)) {
                continue;
            }
            //過濾參數

            Object parameter = getMyParameter(dbMap.get("parameter"));

            allApiNameList.add(path);
            Map apiMap = new HashMap();
            apiMap.put("target_type", "api");
            apiMap.put("name", dbMap.get("action"));
            apiMap.put("mark", dbMap.get("requestMethod"));
            apiMap.put("sort", 1 + i);
            apiMap.put("method", dbMap.get("requestMethod"));
            apiMap.put("mock", "{}");
            apiMap.put("mock_url", "");
            apiMap.put("request", new HashMap() {{
                put("url", dbMap.get("path"));
                put("description", "");
                put("event", new HashMap() {{
                    put("pre_script", "");
                    put("test", "");
                }});
                put("body", new HashMap() {{
                    put("mode", "json");
                    put("parameter", new ArrayList());
                    put("raw", parameter);
                    put("raw_para", new ArrayList());
                }});
            }});
            apiMap.put("response", new HashMap() {{
                put("success", new HashMap() {{
                    put("raw", dbMap.get("result"));
                    put("parameter", new ArrayList());
                    put("expect", new HashMap() {{
                        put("mock", "{}");
                    }});
                }});
                put("error", new HashMap() {{
                    put("raw", "");
                    put("parameter", new ArrayList());
                }});
            }});
            apiMap.put("children", new ArrayList());
            children.add(apiMap);
        }
        log.info("本次新增接口數量:{},檔案夾數量:{},接口名稱:{}", allApiNameList.size(), allFolderNameList.size(), allApiNameList);
        if(createRootFolder){
            Map rootFolder = new HashMap();
            rootFolder.put("target_type", "folder");
            rootFolder.put("name", "接口文檔");
            rootFolder.put("mark", "developing");
            rootFolder.put("sort", 1);
            rootFolder.put("request", new HashMap() {{
                put("description", "");
            }});
            rootFolder.put("children", allFolderList);
            allFolderList = new ArrayList() {{
                add(rootFolder);
            }};
        }
        return allFolderList;
    }

    private static Object getMyParameter(Object parameter) {
        if (parameter == null) {
            return null;
        }
        String parameterString = parameter.toString();
        //如果是json對象,提取除其中的Map
        if (parameterString.startsWith("{") && parameterString.endsWith("}")) {
            JSONObject jsonObject = JSONObject.parseObject(parameterString);
            Map<String, Object> map = new HashMap<>();
            for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
                Object value = entry.getValue();
                //不包含”忽略請求參數“
                if (value instanceof Map ){
                    return JSONObject.toJSONString(value);
                }
                if (value.toString().contains("忽略請求參數")) {
                    continue;
                }
                map.put(entry.getKey(), value);
            }
            return JSONObject.toJSONString(map);
        }
        return parameterString;
    }

    /**
     * 遞歸擷取所有接口
     * @param oldApiList
     * @param allOldApiList
     */
    private void getAllApiList(List<Map> oldApiList, List<Map> allOldApiList) {
        for (Map oldApiMap : oldApiList) {
            if ("api".equals(oldApiMap.get("target_type"))) {
                allOldApiList.add(oldApiMap);
            } else {
                List<Map> children = (List<Map>) oldApiMap.get("children");
                getAllApiList(children, allOldApiList);
            }
        }
    }
}
           

2、将生成的test.json檔案導入ApiPost中,效果展示

Springboot+AOP實作系統日志子產品,請求參數、傳回結果。根據記錄生成ApiPost文檔一、引入AOP依賴二、生成必要枚舉類和接口三、建立注解類 OperationLog.java 四、建立切面處理類(重要!) SystemLogAspect.java五、資料庫SQL六、其他 

 3、這裡隻貼出了關鍵部分代碼,如果有哪裡不清楚的歡迎留言