neoremind / fluent-validator Goto Github PK
View Code? Open in Web Editor NEWA Java validation framework leveraging fluent interface style and JSR 303 specification
License: Apache License 2.0
A Java validation framework leveraging fluent interface style and JSR 303 specification
License: Apache License 2.0
每个字段都要写一个验证类,代码量还是蛮大的,有没有更好的方案,或者用内部类可以吗,POJO对应一个验证类,此类里面包含每个字段验证的子类,并且需要包含对POJO本身为不为空的判断吧?
@DaTa
public class AddClassParams {
@NotNull(message = "班级信息不能为空")
@ApiModelProperty(value = "班级信息")
@FluentValid
private ClassParamsForInsert classInfo;
}
@DaTa
public class ClassParamsForInsert {
@NotNull(message = "班级名称不能为空")
@FluentValidate(value = {StringValidator.class})
@ApiModelProperty(value = "班级名称", example = "秋季1期低年级11班")
private String className;
@NotNull(message = "班主任id不能为空")
@ApiModelProperty(value = "班主任Id", example = "72608")
private Long counselorId;
@NotNull(message = "学期id不能为空")
@ApiModelProperty(value = "学期Id", example = "17")
private Long termId;
@ApiModelProperty(value = "售卖课程包Id", example = "1")
private Long coursePackageId;
}
@FluentValidate 可以生效,@NotNull之类的hibernate validator全部失效
hi,有四个问题请教一下:
FluentValidateInterceptor
类fluentValidator.on(arguments[i], addOnValidatorChain)
针对参数对象执行校验,基于流式风格,属性间的联合约束校验在单属性校验成功的基础上进行应该比较合理,也更利于简化验证逻辑。
@Override
public boolean validate(ValidatorContext context, Car t) {
// 属性级存在非空校验时,自定义校验可以忽略空值处理
if (t.id < 2) {
context.addErrorMsg(String.format("Seat count is not valid, invalid value=%s", t));
return false;
}
return true;
}
场景描述:在校验中会做一些查数据库操作,校验通过想通过返回值拿到这些值,为后续逻辑层使用。
问题:能通过捕获异常的方式,拿到错误信息,但没不知道怎样获取正确的返回?
采用springboot默认的Jackson序列化。GenericResult类中的 isSuccess 字段在序列化时成为 success。
在方法参数中aop注解校验能否支持分组呢?
Good framework, contains all that we need, but it is hard to use, because documentation is not in English.
public javax.validation.Validator getHiberanteValidator() {
return HIBERANTE_VALIDATOR;
}
public HibernateSupportedValidator<T> setHiberanteValidator(javax.validation.Validator validator) {
HibernateSupportedValidator.HIBERANTE_VALIDATOR = validator;
return this;
}
Please correct the name of these functions and members.
版本:1.0.9
和mybatis-plus集成后,创建代理:
@bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator(){
BeanNameAutoProxyCreator proxyCreator = new BeanNameAutoProxyCreator();
proxyCreator.setProxyTargetClass(true);//默认是false,不设置会导致controller 404
proxyCreator.setBeanNames("*ServiceImpl");
proxyCreator.setInterceptorNames("fluentValidateInterceptor");
return proxyCreator;
}
请求报空指针,打断点跟代码发现:
Method implMethod = ReflectionUtil.getMethod(targetClass, invocation.getMethod().getName(), parameterTypes);
无法获取接口中的默认方法,从而implMethod=null
fluent-validator
框架支持Hibernate Validator
,那我该在Hibernate内置注解中如何定义errorCode了,com.baidu.unbiz.fluentvalidator.ValidationError#errorCode
取值
javax.validation 在spring boot3替换成了jakarta.validation,编译无法通过
用的是log4j2吗?
@FluentValid 能否加在接口参数上?
框架返回的校验错误信息有点不友好,怎么自定义
FluentValidator.checkAll()
.configure(new SimpleRegistry())
.on(car)
.doValidate(new SimpleValidateCallback());
class car may like this:
class car{
...
@FluentValidate(SimpleDataValidator.class)
private String startTime;
@FluentValidate(SimpleDataValidator.class)
private String endTime;
...
}
When I use this method, only first filed of car's tow same validator was validated, validator worked on startTime
, ignored endTime
.
@FluentVAlid annotation可以用在TYPE_USE,例如List<@FluentValid Data>
Result ret = FluentValidator.checkAll()
.on(company, new HibernateSupportedValidator<Company>().setHibernateValidator(validator))
.on(company, new CompanyCustomValidator())
.doValidate().result(toSimple());
另外
public class HibernateSupportedValidator<T> extends ValidatorHandler<T> implements Validator<T> {
private static javax.validation.Validator HIBERANTE_VALIDATOR;
private int hibernateDefaultErrorCode;
private ConstraintViolationTransformer constraintViolationTransformer = new DefaultConstraintViolationTransformer();
HIBERANTE_VALIDATOR 为static 何解?
集成spring代码:
@configuration
public class ValidateConfiguartion {
@Bean
public FluentValidateInterceptor fluentValidateInterceptor() {
FluentValidateInterceptor fluentValidateInterceptor = new FluentValidateInterceptor();
fluentValidateInterceptor.setCallback(validateCallback());
return fluentValidateInterceptor;
}
@Bean
public ValidateCallback validateCallback() {
return new HussarValidateCallBack();
}
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator(){
BeanNameAutoProxyCreator proxyCreator = new BeanNameAutoProxyCreator();
proxyCreator.setBeanNames("*Controller");
proxyCreator.setInterceptorNames("fluentValidateInterceptor");
return proxyCreator;
}
private static class HussarValidateCallBack extends DefaultValidateCallback implements ValidateCallback {
@Override
public void onSuccess(ValidatorElementList validatorElementList) {
super.onSuccess(validatorElementList);
}
@Override
public void onFail(ValidatorElementList validatorElementList, List<ValidationError> errors) {
throw new RuntimeException(errors.get(0).getErrorMsg());
}
@Override
public void onUncaughtException(Validator validator, Exception e, Object target) throws Exception {
throw new RuntimeException(e);
}
}
}
public class CarValidator extends ValidatorHandler implements Validator {
@Override
public boolean validate(ValidatorContext context, Car t) {
if (!"en".equals(t.getLanguage()) && !"cn".equals(t.getLanguage())) {
// 构建详细错误信息
// context.addError(ValidationError.create("language值不正确").setErrorCode(100).setField("language").setInvalidValue(t));
// 简单处理,直接放入错误消息
// context.addErrorMsg("language值不正确,只能为en或者cn");
// context.addError(ValidationError.create("FFFF"));
context.addError(ValidationError.create("Something is wrong about the car seat count!").setErrorCode(100).setField("seatCount").setInvalidValue(t));
return false;
}
if (!"0".equals(t.getNetType()) && !"1".equals(t.getNetType())) {
context.addErrorMsg("netType值不正确,只能为0或者1");
return false;
}
return true;
}
}
controller:
@PostMapping("/hello2")
public String hello2(@FluentValid({CarValidator.class}) @requestbody Car car) {
return "hello2";
}
错误拦截:
@RestControllerAdvice
@slf4j
public class ServiceExceptionHandler {
/**
* handleBindException handleBindException
*
* @param ex ex
* @return ResponseResult
*/
@ExceptionHandler(value = Exception.class)
public ResponseResult handleBindException(MethodArgumentNotValidException ex) {
log.error("handleBindException:{}", ex);
List errors = ex.getBindingResult().getAllErrors();
return new ResponseResult("501", formatError(errors), false, null);
}
/**
* 校验错误拦截处理,使用 @RequestBody 接收入参时,校验失败抛 MethodArgumentNotValidException 异常
*
* @param e e
* @return ResponseResult
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public ResponseResult handler(MethodArgumentNotValidException e) {
log.error("MethodArgumentNotValidException handler", e);
BindingResult bindingResult = e.getBindingResult();
if (bindingResult.hasFieldErrors()) {
return new ResponseResult("501", bindingResult.getFieldError().getDefaultMessage(), false, null);
}
return new ResponseResult("501", "parameter is not valid", false, null);
}
/**
* 校验错误拦截处理,使用 @RequestBody 接收入参时,数据类型转换失败抛 HttpMessageConversionException 异常
*
* @param e e
* @return ResponseResult
*/
@ExceptionHandler(value = HttpMessageConversionException.class)
public ResponseResult handler(HttpMessageConversionException e) {
log.error("HttpMessageConversionException handler", e);
return new ResponseResult("501", e.getMessage(), false, null);
}
/**
* 格式化错误信息
*
* @param errors 错误信息
* @return String
*/
private String formatError(List<ObjectError> errors) {
StringBuilder builder = new StringBuilder();
errors.forEach(error -> builder.append(error.getDefaultMessage()).append(";"));
return builder.toString();
}
}
请求时,返回:
{
"timestamp": "2021-02-24 20:26:15",
"status": 500,
"error": "Internal Server Error",
"message": "Something is wrong about the car seat count!",
"path": "/v14/itoc/hello2"
}
如何对请求返回进行定制呢?
Hey! We're not allowed to use a library whose license is not known... Could you specify the license for it please?
Thank you!
I have made the changes and having it in my local. Not sure how to push them.
我看了下文档中比如要返回详细信息的话,这获取字段名称直接给硬编码在代码中,如果写一个验证器同类型字段都能使用,那么这样的话还是希望能在ValidatorContext直接获取到字段信息。例如:字段名称,类型等。
context.addError(ValidationError.create("Something is wrong about the car seat count!").setErrorCode(100).setField("seatCount").setInvalidValue(t));
Is it possible?
Hey I am trying to use chain validation and for that I have two validation class . The problem is that when I validate the chain which contains the two validation class as I mentioned earlier the result returns only one instead of two . So my question is how can I get multiple error messages meanwhile ?
I was wondering while I was making my pull request:
使用api形式先校验,result是
Result{isSuccess=false, errors=[xxxxxxx]}
但是用aop形式就会打印
Annotation-based validation enabled for ArticleWithContent, and to-do validators are empty
然后校验通过,何解?
附上我的配置方式
@Bean(name="fluentValidateInterceptor")
public FluentValidateInterceptor interceptor() {
FluentValidateInterceptor interceptor = new FluentValidateInterceptor();
interceptor.setCallback(callback);
return interceptor;
}
@Bean
public BeanNameAutoProxyCreator transactionAutoProxy() {
BeanNameAutoProxyCreator transactionAutoProxy = new BeanNameAutoProxyCreator();
transactionAutoProxy.setBeanNames("*ServiceImpl");
transactionAutoProxy.setInterceptorNames("fluentValidateInterceptor");
return transactionAutoProxy;
}
简单看了一下例子都是使用bean 注解的方式
是否支持 注解类似 spring MethodValidationPostProcessor 方法验证的方式 ?
您好,我在使用过程中,遇到了方法上单个参数校验问题,这种方式怎样解决了。
尝试过下面这种方式,并不能进行校验
void checkInfo(@FluentValid(HibernateSupportedValidator.class) @NotEmpty(message="info不能为空")String info)
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*Service</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>fluentValidateInterceptor</value>
</list>
</property>
</bean>
First, I really appreciate your library. I tried it out today and really enjoyed it.
I had trouble determining whether it was an open-source library that I could use in my project. Would you consider updating the documentation to make it more obvious while visiting the main Github page.
Thanks!
WARN日志级别频繁打印。在我的验证DTO类中,是没有字段注解FluentValidate
,下面这段代码获取字段上的注解时,获取为空。
if (CollectionUtil.isEmpty(annotationValidators)) {
LOGGER.warn(String.format("Annotation-based validation enabled for %s, and to-do validators are empty", clazz.getSimpleName()));
} else {
CLASS_2_ANNOTATION_VALIDATOR_MAP.putIfAbsent(clazz, annotationValidators);
LOGGER.debug( String.format("Annotation-based validation added for %s, and to-do validators are %s", clazz .getSimpleName(), annotationValidators));
}
neo
2016/11/22·
一般来说对于前端提交的表单,通常后端会使用SpringMVC或者Struts来处理,一般都会封装成一个XXXForm,这样可以check against这个XXXForm整体即可。在这上面加上@FluentValid注解,然后在各个属性字段上写HibernateValidaion的验证或者自己实现Validator验证都可以,这些都是可以通过注解方式配置的。----大神你好,我现在就是这种方式,只不过我是在springboot项目中,用了@FluentValid注解的方式,但是并没有校验实体类上标注了@notblank的字段,这是为什么啊?(测试访问路径:http://localhost:8080/tf)
SpringBoot-master.zip
因为我们项目中使用的ErrorCode是用String数据类型,所以String数据类型感觉会更通用一些吧。
It would be nice if the errors field were always an empty list to avoid the need to null-check for errors before attempting to use them.
We've added an example test to show our expected behavior.
class AlwaysFailingValidator : Validator<String>, ValidatorHandler<String>() {
override fun validate(context: ValidatorContext?, t: String?): Boolean {
return false
}
}
it("should always have errors") {
val result = FluentValidator
.checkAll()
.on("some value", AlwaysFailingValidator())
.failOver()
.doValidate()
.result(ResultCollectors.toComplex())
assertThat(result.isSuccess).isFalse()
assertThat(result.errors).isNotNull()
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.