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

基于SpringBoot+AOP實(shí)現(xiàn)操作日志記錄

 更新時(shí)間:2026年04月17日 08:35:14   作者:希望永不加班  
本文介紹了使用日志記錄的實(shí)現(xiàn)方法,步驟包括明確記錄信息、搭建基礎(chǔ)環(huán)境、創(chuàng)建操作日志實(shí)體類(lèi)和自定義注解、創(chuàng)建AOP切面,重點(diǎn)在于精準(zhǔn)控制需要記錄日志的接口,通過(guò)自定義注解和使用、切點(diǎn)表達(dá)式、環(huán)繞通知實(shí)現(xiàn)實(shí)現(xiàn)日志記錄邏輯,需要的朋友可以參考下

今天就來(lái)講講Spring AOP最實(shí)用的實(shí)戰(zhàn)場(chǎng)景——用 SpringBoot + AOP 實(shí)現(xiàn)操作日志記錄。

操作日志是項(xiàng)目必備功能:比如用戶(hù)登錄、接口調(diào)用、數(shù)據(jù)新增/修改/刪除,都需要記錄操作人、操作時(shí)間、操作內(nèi)容、接口地址等信息,方便后續(xù)排查問(wèn)題、審計(jì)追溯。

一、明確操作日志要記錄哪些信息?

先梳理操作日志的核心字段,避免后續(xù)代碼遺漏,實(shí)戰(zhàn)中可根據(jù)項(xiàng)目需求增減,這里給出通用模板:

  • 操作人:當(dāng)前登錄用戶(hù)的用戶(hù)名/ID(實(shí)戰(zhàn)中結(jié)合 Spring Security 或 Token 獲?。?;
  • 操作時(shí)間:接口執(zhí)行的時(shí)間(精確到毫秒);
  • 操作模塊:比如“用戶(hù)管理”“訂單管理”“商品管理”(標(biāo)記當(dāng)前操作屬于哪個(gè)模塊);
  • 操作描述:比如“新增用戶(hù)”“刪除訂單”“查詢(xún)商品列表”(清晰說(shuō)明操作內(nèi)容);
  • 接口地址:被調(diào)用的接口 URL(比如 /api/user/add);
  • 請(qǐng)求方式:GET/POST/PUT/DELETE;
  • 請(qǐng)求參數(shù):接口接收的參數(shù)(JSON 格式);
  • 返回結(jié)果:接口返回的數(shù)據(jù)(JSON 格式);
  • 執(zhí)行狀態(tài):成功/失??;
  • 異常信息:如果接口執(zhí)行失敗,記錄異常詳情(便于排查);
  • 操作 IP:調(diào)用接口的客戶(hù)端 IP 地址。

二、從零實(shí)現(xiàn) AOP 操作日志

步驟1:搭建基礎(chǔ)環(huán)境(導(dǎo)入依賴(lài))

SpringBoot 項(xiàng)目中,實(shí)現(xiàn) AOP 只需導(dǎo)入 spring-boot-starter-aop 依賴(lài),無(wú)需額外導(dǎo)入其他包,在 pom.xml 中添加:

<!-- Spring AOP 依賴(lài) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- 工具包:用于 JSON 格式化、IP 地址獲?。蛇x,簡(jiǎn)化代碼) -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.32</version>
</dependency>
<!-- 用于獲取客戶(hù)端 IP(可選,也可自己寫(xiě)工具類(lèi)) -->
<dependency>
    <groupId>eu.bitwalker</groupId>
    <artifactId>UserAgentUtils</artifactId>
    <version>1.21</version>
</dependency>

說(shuō)明:fastjson2 用于將請(qǐng)求參數(shù)、返回結(jié)果轉(zhuǎn)為 JSON 字符串;UserAgentUtils 用于獲取客戶(hù)端 IP 和瀏覽器信息,可根據(jù)需求選擇是否導(dǎo)入。

步驟2:創(chuàng)建操作日志實(shí)體類(lèi)(存儲(chǔ)日志數(shù)據(jù))

創(chuàng)建實(shí)體類(lèi) OperationLog,對(duì)應(yīng)操作日志的核心字段,后續(xù)可直接映射到數(shù)據(jù)庫(kù)(這里省略數(shù)據(jù)庫(kù)操作,重點(diǎn)放在 AOP 實(shí)現(xiàn)):

import lombok.Data;
import java.time.LocalDateTime;
/**
 * 操作日志實(shí)體類(lèi)
 */
@Data
public class OperationLog {
    // 主鍵(實(shí)戰(zhàn)中可自增)
    private Long id;
    // 操作人(用戶(hù)名/ID)
    private String operator;
    // 操作時(shí)間
    private LocalDateTime operationTime;
    // 操作模塊
    private String module;
    // 操作描述
    private String description;
    // 接口地址
    private String requestUrl;
    // 請(qǐng)求方式
    private String requestMethod;
    // 請(qǐng)求參數(shù)(JSON 格式)
    private String requestParams;
    // 返回結(jié)果(JSON 格式)
    private String responseResult;
    // 執(zhí)行狀態(tài)(0-失敗,1-成功)
    private Integer status;
    // 異常信息(失敗時(shí)填寫(xiě))
    private String errorMsg;
    // 操作 IP
    private String operationIp;
}

說(shuō)明:用 @Data 注解(lombok)簡(jiǎn)化 getter/setter 方法,實(shí)戰(zhàn)中需導(dǎo)入 lombok 依賴(lài)(如果未導(dǎo)入)。

步驟3:創(chuàng)建自定義注解(精準(zhǔn)定位需要記錄日志的接口)

我們用「自定義注解」來(lái)標(biāo)記需要記錄操作日志的接口,這樣可以靈活控制哪些接口需要記錄日志,哪些不需要——比直接用切點(diǎn)表達(dá)式匹配包/類(lèi)更靈活。

import java.lang.annotation.*;
/**
 * 自定義操作日志注解
 * @Target:注解作用范圍(METHOD:作用在方法上)
 * @Retention:注解保留時(shí)機(jī)(RUNTIME:運(yùn)行時(shí)保留,AOP 可獲?。?
 * @Documented:生成文檔時(shí)包含該注解
 */
@Target(ElementType.METHOD) // 只作用于方法
@Retention(RetentionPolicy.RUNTIME) // 運(yùn)行時(shí)生效
@Documented
public @interface OperationLogAnnotation {
    // 操作模塊(必填,比如“用戶(hù)管理”)
    String module() default "";
    // 操作描述(必填,比如“新增用戶(hù)”)
    String description() default "";
}

說(shuō)明:該注解有兩個(gè)屬性,module(操作模塊)和 description(操作描述),在需要記錄日志的接口方法上添加該注解,并填寫(xiě)對(duì)應(yīng)屬性即可。

步驟4:創(chuàng)建 AOP 切面(實(shí)現(xiàn)日志記錄)

這是本次實(shí)戰(zhàn)的核心,創(chuàng)建切面類(lèi),定義切點(diǎn)(匹配帶有 @OperationLogAnnotation 注解的方法)、通知(環(huán)繞通知,實(shí)現(xiàn)日志記錄邏輯),完成日志的收集和處理。

import com.alibaba.fastjson2.JSON;
import eu.bitwalker.useragentutils.UserAgent;
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.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;
/**
 * 操作日志切面類(lèi)
 * @Aspect:標(biāo)記此類(lèi)為切面
 * @Component:交給 Spring 管理,讓 Spring 掃描到該切面
 */
