接口參數校驗之@Valid與BindingResult


接口方法往往需要對入參做一些校驗,從而判斷入參是否合格,而javax.validation包為我們提供了一些常用的參數校驗注解,使用起來很方便。

下面這個示例是檢驗入參對象中的password是否為空

 

1. 創建一個User.java

import javax.validation.constraints.NotBlank;

public class User {
    private String username;
    @NotBlank
    private String password;
    private Integer age;
}

2. 接口方法

    @PostMapping("/user")
    public User createUser(@Valid  @RequestBody User user) {
        System.out.println(user);
        user.setAge(100);
        return user;
    }

3. 測試代碼 

 @Test
    public void testCreateUser() throws Exception {
        String jsonUser = "{\"username\":\"admin\",\"password\":null}";
        mockMvc.perform(MockMvcRequestBuilders.post("/user")
                .contentType(MediaType.APPLICATION_JSON)
                .content(jsonUser))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.age").value("100"));
    }

4. 測試結果

 

 

 

在測試代碼中, 我們的password=null, 所以檢驗不通過,報400。而password不為null ,測試通過,如下

 

 

 

5. BindingResult

在以上的參數校驗中,如果參數校驗不通過,都不通進入接口方法,我們也不好收集錯誤信息.。 不過,spring為我們提供了一個java類BindingResult.java, 借助它即可!

注意: @Valid與BindingResult要配套使用

5.1 接口代碼 

  @PostMapping("/user")
    public User createUser(@Valid  @RequestBody User user, BindingResult errors) {
        if (errors.hasErrors()) {
            errors.getAllErrors().stream().forEach(x-> System.out.println(x.getDefaultMessage()));
        }
        System.out.println(user);
        user.setAge(100);
        return user;
    }

 

5.2 測試代碼及打印結果

 

 

 

5.3 自定義錯誤信息

public class User {
    private String username;
    @NotBlank(message = "密碼不能為空")
    private String password;
    private Integer age;
}

 

 

 

6. 自定義注解

javax.validation默認提供了不少的注解,但是有時候,我們需要按照自己的邏輯去自定義注解。

下面舉個例子,在創建User對象時,先校驗一下數據庫是否存在相同的用戶名username, 代碼如下:

6.1  查詢邏輯

@Service
public class UserService {

    /**
     * 模擬查詢,檢驗admin用戶名是否存在
     * @param username
     * @return
     */
    public boolean findUserByUsername(String username) {
        if (StringUtils.equals(username, "admin")) {
            return false;
        }
        return true;

    }
}

 

6.2  自定義注解及實現

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
// 該注解的具體實例邏輯類
@Constraint(validatedBy = MyValidatorImpl.class)
public @interface MyValidator {
    String message() default "admin用戶已存在";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };
}

 

import org.springframework.beans.factory.annotation.Autowired;
import qinfeng.zheng.mockmvcdemo.service.UserService;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 * 實現 ConstraintValidator接口的類,spring會將其弄成一個bean
 */
public class MyValidatorImpl implements ConstraintValidator<MyValidator, String> {
    @Autowired
    private UserService userService;

    @Override
    public void initialize(MyValidator anno) {
        System.out.println("初始化。。。。");
    }

    /**
     * @param value   需要校驗的參數值
     * @param constraintValidatorContext
     * @return  false : 校驗不通過
     *          true : 校驗通過
     */
    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
        return userService.findUserByUsername(value);
    }
}

 

6.3 實體類上注解的使用

public class User {
    @MyValidator
    private String username;
    @NotBlank(message = "密碼不能為空")
    private String password;
    private Integer age;
}

 

6.4 校驗接口

  @PostMapping("/user")
    public User createUser(@Valid  @RequestBody User user, BindingResult errors) {
        if (errors.hasErrors()) {
            errors.getAllErrors().stream().forEach(x-> System.out.println(x.getDefaultMessage()));
        }
        System.out.println(user);
        user.setAge(100);
        return user;
    }

 

6.5 測試代碼

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM