欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot實(shí)現(xiàn)字段自動(dòng)填充的兩種方式

 更新時(shí)間:2024年11月11日 11:21:49   作者:waterme1onY  
每個(gè)字段在插入數(shù)據(jù)庫(kù),或者更新時(shí)都要在serviceimpl層對(duì)creatby,updateby等字段進(jìn)行填充,這個(gè)太繁瑣了,所以本文給大家介紹了SpringBoot實(shí)現(xiàn)字段自動(dòng)填充的兩種方式,需要的朋友可以參考下

creatby,updateby等字段自動(dòng)填充

每個(gè)字段在插入數(shù)據(jù)庫(kù),或者更新時(shí)都要在serviceimpl層對(duì)creatby,updateby等字段進(jìn)行填充,這個(gè)太繁瑣了,以下兩種方法可以實(shí)現(xiàn)字段的自動(dòng)填充。本項(xiàng)目使用第一種。

方法一:

首先創(chuàng)建一個(gè)AutoFillInterceptor類(lèi)。下面會(huì)對(duì)代碼逐行分析。
以下代碼也可以直接復(fù)制粘貼,但前提是你的實(shí)體類(lèi)中的自動(dòng)填充的字段和下面四個(gè)靜態(tài)常量名字一樣。

@Component
@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class AutoFillInterceptor implements Interceptor {


    private static final String CREATE_BY = "createdBy";
    private static final String UPDATE_BY = "updatedBy";

    private static final String CREATE_TIME = "createdAt";
    private static final String UPDATE_TIME = "updatedAt";

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        SqlCommandType sqlCommandType = ms.getSqlCommandType();
        Object parameter = args[1];
        if(parameter != null && sqlCommandType!=null){
            if(SqlCommandType.INSERT.equals(sqlCommandType)){
                if(parameter instanceof MapperMethod.ParamMap){
                    MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap) parameter;
                    ArrayList list= (ArrayList) paramMap.get("list");
                    list.forEach(v->{
                        setFieldValByName(CREATE_TIME, LocalDateTime.now(), v);
                        setFieldValByName(UPDATE_TIME, LocalDateTime.now(), v);
                    });
                    paramMap.put("list", list);
                }else{
                    // 單條插入的情況
                    // 設(shè)置創(chuàng)建人和創(chuàng)建時(shí)間字段值
                    setFieldValByName(CREATE_TIME, LocalDateTime.now(), parameter);
                    setFieldValByName(UPDATE_TIME, LocalDateTime.now(), parameter);
                }
            }
            else if(SqlCommandType.UPDATE.equals(sqlCommandType)){
                // 更新操作
                // 設(shè)置更新人和更新時(shí)間字段值
                setFieldValByName(UPDATE_TIME, LocalDateTime.now(), parameter);
            }
        }

        // 繼續(xù)執(zhí)行原始方法
        return invocation.proceed();
    }

    private void setFieldValByName(String fieldName, Object fieldVal, Object parameter) {
        MetaObject metaObject = SystemMetaObject.forObject(parameter);

        if (metaObject.hasSetter(fieldName)) {
            metaObject.setValue(fieldName, fieldVal);
        }
    }

    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }
}

代碼結(jié)構(gòu)與作用

這是一個(gè)實(shí)現(xiàn)了MyBatis攔截器(Interceptor接口)的類(lèi)AutoFillInterceptor,用于在執(zhí)行SQL操作(INSERT或UPDATE)時(shí),自動(dòng)填充一些通用字段,比如創(chuàng)建時(shí)間(createdAt)、更新時(shí)間(updatedAt)等。

在企業(yè)級(jí)項(xiàng)目中,通常需要記錄數(shù)據(jù)的創(chuàng)建時(shí)間和修改時(shí)間,這個(gè)攔截器就是為了解決這種需求,在新增和修改數(shù)據(jù)時(shí)自動(dòng)填充這些字段。下面我們來(lái)逐行分析代碼。

代碼逐行解析

