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

手寫(xiě)一個(gè)@Valid字段校驗(yàn)器的示例代碼

 更新時(shí)間:2022年07月22日 08:30:13   作者:zyqok  
這篇文章主要為大家詳細(xì)介紹了如何手寫(xiě)一個(gè)@Valid字段校驗(yàn)器,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)有一定幫助,需要的可以參考一下

上次給大家講述了 Springboot 中的 @Valid 注解 和 @Validated 注解的詳細(xì)用法:

詳解Spring中@Valid和@Validated注解用法

當(dāng)我們用上面這兩個(gè)注解的時(shí)候,需要首先在對(duì)應(yīng)的字段上打上規(guī)則注解,類(lèi)似如下。

@Data
public class Employee {
 
    /** 姓名 */
    @NotBlank(message = "請(qǐng)輸入名稱(chēng)")
    @Length(message = "名稱(chēng)不能超過(guò)個(gè) {max} 字符", max = 10)
    public String name;
 
    /** 年齡 */
    @NotNull(message = "請(qǐng)輸入年齡")
    @Range(message = "年齡范圍為 {min} 到 {max} 之間", min = 1, max = 100)
    public Integer age;
 
}

其實(shí),在使用這些規(guī)則注解時(shí),我覺(jué)得不夠好用,比如我列舉幾個(gè)點(diǎn):

(1)針對(duì)每個(gè)字段時(shí),如果有多個(gè)校驗(yàn)規(guī)則,需要打多個(gè)對(duì)應(yīng)的規(guī)則注解,這時(shí)看上去,就會(huì)顯得較為臃腫。

(2)某些字段的類(lèi)型根本不能校驗(yàn),比如在校驗(yàn) Double 類(lèi)型的字段規(guī)則時(shí),打上任何校驗(yàn)注解,都會(huì)提示報(bào)錯(cuò),說(shuō)不支持 Double 類(lèi)型的數(shù)據(jù);

(3)每打一個(gè)規(guī)則注解時(shí),都需要寫(xiě)上對(duì)應(yīng)的 message 提示信息,這不但使得寫(xiě)起來(lái)麻煩,而且代碼看起來(lái)又不雅觀,按理說(shuō),我們的一類(lèi)規(guī)則提示應(yīng)該都是相同的,比如 "xxx不能為空",所以,按理來(lái)說(shuō),我只要配置一次提示格式,就可以不用再寫(xiě)了,只需要配置每個(gè)字段的名稱(chēng)xxx即可。

(4)一般來(lái)說(shuō),我們通常進(jìn)行字段校驗(yàn)時(shí),可能還需要一些額外的數(shù)據(jù)處理,比如去掉字符串前后的空格,某些數(shù)據(jù)可以為空的時(shí)候,我們還可以設(shè)置默認(rèn)值這些等。

(5)不能進(jìn)行擴(kuò)展,如果時(shí)自己寫(xiě)的校驗(yàn)器,還可以進(jìn)行需求擴(kuò)展。

(6)他們?cè)龠M(jìn)行校驗(yàn)的時(shí)候,都需要再方法參數(shù)上打上一個(gè) @Valid 注解或者 @Validate 注解,如果我們采用 AOP 去切所有 controller 中的方法的話(huà),那么我們寫(xiě)的自定義規(guī)則校驗(yàn)器,甚至連方法參數(shù)注解都可以不用打,是不是又更加簡(jiǎn)潔了呢。

于是,介于上述點(diǎn),寫(xiě)了一個(gè)自定義注解校驗(yàn)器,包括下面幾個(gè)文件:

Valid

這個(gè)注解作用于字段上,用于規(guī)則校驗(yàn)。

package com.zyq.utils.valid;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * 字段校驗(yàn)注解
 *
 * @author zyqok
 * @since 2022/05/06
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Valid {
 
    /**
     * 屬性名稱(chēng)
     */
    String name() default "";
 
    /**
     * 是否可為空
     */
    boolean required() default true;
 
    /**
     * 默認(rèn)值(如果默認(rèn)值寫(xiě) null 時(shí),則對(duì)所有數(shù)據(jù)類(lèi)型有效,不會(huì)設(shè)置默認(rèn)值)
     */
    String defaultValue() default "";
 
    /**
     * 【String】是否在原來(lái)值的基礎(chǔ)上,去掉前后空格
     */
    boolean trim() default true;
 
    /**
     * 【String】最小長(zhǎng)度
     */
    int minLength() default 0;
 
    /**
     * 【String】最大長(zhǎng)度
     */
    int maxLength() default 255;
 
    /**
     * 【String】自定義正則校驗(yàn)(該配置為空時(shí)則不進(jìn)行正則校驗(yàn))
     */
    String regex() default "";
 
    /**
     * 【Integer】【Long】【Double】范圍校驗(yàn)最小值(該配置為空時(shí)則不進(jìn)行校驗(yàn))
     */
    String min() default "";
 
    /**
     * 【Integer】【Long】【Double】范圍校驗(yàn)最大值(該配置為空時(shí)則不進(jìn)行校驗(yàn))
     */
    String max() default "";
 
}

ValidUtils

自定義規(guī)則校驗(yàn)工具類(lèi)

package com.zyq.utils.valid;
 
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
 
 
/**
 * 字段校驗(yàn)注解工具
 *
 * @author zyqok
 * @since 2022/05/05
 */
public class ValidUtils {
 
    /**
     * 校驗(yàn)對(duì)象,獲取校驗(yàn)結(jié)果(單個(gè)提示)
     *
     * @param obj 待校驗(yàn)對(duì)象
     * @return null-校驗(yàn)通過(guò),非null-校驗(yàn)未通過(guò)
     */
    public static <T> String getMsg(T obj) {
        List<String> msgList = getMsgList(obj);
        return msgList.isEmpty() ? null : msgList.get(0);
    }
 
    /**
     * 校驗(yàn)對(duì)象,獲取校驗(yàn)結(jié)果(所有提示)
     *
     * @param obj 待校驗(yàn)對(duì)象
     * @return null-校驗(yàn)通過(guò),非null-校驗(yàn)未通過(guò)
     */
    public static <T> List<String> getMsgList(T obj) {
        if (Objects.isNull(obj)) {
            return Collections.emptyList();
        }
        Field[] fields = obj.getClass().getDeclaredFields();
        if (fields.length == 0) {
            return Collections.emptyList();
        }
        List<String> msgList = new ArrayList<>();
        for (Field field : fields) {
            // 沒(méi)有打校驗(yàn)注解的字段則不進(jìn)行校驗(yàn)
            Valid valid = field.getAnnotation(Valid.class);
            if (Objects.isNull(valid)) {
                continue;
            }
            field.setAccessible(true);
            // String 類(lèi)型字段校驗(yàn)
            if (field.getType().isAssignableFrom(String.class)) {
                String msg = validString(obj, field, valid);
                if (Objects.nonNull(msg)) {
                    msgList.add(msg);
                }
                continue;
            }
            // int / Integer 類(lèi)型字符校驗(yàn)
            String typeName = field.getType().getTypeName();
            if (field.getType().isAssignableFrom(Integer.class) || "int".equals(typeName)) {
                String msg = validInteger(obj, field, valid);
                if (Objects.nonNull(msg)) {
                    msgList.add(msg);
                }
                continue;
            }
            // double/Double 類(lèi)型字段校驗(yàn)
            if (field.getType().isAssignableFrom(Double.class) || "double".equals(typeName)) {
                String msg = validDouble(obj, field, valid);
                if (Objects.nonNull(msg)) {
                    msgList.add(msg);
                }
                continue;
            }
        }
        return msgList;
    }
 
