溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

SpringBoot2 中參數(shù)參與校驗的實現(xiàn)方法

發(fā)布時間:2021-06-16 09:33:07 來源:億速云 閱讀:96 作者:chen 欄目:開發(fā)技術(shù)

這篇文章主要介紹“SpringBoot2 中參數(shù)參與校驗的實現(xiàn)方法”,在日常操作中,相信很多人在SpringBoot2 中參數(shù)參與校驗的實現(xiàn)方法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”SpringBoot2 中參數(shù)參與校驗的實現(xiàn)方法”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

目錄
  • 一、參數(shù)管理

  • 二、接收參數(shù)

  • 三、響應(yīng)參數(shù)

  • 四、參數(shù)校驗

    • 1、借鑒參考

    • 2、常用校驗方式

  • 五、源代碼地址

    一、參數(shù)管理

    在編程系統(tǒng)中,為了能寫出良好的代碼,會根據(jù)是各種設(shè)計模式、原則、約束等去規(guī)范代碼,從而提高代碼的可讀性、復(fù)用性、可修改,實際上個人覺得,如果寫出的代碼很好,即別人修改也無法破壞原作者的思路和封裝,這應(yīng)該是非常高水準(zhǔn)。

    但是在日常開發(fā)中,礙于很多客觀因素,很少有時間去不斷思考和優(yōu)化代碼,所以只能從實際情況的角度去思考如何構(gòu)建系統(tǒng)代碼,保證以后自己還能讀懂自己的代碼,在自己的幾年編程中,實際會考慮如下幾個方面:代碼層級管理,命名和注釋統(tǒng)一,合理的設(shè)計業(yè)務(wù)數(shù)據(jù)庫,明確參數(shù)風(fēng)格。

    這里就來聊一下參數(shù)管理,圍繞:入?yún)ⅰ⑿r?、返參三個方面內(nèi)容。

    如何理解代碼規(guī)范這個概念:即大多數(shù)開發(fā)認(rèn)同,愿意遵守的約束,例如Spring框架和Mvc模式對于工程的管理,《Java開發(fā)手冊》中對于業(yè)務(wù)開發(fā)的規(guī)定,其根本目的都是想避免隨著業(yè)務(wù)發(fā)展,代碼演變到無法維護(hù)的境界。

    二、接收參數(shù)

    接收參數(shù)方式有很多種,List,Map,Object等等,但是為了明確參數(shù)的語義,通常都需要設(shè)計參數(shù)對象的結(jié)構(gòu)并且遵守一定的規(guī)范,例如明確禁止Map接收參數(shù):

    Rest風(fēng)格接收單個ID參數(shù):

    @GetMapping("/param/single/{id}")
    public String paramSingle (@PathVariable Integer id){
        return "Resp:"+id ;
    }

    接收多個指定的參數(shù):

    @GetMapping("/param/multi")
    public String paramMulti (@RequestParam("key") String key, @RequestParam("var") String var){
        return "Resp:"+key+var ;
    }

    基于Java包裝對象入?yún)ⅲ?/p>

    @PostMapping("/param/wrap")
    public ParamIn paramWrap (@RequestBody ParamIn paramIn){
        return paramIn ;
    }
    
    -- 參數(shù)對象實體
    public class ParamIn {
        private Integer id ;
        private String key ;
        private String var ;
        private String name ;
    }

    以上是在開發(fā)中常用的幾種接參方式,這里通常會遵守下面幾個習(xí)慣:

    • 參數(shù)語義:明確接收參數(shù)的作用;

    • 個數(shù)限制:參數(shù)超過三個使用包裝對象;

    • 避免多個接口使用單個包裝對象入?yún)ⅲ?/p>

    • 避免包裝對象主體過于復(fù)雜;

    參數(shù)接收并沒有很復(fù)雜的約束,整體上也比較容易遵守,通常的問題在于處理較大主體對象時,容易產(chǎn)生一個包裝對象被多處復(fù)用,進(jìn)而導(dǎo)致對象字段屬性很多,這種情況在復(fù)雜業(yè)務(wù)中尤其容易出現(xiàn),這種對象并不利于web層接口使用,或者很多時候都會在業(yè)務(wù)層和接口層混用對象;

    在業(yè)務(wù)層封裝復(fù)雜的BO對象來降低業(yè)務(wù)管理的復(fù)雜度,這是合理常見的操作,可以在web接口層面根據(jù)接口功能各自管理入?yún)⒅黧w,在業(yè)務(wù)實現(xiàn)的過程中,再傳入BO對象中。

    避免復(fù)雜的業(yè)務(wù)包裝對象在各個層亂飄,如果多個接口入?yún)⒍际峭粋€復(fù)雜的對象,很容易讓開發(fā)人員迷茫。

    三、響應(yīng)參數(shù)

    與參數(shù)接收相對應(yīng)的就是參數(shù)響應(yīng),參數(shù)響應(yīng)通常具有明確的約束規(guī)范:響應(yīng)主體數(shù)據(jù),響應(yīng)碼,描述信息。通常來說就是這樣三個核心要素。

    響應(yīng)參數(shù)主體:

    這里泛型的使用通常用來做主體數(shù)據(jù)的接收。

    public class Resp<T> {
    
        private int code ;
        private String msg ;
        private T data ;
    
        public static <T> Resp<T> ok (T data) {
            Resp<T> result = new Resp<>(HttpStatus.OK);
            result.setData(data);
            return result ;
        }
    
        public Resp (HttpStatus httpStatus) {
            this.code = httpStatus.value();
            this.msg = httpStatus.getReasonPhrase();
        }
    
        public Resp(int code, String msg, T data) {
            this.code = code;
            this.msg = msg;
            this.data = data;
        }
    }

    Code狀態(tài)碼

    即接口狀態(tài),建議參照并遵守HttpStatus中狀態(tài)碼的描述,這是開發(fā)普遍遵守的規(guī)范,如果不滿足業(yè)務(wù)需求,在適當(dāng)自定義部分編碼,可以完全自定義一套響應(yīng)碼,但是沒太多必要。

    Msg描述

    描述接口的響應(yīng)的Msg可能就是:成功或失敗,更多的時候是需要處理業(yè)務(wù)異常的提示信息,例如單號不存在,賬號凍結(jié)等等,通常需要從業(yè)務(wù)異常中捕獲提示信息,并響應(yīng)頁面,或者入?yún)⑿r灢煌ㄟ^的描述。

    Data數(shù)據(jù)

    接口響應(yīng)的主體數(shù)據(jù),不同的業(yè)務(wù)響應(yīng)的對象肯定不同,所以這里基于泛型機(jī)制接收即可,再以JSON格式響應(yīng)頁面。

    參考案例

    接口返參:

    @PostMapping("/resp/wrap")
    public Resp<KeyValue> respWrap (@RequestBody KeyValue keyValue){
        return Resp.ok(keyValue) ;
    }

    響應(yīng)格式:

    {
       "code": 200,
       "msg": "OK",
       "data": {
           "key": "hello",
           "value": "world"
       }
    }

    四、參數(shù)校驗

    參數(shù)接收和響應(yīng)相對都不是復(fù)雜的,比較難處理的就是參數(shù)校驗:入?yún)⒓s束校驗,業(yè)務(wù)合法性校驗,響應(yīng)參數(shù)非空非null校驗,等各種場景。

    在系統(tǒng)運行過程中,任何參數(shù)都不是絕對可靠的,所以參數(shù)校驗隨處可見,不同場景下的參數(shù)校驗,都有其必要性,但其根本目的都是為了給到請求端提示信息,快速打斷流程,快速響應(yīng)。

    1、借鑒參考

    很多封裝思想,設(shè)計模式,或者這里說的參數(shù)校驗,都可以參考現(xiàn)有Java源碼或者優(yōu)秀的框架,這是一個應(yīng)該具備的基礎(chǔ)意識。

    Java原生方法之java.lang.Thread線程:

    public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();
        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();   
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }

    在Java源碼中,大部分都是采用原生的if判斷方式,對參數(shù)執(zhí)行校驗

    Spring框架之org.springframework.util.ClassUtils工具類部分代碼:

    public static Class<?> forName(String name, @Nullable ClassLoader classLoader)
    			throws ClassNotFoundException, LinkageError {
    		Assert.notNull(name, "Name must not be null");
    		Class<?> clazz = resolvePrimitiveClassName(name);
    		if (clazz == null) {
    			clazz = commonClassCache.get(name);
    		}
    		if (clazz != null) {
    			return clazz;
    		}
    }

    在Spring框架中除了基礎(chǔ)的if判斷之外,還封裝一個org.springframework.util.Assert斷言工具類。

    2、常用校驗方式

    If判斷

    @GetMapping("/check/base")
    public String baseCheck (@RequestParam("var") String var){
        if (var == null) {
            return var+" is null" ;
        }
        if ("".equals(var)){
            return var+" is empty" ;
        }
        if ("hello".equals(var)){
            return var+" sensitive word " ;
        }
        return var + " through " ;
    }

    這種判斷在代碼中很常見,只是一旦遇到校驗的主體對象很大,并且在分布式的環(huán)境中,需要重復(fù)寫if判斷的話,容易出錯是一個方面,對開發(fā)人員的耐心考驗是另一個方面。

    Valid組件

    在早幾年的時候,比較流行的常用校驗組件Hibernate-Validator,后來興起的Validation-Api,據(jù)說是參考前者實現(xiàn),不過這并不重要,二者都簡化了對JavaBean的校驗機(jī)制。

    基于注解的方式,標(biāo)記Java對象的字段屬性,并設(shè)定如果校驗失敗的提示信息。

    public class JavaValid {
    
        @NotNull(message="ID不能為空")
        private Integer id ;
    
        @Email(message="郵箱格式異常")
        private String email ;
    
        @NotEmpty(message = "字段不能為空")
        @Size(min = 2,max = 10,message = "字段長度不合理")
        private String data ;
    }

    校驗結(jié)果打印:

    public class JavaValidTest {
    
        private static Validator validator ;
    
        @BeforeClass
        public static void beforeBuild (){
            validator = Validation.buildDefaultValidatorFactory().getValidator();
        }
    
        @Test
        public void checkValid (){
            JavaValid valid = new JavaValid(null,"email","data") ;
            Set<ConstraintViolation<JavaValid>> validateInfo = validator.validate(valid) ;
            // 打印校驗結(jié)果
            validateInfo.stream().forEach(validObj -> {
                System.out.println("validateInfo:"+validObj.getMessage());
            });
        }
    }

    接口使用:

    @PostMapping("/java/valid")
    public JavaValid javaValid (@RequestBody @Valid JavaValid javaValid,BindingResult errorMsg){
        if (errorMsg.hasErrors()){
            List<ObjectError> objectErrors = errorMsg.getAllErrors() ;
            objectErrors.stream().forEach(objectError -> {
                logger.info("CheckRes:{}",objectError.getDefaultMessage());
            });
        }
        return javaValid ;
    }

    這種校驗機(jī)制基于注解方式,可以大幅度簡化普通的入?yún)⑿r灒菍I(yè)務(wù)參數(shù)的合法校驗并不適應(yīng),例如常見的ID不存在,狀態(tài)攔截等。

    Assert斷言

    關(guān)于Assert斷言方式,起初是在單元測試中常見,后來在各種優(yōu)秀的框架中開始常見,例如Spring、Mybatis等,然后就開始出現(xiàn)在業(yè)務(wù)代碼中:

    public class AssertTest {
        private String varObject ;
        @Before
        public void before (){
            varObject = RandomUtil.randomString(6) ;
        }
    
        @Test
        public void testEquals (){
            Assert.assertEquals(varObject+"不匹配",varObject,RandomUtil.randomString(6));
        }
        @Test
        public void testEmpty (){
            Assert.assertTrue(StrUtil.isNotEmpty(varObject));
            Assert.assertFalse(varObject+" not empty",StrUtil.isNotEmpty(varObject));
        }
        @Test
        public void testArray (){
            /*
                數(shù)組元素不相等: arrays first differed at element [1];
                Expected :u08
                Actual   :mwm
             */
            String var = RandomUtil.randomString(5) ;
            String[] arrOne = new String[]{var,RandomUtil.randomString(3)} ;
            String[] arrTwo = new String[]{var,RandomUtil.randomString(3)} ;
            Assert.assertArrayEquals("數(shù)組元素不相等",arrOne,arrTwo);
        }
    }

    到此,關(guān)于“SpringBoot2 中參數(shù)參與校驗的實現(xiàn)方法”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI