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>    

  

 

posted @ 2017-09-13 16:59  jlustone  阅读(1652)  评论(0编辑  收藏  举报