国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

boot-admin開源項目中有關(guān)后端參數(shù)校驗的最佳實踐

這篇具有很好參考價值的文章主要介紹了boot-admin開源項目中有關(guān)后端參數(shù)校驗的最佳實踐。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

我們在項目開發(fā)中,經(jīng)常會對一些參數(shù)進(jìn)行校驗,比如非空校驗、長度校驗,以及定制的業(yè)務(wù)校驗規(guī)則等,如果使用if/else語句來對請求的每一個參數(shù)一一校驗,就會出現(xiàn)大量與業(yè)務(wù)邏輯無關(guān)的代碼,繁重不堪且繁瑣的校驗,會大大降低我們的工作效率,而且準(zhǔn)確性也無法保證。為保證數(shù)據(jù)的正確性、完整性,前后端都需要進(jìn)行數(shù)據(jù)檢驗。本文對開源 boot-admin 項目的后端校驗實踐進(jìn)行總結(jié),以饗碼友。
boot-admin 是一款采用前后端分離模式、基于 SpringCloud 微服務(wù)架構(gòu)的SaaS后臺管理框架。系統(tǒng)內(nèi)置基礎(chǔ)管理、權(quán)限管理、運行管理、定義管理、代碼生成器和辦公管理6個功能模塊,集成分布式事務(wù) Seata、工作流引擎 Flowable、業(yè)務(wù)規(guī)則引擎 Drools、后臺作業(yè)調(diào)度框架 Quartz 等,技術(shù)棧包括 Mybatis-plus、Redis、Nacos、Seata、Flowable、Drools、Quartz、SpringCloud、Springboot Admin Gateway、Liquibase、jwt、Openfeign、I18n等。

項目源碼倉庫github
項目源碼倉庫gitee

引入Maven依賴

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
</dependency>

參數(shù)校驗實踐

定義校驗對象

@Data
/** 組合校驗注解(方式1) **/
@OverallValid(value = "check1" ,message="女士不得小于16歲。")
@OverallValid(value = "check2" ,message="男士不得小于18歲。")
public class User {
    //字符個數(shù)檢測(內(nèi)置注解)
    @Size(min = 1,max = 10,message = "姓名長度必須為1到10")
    //占用空間長度檢測(自定義注解)
    @StringLength(min = 1,max = 12,message = "姓名的保存長度不允許超過12個字節(jié)。")
    private String name;
    //利用枚舉類檢測(自定義注解)
    @EnumValid(target = SexEnum.class, message = "性別的取值范圍是【1】和【2】")
    private String sex;
    //注意 @NotNull @NotEmpty @NotBlank 的區(qū)別
    @NotBlank(message = "姓氏是必填項。")
    private String firstName;

    @Min(value = 10,message = "年齡最小為10")
    @Max(value = 100,message = "年齡最大為100")
    private Integer age;

    @Past(message = "出生時間必須為過去時間")
    private Date birth;

    @NotEmpty(message = "興趣不能為空")
    private List<String> interest;

    //嵌套檢測
    @Valid
    private List<User> children;
    @Valid
    private User father;
    @Valid
    private User mother;

    /** 組合校驗(方式2) **/
    @BooleanValid(message = "男性年齡需在60歲以下")
    public boolean getValid1(){
        if(sex.equalsIgnoreCase("1") && age >= 60 ){
            return false;
        }
        return true;
    }
    /** 組合校驗(方式2) **/
    @BooleanValid(message = "女性年齡需在55歲以下")
    public boolean getValid2(){
        if(sex.equalsIgnoreCase("2") && age >= 55 ){
            return false;
        }
        return true;
    }
    /** 組合校驗(方式1)方法 **/
    public boolean check1(){
        if(sex.equalsIgnoreCase("2") && age < 16 ){
            return false;
        }
        return true;
    }
    /** 組合校驗(方式1)方法 **/
    public boolean check2(){
        if(sex.equalsIgnoreCase("1") && age < 18 ){
            return false;
        }
        return true;
    }
}

相關(guān)枚舉類:

public enum SexEnum {
    男("1"),女("2");
    private final String value;
    SexEnum(String value) {
        this.value = value;
    }
    public String getValue() {
        return value;
    }
}

參數(shù)校驗(在 Controller 中使用)

@RestController
@RequestMapping("/api/system")
@Slf4j
public class DemoController {
    //注入校驗信息采集器
    @Resource
    private FormValidator formValidator;