    /**
     * 校驗(yàn)String類(lèi)型字段
     */
    private static <T> String validString(T obj, Field field, Valid valid) {
        // 獲取屬性名稱(chēng)
        String name = getFieldName(field, valid);
        // 獲取原值
        Object v = getValue(obj, field);
        String val = Objects.isNull(v) ? "" : v.toString();
        // 是否需要去掉前后空格
        boolean trim = valid.trim();
        if (trim) {
            val = val.trim();
        }
        // 是否必填
        boolean required = valid.required();
        if (required && val.isEmpty()) {
            return requiredMsg(name);
        }
        // 是否有默認(rèn)值
        if (val.isEmpty()) {
            val = isDefaultNull(valid) ? null : valid.defaultValue();
        }
        // 最小長(zhǎng)度校驗(yàn)
        int length = 0;
        if (Objects.nonNull(val)) {
            length = val.length();
        }
        if (length < valid.minLength()) {
            return minLengthMsg(name, valid);
        }
        // 最大長(zhǎng)度校驗(yàn)
        if (length > valid.maxLength()) {
            return maxLengthMsg(name, valid);
        }
        // 正則判斷
        if (!valid.regex().isEmpty()) {
            boolean isMatch = Pattern.matches(valid.regex(), val);
            if (!isMatch) {
                return regexMsg(name);
            }
        }
        // 將值重新寫(xiě)入原字段中
        setValue(obj, field, val);
        // 如果所有校驗(yàn)通過(guò)后,則返回null
        return null;
    }
 
    private static <T> String validInteger(T obj, Field field, Valid valid) {
        // 獲取屬性名稱(chēng)
        String name = getFieldName(field, valid);
        // 獲取原值
        Object v = getValue(obj, field);
        Integer val = Objects.isNull(v) ? null : (Integer) v;
        // 是否必填
        boolean required = valid.required();
        if (required && Objects.isNull(val)) {
            return requiredMsg(name);
        }
        // 是否有默認(rèn)值
        if (Objects.isNull(val)) {
            boolean defaultNull = isDefaultNull(valid);
            if (!defaultNull) {
                val = parseInt(valid.defaultValue());
            }
        }
        // 校驗(yàn)最小值
        if (!valid.min().isEmpty() && Objects.nonNull(val)) {
            int min = parseInt(valid.min());
            if (val < min) {
                return minMsg(name, valid);
            }
        }
        // 校驗(yàn)最大值
        if (!valid.max().isEmpty() && Objects.nonNull(val)) {
            int max = parseInt(valid.max());
            if (val > max) {
                return maxMsg(name, valid);
            }
        }
        // 將值重新寫(xiě)入原字段中
        setValue(obj, field, val);
        // 如果所有校驗(yàn)通過(guò)后,則返回null
        return null;
    }
 
    private static <T> String validDouble(T obj, Field field, Valid valid) {
        return null;
    }
 
    /**
     * 獲取對(duì)象指定字段的值
     *
     * @param obj   原對(duì)象
     * @param field 指定字段
     * @param <T>   泛型
     * @return 該字段的值
     */
    private static <T> Object getValue(T obj, Field field) {
        try {
            return field.get(obj);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            return null;
        }
    }
 