@Aspect
@Component
public class OperationLogAspect {
    // 1. 定義切點(diǎn):匹配帶有 @OperationLogAnnotation 注解的方法
    @Pointcut("@annotation(com.example.demo.annotation.OperationLogAnnotation)")
    public void operationLogPointcut() {} // 切點(diǎn)方法,無(wú)實(shí)際邏輯,僅用于標(biāo)記
    // 2. 定義環(huán)繞通知:包裹切點(diǎn)方法,可在方法執(zhí)行前、執(zhí)行后、異常時(shí)處理
    @Around("operationLogPointcut()")
    public Object recordOperationLog(ProceedingJoinPoint joinPoint) throws Throwable {
        // 1. 初始化操作日志對(duì)象
        OperationLog operationLog = new OperationLog();
        // 2. 獲取當(dāng)前請(qǐng)求對(duì)象,用于獲取請(qǐng)求信息(URL、請(qǐng)求方式、IP 等)
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 3. 填充日志基礎(chǔ)信息(無(wú)論接口成功/失敗,都需要記錄)
        // 3.1 獲取操作人(實(shí)戰(zhàn)中需結(jié)合 Spring Security/Token 獲取,這里模擬 admin)
        operationLog.setOperator("admin");
        // 3.2 操作時(shí)間(當(dāng)前時(shí)間)
        operationLog.setOperationTime(LocalDateTime.now());
        // 3.3 接口地址
        operationLog.setRequestUrl(request.getRequestURI());
        // 3.4 請(qǐng)求方式(GET/POST)
        operationLog.setRequestMethod(request.getMethod());
        // 3.5 操作 IP(獲取客戶(hù)端真實(shí) IP)
        operationLog.setOperationIp(getClientIp(request));
        // 3.6 請(qǐng)求參數(shù)(將方法參數(shù)轉(zhuǎn)為 JSON 字符串)
        Object[] args = joinPoint.getArgs();
        operationLog.setRequestParams(JSON.toJSONString(args));
        // 4. 獲取自定義注解的屬性(模塊、描述)
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        OperationLogAnnotation annotation = method.getAnnotation(OperationLogAnnotation.class);
        operationLog.setModule(annotation.module());
        operationLog.setDescription(annotation.description());
        // 5. 執(zhí)行目標(biāo)方法(核心業(yè)務(wù)邏輯),捕獲執(zhí)行結(jié)果和異常
        Object result = null;
        try {
            // 執(zhí)行目標(biāo)方法(比如接口的核心邏輯)
            result = joinPoint.proceed();
            // 方法執(zhí)行成功:設(shè)置狀態(tài)為 1(成功),記錄返回結(jié)果
            operationLog.setStatus(1);
            operationLog.setResponseResult(JSON.toJSONString(result));
        } catch (Throwable throwable) {
            // 方法執(zhí)行失?。涸O(shè)置狀態(tài)為 0(失敗),記錄異常信息
            operationLog.setStatus(0);
            operationLog.setErrorMsg(throwable.getMessage());
            // 拋出異常,不影響原有業(yè)務(wù)邏輯的異常處理
            throw throwable;
        } finally {
            // 6. 日志持久化(實(shí)戰(zhàn)中可存入數(shù)據(jù)庫(kù)、ElasticSearch 等,這里模擬打印)
            System.out.println("操作日志記錄:" + JSON.toJSONString(operationLog, true));
            // TODO: 實(shí)戰(zhàn)中替換為數(shù)據(jù)庫(kù)插入操作(比如調(diào)用 OperationLogService.save(operationLog))
        }
        // 返回目標(biāo)方法的執(zhí)行結(jié)果,不影響原有接口的返回值
        return result;
    }
    /**
     * 工具方法:獲取客戶(hù)端真實(shí) IP(處理代理場(chǎng)景,比如 Nginx 代理)
     */
    private String getClientIp(HttpServletRequest request) {
        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("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 處理多代理場(chǎng)景,取第一個(gè)非 unknown 的 IP
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }
}

核心解讀:

  • 切點(diǎn):通過(guò) @annotation 匹配帶有自定義注解的方法,精準(zhǔn)控制需要記錄日志的接口;
  • 環(huán)繞通知:用 @Around 包裹目標(biāo)方法,先收集請(qǐng)求信息、注解屬性,再執(zhí)行目標(biāo)方法,最后處理日志(成功/失?。?/li>
  • IP 獲?。禾幚砹?Nginx 代理等場(chǎng)景,確保獲取到客戶(hù)端真實(shí) IP;
  • 異常處理:捕獲目標(biāo)方法的異常,記錄異常信息,同時(shí)重新拋出異常,不影響原有業(yè)務(wù)的異常處理邏輯;
  • 日志持久化:這里用打印模擬,實(shí)戰(zhàn)中需替換為數(shù)據(jù)庫(kù)插入、ES 存儲(chǔ)等邏輯。

步驟5:接口測(cè)試(驗(yàn)證日志記錄效果)

創(chuàng)建一個(gè)測(cè)試接口,添加自定義 @OperationLogAnnotation 注解,啟動(dòng)項(xiàng)目,調(diào)用接口,查看日志是否正常記錄。

import com.example.demo.annotation.OperationLogAnnotation;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
 * 測(cè)試接口:用戶(hù)管理模塊
 */
@RestController
@RequestMapping("/api/user")
public class UserController {
    // 添加 @OperationLogAnnotation 注解,標(biāo)記需要記錄日志
    @OperationLogAnnotation(module = "用戶(hù)管理", description = "新增用戶(hù)")
    @PostMapping("/add")
    public Map<String, Object> addUser(@RequestBody Map<String, String> params) {
        // 模擬新增用戶(hù)核心邏輯
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg", "新增用戶(hù)成功");
        result.put("data", params);
        return result;
    }
    // 測(cè)試異常場(chǎng)景
    @OperationLogAnnotation(module = "用戶(hù)管理", description = "刪除用戶(hù)")
    @DeleteMapping("/delete/{id}")
    public Map<String, Object> deleteUser(@PathVariable Long id) {
        // 模擬異常(比如刪除不存在的用戶(hù))
        if (id <= 0) {
            throw new RuntimeException("用戶(hù)ID非法,無(wú)法刪除");
        }
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("msg", "刪除用戶(hù)成功");
        return result;
    }
}

測(cè)試1:調(diào)用新增用戶(hù)接口

請(qǐng)求地址:http://localhost:8080/api/user/add
請(qǐng)求方式:POST
請(qǐng)求參數(shù):{"username":"test","password":"123456"}

控制臺(tái)打印的日志(格式化后):

操作日志記錄:{
    "description":"新增用戶(hù)",
    "module":"用戶(hù)管理",
    "operationIp":"127.0.0.1",
    "operationTime":"2026-04-14T15:30:00",
    "operator":"admin",
    "requestMethod":"POST",
    "requestParams":"[{\"password\":\"123456\",\"username\":\"test\"}]",
    "requestUrl":"/api/user/add",
    "responseResult":"{\"code\":200,\"data\":{\"password\":\"123456\",\"username\":\"test\"},\"msg\":\"新增用戶(hù)成功\"}",
    "status":1
}

測(cè)試2:調(diào)用刪除用戶(hù)接口

請(qǐng)求地址:http://localhost:8080/api/user/delete/-1
請(qǐng)求方式:DELETE

控制臺(tái)打印的日志(格式化后):

操作日志記錄:{
    "description":"刪除用戶(hù)",
    "errorMsg":"用戶(hù)ID非法,無(wú)法刪除",
    "module":"用戶(hù)管理",
    "operationIp":"127.0.0.1",
    "operationTime":"2026-04-14T15:35:00",
    "operator":"admin",
    "requestMethod":"DELETE",
    "requestParams":"[-1]",
    "requestUrl":"/api/user/delete/-1",
    "responseResult":"null",
    "status":0
}

驗(yàn)證結(jié)果:兩種場(chǎng)景的日志都正常記錄,包含了所有核心字段,符合預(yù)期!

三、優(yōu)化技巧

上面的基礎(chǔ)實(shí)現(xiàn)已經(jīng)能滿(mǎn)足大部分項(xiàng)目需求,下面補(bǔ)充3個(gè)實(shí)戰(zhàn)常用的優(yōu)化點(diǎn),讓日志功能更完善。

優(yōu)化1:獲取真實(shí)操作人(替換模擬值)

實(shí)戰(zhàn)中,操作人不能用模擬的“admin”,需結(jié)合 Spring Security 或 Token 解析獲取當(dāng)前登錄用戶(hù):

// 結(jié)合 Spring Security 獲取當(dāng)前登錄用戶(hù)
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && !(authentication.getPrincipal() instanceof String)) {
    UserDetails userDetails = (UserDetails) authentication.getPrincipal();
    operationLog.setOperator(userDetails.getUsername()); // 獲取用戶(hù)名
}

優(yōu)化2:日志持久化(存入數(shù)據(jù)庫(kù))

創(chuàng)建 OperationLogService 和 OperationLogMapper,將日志對(duì)象存入數(shù)據(jù)庫(kù)(以 MyBatis-Plus 為例):

// 1. 注入 OperationLogService
@Autowired
private OperationLogService operationLogService;
// 2. 在 finally 中替換打印邏輯,改為存入數(shù)據(jù)庫(kù)
finally {
    operationLogService.save(operationLog); // MyBatis-Plus 自帶的保存方法
}

優(yōu)化3:忽略敏感參數(shù)(避免日志泄露)

接口參數(shù)中可能包含密碼、手機(jī)號(hào)等敏感信息,需要忽略這些參數(shù),避免日志泄露,可自定義注解+攔截處理:

// 1. 自定義忽略敏感參數(shù)注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreSensitive {
}
// 2. 在實(shí)體類(lèi)敏感字段上添加注解
@Data
public class User {
    private Long id;
    private String username;
    @IgnoreSensitive // 忽略密碼字段
    private String password;
}
// 3. 在切面中,處理敏感參數(shù)(替換為 ****)
// (核心邏輯:反射獲取字段,判斷是否有 @IgnoreSensitive 注解,有則替換值)

