使用 hibernate 的 validator 校验器验证
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(); } }
到现在就已经配置成功了,是不是很简单呢
只要你不觉得尴尬,那尴尬的就是别人