    @PostMapping("/free/user/check")
    public ResultDTO check(@Valid @RequestBody User user, BindingResult bindingResult, HttpServletRequest request) throws Exception{
        /** 參數(shù)校驗 **/
        if (bindingResult.hasErrors()) {
            return formValidator.generateMessage(bindingResult);
        }
        /** 繼續(xù)執(zhí)行業(yè)務(wù)邏輯 **/
        return ResultDTO.success();
    }
}

在Controller中使用的校驗結(jié)果信息采集器實現(xiàn)

接口定義:

public interface FormValidator {
    ResultDTO generateMessage(BindingResult bindingResult) throws Exception;
}

類實現(xiàn):

@Service
@Slf4j
public class FormValidatorImpl implements FormValidator {
    @Override
    public ResultDTO generateMessage(BindingResult bindingResult) throws Exception {
        String msg = this.getMessage(bindingResult);
        return ResultDTO.failureCustom(msg);
    }
    /**
     * 生成校驗結(jié)果
     * @param bindingResult
     * @return
     */
    private String getMessage(BindingResult bindingResult){
        log.info(bindingResult.toString());
        List<ObjectError> objectErrorList=bindingResult.getAllErrors();
        String msg= this.getFormValidErrsMsgNoBr(objectErrorList);
        log.info(msg);
        return msg;
    }
    private String getFormValidErrsMsgNoBr(List<ObjectError> objectErrorList) {
        if (objectErrorList==null) {
            return "";
        }
        StringBuffer csv = new StringBuffer();
        csv.append("數(shù)據(jù)驗證未通過:[");
        for (int i = 0; i < objectErrorList.size(); i++){
            if (i > 0){
                csv.append("],[");
            }
            csv.append(objectErrorList.get(i).getDefaultMessage());
        }
        csv.append("]");
        return csv.toString();
    }
}

相關(guān)注解介紹

JSR-303 規(guī)范常用注解

以下列舉常用內(nèi)置注解,可直接使用。

注解 描述
@Valid 對po實體盡心校驗
@AssertFalse 所注解的元素必須是Boolean類型,且值為false
@AssertTrue 所注解的元素必須是Boolean類型,且值為true
@DecimalMax 所注解的元素必須是數(shù)字,且值小于等于給定的值
@DecimalMin 所注解的元素必須是數(shù)字,且值大于等于給定的值
@Digits 所注解的元素必須是數(shù)字,且值必須是指定的位數(shù)
@Future 所注解的元素必須是將來某個日期
@Max 所注解的元素必須是數(shù)字,且值小于等于給定的值
@Min 所注解的元素必須是數(shù)字,且值大于等于給定的值
@Range 所注解的元素需在指定范圍區(qū)間內(nèi)
@NotNull 所注解的元素值不能為null
@NotBlank 所注解的元素值有內(nèi)容
@Null 所注解的元素值為null
@Past 所注解的元素必須是某個過去的日期
@PastOrPresent 所注解的元素必須是過去某個或現(xiàn)在日期
@Pattern 所注解的元素必須滿足給定的正則表達(dá)式
@Size 所注解的元素必須是String、集合或數(shù)組,且長度大小需保證在給定范圍之內(nèi)
@Email 所注解的元素需滿足Email格式

自定義注解

僅僅使用內(nèi)置的注解,無法滿足復(fù)雜的業(yè)務(wù)需求,故擴(kuò)展下面幾個自定義注解。

UTF-8 字符串長度校驗

對字符串長度的校驗?zāi)康?,一般是用于保證數(shù)據(jù)表字段可以容納,當(dāng)字符串內(nèi)容是中文時,內(nèi)置的 @Size 是不適用的,此時就需要自行擴(kuò)展 UTF-8 字符串長度校驗。
注解類:

@Target( {
        METHOD,
        FIELD,
        ANNOTATION_TYPE,
        CONSTRUCTOR,
        PARAMETER
})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {StringLengthValidator.class})
public @interface StringLength {
    int max() default 4000;
    int min() default 0;
    String message() default "字符串長度不符合要求。";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

注解類實現(xiàn):

@Slf4j
public class StringLengthValidator implements ConstraintValidator<StringLength, String> {
    private int max;
    private int min;
    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
        try {
            if(StringUtils.isBlank(value)){
                if(min > 0){
                    return false;
                }else {
                    return true;
                }
            }
            byte[] tmpbyte = value.getBytes("UTF-8");
            int length = tmpbyte.length;
            if(length < min || length > max){
                return false;
            }
            return true;
        }catch (Exception ex){
            log.error("注解校驗StringLength發(fā)生異常。");
            log.error(ex.getMessage(),ex);
            return false;
        }
    }
    @Override
    public void initialize(StringLength constraintAnnotation) {
        max = constraintAnnotation.max();
        min = constraintAnnotation.min();
    }
}

