欧美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)文章

  • Java之jdbc連接mysql數(shù)據(jù)庫(kù)的方法步驟詳解

    Java之jdbc連接mysql數(shù)據(jù)庫(kù)的方法步驟詳解

    這篇文章主要介紹了Java之jdbc連接mysql數(shù)據(jù)庫(kù)的方法步驟詳解,JCBC技術(shù)是java開(kāi)發(fā)必備的只是,jdbc連接mysql數(shù)據(jù)庫(kù),這是一個(gè)比較簡(jiǎn)單的方法,有興趣的可以了解一下
    2020-07-07
  • 詳解springcloud Feign的Hystrix支持

    詳解springcloud Feign的Hystrix支持

    這篇文章主要介紹了詳解springcloud Feign的Hystrix支持,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • 關(guān)于MVC與SpringMVC的介紹、區(qū)別、執(zhí)行流程

    關(guān)于MVC與SpringMVC的介紹、區(qū)別、執(zhí)行流程

    這篇文章主要介紹了關(guān)于MVC與SpringMVC的介紹、區(qū)別、執(zhí)行流程,MVC框架的主要目標(biāo)是將應(yīng)用程序的業(yè)務(wù)邏輯(Model)與用戶(hù)界面(View)分離開(kāi)來(lái),從而提高應(yīng)用程序的可維護(hù)性和可擴(kuò)展性,需要的朋友可以參考下
    2023-05-05
  • Mybatis下動(dòng)態(tài)sql中##和$$的區(qū)別講解

    Mybatis下動(dòng)態(tài)sql中##和$$的區(qū)別講解

    今天小編就為大家分享一篇關(guān)于Mybatis下動(dòng)態(tài)sql中##和$$的區(qū)別講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-03-03
  • 純Java代碼實(shí)現(xiàn)流星劃過(guò)天空

    純Java代碼實(shí)現(xiàn)流星劃過(guò)天空

    本文給大家介紹純java代碼實(shí)現(xiàn)流星劃過(guò)天空,包括流星個(gè)數(shù),流星飛行的速度,色階,流星大小相關(guān)變量設(shè)置。對(duì)java流星劃過(guò)天空特效代碼感興趣的朋友可以參考下本文
    2015-10-10
  • SpringBoot實(shí)現(xiàn)kafka多源配置的示例代碼

    SpringBoot實(shí)現(xiàn)kafka多源配置的示例代碼

    實(shí)際開(kāi)發(fā)中,不同的topic可能來(lái)自不同的集群,所以就需要配置不同的kafka數(shù)據(jù)源,基于springboot自動(dòng)配置的思想,最終通過(guò)配置文件的配置,自動(dòng)生成生產(chǎn)者及消費(fèi)者的配置,本文介紹了SpringBoot實(shí)現(xiàn)kafka多源配置,需要的朋友可以參考下
    2024-06-06
  • Java編程刪除鏈表中重復(fù)的節(jié)點(diǎn)問(wèn)題解決思路及源碼分享

    Java編程刪除鏈表中重復(fù)的節(jié)點(diǎn)問(wèn)題解決思路及源碼分享

    這篇文章主要介紹了Java編程刪除鏈表中重復(fù)的節(jié)點(diǎn)問(wèn)題解決思路及源碼分享,具有一定參考價(jià)值,這里分享給大家,供需要的朋友了解。
    2017-10-10
  • 使用Spring底層組件實(shí)現(xiàn)Aware接口

    使用Spring底層組件實(shí)現(xiàn)Aware接口

    這篇文章主要介紹了使用Spring底層組件實(shí)現(xiàn)Aware接口,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • Java實(shí)現(xiàn)輕松處理日期和時(shí)間的API小結(jié)

    Java實(shí)現(xiàn)輕松處理日期和時(shí)間的API小結(jié)

    這篇文章主要為大家詳細(xì)介紹了Java中的日期和時(shí)間API,可以輕松處理日期和時(shí)間,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03
  • Java利用Request請(qǐng)求如何獲取IP地址對(duì)應(yīng)的省份、城市詳解

    Java利用Request請(qǐng)求如何獲取IP地址對(duì)應(yīng)的省份、城市詳解

    之前已經(jīng)給大家介紹了關(guān)于Java用Request請(qǐng)求獲取IP地址的相關(guān)內(nèi)容,那么下面這篇文章將給大家進(jìn)入深入的介紹,關(guān)于Java利用Request請(qǐng)求如何獲取IP地址對(duì)應(yīng)省份、城市的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-10-10

最新評(píng)論