数据验证框架 Apache BVal 再使用
Posted sp42a
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据验证框架 Apache BVal 再使用相关的知识,希望对你有一定的参考价值。
关于 Apache BVal,我 N 久之前使用过,还写了甚至全网唯一的简中教程《数据验证框架 Apache BVal 简介》,我依然还是那个观点:
Apache BVal (源码)是实体数据验证 Java Bean Validation 的参考实现。Apache BVal 提供了 JSR 303 规范中所有内置 constraint 的实现,用于对 Bean 中的字段的值进行约束定义、描述和验证。若单单说 JSR 规范大渣可能还不清楚,但做过 POJO 的 Hibernate Validator 注解的朋友就知道是啥,——那为什么不使用主流的 Hibernate Validator 呢?因为这货净是个压缩包都已经 13mb 了(尽管可以有文档、源码其他在内),BVal 才只有 400 多 kb,而我只需要服务端验证而已,——天真的孩纸伤不起啊。俺的 ORM 也是 Mybatis 的,务求尽可能地轻量级。
用法
Maven 引用
添加以下两个 Maven 依赖:
<dependency>
<groupId>org.apache.bval</groupId>
<artifactId>bval-jsr</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
2.0 要求 Java 8,Apache CommonUtils 不是强依赖了,同时 JSR 验证规范也升级到 2.x。
整合 Spring
Spring 里面注入 Provider。
/**
* 数据验证框架
*
* @return
*/
@Bean
LocalValidatorFactoryBean localValidatorFactoryBean()
LocalValidatorFactoryBean v = new LocalValidatorFactoryBean();
v.setProviderClass(ApacheValidationProvider.class);
return v;
调用校验
手动校验方法,先试试
@Autowired
LocalValidatorFactoryBean v;
public List<DataDict> getDataDict(Long parentId)
List<DataDict> list = DataDictDao.DataDictDAO.setWhereQuery("parentId", parentId).findList();
Validator validator = v.getValidator();
Set<ConstraintViolation<DataDict>> violations = validator.validate(list.get(0));
System.out.println(violations.size()); // 校验结果
System.out.println(list.get(0).getParentId());
if (CollectionUtils.isEmpty(list))
list = new ArrayList<>();
return list;
上述代码是对一个 Java Bean:DataDict 进行校验,Bean 的字段可配置如下的约束。
public class DataDict implements CommonEntity
/**
* 主键 id,自增
*/
private Long id;
/**
* 父 id
*/
@NotNull
private Long parentId;
/**
* 类型 id
*/
@NotNull
private Long type;
……
更多校验注解参见旧文。
Spring MVC 自动校验
很简单,添加注解 @Valid
在 Bean 参数上。
/**
* 新建
* @return
*/
@RequestMapping(method = RequestMethod.POST)
public String create(@Valid T news, Model model)
System.out.println("新建");
if (result.hasErrors())
LOGGER.info("create error!");
else
LOGGER.info("create ok!");
news.setService(getService());
try
getService().create(news);
model.addAttribute("newlyId", news.getId());
catch (ServiceException e)
model.addAttribute("errMsg", e.toString());
return "common/entity/json_cud";
接着说说怎么处理错误,或者不处理默认交由 Servlet 处理也可以。下面是自定义异常的处理器,转化为 JSON 返回。
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import com.ajaxjs.util.WebHelper;
/**
* 后端表单、数据校验的异常捕获
*
* @author Frank Cheung<sp42@qq.com>
*
*/
@ControllerAdvice
public class RestResponseEntityExceptionHandler
static final String TPL = "输入字段 [%s] 未通过校验,原因 [%s],输入值为 [%s],请检查后再提交。";
@ExceptionHandler(value = BindException.class)
public void exceptionHandler(HttpServletRequest req, HttpServletResponse resp, BindException e)
String msg = "";
List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
for (FieldError err : fieldErrors)
msg += String.format(TPL, err.getField(), err.getDefaultMessage(), err.getRejectedValue());
// msg += "\\\\\\\\n";
ResponseResult result = new ResponseResult();
result.setErrorCode("400");
result.setMessage(msg);
WebHelper.outputJson(resp, result.toString());
这个 RestResponseEntityExceptionHandler 按照正常注入 Spring 组件方式即可,下面是一种方法:
@Bean
RestResponseEntityExceptionHandler initRestResponseEntityExceptionHandler()
return new RestResponseEntityExceptionHandler();
JSR 303 可以自定义约束的原因,这样就不会输出默认的英文,但要逐个说明也比较麻烦。
另外有个 getAllErrors,这个不是针对字段的,估计是 for 校验方法的。
List<ObjectError> allErrors = e.getAllErrors();
for (ObjectError err : allErrors)
msg += err.getDefaultMessage();
msg += StringUtils.arrayToDelimitedString(err.getCodes(), ",");
高级用法
Apache BVal 的功能还远不止这些,可以参考老外的文章学习更多高级用法。还有这篇介绍如何对枚举校验,非常不错。
以上是关于数据验证框架 Apache BVal 再使用的主要内容,如果未能解决你的问题,请参考以下文章