最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring AOP結(jié)合注解實現(xiàn)接口層操作日志記錄

 更新時間:2022年08月18日 10:57:53   作者:llp1110  
在項目開發(fā)中我們需要記錄接口的操作日志:包含請求參數(shù)、響應(yīng)參數(shù)、接口所屬模塊、接口功能描述、請求地址、ip地址等信息;實現(xiàn)思路很簡單就是基于注解和aop的方式去記錄日志,主要的難點在于日志表結(jié)構(gòu)、注解的設(shè)計已經(jīng)aop實現(xiàn)的一些比較好的實現(xiàn)方式的借鑒

1.表和實體設(shè)計

1.實體設(shè)計

實體基類

@Data
//映射將僅應(yīng)用于其子類
@MappedSuperclass
//指定要用于實體或映射超類的回調(diào)偵聽器類。此注釋可以應(yīng)用于實體類或映射的超類。
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity implements Serializable {
    /**
     * @Id 注解標識
     * @GeneratedValue(generator = "snowflakeIdIDGenerator") 指定生成策略
     * @GenericGenerator(name = "snowflakeIdIDGenerator", strategy = "net.cqnews.base.idconfig.SnowflakeIdGenerator")
     * name 唯一的生成器名稱
     * strategy 生成器策略可以是預(yù)定義的 Hibernate 策略或完全限定的類名。
     * parameters 可選的生成器參數(shù)。
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(columnDefinition = "bigint(20) COMMENT '主鍵Id'")
    private Long id;
    @CreatedBy
    @Column(columnDefinition = "bigint(20) COMMENT '創(chuàng)建人Id'")
    private Long createId;
    @CreatedDate
    @Column(columnDefinition = "datetime COMMENT '創(chuàng)建時間'")
    private Date createTime;
    @LastModifiedBy
    @Column(columnDefinition = "bigint(20) COMMENT '修改人Id'")
    private Long updateId;
    @LastModifiedDate
    @Column(columnDefinition = "datetime COMMENT '修改時間'")
    private Date updateTime;
    /**
     * 是否刪除
     */
    @Column(columnDefinition = "tinyint default 0 COMMENT '是否刪除,默認否'")
    private Boolean deleted = Boolean.FALSE;
}

操作日志表實體

@Entity
@Data
//指定表名
@Table(name = "sys_oper_log")
//表名注釋
@org.hibernate.annotations.Table(appliesTo = "sys_oper_log", comment = "系統(tǒng)操作日志表")
public class SysOperLog extends BaseEntity {
    @Column(columnDefinition = "varchar(50) COMMENT '模塊標題'")
    private String title;
    @Column(columnDefinition = "varchar(255) COMMENT '接口功能描述'")
    private String description;
    @Column(columnDefinition = "varchar(100) COMMENT '方法名稱'")
    private String method;
    @Column(columnDefinition = "varchar(10) COMMENT '請求方式'")
    private String requestMethod;
    @Column(columnDefinition = "varchar(50) COMMENT '操作人員名稱'")
    private String operatorName;
    @Column(columnDefinition = "varchar(255) COMMENT '請求URL'")
    private String requestUrl;
    @Column(columnDefinition = "varchar(255) COMMENT '主機地址'")
    private String requestIp;
    @Column(columnDefinition = "varchar(255) COMMENT '操作地點'")
    private String operationLocation;
    @Column(columnDefinition = "varchar(2000) COMMENT '請求參數(shù)'")
    private String operatorParam;
    @Column(columnDefinition = "varchar(2000) COMMENT '返回參數(shù)'")
    private String jsonResult;
    @Enumerated(EnumType.STRING)
    @Column(columnDefinition = "varchar(20) COMMENT '操作狀態(tài)'")
    private StatusEnum status;
    @Column(columnDefinition = "varchar(2000) COMMENT '錯誤描述'")
    private String errorMsg;
}

狀態(tài)枚舉類

@AllArgsConstructor
@Getter
public enum StatusEnum {
    SUCCESS,
    FAIL
}

2.表結(jié)構(gòu)設(shè)計

