溫馨提示×

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

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

如何使用@Valid+BindingResult進(jìn)行controller參數(shù)校驗(yàn)

發(fā)布時(shí)間:2021-12-03 16:50:15 來(lái)源:億速云 閱讀:214 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹“如何使用@Valid+BindingResult進(jìn)行controller參數(shù)校驗(yàn)”,在日常操作中,相信很多人在如何使用@Valid+BindingResult進(jìn)行controller參數(shù)校驗(yàn)問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”如何使用@Valid+BindingResult進(jìn)行controller參數(shù)校驗(yàn)”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

@Valid+BindingResult進(jìn)行controller參數(shù)校驗(yàn)

由于controller是調(diào)用的第一層,經(jīng)常參數(shù)校驗(yàn)將在這里完成,常見(jiàn)有非空校驗(yàn)、類型校驗(yàn)等,常見(jiàn)寫法為以下偽代碼:

public void round(Object a){
  if(a.getLogin() == null){
     return "手機(jī)號(hào)不能為空!";
   }
}

但是調(diào)用對(duì)象的位置會(huì)有很多,而且手機(jī)號(hào)都不能為空,那么我們會(huì)想到把校驗(yàn)方法抽出來(lái),避免重復(fù)的代碼。但有框架支持我們通過(guò)注解的方式進(jìn)行參數(shù)校驗(yàn)。

先立個(gè)場(chǎng)景,為往動(dòng)物園添加動(dòng)物,動(dòng)物對(duì)象如下,時(shí)間節(jié)點(diǎn)大概在3030年,我們認(rèn)為動(dòng)物可登陸動(dòng)物專用的系統(tǒng),所以有password即自己的登錄密碼。

public class Animal {
    private String name;
    private Integer age;
    private String password;
    private Date birthDay;
}

調(diào)用創(chuàng)建動(dòng)物的controller層如下,簡(jiǎn)潔明了,打印下信息后直接返回。

@RestController
@RequestMapping("/animal")
public class AnimalController {
   @PostMapping
    public Animal createAnimal(@RequestBody Animal animal){
        logger.info(animal.toString());
        return animal;
    }
}

偽造Mvc調(diào)用的測(cè)試類。

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestAnimal {
 
    private final static Logger logger = LoggerFactory.getLogger(TestAnimal.class);
    @Autowired
    private WebApplicationContext wac;
    private MockMvc mockMvc;
 
    @Before
    public void initMock(){
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }
 
    @Test
    public void createAnimal() throws Exception {
        String content = "{\"name\":\"elephant\",\"password\":null,\"birthDay\":"+System.currentTimeMillis()+"}";
        String result = mockMvc.perform(MockMvcRequestBuilders.post("/animal")
                .content(content)
                .contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andReturn().getResponse().getContentAsString();
        logger.info(result);
    }
}

以上代碼基于搭建的springboot項(xiàng)目,想搭建的同學(xué)可以參考搭建篇 http://www.kemok4.com/article/226998.htm

代碼分析,日期格式的參數(shù)建議使用時(shí)間戳傳遞,以上birthDay傳遞 "2018-05-08 20:00:00",將會(huì)拋出日期轉(zhuǎn)換異常,感興趣的同學(xué)可以試試。

由于密碼很重要,現(xiàn)在要求密碼為必填,操作如下,添加@NotBlank注解到password上:

@NotBlank
private String password;

但光加校驗(yàn)注解是不起作用的,還需要在方法參數(shù)上添加@Valid注解,如下:

@Valid @RequestBody Animal animal

此時(shí)執(zhí)行測(cè)試方法,拋出異常,返回狀態(tài)為400:

java.lang.AssertionError: Status
Expected :200
Actual :400
<Click to see difference>


at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:54)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:81)

說(shuō)明對(duì)password的非空校驗(yàn)已經(jīng)生效了,直接拋出異常。如果不想拋出異常,想返回校驗(yàn)信息給前端,這個(gè)時(shí)候就需要用到BindingResult了,修改創(chuàng)建動(dòng)物的方法,添加BindingResult參數(shù):

@PostMapping
    public Animal createAnimal(@Valid @RequestBody Animal animal, BindingResult bindingResult){
        if (bindingResult.hasErrors()){
            bindingResult.getAllErrors().forEach(o ->{
                FieldError error = (FieldError) o;
                logger.info(error.getField() + ":" + error.getDefaultMessage());
            });
        }
        logger.info(animal.toString());
        return animal;
    }

此時(shí),執(zhí)行測(cè)試,可以看到日志中的錯(cuò)誤信息:

2018-05-09 00:59:37.453 INFO 14044 --- [ main] c.i.s.d.web.controller.AnimalController : password:may not be empty

為了滿足我們編碼需要我們需要進(jìn)行代碼改造,1.不能直接返回animal。2.返回的提示信息得是用戶可讀懂的信息。

controller方法改造如下,通過(guò)Map對(duì)象傳遞請(qǐng)求成功后的信息或錯(cuò)誤提示信息。

@PostMapping
    public Map<String,Object> createAnimal(@Valid @RequestBody Animal animal, BindingResult bindingResult){
        logger.info(animal.toString());
        Map<String,Object> result = new HashMap<>();
        if (bindingResult.hasErrors()){
            FieldError error = (FieldError) bindingResult.getAllErrors().get(0);
            result.put("code","400");//錯(cuò)誤編碼400
            result.put("message",error.getDefaultMessage());//錯(cuò)誤信息
            return result;
        }
        result.put("code","200");//成功編碼200
        result.put("data",animal);//成功返回?cái)?shù)據(jù)
        return result;
    }

返回的密碼提示信息如下:

@NotBlank(message = "密碼不能為空!")
private String password;

執(zhí)行測(cè)試方法,返回結(jié)果

com.imooc.security.demo.TestAnimal : {"code":"400","message":"密碼不能為空!"}

最后貼一個(gè),設(shè)置password值返回成功的信息

com.imooc.security.demo.TestAnimal : {"code":"200","data":{"name":"elephant","age":null,"password":"lalaland","birthDay":1525799768955}}

由于篇幅有限,下次會(huì)以這個(gè)實(shí)例為基礎(chǔ),實(shí)現(xiàn)一個(gè)自定義的注解實(shí)現(xiàn),該篇文章到此結(jié)束。

Controller層方法的參數(shù)校驗(yàn)

import com.example.demo.pojo.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; 
import javax.validation.Valid;
 
@Controller
@RequestMapping("/stu")
public class StudentController { 
    @PostMapping("/addStu")
    @ResponseBody
    public String addStudent(@Valid Student student){
        System.out.println("存儲(chǔ)student對(duì)象");
        System.out.println(student);
        return "ok";
    } 
}
import org.hibernate.validator.constraints.Length; 
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
 
public class Student { 
    @NotNull(message = "傳入的是空值,請(qǐng)傳值")
    @Min(value = 0,message = "傳入學(xué)生分?jǐn)?shù)有誤,分?jǐn)?shù)在0-100之間")
    @Max(value = 100,message = "傳入學(xué)生分?jǐn)?shù)有誤,分?jǐn)?shù)在0-100之間")
    private Integer score;
 
    @NotEmpty(message = "傳入的是空字符串,請(qǐng)傳值")
    @NotNull(message = "傳入的是空值,請(qǐng)傳值")
    private String name;
 
    @NotNull(message = "傳入的是空值,請(qǐng)傳值")
    @NotEmpty(message = "傳入的是空字符串,請(qǐng)傳值")
    @Length(min = 11,max = 11,message = "號(hào)碼有誤,長(zhǎng)度應(yīng)為11位")
    private String mobile;
 
    public Integer getScore() {
        return score;
    }
 
    public void setScore(Integer score) {
        this.score = score;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getMobile() {
        return mobile;
    }
 
    public void setMobile(String mobile) {
        this.mobile = mobile;
    }
 
    @Override
    public String toString() {
        return "Student{" +
                "score=" + score +
                ", name='" + name + '\'' +
                ", mobile='" + mobile + '\'' +
                '}';
    }
}

全局統(tǒng)一異常攔截器

import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; 
 
@ControllerAdvice
public class GlobalExceptionInterceptor { 
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public String exceptionHandler(Exception e){
        String failMessage=null; 
        if(e instanceof BindException){
            failMessage=((BindException) e).getBindingResult().getFieldError().getDefaultMessage();
        }
        return failMessage;
    } 
}

如何使用@Valid+BindingResult進(jìn)行controller參數(shù)校驗(yàn)

如何使用@Valid+BindingResult進(jìn)行controller參數(shù)校驗(yàn)

當(dāng)我們傳入的參數(shù)有誤時(shí),就會(huì)被異常攔截器捕獲,返回給我們錯(cuò)誤信息。

如何使用@Valid+BindingResult進(jìn)行controller參數(shù)校驗(yàn)

到此,關(guān)于“如何使用@Valid+BindingResult進(jìn)行controller參數(shù)校驗(yàn)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

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

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

AI