日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

前言

在后端的接口開發(fā)過(guò)程,實(shí)際上每一個(gè)接口都或多或少有不同規(guī)則的參數(shù)校驗(yàn),有一些是基礎(chǔ)校驗(yàn),如非空校驗(yàn)、長(zhǎng)度校驗(yàn)、大小校驗(yàn)、格式校驗(yàn);也有一些校驗(yàn)是業(yè)務(wù)校驗(yàn),如學(xué)號(hào)不能重重復(fù)、手機(jī)號(hào)不能重復(fù)注冊(cè)等;對(duì)于業(yè)務(wù)校驗(yàn),是需要和數(shù)據(jù)庫(kù)交互才能知道校驗(yàn)結(jié)果;對(duì)于參數(shù)的基礎(chǔ)校驗(yàn),是有一些共有特征可以抽象出來(lái),可以做成一個(gè)通用模板(JAVA就是一種面向?qū)ο蟮木幊陶Z(yǔ)言,還記得天天快要說(shuō)爛問(wèn)爛的面向?qū)ο蟮娜筇匦詥幔浚;趯?shí)際場(chǎng)景的需要,java API中定義了一些Bean校驗(yàn)的規(guī)范標(biāo)準(zhǔn)(JSR303:validation-api),但是沒(méi)有具體實(shí)現(xiàn),不過(guò)hibernate validation和spring validation都提供了一些比較優(yōu)秀的實(shí)現(xiàn)。如果在項(xiàng)目里,你還是像類似這樣的方式來(lái)進(jìn)行參數(shù)校驗(yàn)就太low了,活該加班到天亮(當(dāng)然如果你所在公司目前仍然用統(tǒng)計(jì)代碼量來(lái)考核你的工作,就算我沒(méi)說(shuō),你可以繼續(xù)使用這種方式)。

@PostMApping("/add")
public String add(Student student) {
    if (null == student) {
        throw new RuntimeException("學(xué)生不為空");
    }
    if ("".equals(student.getStuCode())) {
        throw new RuntimeException("學(xué)號(hào)不能為空");
    }
    if ("".equals(student.getStuName())) {
        throw new RuntimeException("學(xué)生姓名不能為空");
    }
    if (null == student.getTeacher()) {
        throw new RuntimeException("學(xué)生的老師的不能為空");
    }
    if ("".equals(student.getTeacher().getTecName())) {
        throw new RuntimeException("學(xué)生的老師的姓名不能為空");
    }
    if ("".equals(student.getTeacher().getSubject())) {
        throw new RuntimeException("學(xué)生的老師的所授科目不為能空");
    }
    return "success";
}

依賴引入

分享的這篇文章里的校驗(yàn)參數(shù)注解使用方法,我是在一個(gè)springboot項(xiàng)目里親自重新測(cè)試驗(yàn)證過(guò)的,springboot的版本是2.3.9.RELEASE,另外也引入了關(guān)于參數(shù)校驗(yàn)的starter包,這樣就不用額外去引關(guān)于參數(shù)校驗(yàn)的其他包了;

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-validation</artifactId>
  <version>2.3.9.RELEASE</version>
</dependency>

參數(shù)形式

在java項(xiàng)目中,前端請(qǐng)求后端的接口中,常用的請(qǐng)求類型主要是post和get。

  • 在POST請(qǐng)求中,通常使用requestBody傳遞參數(shù),即前端以json報(bào)文的格式傳遞到后端controller層,spring會(huì)把json報(bào)文自動(dòng)映射到@RequestBody修飾的形參實(shí)例;
  • 在GET請(qǐng)求中,通常使用requestParam/PathVariable傳遞參數(shù),其中requestParam是指前端以key-value的形式把參數(shù)傳遞到后端,spring會(huì)把參數(shù)自動(dòng)映射到@RequestParam修飾的形參數(shù)實(shí)例對(duì)象(@RequestParam可以,也可以沒(méi)有,只要參數(shù)key與controller層方法內(nèi)形參類型的屬性名稱可以對(duì)應(yīng)的上);@PathVariable是指spring可以將請(qǐng)求URL中占位符參數(shù)綁定到controller層方法的形參上;

常用到的約束注解

@Valid

被注釋的元素是一個(gè)對(duì)象,需要檢查此對(duì)象的所有字段值