    /**
     * 給對(duì)象指定字段設(shè)值,一般校驗(yàn)后值可能有變化(生成默認(rèn)值/去掉前后空格等),需要新的值重新設(shè)置到對(duì)象中
     *
     * @param obj   原對(duì)象
     * @param field 指定字段
     * @param val   新值
     * @param <T>   泛型
     */
    private static <T> void setValue(T obj, Field field, Object val) {
        try {
            field.set(obj, val);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
 
    /**
     * 獲取字段名稱(chēng)(主要用于錯(cuò)誤時(shí)提示用)
     *
     * @param field 字段對(duì)象
     * @param valid 校驗(yàn)注解
     * @return 字段名稱(chēng)(如果注解有寫(xiě)名稱(chēng),則取注解名稱(chēng);如果沒(méi)有注解名稱(chēng),則取字段)
     */
    private static String getFieldName(Field field, Valid valid) {
        return valid.name().isEmpty() ? field.getName() : valid.name();
    }
 
    /**
     * 該字段是否默認(rèn)為 null
     *
     * @param valid 校驗(yàn)注解
     * @return true - 默認(rèn)為 null; false - 默認(rèn)不為 null
     */
    private static boolean isDefaultNull(Valid valid) {
        return "null".equals(valid.defaultValue());
    }
 
    /**
     * 提示信息(該方法用于統(tǒng)一格式化提示信息樣式)
     *
     * @param name 字段名稱(chēng)
     * @param msg  提示原因
     * @return 提示信息
     */
    private static String msg(String name, String msg) {
        return "【" + name + "】" + msg;
    }
 
    /**
     * 必填字段提示
     *
     * @param name 字段名稱(chēng)
     * @return 提示信息
     */
    private static String requiredMsg(String name) {
        return msg(name, "不能為空");
    }
 
    /**
     * String 類(lèi)型字段少于最小長(zhǎng)度提示
     *
     * @param name  字段名稱(chēng)
     * @param valid 校驗(yàn)注解
     * @return 提示信息
     */
    private static String minLengthMsg(String name, Valid valid) {
        return msg(name, "不能少于" + valid.minLength() + "個(gè)字符");
    }
 
    /**
     * String 類(lèi)型字段超過(guò)最大長(zhǎng)度提示
     *
     * @param name  字段名稱(chēng)
     * @param valid 校驗(yàn)注解
     * @return 提示信息
     */
    private static String maxLengthMsg(String name, Valid valid) {
        return msg(name, "不能超過(guò)" + valid.maxLength() + "個(gè)字符");
    }
 
    /**
     * String 類(lèi)型正則校驗(yàn)提示
     *
     * @param name 字段名稱(chēng)
     * @return 提示信息
     */
    private static String regexMsg(String name) {
        return msg(name, "填寫(xiě)格式不正確");
    }
 
    /**
     * 數(shù)字類(lèi)型小于最小值的提示
     *
     * @param name  字段名稱(chēng)
     * @param valid 校驗(yàn)注解
     * @return 提示信息
     */
    private static String minMsg(String name, Valid valid) {
        return msg(name, "不能小于" + valid.min());
    }
 
    /**
     * 數(shù)字類(lèi)型大于最大值的提示
     *
     * @param name  字段名稱(chēng)
     * @param valid 校驗(yàn)注解
     * @return 提示信息
     */
    private static String maxMsg(String name, Valid valid) {
        return msg(name, "不能大于" + valid.max());
    }
 
    /**
     * 將字符串?dāng)?shù)字轉(zhuǎn)化為 int 類(lèi)型的數(shù)字,轉(zhuǎn)換異常時(shí)返回 0
     *
     * @param intStr 字符串?dāng)?shù)字
     * @return int 類(lèi)型數(shù)字
     */
    private static int parseInt(String intStr) {
        try {
            return Integer.valueOf(intStr);
        } catch (NumberFormatException e) {
            return 0;
        }
    }
}

ValidAop

這是一個(gè) controller 攔截切面,寫(xiě)了這個(gè),就不用再 controller 方法參數(shù)上打上類(lèi)似于原@Valid 和 @Validate 注解,還原的方法參數(shù)的原始整潔度。

但需要注意的是:類(lèi)中 controller 的路徑需要替換為你的包路徑(我這里 controller 包路徑為com.zyq.controller)。

package com.zyq.aop;
 
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.unisoc.outsource.config.global.ValidException;
import com.unisoc.outsource.utils.valid.ValidUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
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.util.Map;
import java.util.Objects;
 
/**
 * @author zyqok
 * @since 2022/05/05
 */
@Aspect
@Component
public class ValidAop {
 
    private static final String APPLICATION_JSON = "application/json";
 
    // 這里為你的 controller 包路徑
    @Pointcut("execution(* com.zyqok.controller.*Controller.*(..))")
    public void pointCut() {
    }
 
    @Before("pointCut()")
    public void doBefore(JoinPoint jp) throws ValidException {
        // 獲取所有請(qǐng)求對(duì)象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 獲取請(qǐng)求類(lèi)型
        String contentType = request.getHeader("Content-Type");
        String json = null;
        if (contentType != null && contentType.startsWith(APPLICATION_JSON)) {
            // JSON請(qǐng)求體
            json = JSON.toJSONString(jp.getArgs()[0]);
        } else {
            // 鍵值對(duì)參數(shù)
            json = getParams(request);
        }
        // 獲取請(qǐng)求類(lèi)對(duì)象
        String validClassName = getParamClassName(jp);
        String msg = valid(json, validClassName);
        if (!isEmpty(msg)) {
            throw new ValidException(msg);
        }
    }
 
    /**
     * 獲取方法參數(shù)對(duì)象名稱(chēng)
     */
    private String getParamClassName(JoinPoint jp) {
        // 獲取參數(shù)對(duì)象
        MethodSignature signature = (MethodSignature) jp.getSignature();
        Class<?>[] types = signature.getParameterTypes();
        // 沒(méi)有參數(shù)則不進(jìn)行校驗(yàn)
        if (types == null || types.length == 0) {
            return null;
        }
        // 返回項(xiàng)目中的對(duì)象類(lèi)名
        for (Class<?> clazz : types) {
            if (clazz.getName().startsWith("com.unisoc.outsource")) {
                return clazz.getName();
            }
        }
        return null;
    }
 
    /**
     * 獲取請(qǐng)求對(duì)象
     */
    private String getParams(HttpServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        if (Objects.isNull(parameterMap) || parameterMap.isEmpty()) {
            return "{}";
        }
        JSONObject obj = new JSONObject();
        parameterMap.forEach((k, v) -> {
            if (Objects.nonNull(v) && v.length == 1) {
                obj.put(k, v[0]);
            } else {
                obj.put(k, v);
            }
        });
        return obj.toString();
    }
 
    /**
     * 校驗(yàn)請(qǐng)求值合規(guī)性
     */
    private String valid(String json, String className) {
        if (isEmpty(className)) {
            return null;
        }
        System.out.println("json : " + json);
        System.out.println("className : " + className);
        try {
            Class<?> clazz = Class.forName(className);
            Object o = JSON.parseObject(json, clazz);
            return ValidUtils.getMsg(o);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
 
    /**
     * 校驗(yàn)字符串是否為空
     */
    private boolean isEmpty(String s) {
        return Objects.isNull(s) || s.trim().isEmpty();
    }
}

ValidException

因?yàn)?AOP 切面里,不能在前置切面中直接返回校驗(yàn)規(guī)則的錯(cuò)誤提示,所以我們可以采用拋異常的方式,最后對(duì)異常進(jìn)行捕捉,再提示給用戶(hù)(原 Springboot 的 @Validate 也是采用類(lèi)似方式進(jìn)行處理)。

package com.zyq.valid;
 
/**
 * 自定義注解異常
 *
 * @author zyqok
 * @since 2022/05/06
 */
public class ValidException extends RuntimeException {
 
    private String msg;
 
    public String getMsg() {
        return msg;
    }
 
    public void setMsg(String msg) {
        this.msg = msg;
    }
 
    public ValidException(String msg) {
        this.msg = msg;
    }
}

ValidExceptionHandler

這個(gè)異常處理器就是用于捕捉上面的異常,最后提示給前端。

@ControllerAdvice
@ResponseBody
public class ValidExceptionHandler {
 
    @ExceptionHandler(ValidException.class)
    public Map<String, String> validExceptionHandler(ValidException ex) {
        Map<String, String> map = new HashMap();
        map.put("code", 1);
        map.put("msg", ex.getMsg());
        return map;
    }
 
}

當(dāng)把所有文件復(fù)制到文件中后,那么在使用的時(shí)候

只需要將方法中的參數(shù)打上我們定義的 @Valid 即可,其余不用做任何操作就OK

/**
 * @author zyqok
 * @since 2022/05/06
 */
@Data
public class EntryApplyCancelReq {
 
    @Valid
    private Integer id;
 
    @Valid(name = "取消原因", maxLength = 50)
    private String reason;
 
}

到此這篇關(guān)于手寫(xiě)一個(gè)@Valid字段校驗(yàn)器的示例代碼的文章就介紹到這了,更多相關(guān)@Valid字段校驗(yàn)器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA啟動(dòng)服務(wù)提示端口被占用,Web?server?failed?to?start.Port?was?already?in?use.

    IDEA啟動(dòng)服務(wù)提示端口被占用,Web?server?failed?to?start.Port?was?al

    這篇文章主要介紹了IDEA啟動(dòng)服務(wù)提示端口被占用,Web?server?failed?to?start.Port?was?already?in?use.,本文給大家分享解決方案,分為linux系統(tǒng)和windows系統(tǒng)解決方案,需要的朋友可以參考下
    2023-07-07
  • 詳解Java中AC自動(dòng)機(jī)的原理與實(shí)現(xiàn)

    詳解Java中AC自動(dòng)機(jī)的原理與實(shí)現(xiàn)

    AC自動(dòng)機(jī)是一個(gè)多模式匹配算法,在模式匹配領(lǐng)域被廣泛應(yīng)用。本文將詳細(xì)為大家介紹AC自動(dòng)機(jī)的原理與實(shí)現(xiàn)方法,感興趣的可以了解一下
    2022-05-05
  • IDEA關(guān)閉git管理,文件變成紅色解決方案

    IDEA關(guān)閉git管理,文件變成紅色解決方案

    在軟件開(kāi)發(fā)中,當(dāng)一個(gè)文件夾內(nèi)的Java項(xiàng)目啟用Git版本控制,通常會(huì)導(dǎo)致該文件夾下所有項(xiàng)目同步開(kāi)啟Git,這種做法有助于保持項(xiàng)目的一致性和可追溯性,但也可能帶來(lái)管理上的復(fù)雜性,如果需要解除某個(gè)項(xiàng)目的Git管理,可以通過(guò)IDE的設(shè)置選項(xiàng)進(jìn)行調(diào)整
    2024-10-10
  • java并發(fā)編程之ThreadLocal詳解

    java并發(fā)編程之ThreadLocal詳解

    在鎖的使用中會(huì)導(dǎo)致運(yùn)行效率降低,ThreadLocal的使用徹底避免對(duì)共享資源的競(jìng)爭(zhēng),同時(shí)又可以不影響效率。本文詳細(xì)講解了ThreadLocal,需要了解的小伙伴可以看一看這篇文章
    2021-08-08
  • Java concurrency集合之LinkedBlockingDeque_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java concurrency集合之LinkedBlockingDeque_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    LinkedBlockingDeque是雙向鏈表實(shí)現(xiàn)的雙向并發(fā)阻塞隊(duì)列。該阻塞隊(duì)列同時(shí)支持FIFO和FILO兩種操作方式,即可以從隊(duì)列的頭和尾同時(shí)操作(插入/刪除);并且,該阻塞隊(duì)列是支持線(xiàn)程安全。
    2017-06-06
  • Maven報(bào)錯(cuò)之導(dǎo)入Junit包來(lái)實(shí)現(xiàn)@Test注解問(wèn)題

    Maven報(bào)錯(cuò)之導(dǎo)入Junit包來(lái)實(shí)現(xiàn)@Test注解問(wèn)題

    這篇文章主要介紹了Maven報(bào)錯(cuò)之導(dǎo)入Junit包來(lái)實(shí)現(xiàn)@Test注解問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • java 代碼中預(yù)防空指針異常的處理辦法

    java 代碼中預(yù)防空指針異常的處理辦法

    個(gè)人在做項(xiàng)目時(shí),對(duì)NullPointerException的幾點(diǎn)總結(jié),請(qǐng)網(wǎng)友拍磚?。?!多多提意見(jiàn),
    2013-03-03
  • SpringBoot中Shiro緩存使用Redis、Ehcache的方法

    SpringBoot中Shiro緩存使用Redis、Ehcache的方法

    這篇文章主要介紹了SpringBoot中Shiro緩存使用Redis、Ehcache的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 如何將Java枚舉名稱(chēng)作為注解的屬性值實(shí)現(xiàn)詳解

    如何將Java枚舉名稱(chēng)作為注解的屬性值實(shí)現(xiàn)詳解

    這篇文章主要為大家介紹了如何將Java枚舉名稱(chēng)作為注解的屬性值實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • Java微信支付之服務(wù)號(hào)支付代碼示例

    Java微信支付之服務(wù)號(hào)支付代碼示例

    這篇文章主要介紹了Java微信支付之服務(wù)號(hào)支付代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11

最新評(píng)論

从化市| 岳阳市| 永年县| 寿光市| 宣恩县| 伊宁市| 松滋市| 海安县| 昌吉市| 呼和浩特市| 淮安市| 承德县| 富阳市| 青冈县| 桓仁| 柞水县| 石河子市| 广平县| 泰顺县| 义乌市| 绥棱县| 四川省| 和田市| 阿拉善盟| 玛多县| 井冈山市| 神木县| 长岭县| 通城县| 大丰市| 凤台县| 博白县| 商城县| 方山县| 张掖市| 剑川县| 台南市| 鹤岗市| 玉林市| 杭锦后旗| 麟游县|