Spring validation的Validated注解的使用
在Controller层有时候需要对接口的输入参数进行校验,若是采用自身的校验逻辑代码来实现的话,会有一些弊端,一是会分散自己的注意力,不能让自己专心撰写业务逻辑代码;二是会让校验逻辑代码和业务逻辑代码产生耦合性,代码体积也比较臃肿。为了规避这种情况,我们可以采用Spring validation的Validated注解来完成接口参数校验的工作,下面举实例说明。
(1)PositionDO实体类
public class PositionDO { @NotEmpty private String state; @NotEmpty private String province; @NotEmpty private String city; public PositionDO() { } public PositionDO(@NotEmpty String state, @NotEmpty String province, @NotEmpty String city) { this.state = state; this.province = province; this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Override public String toString() { return "PositionDO{" + "state='" + state + '\'' + ", province='" + province + '\'' + ", city='" + city + '\'' + '}'; } }
此处,@NotEmpty采用默认的错误提示,可以通过message方法来提供指定的错误信息。
(2)PersonProfileDO实体类
public class PersonProfileDO { @NotEmpty private String id; @NotEmpty private String sex; @NotEmpty private String age; @NotEmpty private String photo; @NotNull private PositionDO positionDo; public PersonProfileDO() { } public PersonProfileDO(@NotEmpty String id, @NotEmpty String sex, @NotEmpty String age, @NotEmpty String photo, @NotNull PositionDO positionDo) { this.id = id; this.sex = sex; this.age = age; this.photo = photo; this.positionDo = positionDo; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getPhoto() { return photo; } public void setPhoto(String photo) { this.photo = photo; } public PositionDO getPositionDo() { return positionDo; } public void setPositionDo(PositionDO positionDo) { this.positionDo = positionDo; } @Override public String toString() { return "PersonProfileDO{" + "id='" + id + '\'' + ", sex='" + sex + '\'' + ", age='" + age + '\'' + ", photo='" + photo + '\'' + ", positionDo=" + positionDo + '}'; } }
此处,@NotEmpty和@NotNull采用默认的错误提示,可以通过message方法来提供指定的错误信息。
(3)Controller层接口
@ApiOperation(value="设置个人信息", notes="设置个人详细信息") @RequestMapping(value = "/setProfileInfo", method = RequestMethod.POST) public Map<String, Object> setProfileInfo(@Validated @RequestBody @ApiParam(value="个人详细信息", required=true)PersonProfileDO personProfileDo, BindingResult bindingResult) { Map<String, Object> map = new HashMap<>(16); if (null != bindingResult && bindingResult.hasErrors()) { List<FieldError> fieldErrorsList = bindingResult.getFieldErrors(); System.out.println("the field error is " + fieldErrorsList); map.put("parameterErrors", fieldErrorsList); } return map; }
这里需要注意了,使用@Validated注解的话,必须要结合BindingResult,否则不会起到自动校验的作用;BindingResult的作用是存放@Validated校验不通过的错误信息;此外,BindingResult和@Validated位置必须是邻近的,它们所在的两个参数必须要靠近,中间不能插入第三着,比如下面这样的话,就达不到校验的目的:
setProfileInfo(@Validated @RequestBody @ApiParam(value="个人详细信息", required=true)PersonProfileDO personProfileDo,
HttpServletRequest httpServletRequest, BindingResult bindingResult)
在上述的示例接口中,由于@Validated和BindingResult之间插入了HttpServletRequest参数,这样导致@Validated没有起到有效的检验作用。故,@Validate必须和BindingResult绑定使用,并且要遵循就近原则。
(4)校验效果
通过swagger来测验,输入参数内容如下,id的值为空:
接口返回的结果如下:
上图的红色框就是字段校验失败时的提示信息,目前都是采用默认的消息。
(5)嵌套校验
在上述例子中,接口的输入参数PersonProfileDO对象,它若是想对其内部成员PositionDO对象的内部字段进行校验的话,那么在PersonProfileDO类中还需要这样处理positionDo成员,如下图所示:
必须在字段前面添加@Valid注解,注意了这里不能使用@Validated注解,因为它不支持用于字段。
(6)嵌套校验的输入参数和校验结果,如下图所示:
输入参数示例: 校验结果:
到此,Spring的Validation的基本用法已介绍完毕,上述示例可以按部就班地应用到自己的项目中。