Skip to content

这是一个服务端参数验证框架,可以对JavaBean中的属性以及方法中参数列表进行验证

Notifications You must be signed in to change notification settings

lichao4Java/smart-validate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

一个非常实用的Java参数验证框架

image.png

简介

在日常开发中,不论是在REST API还是RPC接口在代码上都会做参数校验,用来验证输入参数的合法性,举个最简单的例子:

(一)验证Spring MVC接口入参

@RequestMapping(value = "helloworld")
@ResponseBody
public Object helloworld(String str) throws Exception {
	if(str == null || str.trim().length() == 0) {
    	throw new IllegalArgumentException("str is required");
    }
}

Spring MVC 中也可以使用 @RequestParam(required = true) 注解来约束str参数为必填项,但这个框架层会做拦截,被拦截后的效果一般不是预期想要的


(二)验证RPC接口中的入参

class Request {
 String id;
 String name;
 getter ……
 setter ……
}
public Response helloworld(Request request) {
    if(StringUtils.isEmpty(request.getId()) || StringUtils.isEmpty(request.getName())) {
       throw new IllegalArgumentException("id or name is required");
    }
}

一个非空判断需要写一行代码、如果需要验证的参数很多或者还需要判断参数长度、取值范围、集合大小等,又或者参数是一个对象,对象里面循环嵌套了对象,每个对象中又有很多字段需要验证参数的合法性等等,这个时候如果仍然使用hard code来实现的话,实现、维护成本就太高了,而且代码的可读性也是非常糟糕的,因此给大家分享下Smart-Validate验证框架,用来解决以上的问题。
Smart-Validate,一个非常实用的Java参数验证框架,具有以下特点:

  • 足够轻,整个代码量不足500行
  • 基于注解声明规则,使用成本低
  • 内置常见的验证规则
  • 支持嵌套对象的验证
  • 可自由拓展验证规则


框架内置以下规则列表

规则注解 说明 支持的数据类型
MaxLengthValidate 验证最大长度 String、Collection、Map、Array
MaxValueValidate 验证最大值 Integer、Long、Byte、Short、Double、Float
MinLengthValidate 验证最小长度 String、Collection、Map、Array
MinValueValidate 验证最小值 Integer、Long、Byte、Short、Double、Float
NotNullValidate 验证非空 Object、String
RangeLengthValidate 验证长度范围 String、Collection、Map、Array
RangeValueValidate 验证值范围 Integer、Long、Byte、Short、Double、Float
RegexpValidate 验证正则规则 String

使用方法

验证对象参数

@ValidateBean
public class Request {
    //ID不能为空
    @NotNullValidate
    private String id;
    //name最小长度为5
    @MinLengthValidate(length = 5)
    private String name;
    public Request() {}
    getter ……
 	setter ……
}
public void helloworld(Request request) throws SmartValidateException {
    SmartValidate.validate(request);
    //code
}
public static void main(String[] args) {
    try {
        Request req = new Request();
        req.setId(null);
        req.setName("haha");
        new Demo().helloworld(req);
    } catch (SmartValidateException e) {
        System.err.println(e.getMessage());
    }
}
LOG Print: id为必填项
public static void main(String[] args) {
    try {
        Request req = new Request();
        req.setId("1");
        req.setName("haha");
        new Demo().helloworld(req);
    } catch (SmartValidateException e) {
        System.err.println(e.getMessage());
    }
}
LOG Print: name的长度不能小于5

验证嵌套对象参数

@ValidateBean
public class Request {
    @NotNullValidate
    private InnerRquest param;
    getter ……
 	setter ……
}
@ValidateBean
public class InnerRquest {
    @NotNullValidate
    private String id;
    @MaxValueValidate(value = "99")
    private Integer age;
    public InnerRquest() {}
   	getter ……
 	setter ……
}
public void helloworld(Request request) throws SmartValidateException {
    SmartValidate.validate(request);
    //code
}
public static void main(String[] args) {
    try {
        Request req = new Request();
        InnerRquest ireq = new InnerRquest();
        ireq.setId("1");
        ireq.setAge(100);
        req.setParam(ireq);
        new Demo().helloworld(req);
    } catch (SmartValidateException e) {
        System.err.println(e.getMessage());
    }
}
LOG Print: age的值不能大于99

验证集合中的对象

@ValidateBean
public class Request {
    @NotNullValidate
    private List<InnerRquest> param;
  	getter ……
 	setter ……
}
public void helloworld(Request request) throws SmartValidateException {
    SmartValidate.validate(request);
    //code
}
public static void main(String[] args) {
     try {
         Request req = new Request();
         InnerRquest ireq = new InnerRquest();
         ireq.setId("1");
         ireq.setAge(100);
         req.setParam(Arrays.asList(ireq));
         new Demo().helloworld(req);
     } catch (SmartValidateException e) {
         System.err.println(e.getMessage());
     }
}
LOG Print: age的值不能大于99

验证方法中的参数列表

public void helloworld(
    @ValidateArgument(
        notNull=@NotNullValidate,
        maxLength=@MaxLengthValidate(length=1)
    )String str) throws Exception {
    //code
}


配置拦截器

<aop:config>
	<!-- pointcut 配置成需要拦截的路径 -->
	<aop:advisor pointcut="execution(*.*(..))" advice-ref="smartValidateInterceptor"/>
</aop:config>
<bean id="smartValidateInterceptor" class="com.smart.validate.interceptor.SmartValidateInterceptor" />

拓展自定义验证规则


(一)定义规则注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomerValidate {
    String message () default "";
    String name () default ""; 
}


(二)实现规则

public class MatchCustomerValidate extends AbstractMatchValidate<CustomerValidate >{
    @Override
    public void validate(CustomerValidate t,
                         String fieldName,
                         Object value)
        throws SmartValidateException {
        //your code
    }
}


(三)生效规则

ValidateRulePool.mount(CustomerValidate.class, new MatchCustomerValidate());


(四)使用 @CustomerValidate 注解来验证参数

使用多个验证规则

不论是参数列表还是对象中的字段,都可以同时支持多个验证规则。

(一)对象参数

@NotNullValidate
@RangeValueValidate(min = "1", max = "100")
private Integer age;

(二)方法参数

public void helloworld(
    @ValidateArgument(
        notNull=@NotNullValidate,
        rangeValue=@RangeValueValidate(min = "1", max = "100")
    )Integer age) throws Exception {}

自定义提示消息

内置的验证规则均支持自定义message,以NotNullValidate为例,在注解中声明可以声明name或message属性,例如:

自定义name属性

//name=“年龄”,在验证不通过时message为 “年龄为必填项”
@NotNullValidate(name = "年龄")
private Integer age;

自定义message属性

//message=“请输入年龄”,在验证不通过时message为 “请输入年龄”
@NotNullValidate(message = "请输入年龄")
private Integer age;

如果name和message都未定义,则message为默认值 “age为必填项”

最佳实践

不论是Spring MVC的REST API参数,还是RPC中的对象入参,一般都会有相应的拦截器去处理日志打印、异常等相关的逻辑,因此参数验证也可以在这一层中使用SmartValidate.validate方法来统一接入,框架中也内置了基于Spring的SmartValidateInterceptor拦截器,也可以自己跟实际情况来实现自己的验证策略。

源码

https://github.com/lichao4Java/smart-validate

About

这是一个服务端参数验证框架,可以对JavaBean中的属性以及方法中参数列表进行验证

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages