springmvc使用JSR-303对复杂对象进行校验
JSR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation,官方参考实现是Hibernate Validator。此实现与Hibernate ORM 没有任何关系。JSR 303 用于对Java Bean 中的字段的值进行验证。
1.配置Maven
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
2.编写需要校验的bean
public class QuestionnaireDetailDto {
/**问卷id*/
private BigInteger key;
/**问卷标题*/
@NotBlank(message = "请输入问卷标题")
private String title;
/**问卷备注*/
@NotBlank(message = "请输入问卷备注")
private String note;
/**问卷对应的策略*/
private List<BigInteger> strategys = Lists.newArrayList();
/**题目list*/
@Size(min = 1, max = 10, message = "可输入1-10个题目")
private List<QuestionDto> questions = Lists.newArrayList();
//省略get,set,toString方法
}
3.校验
@ResponseBody
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Object addQuestionnaire(@Validated @RequestBody QuestionnaireDetailDto questionnaireDetailDto, BindingResult bindingResult) {
validQuestionnaireDetailDto(bindingResult);
if (questionnaireService.addQuestionnaire(questionnaireDetailDto)) {
LOGGER.info("添加问卷成功");
return JsonResult.getSuccessMessage("添加问卷成功");
} else {
LOGGER.error("添加问卷失败");
return JsonResult.getErrorMessage("添加问卷失败");
}
}
valid方法和validQuestionnaireDetailDto方法:
@Autowired
protected Validator validator;
protected void validData(BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
StringBuffer sb = new StringBuffer();
for (ObjectError error : bindingResult.getAllErrors()) {
sb.append(error.getDefaultMessage());
}
throw new DataException(sb.toString());
}
}
/**
* 对QuestionnaireDetailDto参数校验
*
* @param bindingResult bindingResult
*/
protected void validQuestionnaireDetailDto(BindingResult bindingResult) {
validData(bindingResult);
//如果bindingResult中有List<pojo>,只通过bindingResult.hasErrors是检测不到pojo中的异常的
//针对这种情况,先取到List<pojo>对象,再进行验证
Object object = bindingResult.getModel().get(bindingResult.getObjectName());
QuestionnaireDetailDto questionnaireDetailDto = (QuestionnaireDetailDto) object;
List<QuestionDto> questionDtos = questionnaireDetailDto.getQuestions();
for (QuestionDto questionDto : questionDtos) {
validateWithException(validator, questionDto);
//拿到questionDto中的options属性(类型为List<ChoiceDto>)
List<ChoiceDto> choiceDtos = questionDto.getOptions();
for (ChoiceDto choiceDto : choiceDtos) {
validateWithException(validator, choiceDto);
}
}
}
/**
* 服务端参数有效性验证
*
* @param object 验证的实体对象
* @param groups 验证组
* @return 验证成功:返回true;验证失败:将错误信息添加到message中
*/
@SuppressWarnings("rawtypes")
protected static void validateWithException(Validator validator, Object object, Class<?>... groups) {
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
StringBuffer sb = new StringBuffer();
for (ConstraintViolation constraintViolation : constraintViolations) {
sb.append(constraintViolation.getMessage());
}
throw new DataException(sb.toString());
}
}
需要注意的是:如果仅仅调用validData方法,校验不到QuestionnaireDetailDto中QuestionDto的属性,所以重写了一个validQuestionnaireDetailDto。
此时需要多引入两个依赖:
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>el-impl</groupId>
<artifactId>el-impl</artifactId>
<version>1.0</version>
</dependency>

浙公网安备 33010602011771号