手機(jī)號碼校驗

注解類:

@Target( {
        METHOD,
        FIELD,
        ANNOTATION_TYPE,
        CONSTRUCTOR,
        PARAMETER
})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {MobileValidator.class})
public @interface Mobile {
    String regexp() default "";
    String message() default "手機(jī)號碼格式不正確";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

注解類實現(xiàn):

public class MobileValidator implements ConstraintValidator<Mobile, String> {
    /**
     * 手機(jī)號的正則表達(dá)式.
     */
    private static Pattern pattern = Pattern.compile(
            "^0?(13[0-9]|14[0-9]|15[0-9]|16[0-9]|17[0-9]|18[0-9]|19[0-9])[0-9]{8}$");
    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
        Matcher m = pattern.matcher(value);
        return m.matches();
    }
    @Override
    public void initialize(Mobile constraintAnnotation) {}
}

這里對手機(jī)號碼的校驗使用了正則表達(dá)式,也可以直接使用內(nèi)置注解 @Pattern 定義校驗規(guī)則。

枚舉類整數(shù)值校驗

有時需要校驗參數(shù)值必須是系統(tǒng)定義的枚舉值(整數(shù)值),此時需要擴(kuò)展以下注解。
注解類:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {EnumIntegerValidator.class})
public @interface EnumIntegerValid {
    String message() default "";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    /**     * 目標(biāo)枚舉類     */
    Class<?> target() default Class.class;
    /**     * 是否忽略空值     */
    boolean ignoreEmpty() default true;
}

注解類實現(xiàn):

@Slf4j
public class EnumIntegerValidator implements ConstraintValidator<EnumIntegerValid, Integer> {
    /** 枚舉校驗注解 */
    private EnumIntegerValid annotation;
    @Override
    public void initialize(EnumIntegerValid constraintAnnotation) {
        annotation = constraintAnnotation;
    }
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
        boolean result = false;
        Class<?> cls = annotation.target();
        boolean ignoreEmpty = annotation.ignoreEmpty();
        // target為枚舉,并且value有值,或者不忽視空值,才進(jìn)行校驗
        if (cls.isEnum() && value != null) {
            Object[] objects = cls.getEnumConstants();
            try {
                Method method = cls.getMethod("getValue");
                for (Object obj : objects) {
                    Object code = method.invoke(obj);
                    if (value.compareTo((Integer) code) == 0) {
                        result = true;
                        break;
                    }
                }
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                log.warn("EnumValidator call isValid() method exception.");
                result = false;
            }
        } else {
            result = true;
        }
        return result;
    }
}

枚舉類字符串校驗

有時需要校驗參數(shù)值必須是系統(tǒng)定義的枚舉值(字符串),此時需要擴(kuò)展以下注解。
注解類:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {EnumValidator.class})
public @interface EnumValid {
    String message() default "";
       Class<?>[] groups() default {};
       Class<? extends Payload>[] payload() default {};
       /**     * 目標(biāo)枚舉類     */
       Class<?> target() default Class.class;
       /**     * 是否忽略空值     */
       boolean ignoreEmpty() default true;
}

注解類實現(xiàn):

@Slf4j
public class EnumValidator implements ConstraintValidator<EnumValid, String> {
    /** 枚舉校驗注解 */
    private EnumValid annotation;
    @Override
    public void initialize(EnumValid constraintAnnotation) {
        annotation = constraintAnnotation;
    }
    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
        boolean result = false;
        Class<?> cls = annotation.target();
        boolean ignoreEmpty = annotation.ignoreEmpty();
        // target為枚舉,并且value有值,或者不忽視空值,才進(jìn)行校驗
        boolean fitCheck = cls.isEnum() && (isNotEmpty(value) || !ignoreEmpty);
        if (fitCheck) {
            Object[] objects = cls.getEnumConstants();
            try {
                Method method = cls.getMethod("getValue");
                for (Object obj : objects) {
                    Object code = method.invoke(obj);
                    if (value.equals(code.toString())) {
                        result = true;
                        break;
                    }
                }
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                log.warn("EnumValidator call isValid() method exception.");
                result = false;
            }
        } else {
            result = true;
        }
        return result;
    }
}