@Component
@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
  • @Component:Spring的注解,將這個(gè)類(lèi)注冊(cè)為一個(gè)Spring Bean,便于管理。
  • @Intercepts:MyBatis的注解,聲明這是一個(gè)攔截器,并指定要攔截的目標(biāo)。
    • @Signature:定義攔截器的具體攔截方法。
      • type = Executor.class:表示攔截MyBatis的Executor類(lèi)。
      • method = "update":表示攔截update方法,這個(gè)方法用于執(zhí)行更新操作(包括INSERT、UPDATE、DELETE)。
      • args = {MappedStatement.class, Object.class}:指定update方法的參數(shù)類(lèi)型,即SQL映射信息MappedStatement和參數(shù)對(duì)象Object。
public class AutoFillInterceptor implements Interceptor {
  • 這幾行定義了一些常量,分別表示字段名稱(chēng),如創(chuàng)建者、修改者、創(chuàng)建時(shí)間和修改時(shí)間。這些常量將在攔截邏輯中用來(lái)自動(dòng)填充字段。
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        SqlCommandType sqlCommandType = ms.getSqlCommandType();
        Object parameter = args[1];
  • intercept方法是攔截器的核心邏輯。
    • Object[] args = invocation.getArgs():獲取攔截方法的參數(shù)。
    • MappedStatement ms = (MappedStatement) args[0]:獲取MappedStatement,包含了有關(guān)SQL語(yǔ)句的信息。
    • SqlCommandType sqlCommandType = ms.getSqlCommandType():獲取SQL的操作類(lèi)型(INSERT、UPDATE、DELETE)。
    • Object parameter = args[1]:獲取參數(shù)對(duì)象,通常是用戶(hù)要插入或更新的數(shù)據(jù)。
        if(parameter != null && sqlCommandType != null){
  • 檢查參數(shù)是否為空,并確認(rèn)操作類(lèi)型是否非空,確保有必要繼續(xù)執(zhí)行后續(xù)操作。
            if(SqlCommandType.INSERT.equals(sqlCommandType)){
                if(parameter instanceof MapperMethod.ParamMap){
                    MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap) parameter;
                    ArrayList list= (ArrayList) paramMap.get("list");
                    list.forEach(v -> {
                        setFieldValByName(CREATE_TIME, LocalDateTime.now(), v);
                        setFieldValByName(UPDATE_TIME, LocalDateTime.now(), v);
                    });
                    paramMap.put("list", list);
                } else {
                    // 單條插入的情況
                    // 設(shè)置創(chuàng)建人和創(chuàng)建時(shí)間字段值
                    setFieldValByName(CREATE_TIME, LocalDateTime.now(), parameter);
                    setFieldValByName(UPDATE_TIME, LocalDateTime.now(), parameter);
                }
            }
  • if (SqlCommandType.INSERT.equals(sqlCommandType)):如果當(dāng)前SQL是INSERT操作:
    • if (parameter instanceof MapperMethod.ParamMap):判斷參數(shù)是否是MapperMethod.ParamMap類(lèi)型,這通常用于批量插入。
      • ArrayList list = (ArrayList) paramMap.get("list"):從參數(shù)Map中獲取名為list的參數(shù),這是批量插入的數(shù)據(jù)集合。
      • list.forEach(v -> {...}):對(duì)每個(gè)元素進(jìn)行操作,調(diào)用setFieldValByName方法設(shè)置createdAtupdatedAt為當(dāng)前時(shí)間。
    • else部分:處理單條插入的情況,直接給parameter對(duì)象設(shè)置創(chuàng)建時(shí)間和更新時(shí)間。
            else if(SqlCommandType.UPDATE.equals(sqlCommandType)){
                // 更新操作
                // 設(shè)置更新人和更新時(shí)間字段值
                setFieldValByName(UPDATE_TIME, LocalDateTime.now(), parameter);
            }
  • else if (SqlCommandType.UPDATE.equals(sqlCommandType)):如果當(dāng)前SQL是UPDATE操作:
    • 使用setFieldValByName方法將updatedAt字段設(shè)置為當(dāng)前時(shí)間。
        }

        // 繼續(xù)執(zhí)行原始方法
        return invocation.proceed();
    }
  • 最終通過(guò)invocation.proceed()調(diào)用被攔截的方法,繼續(xù)執(zhí)行原始的數(shù)據(jù)庫(kù)操作。
    private void setFieldValByName(String fieldName, Object fieldVal, Object parameter) {
        MetaObject metaObject = SystemMetaObject.forObject(parameter);

        if (metaObject.hasSetter(fieldName)) {
            metaObject.setValue(fieldName, fieldVal);
        }
    }
  • setFieldValByName方法用于設(shè)置對(duì)象中指定字段的值:
    • MetaObject metaObject = SystemMetaObject.forObject(parameter):創(chuàng)建MetaObject,用于操作傳入對(duì)象的元數(shù)據(jù)。
    • if (metaObject.hasSetter(fieldName)):檢查對(duì)象是否有對(duì)應(yīng)字段的setter方法。
    • metaObject.setValue(fieldName, fieldVal):如果有setter方法,則設(shè)置字段的值。
    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }
}
  • setPropertiesplugin方法是Interceptor接口的默認(rèn)實(shí)現(xiàn),plugin方法用于生成代理對(duì)象。

總結(jié)

  • 這個(gè)攔截器的作用是自動(dòng)填充createdAtupdatedAt字段,以便在執(zhí)行INSERT和UPDATE操作時(shí)自動(dòng)記錄創(chuàng)建和更新時(shí)間。
  • 主要攔截Executorupdate方法,通過(guò)判斷SQL類(lèi)型來(lái)確定是INSERT還是UPDATE操作,從而設(shè)置相應(yīng)字段。
  • 使用了MyBatis的MetaObject工具類(lèi)來(lái)動(dòng)態(tài)操作參數(shù)對(duì)象的字段值。

通過(guò)這個(gè)攔截器,開(kāi)發(fā)者不需要在業(yè)務(wù)代碼中手動(dòng)設(shè)置createdAtupdatedAt,大大減少了重復(fù)代碼,也保證了這些公共字段的一致性和正確性。

方法二:

這個(gè)方法是使用自定義注解來(lái)寫(xiě)的,所以要在需要填充的sql上加上這個(gè)注解。這個(gè)可能更加靈活更加簡(jiǎn)單把。

公共字段自動(dòng)填充

技術(shù)點(diǎn):枚舉、注解、AOP、反射
創(chuàng)建時(shí)間、修改時(shí)間、創(chuàng)建人、修改人這4個(gè)公共字段。
為mapper方法加注解AutoFill,標(biāo)識(shí)需要進(jìn)行公共字段自動(dòng)填充
自定義切面類(lèi)AutoFillAspect,統(tǒng)一攔截加入了AutoFill注解的方法,通過(guò)反射為公共字段賦值。
在Mapper的方法上接入AutoFill注解。

public enum OperationType {
    更新操作
    UPDATE,
    插入操作
    INSERT
}

@Target(ElementType.METHOD)當(dāng)前注解加在什么位置
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
    //數(shù)據(jù)庫(kù)操作類(lèi)型:UPDATE INSERT
    OperationType value();
}

補(bǔ)充注解基本知識(shí)

public @interface MyAnnotation {
    // 定義注解的成員
    String value(); // 這是一個(gè)名為"value"的成員
    int count() default 1; // 這是一個(gè)名為"count"的成員,帶有默認(rèn)值
}

@MyAnnotation(value = "Hello", count = 3)
public class MyClass {
    // 類(lèi)的代碼
}

對(duì)于AutoFillAspect類(lèi)切點(diǎn)、execution表達(dá)式