四、注意事項(xiàng)

切面類(lèi)忘記加 @Component 注解

? 錯(cuò)誤做法:只加 @Aspect 標(biāo)記切面,忘記加 @Component;
? 正確做法:@Aspect 只是標(biāo)記切面,必須加 @Component 交給 Spring 管理,否則 Spring 無(wú)法掃描到切面,日志記錄失效。

環(huán)繞通知中忘記調(diào)用 joinPoint.proceed()

? 錯(cuò)誤做法:只收集日志,不執(zhí)行目標(biāo)方法,導(dǎo)致接口無(wú)法正常返回;
? 正確做法:必須調(diào)用 joinPoint.proceed() 執(zhí)行目標(biāo)方法,同時(shí)接收返回結(jié)果,否則核心業(yè)務(wù)邏輯無(wú)法執(zhí)行。

請(qǐng)求參數(shù)為 MultipartFile(文件上傳)時(shí),JSON 格式化報(bào)錯(cuò)

? 錯(cuò)誤表現(xiàn):文件上傳接口,日志記錄時(shí),JSON.toJSONString(args) 報(bào)錯(cuò);
? 解決方案:判斷參數(shù)類(lèi)型,如果是 MultipartFile,不進(jìn)行 JSON 格式化,直接標(biāo)記為“文件上傳”。

文末小結(jié)

用 SpringBoot + AOP 實(shí)現(xiàn)操作日志,核心就是“自定義注解標(biāo)記接口 + 切面收集日志信息 + 環(huán)繞通知處理增強(qiáng)”,全程無(wú)侵入式編碼,復(fù)用性極高。

記?。篈OP 的核心是“解耦”,把日志這種通用功能,和核心業(yè)務(wù)邏輯分離,既保證了核心代碼的簡(jiǎn)潔,又方便后續(xù)維護(hù)和擴(kuò)展。