Bean 內(nèi)多屬性組合校驗(組合校驗)

此類校驗一般屬于業(yè)務(wù)邏輯校驗,常常要求多個屬性符合一定的邏輯設(shè)定。此時需要在Bean中編寫校驗方法,并在類定義前面添加自定義注解 @OverallValid 或者在方法前面加上自定義注解 @BooleanValid

方式1:

注解在類定義前面,類方法要求:

  1. 方法的可訪問屬性:public
  2. 方法的返回類型: boolean
    @OverallValid注解類:
@Target({METHOD, FIELD,TYPE})
@Retention(RUNTIME)
@Repeatable(OverallValids.class)
@Documented
@Constraint(validatedBy = {OverallValidImpl.class})
public @interface OverallValid {
    String value() default "overallValid";
    String message() default "組合校驗未通過。";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

上面注解要求可重復(fù)使用,使用了 @Repeatable(OverallValids.class),OverallValids 代碼如下:

@Target({METHOD, FIELD,TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OverallValids {
    OverallValid[] value();
}

使用注入的方法名,通過反射執(zhí)行該方法,得到校驗結(jié)果。注解實現(xiàn)如下:

@Slf4j
public class OverallValidImpl implements ConstraintValidator<OverallValid, Object> {
    private String functionName;
    @Override
    public void initialize(OverallValid overallValid) {
        functionName = overallValid.value();
    }
    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        try {
            //得到方法對象
            Method checkMethod = o.getClass().getMethod(functionName);
            //調(diào)用方法,得到返回值
            Object checkRet = checkMethod.invoke(o);
            return Boolean.valueOf(checkRet.toString());
        }catch (Exception ex){
            log.error("綜合校驗異常。");
            log.error(ex.getMessage(),ex);
        }
        return false;
    }
}

方式2:

注解在方法前面,類方法要求:

  1. 方法的可訪問屬性:public
  2. 方法的返回類型: boolean
  3. 方法名稱格式:get+首字母大寫駝峰,如 getValid1

@BooleanValid注解類:

@Target( {
        METHOD,
        FIELD,
        ANNOTATION_TYPE,
        CONSTRUCTOR,
        PARAMETER
})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {BooleanValidImpl.class})
public @interface BooleanValid {
    boolean value() default true;
    String message() default "綜合校驗未通過。";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

類實現(xiàn):

@Slf4j
public class BooleanValidImpl implements ConstraintValidator<BooleanValid, Boolean> {
    @Override
    public boolean isValid(Boolean value, ConstraintValidatorContext constraintValidatorContext) {
        return value;
    }
    @Override
    public void initialize(BooleanValid constraintAnnotation) {
    }
}

嵌套校驗

在成員屬性上加注解 @Valid ,意味著對該成員屬性進(jìn)行嵌套校驗,校驗規(guī)則按該成員的內(nèi)部校驗注解執(zhí)行。文章來源地址http://www.zghlxwxcb.cn/news/detail-435864.html

到了這里,關(guān)于boot-admin開源項目中有關(guān)后端參數(shù)校驗的最佳實踐的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • boot-admin整合flowable官方editor-app源碼進(jìn)行BPMN2-0建模(續(xù))

    boot-admin整合flowable官方editor-app源碼進(jìn)行BPMN2-0建模(續(xù))

    boot-admin整合flowable官方editor-app源碼進(jìn)行BPMN2-0建模(續(xù)) 書接上回 項目源碼倉庫github 項目源碼倉庫gitee boot-admin 是一款采用前后端分離模式、基于SpringCloud微服務(wù)架構(gòu)的SaaS后臺管理框架。系統(tǒng)內(nèi)置基礎(chǔ)管理、權(quán)限管理、運行管理、定義管理、代碼生成器和辦公管理6個功能模

    2023年04月21日
    瀏覽(19)
  • ELADMIN - 免費開源 admin 后臺管理系統(tǒng),基于 Spring Boot 和 Vue ,包含前端和后端源碼

    ELADMIN - 免費開源 admin 后臺管理系統(tǒng),基于 Spring Boot 和 Vue ,包含前端和后端源碼