CREATE TABLE `sys_oper_log` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主鍵Id',
  `create_id` bigint DEFAULT NULL COMMENT '創(chuàng)建人Id',
  `create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',
  `deleted` tinyint DEFAULT '0' COMMENT '是否刪除,默認否',
  `update_id` bigint DEFAULT NULL COMMENT '修改人Id',
  `update_time` datetime DEFAULT NULL COMMENT '修改時間',
  `description` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '接口功能描述',
  `error_msg` varchar(2000) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '錯誤描述',
  `json_result` varchar(2000) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '返回參數(shù)',
  `method` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '方法名稱',
  `operation_location` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作地點',
  `operator_name` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作人員名稱',
  `operator_param` varchar(2000) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '請求參數(shù)',
  `request_ip` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '主機地址',
  `request_method` varchar(10) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '請求方式',
  `request_url` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '請求URL',
  `status` varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作狀態(tài)',
  `title` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '模塊標題',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系統(tǒng)操作日志表';

2.日志注解

參考下面這段swagger接口文檔屬性的方式,在controller層日志記錄主要包含:接口所屬模塊、接口功能描述、請求參數(shù)、響應(yīng)參數(shù)等

當然請求參數(shù)和響應(yīng)參數(shù)不是每個接口都會包含的,因此這里注解設(shè)計了isSaveRequestData是否保存請求參數(shù)、isSaveResponseData是否保存響應(yīng)的參數(shù)兩個字段便于靈活控制,當然我們在做日志記錄處理時也需要考慮為空的情況。

@Log(title = "測試模塊",description = "更新配置")
@ApiOperation(value = "更新配置")
@RequestMapping(value = "/update", method = RequestMethod.PUT)
public BaseResult update(@Validated @RequestBody AuthConfigUpdateRequest request) {
    return BaseResult.judgeOperate(authConfigService.update(request));
}
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    /**
     * 接口所屬模塊
     */
    public String title() default "";
    /**
     * 接口功能描述
     */
    public String description() default "";
    /**
     * 是否保存請求的參數(shù)
     */
    public boolean isSaveRequestData() default true;
    /**
     * 是否保存響應(yīng)的參數(shù)
     */
    public boolean isSaveResponseData() default true;
}

3.核心AOP類

我們設(shè)計的@Log注解主要用于修飾controller層,MyLogAspect主要就是對被@Log修飾的目標方法做增強處理,包含處理完請求后執(zhí)行:記錄目標方法正在執(zhí)行的日志、處理請求異常后執(zhí)行:記錄目標方法執(zhí)行錯誤的日志

@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class MyLogAspect {
    private final SysOperLogService sysOperLogService;
    /**
     * 處理完請求后執(zhí)行
     *
     * @param joinPoint     切入點對象
     * @param controllerLog @Log注解對象
     * @param jsonResult    返回值對象
     */
    @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
        handleLog(joinPoint, controllerLog, jsonResult, null);
    }
    /**
     * 處理請求異常后執(zhí)行
     *
     * @param joinPoint
     * @param controllerLog
     * @param e
     */
    @AfterThrowing(pointcut = "@annotation(controllerLog)", throwing = "e")
    public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Throwable e) {
        handleLog(joinPoint, controllerLog, null, e);
    }
    /**
     * 記錄日志
     *
     * @param joinPoint
     * @param controllerLog
     * @param e
     * @param jsonResult
     */
    private void handleLog(JoinPoint joinPoint, Log controllerLog, Object jsonResult, Throwable e) {
        try {
            //獲取HttpServletRequest對象
            HttpServletRequest request = getRequest();
            //獲取ip地址
            String requestIp = IpUtils.getIpAddr(request);
            //獲取請求地址
            String requestUrl = request.getRequestURI();
            //獲取類全名
            String classFullName = joinPoint.getTarget().getClass().getName();
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            //方法名稱
            String methodName = methodSignature.getMethod().getName();
            //POST、GET、PUT、DELETE
            String requestMethod = request.getMethod();
            String operationLocation = AddressUtils.getRealAddressByIP(requestIp);
            //保存日志
            SysOperLog sysOperLog = new SysOperLog();
            sysOperLog.setStatus(StatusEnum.SUCCESS);
            sysOperLog.setOperationLocation(operationLocation);
            sysOperLog.setRequestIp(requestIp);
            sysOperLog.setRequestUrl(requestUrl);
            sysOperLog.setMethod(classFullName + "." + methodName);
            sysOperLog.setRequestMethod(requestMethod);
            //獲取注解中對方法的描述信息 用于Controller層注解 請求參數(shù)、響應(yīng)參數(shù)設(shè)置
            getControllerMethodDescription(joinPoint, controllerLog, sysOperLog, jsonResult);
            if (e != null) {
                //操作狀態(tài)(0正常 1異常)
                sysOperLog.setStatus(StatusEnum.FAIL);
                sysOperLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
            }
            sysOperLogService.saveOperatorLog(sysOperLog);
        } catch (Exception err) {
            if (e != null) {
                log.error("方法執(zhí)行后異常通知,執(zhí)行錯誤:{}", err.getMessage());
            } else {
                log.error("方法執(zhí)行成功返回通知,執(zhí)行錯誤:{}", err.getMessage());
            }
        }
    }
    /**
     * 獲取注解中對方法的描述信息 用于Controller層注解
     * 請求參數(shù)、響應(yīng)參數(shù)設(shè)置
     *
     * @param joinPoint
     * @param controllerLog
     * @param sysOperLog
     * @param jsonResult
     */
    private void getControllerMethodDescription(JoinPoint joinPoint, Log controllerLog, SysOperLog sysOperLog, Object jsonResult) {
        //接口所屬模塊
        String title = controllerLog.title();
        //接口功能描述
        String description = controllerLog.description();
        sysOperLog.setDescription(description);
        sysOperLog.setTitle(title);
        //判斷是否需要保存請求參數(shù)
        if (controllerLog.isSaveRequestData()) {
            // 獲取參數(shù)的信息,傳入到數(shù)據(jù)庫中。
            setRequestValue(joinPoint, sysOperLog);
        }
        //判斷是否需要保存響應(yīng)數(shù)據(jù)
        if (controllerLog.isSaveResponseData() && !ObjectUtils.isEmpty(jsonResult)) {
            sysOperLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000));
        }
    }
    /**
     * 保存請求參數(shù)
     *
     * @param joinPoint
     * @param sysOperLog
     */
    private void setRequestValue(JoinPoint joinPoint, SysOperLog sysOperLog) {
        //獲取請求參數(shù)
        String requestMethod = sysOperLog.getRequestMethod();
        if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
            String params = argsArrayToString(joinPoint.getArgs());
            sysOperLog.setOperatorParam(StringUtils.substring(params, 0, 2000));
        } else if (HttpMethod.GET.name().equals(requestMethod)) {
            Map<?, ?> paramsMap = (Map<?, ?>) getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
            log.info("paramsMap:{}", paramsMap);
            Map<String, String[]> parameterMap = getRequest().getParameterMap();
            sysOperLog.setOperatorParam(StringUtils.substring(JSON.toJSONString(parameterMap), 0, 2000));
        } else {
            Map<?, ?> paramsMap = (Map<?, ?>) getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
            log.info("paramsMap:{}", paramsMap);
            sysOperLog.setOperatorParam(StringUtils.substring(paramsMap.toString(), 0, 2000));
        }

    }
    /**
     * 參數(shù)拼裝
     */
    private String argsArrayToString(Object[] paramsArray) {
        String params = "";
        if (paramsArray != null && paramsArray.length > 0) {
            for (Object o : paramsArray) {
                if (!ObjectUtils.isEmpty(o) && !isFilterObject(o)) {
                    try {
                        Object jsonObj = JSON.toJSON(o);
                        params += jsonObj.toString() + " ";
                    } catch (Exception e) {
                    }
                }
            }
        }
        return params.trim();
    }
    /**
     * 判斷是否需要過濾的對象。
     *
     * @param o 對象信息。
     * @return 如果是需要過濾的對象,則返回true;否則返回false。
     */
    @SuppressWarnings("rawtypes")
    public boolean isFilterObject(final Object o) {
        Class<?> clazz = o.getClass();
        if (clazz.isArray()) {
            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
        } else if (Collection.class.isAssignableFrom(clazz)) {
            Collection collection = (Collection) o;
            for (Object value : collection) {
                return value instanceof MultipartFile;
            }
        } else if (Map.class.isAssignableFrom(clazz)) {
            Map map = (Map) o;
            for (Object value : map.entrySet()) {
                Map.Entry entry = (Map.Entry) value;
                return entry.getValue() instanceof MultipartFile;
            }
        }
        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
                || o instanceof BindingResult;
    }
    /**
     * 獲取request對象
     *
     * @return
     */
    private HttpServletRequest getRequest() {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) attributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        return request;
    }
}

4.用到的工具類

獲取ip地址

/**
 * 獲取IP方法
 *
 */
public class IpUtils {
    /**
     * 獲取客戶端IP
     *
     * @param request 請求對象
     * @return IP地址
     */
    public static String getIpAddr(HttpServletRequest request) {
        if (request == null) {
            return "unknown";
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Forwarded-For");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
    }
    /**
     * 檢查是否為內(nèi)部IP地址
     *
     * @param ip IP地址
     * @return 結(jié)果
     */
    public static boolean internalIp(String ip) {
        byte[] addr = textToNumericFormatV4(ip);
        return internalIp(addr) || "127.0.0.1".equals(ip);
    }
    /**
     * 檢查是否為內(nèi)部IP地址
     *
     * @param addr byte地址
     * @return 結(jié)果
     */
    private static boolean internalIp(byte[] addr) {
        if (addr == null || addr.length < 2) {
            return true;
        }
        final byte b0 = addr[0];
        final byte b1 = addr[1];
        // 10.x.x.x/8
        final byte SECTION_1 = 0x0A;
        // 172.16.x.x/12
        final byte SECTION_2 = (byte) 0xAC;
        final byte SECTION_3 = (byte) 0x10;
        final byte SECTION_4 = (byte) 0x1F;
        // 192.168.x.x/16
        final byte SECTION_5 = (byte) 0xC0;
        final byte SECTION_6 = (byte) 0xA8;
        switch (b0) {
            case SECTION_1:
                return true;
            case SECTION_2:
                if (b1 >= SECTION_3 && b1 <= SECTION_4) {
                    return true;
                }
            case SECTION_5:
                switch (b1) {
                    case SECTION_6:
                        return true;
                }
            default:
                return false;
        }
    }
    /**
     * 將IPv4地址轉(zhuǎn)換成字節(jié)
     *
     * @param text IPv4地址
     * @return byte 字節(jié)
     */
    public static byte[] textToNumericFormatV4(String text) {
        if (text.length() == 0) {
            return null;
        }
        byte[] bytes = new byte[4];
        String[] elements = text.split("\\.", -1);
        try {
            long l;
            int i;
            switch (elements.length) {
                case 1:
                    l = Long.parseLong(elements[0]);
                    if ((l < 0L) || (l > 4294967295L)) {
                        return null;
                    }
                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 2:
                    l = Integer.parseInt(elements[0]);
                    if ((l < 0L) || (l > 255L)) {
                        return null;
                    }
                    bytes[0] = (byte) (int) (l & 0xFF);
                    l = Integer.parseInt(elements[1]);
                    if ((l < 0L) || (l > 16777215L)) {
                        return null;
                    }
                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 3:
                    for (i = 0; i < 2; ++i) {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L)) {
                            return null;
                        }
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    l = Integer.parseInt(elements[2]);
                    if ((l < 0L) || (l > 65535L)) {
                        return null;
                    }
                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 4:
                    for (i = 0; i < 4; ++i) {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L)) {
                            return null;
                        }
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    break;
                default:
                    return null;
            }
        } catch (NumberFormatException e) {
            return null;
        }
        return bytes;
    }
    /**
     * 獲取IP地址
     *
     * @return 本地IP地址
     */
    public static String getHostIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
        }
        return "127.0.0.1";
    }
    /**
     * 獲取主機名
     *
     * @return 本地主機名
     */
    public static String getHostName() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
        }
        return "未知";
    }
    /**
     * 從多級反向代理中獲得第一個非unknown IP地址
     *
     * @param ip 獲得的IP地址
     * @return 第一個非unknown IP地址
     */
    public static String getMultistageReverseProxyIp(String ip) {
        // 多級反向代理檢測
        if (ip != null && ip.indexOf(",") > 0) {
            final String[] ips = ip.trim().split(",");
            for (String subIp : ips) {
                if (false == isUnknown(subIp)) {
                    ip = subIp;
                    break;
                }
            }
        }
        return ip;
    }
    /**
     * 檢測給定字符串是否為未知,多用于檢測HTTP請求相關(guān)
     *
     * @param checkString 被檢測的字符串
     * @return 是否未知
     */
    public static boolean isUnknown(String checkString) {
        return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
    }
    public static void main(String[] args) {
        String hostIp = IpUtils.getHostIp();
        System.out.println(hostIp);
    }
}

根據(jù)ip地址獲取位置信息

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
/**
 * 根據(jù)ip獲取地理位置信息
 */
public class AddressUtils {
    private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
    // IP地址查詢,太平洋ip地址查詢
    public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
    // 未知地址
    public static final String UNKNOWN = "XX XX";
    /**
     * UTF-8 字符集
     */
    public static final String UTF8 = "UTF-8";
    /**
     * GBK 字符集
     */
    public static final String GBK = "GBK";
    public static String getRealAddressByIP(String ip) {
        // 內(nèi)網(wǎng)不查詢
        if (IpUtils.internalIp(ip)) {
            return "內(nèi)網(wǎng)IP";
        }
        try {
            String rspStr = sendGet(IP_URL, "ip=" + ip + "&json=true", GBK);
            if (StringUtils.isNotBlank(rspStr)) {
                log.error("獲取地理位置異常 {}", ip);
                return UNKNOWN;
            }
            JSONObject obj = JSON.parseObject(rspStr);
            String region = obj.getString("pro");
            String city = obj.getString("city");
            return String.format("%s %s", region, city);
        } catch (Exception e) {
            log.error("獲取地理位置異常 {}", ip);
        }
        return UNKNOWN;
    }
    /**
     * 向指定 URL 發(fā)送GET方法的請求
     *
     * @param url         發(fā)送請求的 URL
     * @param param       請求參數(shù),請求參數(shù)應(yīng)該是 name1=value1&name2=value2 的形式。
     * @param contentType 編碼類型
     * @return 所代表遠程資源的響應(yīng)結(jié)果
     */
    public static String sendGet(String url, String param, String contentType) {
        StringBuilder result = new StringBuilder();
        BufferedReader in = null;
        try {
            String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
            log.info("sendGet - {}", urlNameString);
            URL realUrl = new URL(urlNameString);
            URLConnection connection = realUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            connection.connect();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            log.info("recv - {}", result);
        } catch (ConnectException e) {
            log.error("調(diào)用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
        } catch (SocketTimeoutException e) {
            log.error("調(diào)用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
        } catch (IOException e) {
            log.error("調(diào)用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
        } catch (Exception e) {
            log.error("調(diào)用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception ex) {
                log.error("調(diào)用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }
}

5.測試類

在需要記錄日志的目標方法添加我們自定義的@Log注解,通過aop記錄日志

@Api(tags = "測試模塊")
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/test")
public class AuthController {
    private final AuthConfigService authConfigService;
    @Log(title = "測試模塊",description = "更新配置")
    @ApiOperation(value = "更新配置")
    @RequestMapping(value = "/update", method = RequestMethod.PUT)
    public BaseResult update(@Validated @RequestBody AuthConfigUpdateRequest request) {
        return BaseResult.judgeOperate(authConfigService.update(request));
    }
    @Log(title = "測試模塊",description = "新增配置")
    @ApiOperation(value = "新增配置")
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public BaseResult create(@Validated @RequestBody AuthConfigRequest request) {
        return BaseResult.judgeOperate(authConfigService.create(request));
    }
    @Log(title = "測試模塊",description = "刪除配置")
    @ApiOperation(value = "刪除配置")
    @DeleteMapping(value = "/delete/{ids}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ids", value = "配置id,多個id用逗號分隔", required = true)
    })
    public BaseResult delete(@PathVariable("ids") List<Long> ids) {
        return BaseResult.judgeOperate(authConfigService.delete(ids));
    }
    @Log(title = "測試模塊",description = "配置分頁")
    @ApiOperation(value = "配置分頁")
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public BaseResult<PageResponse<AuthConfigListResponse>> list(@RequestBody AuthConfigListRequest request) {
        return BaseResult.success(PageResponse.getInstance(authConfigService.list(request)));
    }
    @Log(title = "測試模塊",description = "根據(jù)appId獲取配置信息")
    @ApiOperation(value = "根據(jù)appId獲取配置信息")
    @RequestMapping(value = "/detail", method = RequestMethod.GET)
    public BaseResult<EduAuthConfig> detail(String appId) {
        return BaseResult.success(authConfigService.getAuthConfig(appId));
    }
}

6.測試結(jié)果

到此這篇關(guān)于Spring AOP結(jié)合注解實現(xiàn)接口層操作日志記錄的文章就介紹到這了,更多相關(guān)Spring AOP接口層內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot集成drools的實現(xiàn)示例

    SpringBoot集成drools的實現(xiàn)示例

    本文主要介紹了SpringBoot集成drools的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2022-05-05
  • SpringBoot2 task scheduler 定時任務(wù)調(diào)度器四種方式

    SpringBoot2 task scheduler 定時任務(wù)調(diào)度器四種方式

    這篇文章主要介紹了SpringBoot2 task scheduler 定時任務(wù)調(diào)度器四種方式,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2019-03-03
  • Java 根據(jù)貸款年限對應(yīng)利率計算功能實現(xiàn)解析

    Java 根據(jù)貸款年限對應(yīng)利率計算功能實現(xiàn)解析

    這篇文章主要介紹了Java 根據(jù)貸款年限對應(yīng)利率計算功能實現(xiàn)解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友可以參考下
    2019-10-10
  • Java中實現(xiàn)樹形菜單的兩種方式

    Java中實現(xiàn)樹形菜單的兩種方式

    這篇文中,我一共會用兩種方式來實現(xiàn)目錄樹的數(shù)據(jù)結(jié)構(gòu),兩種寫法邏輯是一樣的,只是一種適合新手理解,一種看著簡單明了但是對于小白不是很好理解,在這里我會很詳細的講解每一步代碼,主要是方便新人看懂,彌補曾經(jīng)自己學(xué)習過程中的苦惱,需要的朋友可以參考下
    2023-09-09
  • Java中值類型和引用類型的比較與問題解決

    Java中值類型和引用類型的比較與問題解決

    這篇文章主要給大家介紹了關(guān)于Java中值類型和引用類型的比較與問題解決方法,文中通過示例代碼介紹的非常詳細,對大家學(xué)習或者使用Java具有一定的參考學(xué)習價值,需要的朋友們下面來一起學(xué)習學(xué)習吧
    2019-12-12
  • Java并發(fā)編程之Fork/Join框架詳解

    Java并發(fā)編程之Fork/Join框架詳解

    這篇文章主要介紹了Java并發(fā)編程之Fork/Join框架詳解,Fork/Join框架是Java7提供的一個用于并行執(zhí)行任務(wù)的框架,是一個把大任務(wù)分割成若干個小任務(wù),最終匯總每個小任務(wù)結(jié)果后得到大任務(wù)結(jié)果的框架,需要的朋友可以參考下
    2023-12-12
  • Java快速實現(xiàn)PDF轉(zhuǎn)圖片功能實例代碼

    Java快速實現(xiàn)PDF轉(zhuǎn)圖片功能實例代碼

    PDFBox是一個開源Java類庫,用于讀取和創(chuàng)建PDF文檔,它支持文本提取、表單處理、文檔加密解密、合并分割、內(nèi)容覆蓋追加、文檔打印和轉(zhuǎn)換等功能,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-09-09
  • Springboot自定義注解&傳參&簡單應(yīng)用方式

    Springboot自定義注解&傳參&簡單應(yīng)用方式

    SpringBoot框架中,通過自定義注解結(jié)合AOP可以實現(xiàn)功能如日志記錄與耗時統(tǒng)計,首先創(chuàng)建LogController和TimeConsuming注解,并為LogController定義參數(shù),然后,在目標方法上應(yīng)用這些注解,最后,使用AspectJ的AOP功能,通過切點表達式定位這些注解
    2024-10-10
  • Java數(shù)據(jù)脫敏實現(xiàn)的方法總結(jié)

    Java數(shù)據(jù)脫敏實現(xiàn)的方法總結(jié)

    數(shù)據(jù)脫敏,指的是對某些敏感信息通過脫敏規(guī)則進行數(shù)據(jù)的變形,實現(xiàn)敏感隱私數(shù)據(jù)的可靠保護,本文主要是對后端數(shù)據(jù)脫敏實現(xiàn)的簡單總結(jié),希望對大家有所幫助
    2023-07-07
  • Java之一文詳解String字符串的用法

    Java之一文詳解String字符串的用法

    本文將給大家重點講解一下String的用法,因為這個太常用,也太??剂?。String字符串的內(nèi)容是比較多的,需要初學(xué)者進行專門的學(xué)習,尤其是它的一些底層原理更需要我們來了解,需要的同學(xué)跟著小編一起學(xué)習吧
    2023-05-05

最新評論

临洮县| 威宁| 富宁县| 诏安县| 灵宝市| 南部县| 八宿县| 兴隆县| 观塘区| 洪江市| 富阳市| 迭部县| 肇庆市| 九台市| 留坝县| 东明县| 西青区| 桂林市| 故城县| 武定县| 平潭县| 四平市| 高州市| 嘉义市| 云安县| 崇信县| 神农架林区| 临颍县| 青海省| 霍林郭勒市| 平陆县| 沈丘县| 西乡县| 临汾市| 邳州市| 衡阳县| 六枝特区| 舒城县| 富平县| 卢龙县| 崇明县|