以上就是基于SpringBoot+AOP實(shí)現(xiàn)操作日志記錄的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot AOP日志記錄的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot Logback日志記錄到數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法

    SpringBoot Logback日志記錄到數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法

    這篇文章主要介紹了SpringBoot Logback日志記錄到數(shù)據(jù)庫(kù)的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Java多線(xiàn)程讀寫(xiě)鎖ReentrantReadWriteLock類(lèi)詳解

    Java多線(xiàn)程讀寫(xiě)鎖ReentrantReadWriteLock類(lèi)詳解

    本文詳細(xì)講解了Java多線(xiàn)程讀寫(xiě)鎖ReentrantReadWriteLock類(lèi),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • Java實(shí)現(xiàn)五子棋AI算法

    Java實(shí)現(xiàn)五子棋AI算法

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)五子棋AI算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • SpringBoot結(jié)合WebSocket實(shí)現(xiàn)聊天功能

    SpringBoot結(jié)合WebSocket實(shí)現(xiàn)聊天功能

    本文介紹了如何使用SpringBoot和WebSocket實(shí)現(xiàn)一個(gè)簡(jiǎn)單的聊天功能,包括導(dǎo)入依賴(lài)、配置類(lèi)、創(chuàng)建消息實(shí)體、指定ServerEndpoint、創(chuàng)建客戶(hù)端等步驟,通過(guò)具體示例,演示了如何發(fā)送個(gè)人消息和群發(fā)消息,實(shí)現(xiàn)了基本的聊天功能,適合需要在項(xiàng)目中實(shí)現(xiàn)實(shí)時(shí)通訊功能的開(kāi)發(fā)者參考
    2024-11-11
  • Spring Boot 集成 Solr 的詳細(xì)示例

    Spring Boot 集成 Solr 的詳細(xì)示例

    這篇文章主要介紹了Spring Boot 集成 Solr 的詳細(xì)示例,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-05-05
  • Java8 接口默認(rèn)方法和靜態(tài)方法

    Java8 接口默認(rèn)方法和靜態(tài)方法

    這篇文章主要介紹了Java8 接口默認(rèn)方法和靜態(tài)方法,在默認(rèn)接口中使用關(guān)鍵字default聲明并提供具體實(shí)現(xiàn),而且該方法不需要添加public關(guān)鍵字就可以公開(kāi)調(diào)用,甚至你可以在其實(shí)現(xiàn)類(lèi)中覆寫(xiě),帶著對(duì)默認(rèn)接口的方法和小編一起探索下面文章內(nèi)容的靜態(tài)方法吧
    2021-10-10
  • JAVA DOM解析XML文件過(guò)程詳解

    JAVA DOM解析XML文件過(guò)程詳解

    這篇文章主要介紹了JAVA DOM解析XML文件過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • Java集成presto查詢(xún)方式

    Java集成presto查詢(xún)方式

    這篇文章主要介紹了Java集成presto查詢(xún)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java toString方法重寫(xiě)工具之ToStringBuilder案例詳解

    Java toString方法重寫(xiě)工具之ToStringBuilder案例詳解

    這篇文章主要介紹了Java toString方法重寫(xiě)工具之ToStringBuilder案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Java并發(fā)編程之ReentrantLock可重入鎖的實(shí)例代碼

    Java并發(fā)編程之ReentrantLock可重入鎖的實(shí)例代碼

    這篇文章主要介紹了Java并發(fā)編程之ReentrantLock可重入鎖的實(shí)例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02

最新評(píng)論

白水县| 庆城县| 贵溪市| 都江堰市| 连平县| 平利县| 红河县| 临江市| 海兴县| 蒙山县| 德惠市| 洛南县| 浦江县| 卢龙县| 长春市| 集贤县| 盐津县| 琼结县| 昌都县| 宁强县| 霍州市| 康马县| 大英县| 河源市| 百色市| 山丹县| 当雄县| 尖扎县| 台山市| 苍梧县| 额济纳旗| 天津市| 大同市| 宣威市| 达日县| 赤壁市| 孟津县| 荆门市| 通州区| 双鸭山市| 延长县|