/**
 * 自定義切面,實(shí)現(xiàn)公共字段自動(dòng)填充處理邏輯
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {


    /**
     * 切入點(diǎn)
     */
     									所有的類(lèi),所有的方法,所有的參數(shù)類(lèi)型
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointCut(){}

    /**
     * 前置通知,在通知中進(jìn)行公共字段的賦值
     */
    @Before("autoFillPointCut()")指定切入點(diǎn)
    public void autoFill(JoinPoint joinPoint){連接點(diǎn)
        log.info("開(kāi)始進(jìn)行公共字段自動(dòng)填充...");

        //獲取到當(dāng)前被攔截的方法上的數(shù)據(jù)庫(kù)操作類(lèi)型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法簽名對(duì)象
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//獲得方法上的注解對(duì)象
        OperationType operationType = autoFill.value();//獲得數(shù)據(jù)庫(kù)操作類(lèi)型

        //獲取到當(dāng)前被攔截的方法的參數(shù)--實(shí)體對(duì)象	做一個(gè)約定,實(shí)體對(duì)象放第一個(gè)
        Object[] args = joinPoint.getArgs();
        if(args == null || args.length == 0){
            return;
        }

        Object entity = args[0];實(shí)體

        //準(zhǔn)備賦值的數(shù)據(jù)
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();

        //根據(jù)當(dāng)前不同的操作類(lèi)型,為對(duì)應(yīng)的屬性通過(guò)反射來(lái)賦值
        if(operationType == OperationType.INSERT){
            //為4個(gè)公共字段賦值
            try {
                Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

                //通過(guò)反射為對(duì)象屬性賦值
                setCreateTime.invoke(entity,now);
                setCreateUser.invoke(entity,currentId);
                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,currentId);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else if(operationType == OperationType.UPDATE){
            //為2個(gè)公共字段賦值
            try {
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

                //通過(guò)反射為對(duì)象屬性賦值
                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,currentId);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

使用

@AutoFill(value = OperationType.UPDATE)
void update(Employee employee);

自定義切面:實(shí)現(xiàn)公共字段的自動(dòng)填充

這段代碼使用了 Spring AOP(面向切面編程)來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)操作時(shí),自動(dòng)填充一些公共字段,例如創(chuàng)建時(shí)間、更新時(shí)間、創(chuàng)建人、更新人等。接下來(lái),我們逐行解析這段代碼,以幫助你理解各個(gè)部分的功能和實(shí)現(xiàn)邏輯。

代碼結(jié)構(gòu)概覽

@Aspect
@Component
@Slf4j
public class AutoFillAspect {
    // 切入點(diǎn)
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointCut(){}

    // 前置通知
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint){
        log.info("開(kāi)始進(jìn)行公共字段自動(dòng)填充...");
        ...
    }
}

這段代碼定義了一個(gè)切面 AutoFillAspect,它會(huì)在符合條件的數(shù)據(jù)庫(kù)操作方法執(zhí)行之前,通過(guò)前置通知 (@Before) 自動(dòng)對(duì)某些公共字段進(jìn)行填充。

注解解釋

  1. @Aspect:表示當(dāng)前類(lèi)是一個(gè)切面類(lèi),用于定義通知和切入點(diǎn)。
  2. @Component:把這個(gè)切面類(lèi)注冊(cè)為 Spring 容器中的一個(gè)組件。
  3. @Slf4j:用來(lái)啟用日志功能,以方便調(diào)試和記錄信息。

切入點(diǎn)定義

@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut(){}

解釋?zhuān)?/strong>

  • @Pointcut:用于定義一個(gè)切入點(diǎn),描述哪些方法需要被切面邏輯攔截。
  • execution(* com.sky.mapper.*.*(..)):匹配 com.sky.mapper 包下的所有類(lèi)和所有方法,(..) 表示任意參數(shù)類(lèi)型和數(shù)量。
  • && @annotation(com.sky.annotation.AutoFill):表示只攔截被 @AutoFill 注解標(biāo)記的方法。

通過(guò)這種定義,只有符合指定包下的類(lèi)且有 @AutoFill 注解的方法,才會(huì)被切面邏輯攔截。

前置通知(Before Advice)

@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint) {
    log.info("開(kāi)始進(jìn)行公共字段自動(dòng)填充...");
    ...
}
  • @Before("autoFillPointCut()"):這是前置通知,表示在切入點(diǎn)所匹配的方法執(zhí)行之前,執(zhí)行 autoFill() 方法。
  • JoinPoint joinPoint:JoinPoint 是一個(gè)連接點(diǎn),表示被攔截的方法,允許獲取到目標(biāo)方法的一些信息,比如方法名和參數(shù)等。

獲取注解和方法信息