@Null

被注釋的元素必須為 null

@NotNull

被注釋的元素必須不為 null

@AssertTrue

被注釋的元素必須為 true

@AssertFalse

被注釋的元素必須為 false

@Min(value)

被注釋的元素必須是一個(gè)數(shù)字,其值必須大于等于指定的最小值

@Max(value)

被注釋的元素必須是一個(gè)數(shù)字,其值必須小于等于指定的最大值

@DecimalMin(value)

被注釋的元素必須是一個(gè)數(shù)字,其值必須大于等于指定的最小值

@DecimalMax(value)

被注釋的元素必須是一個(gè)數(shù)字,其值必須小于等于指定的最大值

@Size(max, min)

被注釋的元素的大小必須在指定的范圍內(nèi)

@Digits (integer, fraction)

被注釋的元素必須是一個(gè)數(shù)字,其值必須在可接受的范圍內(nèi)

@Past

被注釋的元素必須是一個(gè)過(guò)去的日期

@Future

被注釋的元素必須是一個(gè)將來(lái)的日期

@Pattern(value)

被注釋的元素必須符合指定的正則表達(dá)式

Hibernate Validator 附加的 constrAInt

注解

作用

@Email

被注釋的元素必須是電子郵箱地址

@Length(min=, max=)

被注釋的字符串的大小必須在指定的范圍內(nèi)

@NotEmpty

被注釋的字符串的必須非空

@Range(min=, max=)

被注釋的元素必須在合適的范圍內(nèi)

@NotBlank

被注釋的字符串的必須非空

@URL(protocol=,

host=,    port=, 

regexp=, flags=)

被注釋的字符串必須是一個(gè)有效的url

@CreditCardNumber

被注釋的字符串必須通過(guò)Luhn校驗(yàn)算法,

銀行卡,信用卡等號(hào)碼一般都用Luhn

計(jì)算合法性

@ScriptAssert

(lang=, script=, alias=)

要有Java Scripting API 即JSR 223 

("Scripting for the JavaTM Platform")的實(shí)現(xiàn)

@Safehtml

(whitelistType=, 

additionalTags=)

classpath中要有jsoup包

參數(shù)基礎(chǔ)校驗(yàn)

參數(shù)的基礎(chǔ)校驗(yàn),通常是指的非空、長(zhǎng)度、最大值、最小值、格式(數(shù)字、郵箱、正則)等這些場(chǎng)景的校驗(yàn)。

@RequestBody參數(shù)

1.在controller層的方法的形參數(shù)前面加一個(gè)@Valid或@Validated的注解;

2.在用@RequestBody修飾的類的屬性上加上約束注解,如@NotNull、@Length、@NotBlank;

3.@RequestBody參數(shù)在觸發(fā)校驗(yàn)規(guī)則時(shí),會(huì)拋出MethodArgumentNotValidException,這里使用統(tǒng)一的異常處理機(jī)制來(lái)處理異常;

總結(jié):第1步的valid的作用就是一個(gè)標(biāo)記,標(biāo)明這個(gè)參數(shù)需要進(jìn)行校驗(yàn);第2步的約束注解的上注明校驗(yàn)的規(guī)則;第3步的統(tǒng)一校驗(yàn)機(jī)制是前后臺(tái)請(qǐng)求后臺(tái)接口時(shí),如果校驗(yàn)參數(shù)的校驗(yàn)規(guī)則后會(huì)拋出異常,異常附帶有約束注解上的提示信息,那么通過(guò)異常統(tǒng)一處理機(jī)制就可以統(tǒng)一處理異常信息,并以合適的方式返回給前臺(tái)(所謂合適的方式是指異常信息的格式可以自行制定)。

@PostMapping("/add")
public Student add( @Valid@RequestBody Student student){
    System.out.println(student.getStuName());
    return student;
}
@Data
public class Student  {
    @NotNull(message = "學(xué)號(hào)不能為空")
    @Length(min = 2, max = 4, message = "學(xué)號(hào)的長(zhǎng)度范圍是(2,4)")
    private String stuCode;
    @NotNull(message = "姓名不能為空")
    @Length(min = 2, max = 3, message = "姓名的長(zhǎng)度范圍是(2,3)")
    private String stuName;
}

