spring boot 雖然集成了 valid 驗證,但是只是針對單個參數,不能是整個類,這時就可以使用 hibernate 的 validator 驗證器,而且有分組的功能,例如:在注冊時要驗證 A 類三個字段,但在登錄時只需要驗證 A 類的兩個字段,如果要另外創建一個 VO 類就很沒必要,這時就可以使用分組來解決
1、創建一個驗證的工具類
package io.xiongdi.common.validator; import io.xiongdi.common.exception.XDException; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import java.util.Set; /** * @author wujiaxing * @date 2019-07-07 * <p> * hibernate-validator校驗工具類 * 可以參考 http://docs.jboss.org/hibernate/validator/5.4/reference/en-US/html_single/ * </p> */ public class ValidatorUtils { /** * 驗證器 */ private static Validator validator; static { validator = Validation.buildDefaultValidatorFactory().getValidator(); } /** * 驗證方法 * <p> * 同一個pojo類,可能會被多個controller使用驗證,而每個controller的驗證規則有不同, * 這是就需要分組驗證,其實就是幾個要分組的空接口,指定屬性A屬於哪個組,屬性B又屬於 * 哪個組,這樣在controller驗證時就指定我要驗證哪個組 * </p> * @param object 被校驗的對象 * @param groups 被校驗的組 * @throws XDException 校驗不通過拋出自定義異常 */ public static void validateEntity(Object object, Class<?>... groups) throws XDException{ // 用驗證器執行驗證,返回一個違反約束的set集合 Set<ConstraintViolation<Object>> violationSet = validator.validate(object, groups); // 判斷是否為空,空:說明驗證通過,否則就驗證失敗 if(!violationSet.isEmpty()) { // 獲取第一個驗證失敗的屬性 ConstraintViolation<Object> violation = violationSet.iterator().next(); // 拋出自定義異常 throw new XDException(violation.getMessage()); } } }
2、定義驗證的 VO 類,hibernate 定義了很多的注解,可自行查閱,這里只使用了 @NotBlank
package io.xiongdi.form; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; /** * 登錄表單 * @author wujiaxing * @date 2019-06-30 */ @Data @ApiModel(value = "登錄表單") public class LoginForm { @ApiModelProperty(value = "手機號") @NotBlank(message = "手機號不能為空") private String mobile; @ApiModelProperty(value = "密碼") @NotBlank(message = "密碼不能為空") private String password; }
3、從 Controller 中調用驗證工具方法執行驗證
package io.xiongdi.controller; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.xiongdi.annotation.Login; import io.xiongdi.common.utils.R; import io.xiongdi.common.validator.ValidatorUtils; import io.xiongdi.form.LoginForm; import io.xiongdi.service.TokenService; import io.xiongdi.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import springfox.documentation.annotations.ApiIgnore; import java.util.Map; /** * @author wujiaxing * @date 2019-07-07 */ @Api(tags = "登錄接口") @RequestMapping("/api") @RestController public class ApiLoginController { @Autowired private TokenService tokenService; @Autowired private UserService userService; @RequestMapping("login") @ApiOperation("登錄") public R login(@RequestBody LoginForm loginForm) { // 服務端表單校驗 System.out.println("已進入login"+loginForm); ValidatorUtils.validateEntity(loginForm); // 在這里調用了 // 執行登錄 Map<String, Object> map = userService.login(loginForm); return R.ok(map); } /** * <p> * 登出需要請求中帶token * @RequestAttribute 這個注解表示訪問有過濾器或攔截器創建的、預先存在的屬性 * </p> * @param userId * @return */ @Login @ApiOperation("登出") @RequestMapping("logout") public R logout(@RequestAttribute("userId") @ApiIgnore long userId) { tokenService.expireToken(userId); return R.ok(); } }
到現在就已經配置成功了,是不是很簡單呢