MethodSignature signature = (MethodSignature) joinPoint.getSignature();
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);
OperationType operationType = autoFill.value();
  1. MethodSignature signature = (MethodSignature) joinPoint.getSignature();:獲取當(dāng)前攔截的方法的簽名信息,轉(zhuǎn)換為 MethodSignature 類(lèi)型。
  2. AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);:獲取方法上的 @AutoFill 注解對(duì)象。
  3. OperationType operationType = autoFill.value();:獲取注解中指定的數(shù)據(jù)庫(kù)操作類(lèi)型(例如 INSERT 或 UPDATE)。

獲取方法參數(shù)

Object[] args = joinPoint.getArgs();
if (args == null || args.length == 0) {
    return;
}
Object entity = args[0];
  • Object[] args = joinPoint.getArgs();:獲取當(dāng)前被攔截的方法的參數(shù)。
  • if (args == null || args.length == 0):如果沒(méi)有參數(shù),直接返回。
  • Object entity = args[0];:假設(shè)第一個(gè)參數(shù)是實(shí)體對(duì)象,用于操作數(shù)據(jù)庫(kù)。這里有一個(gè)約定,即實(shí)體對(duì)象總是第一個(gè)參數(shù)。

準(zhǔn)備賦值的數(shù)據(jù)

LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
  • LocalDateTime now = LocalDateTime.now();:獲取當(dāng)前時(shí)間,用于填充創(chuàng)建時(shí)間和更新時(shí)間。
  • Long currentId = BaseContext.getCurrentId();:獲取當(dāng)前操作用戶(hù)的 ID,用于填充創(chuàng)建人和更新人信息。

根據(jù)操作類(lèi)型進(jìn)行賦值

插入操作(INSERT)

if (operationType == OperationType.INSERT) {
    try {
        Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
        Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
        Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
        Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

        setCreateTime.invoke(entity, now);
        setCreateUser.invoke(entity, currentId);
        setUpdateTime.invoke(entity, now);
        setUpdateUser.invoke(entity, currentId);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • if (operationType == OperationType.INSERT):如果數(shù)據(jù)庫(kù)操作類(lèi)型是插入(INSERT)。
  • 通過(guò)反射的方式獲取實(shí)體類(lèi)中的 setCreateTimesetCreateUser、setUpdateTime 和 setUpdateUser 方法。
  • invoke() 方法用于調(diào)用這些 setter 方法并傳入相應(yīng)的值,完成公共字段的賦值。

更新操作(UPDATE)

else if (operationType == OperationType.UPDATE) {
    try {
        Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
        Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

        setUpdateTime.invoke(entity, now);
        setUpdateUser.invoke(entity, currentId);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • else if (operationType == OperationType.UPDATE):如果操作類(lèi)型是更新(UPDATE)。
  • 這里只需填充更新相關(guān)的字段,即更新時(shí)間和更新人。

小結(jié)

這段代碼實(shí)現(xiàn)了對(duì)數(shù)據(jù)庫(kù)操作的公共字段自動(dòng)填充,具體如下:

  • 定義一個(gè)切面 AutoFillAspect,用于攔截特定包中的方法,并且方法需要用 @AutoFill 注解進(jìn)行標(biāo)記。
  • 使用 AOP 的前置通知在方法執(zhí)行前進(jìn)行字段自動(dòng)填充。
  • 通過(guò)反射機(jī)制獲取實(shí)體對(duì)象的方法并進(jìn)行賦值,根據(jù)操作類(lèi)型填充不同的字段。

這使得代碼變得更加簡(jiǎn)潔和可維護(hù),減少了重復(fù)的公共字段賦值邏輯,也方便對(duì)創(chuàng)建時(shí)間、更新時(shí)間等公共屬性的一致性管理。

以上就是SpringBoot實(shí)現(xiàn)字段自動(dòng)填充的兩種方式的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot字段自動(dòng)填充的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot實(shí)現(xiàn)國(guó)際化i18n詳解

    SpringBoot實(shí)現(xiàn)國(guó)際化i18n詳解

    國(guó)際化(Internationalization,簡(jiǎn)稱(chēng)i18n)是指在軟件應(yīng)用中支持多種語(yǔ)言和文化的能力,本文將介紹如何在Spring?Boot應(yīng)用中實(shí)現(xiàn)國(guó)際化,需要的可以參考下
    2024-12-12
  • 通過(guò)實(shí)例了解java checked和unchecked異常

    通過(guò)實(shí)例了解java checked和unchecked異常

    這篇文章主要介紹了通過(guò)實(shí)例了解checked和unchecked異常,Java異常分為兩種類(lèi)型,checked異常和unchecked異常,另一種叫法是異常和錯(cuò)誤。下面小編就帶大家來(lái)一起學(xué)習(xí)一下吧
    2019-06-06
  • Java的jmap命令的具體使用

    Java的jmap命令的具體使用

    jmap是JDK提供的一個(gè)可以生成Java虛擬機(jī)的堆轉(zhuǎn)儲(chǔ)快照dump文件的命令行工具,本文主要介紹了Java的jmap命令的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • SpringBoot+Vue項(xiàng)目部署實(shí)現(xiàn)傳統(tǒng)方式

    SpringBoot+Vue項(xiàng)目部署實(shí)現(xiàn)傳統(tǒng)方式

    我們?cè)谶M(jìn)行前后端分離開(kāi)發(fā)的時(shí)候,一般是將前端項(xiàng)目部署到nginx服務(wù)器上,與后端項(xiàng)目分開(kāi)部署,這篇文章主要給大家介紹了關(guān)于SpringBoot+Vue項(xiàng)目部署實(shí)現(xiàn)傳統(tǒng)方式的相關(guān)資料,需要的朋友可以參考下
    2024-01-01
  • Java中的String對(duì)象數(shù)據(jù)類(lèi)型全面解析

    Java中的String對(duì)象數(shù)據(jù)類(lèi)型全面解析

    首先String不屬于8種基本數(shù)據(jù)類(lèi)型,String是一個(gè)對(duì)象,因?yàn)閷?duì)象的默認(rèn)值是null,所以String的默認(rèn)值也是null;但它又是一種特殊的對(duì)象,有其它對(duì)象沒(méi)有的一些特性
    2012-11-11
  • Java的volatile和sychronized底層實(shí)現(xiàn)原理解析

    Java的volatile和sychronized底層實(shí)現(xiàn)原理解析

    文章詳細(xì)介紹了Java中的synchronized和volatile關(guān)鍵字的底層實(shí)現(xiàn)原理,包括字節(jié)碼層面、JVM層面的實(shí)現(xiàn)細(xì)節(jié),以及鎖的類(lèi)型和MESI協(xié)議在多核處理器中的作用,文章還探討了synchronized和volatile的區(qū)別,以及如何通過(guò)Atomic類(lèi)來(lái)實(shí)現(xiàn)更細(xì)粒度的原子操作,感興趣的朋友一起看看吧
    2025-03-03
  • 詳細(xì)分析Java并發(fā)集合LinkedBlockingQueue的用法

    詳細(xì)分析Java并發(fā)集合LinkedBlockingQueue的用法

    這篇文章主要介紹了詳細(xì)分析Java并發(fā)集合LinkedBlockingQueue的用法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • Java的訪問(wèn)修飾符與變量的作用域講解

    Java的訪問(wèn)修飾符與變量的作用域講解

    這篇文章主要介紹了Java的訪問(wèn)修飾符與變量的作用域講解,是Java入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • 一文掌握spring cloud gateway(總結(jié)篇)

    一文掌握spring cloud gateway(總結(jié)篇)

    Spring Cloud Gateway是Spring Cloud的全新項(xiàng)目,該項(xiàng)目是基于Spring 5.0,Spring WebFlux和Project Reactor等技術(shù)開(kāi)發(fā)的網(wǎng)關(guān),它旨在為微服務(wù)架構(gòu)提供一種簡(jiǎn)單有效的統(tǒng)一的API路由管理方式,本文通過(guò)實(shí)例代碼總結(jié)介紹spring cloud gateway的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2024-12-12
  • SpringMVC中RequestMapping注解(作用、出現(xiàn)的位置、屬性)

    SpringMVC中RequestMapping注解(作用、出現(xiàn)的位置、屬性)

    這篇文章主要介紹了SpringMVC中RequestMapping注解(作用、出現(xiàn)的位置、屬性),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01

最新評(píng)論