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>