    一款簡單好用、功能強(qiáng)大的 admin 管理系統(tǒng),包含前端和后端源碼,分享給大家。 ELADMIN?是一款基于 Spring Boot、Jpa 或 Mybatis-Plus、 Spring Security、Redis、Vue 的前后端分離的后臺管理系統(tǒng)。 ELADMIN 的作者在 Github 和 Gitee 上看了很多的項目,發(fā)現(xiàn)大多數(shù)都是基于 Mybatis , 而基于 Sp

    2024年02月04日
    瀏覽(29)
  • Spring Boot中參數(shù)校驗

    Spring Boot中參數(shù)校驗

    為了保證數(shù)據(jù)的正確性、完整性,前后端都需要進(jìn)行數(shù)據(jù)檢驗。作為一名后端開發(fā)工程師,不能僅僅依靠前端來校驗數(shù)據(jù),我們還需要對接口請求的參數(shù)進(jìn)行后端的校驗。最常見的做法就是通過if/else語句來對請求的每一個參數(shù)一一校驗,當(dāng)很多參數(shù)需要校驗的時候,if/else語

    2023年04月16日
    瀏覽(22)
  • Spring Boot 使用validation校驗參數(shù)

    在看公司代碼的時候,發(fā)現(xiàn)是用了 Spring Boot Validation 去檢驗參數(shù)的,但是后面又在代碼里去檢驗參數(shù)去了,而且這個 Spring Boot Validation 校驗好像并不生效。于是自己摸索研究了一下。 雖然項目使用的校驗都是 javax.validation ,但是不引入這個依賴他是真的不生效。 gradle如下:

    2024年01月25日
    瀏覽(26)
  • spring-boot 請求參數(shù)校驗:注解 @Validated 的使用、手動校驗、自定義校驗

    spring-boot中可以用@validated來校驗數(shù)據(jù),如果數(shù)據(jù)異常則會統(tǒng)一拋出異常,方便異常中心統(tǒng)一處理。 spring-boot已經(jīng)引入了基礎(chǔ)包,所以直接使用就可以。 在屬性上添加校驗注解: 在Controller上添加 @Validated 注解 校驗未通過時,可能看到: 在 @Validated 后面緊跟著追加BindingResult,

    2023年04月16日
    瀏覽(33)
  • spring boot3參數(shù)校驗基本用法

    spring boot3參數(shù)校驗基本用法

    ??個人主頁:? ? ? 蒾酒 ??系列專欄: 《spring boot實戰(zhàn)》 ??山高路遠(yuǎn),行路漫漫,終有歸途。 目錄 前置條件 前言 導(dǎo)入依賴 使用介紹 配置檢驗規(guī)則 開啟校驗 使用注意 全局異常捕獲返回友好提示信息 常用的校驗規(guī)則注解 使用技巧 已經(jīng)初始化好一個spring boot項目且版本為

    2024年02月21日
    瀏覽(11)
  • spring boot實現(xiàn)實體類參數(shù)自定義校驗

    安裝依賴項 1、新建實體類 2、新建驗證類 3、在控制器中 3.1 首先寫入方法 @InitBinder注解的作用是在控制器方法執(zhí)行之前,先執(zhí)行有 @InitBinder注解的方法,使用WebDataBinder 把新建的驗證規(guī)則綁定 3.2 在控制器接口參數(shù)中

    2024年02月12日
    瀏覽(22)
  • Spring Boot使用 Hibernate-Validator校驗參數(shù)時的長度校驗

    今天在使用Validator框架數(shù)據(jù)驗證的時候碰到了三個類似的注解,都是用來限制長度,但是用法上有區(qū)別: ?@Size是一個Bean驗證注釋,用于驗證關(guān)聯(lián)的String具有的長度受最小值和最大值限制的值. ?@Length是一個Hibernate特定的注釋,與@Size具有相同的含義; 兩者的區(qū)別: ? 用@length限

    2024年02月14日
    瀏覽(29)
  • 如何在Spring Boot中優(yōu)雅地進(jìn)行參數(shù)校驗

    在平時的開發(fā)工作中,我們通常需要對接口進(jìn)行參數(shù)格式驗證。當(dāng)參數(shù)個數(shù)較少(個數(shù)小于3)時,可以使用 if ... else ... 手動進(jìn)行參數(shù)驗證。當(dāng)參數(shù)個數(shù)大于3個時,使用 if ... else ... 進(jìn)行參數(shù)驗證就會讓代碼顯得臃腫,這個時候推薦使用注解來進(jìn)行參數(shù)驗證。 在Java中,注解

    2024年01月17日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包