当前位置:网站首页>數據驗證框架 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 的功能還遠不止這些,可以參考老外的文章學習更多高級用法。
边栏推荐
- Industry case | digital operation base helps the transformation of life insurance industry
- Live broadcast software construction, canvas Text Bold
- socket編程之常用api介紹與socket、select、poll、epoll高並發服務器模型代碼實現
- idea彻底卸载安装及配置笔记
- 卖空、加印、保库存,东方甄选居然一个月在抖音卖了266万单书
- String type, constant type and container type of go language
- PIP related commands
- 2022年推荐免费在线接收短信平台(国内、国外)
- [paddleseg source code reading] add boundary IOU calculation in paddleseg validation (1) -- val.py file details tips
- 现在网上期货开户安全吗?国内有多少家正规的期货公司?
猜你喜欢
随机推荐
Datasimba launched wechat applet, and datanuza accepted the test of the whole scene| StartDT Hackathon
[unity shader] insert pass to realize the X-ray perspective effect of model occlusion
Kirk Borne的本周学习资源精选【点击标题直接下载】
线程池中的线程工厂
[principles and technologies of network attack and Defense] Chapter 3: network reconnaissance technology
Tips for short-term operation of spot silver that cannot be ignored
【软件测试】从企业版BOSS直聘,看求职简历,你没被面上是有原因的
nest.js入门之 database
[paper sharing] where's crypto?
Wireshark分析抓包数据*.cap
debian10编译安装mysql
CVPR 2022 - learning non target knowledge for semantic segmentation of small samples
Antisamy: a solution against XSS attack tutorial
Nunjuks template engine
[paddleseg source code reading] add boundary IOU calculation in paddleseg validation (1) -- val.py file details tips
云安全日报220707:思科Expressway系列和网真视频通信服务器发现远程攻击漏洞,需要尽快升级
Charles+Postern的APP抓包
Using stored procedures, timers, triggers to solve data analysis problems
Charles+drony的APP抓包
Learn to make dynamic line chart in 3 minutes!