@RequestParam參數(shù)/@PathVariable參數(shù)

1.在controller層的控制類上添加@Validated注解;

2.在controller層方法的校驗(yàn)參數(shù)上添加約束注解,如@NotNull、@Pattern;

3.@RequestParam參數(shù)/@PathVariable參數(shù)在觸發(fā)校驗(yàn)規(guī)則時(shí),會(huì)拋出ConstraintViolationException類型的異常,所以在統(tǒng)一異常處理機(jī)制中添加對(duì)這種類型異常的處理機(jī)制;

@RestController
@RequestMapping("/student")
@Validated
public class StudentController {
    @GetMapping("/{sex}/info")
    public String getBySex(@PathVariable("sex") @Pattern(regexp = "boy||girl",message = "學(xué)生性別只能是boy或girl") String sex) {
        System.out.println("學(xué)生性別:" + sex);
    return "success";
    }
    @GetMapping("/getOne")
    public String getOne(@NotNull(message = "學(xué)生姓名不能為空") String stuName, @NotNull(message = "學(xué)生學(xué)號(hào)不能為空") String stuCode) {
        System.out.println("stuName:" + stuName + ",stuCode:" + stuCode);
    return "success";
    }
}

異常統(tǒng)一處理

@RestControllerAdvice
public class CommonExceptionHandler {


    /**
     * 用于捕獲@RequestBody類型參數(shù)觸發(fā)校驗(yàn)規(guī)則拋出的異常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public String handleValidException(MethodArgumentNotValidException e) {
        StringBuilder sb = new StringBuilder();
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        if (!CollectionUtils.isEmpty(allErrors)) {
            for (ObjectError error : allErrors) {
                sb.append(error.getDefaultMessage()).append(";");
            }
        }
        return sb.toString();
    }


    /**
     * 用于捕獲@RequestParam/@PathVariable參數(shù)觸發(fā)校驗(yàn)規(guī)則拋出的異常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public String handleConstraintViolationException(ConstraintViolationException e) {
        StringBuilder sb = new StringBuilder();
        Set<ConstraintViolation<?>> conSet = e.getConstraintViolations();
        for (ConstraintViolation<?> con : conSet) {
            String message = con.getMessage();
            sb.append(message).append(";");
        }
        return sb.toString();
    }
}

嵌套校驗(yàn)

在實(shí)際項(xiàng)目中有這樣一種場(chǎng)景,用來(lái)接收參數(shù)的類的屬性字段也是一個(gè)對(duì)象,屬性對(duì)象的字段也需要進(jìn)行必要的參數(shù)校驗(yàn),這個(gè)時(shí)候可以使用嵌套校驗(yàn)來(lái)解決這個(gè)問(wèn)題,hibernate-validator提供了具體的解決方式。

1.在controller層方法的形參數(shù)前添加@Validated注解,如果有分組校驗(yàn)的場(chǎng)景,則注明分組信息;如果校驗(yàn)不需要分組,可以不注明分組信息;

2.在接收參數(shù)的類的屬性是對(duì)象的字段上添加@Valide注解,這里需要注意的是一定是@Valid,不是@Validated,因?yàn)锧Valid的實(shí)現(xiàn)是由hibernate-validator提供,有嵌套校驗(yàn)的能力,而@Validated是由spring-validation提供的具體實(shí)現(xiàn)方式,@Validated有分組校驗(yàn)的能力,但是沒(méi)有嵌套校驗(yàn)的能力;(java API規(guī)范(JSR303)定義了Bean的校驗(yàn)標(biāo)準(zhǔn)validation-api,但是沒(méi)有具體的實(shí)現(xiàn),所以各有各的實(shí)現(xiàn),在功能上也是有區(qū)別的)

3.嵌套屬性類上的約束注解的用法,與用來(lái)接收參數(shù)的對(duì)象屬性上的約束注解的用法是一樣的;

總結(jié):@Valid的實(shí)現(xiàn)是由hibernate-validator提供,有嵌套校驗(yàn)的能力,但是沒(méi)有分組校驗(yàn)的能力,@Validated是由spring-validation提供的具體實(shí)現(xiàn)方式,@Validated有分組校驗(yàn)的能力,但是沒(méi)有嵌套校驗(yàn)的能力,在使用的過(guò)程須特別注意,要根據(jù)實(shí)際需要進(jìn)行剪裁。

@PostMapping("/addStuaAndTeach")
public String addStuaAndTeach(@Validated(AddStuAndTeach.class) @RequestBody Student student){
    System.out.println("學(xué)生的工號(hào):"+student.getStuCode()+",學(xué)生的老師的姓名:"+student.getTeacher().getTecName());
    return "success";
}
@Data
public class Teacher {
    @NotNull(message = "學(xué)生的老師姓名不能為空",groups = AddStuAndTeach.class)
    private String tecName;
    @NotNull(message = "學(xué)生的老師教授科目不能為空",groups = AddStuAndTeach.class)
    private String subject;
}
public interface AddStuAndTeach {
}
 
@Data
public class Student {
   
    @NotNull(message = "學(xué)生id不能為空",groups = QueryDetail.class)
    private Integer id;
    @NotNull(message = "學(xué)號(hào)不能為空",groups = AddStudent.class)
    @Length(min = 2, max = 4, message = "學(xué)號(hào)的長(zhǎng)度范圍是(2,4)")
    private String stuCode;
    @NotNull(message = "姓名不能為空",groups = AddStudent.class)
    @Length(min = 2, max = 3, message = "姓名的長(zhǎng)度范圍是(2,3)",groups = AddStudent.class)
    private String stuName;
    @Valid
    @NotNull(message = "學(xué)生的老師不能為空",groups = AddStuAndTeach.class)
    private Teacher teacher;
}

分組校驗(yàn)

在實(shí)際的項(xiàng)目中,可能多個(gè)方法使用同一個(gè)類來(lái)接收參數(shù),但是不同的方法的校驗(yàn)規(guī)則又是不同的,這個(gè)時(shí)候就可以使用分組校驗(yàn)的方式來(lái)解決這個(gè)問(wèn)題了,spring-validation提供了具體的實(shí)現(xiàn)方式。

1.聲明分組用的接口,比如添加和查詢?cè)斍榈臅r(shí)候,校驗(yàn)的規(guī)則肯定是不一樣的,添加的時(shí)候一般不用傳id,由后臺(tái)自增長(zhǎng)生成,查詢?cè)斍榈臅r(shí)候id是必須傳的;

2.在controller層方法的校驗(yàn)參數(shù)上添加@Validated參數(shù),同時(shí)注解里要注明校驗(yàn)參數(shù)的分組信息;

3.在校驗(yàn)參數(shù)的類上的線束注解上,也要注明校驗(yàn)參數(shù)的分組信息;

總結(jié):在接口的入口方法參數(shù)上、校驗(yàn)參數(shù)上都注明了分組的信息,那么接口被用的時(shí)候,就可以根據(jù)不同的分組信息執(zhí)行不同約束注解的校驗(yàn)邏輯了,這個(gè)能力是spring-validation提供的,所以這種場(chǎng)景下,controller層方法的上注解要用@Validated,@Valid注解沒(méi)有這種能力。

//用于添加場(chǎng)景參數(shù)校驗(yàn)分組
public interface AddStudent {
}
 
//用于查詢?cè)斍閳?chǎng)景參數(shù)校驗(yàn)分組
public interface QueryDetail {
}
 
@PostMapping("/add")
public Student add(@Validated(AddStudent.class) @RequestBody Student student) {
    System.out.println(student.getStuName());
    return student;
}


@PostMapping("/detail")
public String detail(@Validated(QueryDetail.class)@RequestBody Student student){
    System.out.println("學(xué)生id:"+student.getId());
    return "success";
}
@Data
public class Student {
 
    @NotNull(message = "學(xué)生id不能為空",groups = QueryDetail.class)
    private Integer id;
    @NotNull(message = "學(xué)號(hào)不能為空",groups = AddStudent.class)
    @Length(min = 2, max = 4, message = "學(xué)號(hào)的長(zhǎng)度范圍是(2,4)")
    private String stuCode;
    @NotNull(message = "姓名不能為空",groups = AddStudent.class)
    @Length(min = 2, max = 3, message = "姓名的長(zhǎng)度范圍是(2,3)",groups = AddStudent.class)
    private String stuName;
    }

 

分享到:
標(biāo)簽:springboot
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定