当前位置:网站首页>數據驗證框架 Apache BVal 再使用
數據驗證框架 Apache BVal 再使用
2022-07-07 18:54:00 【sp42a】
關於 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<[email protected]> * */
@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 的功能還遠不止這些,可以參考老外的文章學習更多高級用法。
边栏推荐
- 强化学习-学习笔记8 | Q-learning
- Year SQL audit platform
- CVPR 2022丨学习用于小样本语义分割的非目标知识
- Calculation of torque target value (ftorque) in servo torque control mode
- Charles+Postern的APP抓包
- 卖空、加印、保库存,东方甄选居然一个月在抖音卖了266万单书
- nest. Database for getting started with JS
- 【剑指 Offer】59 - I. 滑动窗口的最大值
- Five network IO models
- 小试牛刀之NunJucks模板引擎
猜你喜欢
Redis
伺服力矩控制模式下的力矩目标值(fTorque)计算
Tear the Nacos source code by hand (tear the client source code first)
RIP和OSPF的区别和配置命令
链式二叉树的基本操作(C语言实现)
低代码助力企业数字化转型会让程序员失业?
Introduction de l'API commune de programmation de socket et mise en œuvre de socket, select, Poll et epoll
回归问题的评价指标和重要知识点总结
Ten thousand words nanny level long article -- offline installation guide for datahub of LinkedIn metadata management platform
Wireshark分析抓包数据*.cap
随机推荐
[tpm2.0 principle and Application guide] Chapter 5, 7 and 8
[unity shader] insert pass to realize the X-ray perspective effect of model occlusion
小程序中实现付款功能
直播软件搭建,canvas文字加粗
6.关于jwt
线程池和单例模式以及文件操作
Thread factory in thread pool
Backup Alibaba cloud instance OSS browser
SQLite SQL exception near "with": syntax error
Yunjing network technology interview question [Hangzhou multi tester] [Hangzhou multi tester _ Wang Sir]
[论文分享] Where’s Crypto?
Simple configuration of single arm routing and layer 3 switching
Kirk borne's selection of learning resources this week [click the title to download directly]
面试唯品会实习测试岗、抖音实习测试岗【真实投稿】
Three forms of multimedia technology commonly used in enterprise exhibition hall design
小试牛刀之NunJucks模板引擎
[network attack and defense principle and technology] Chapter 4: network scanning technology
Wireshark analyzes packet capture data * cap
The performance and efficiency of the model that can do three segmentation tasks at the same time is better than maskformer! Meta & UIUC proposes a general segmentation model with better performance t
String type, constant type and container type of go language