【原创】JSR303与ApacheValidate性能测试
软件开发中涉及到这样一个问题,那就是关于后台系统的数据验证,任何系统的绕不过去的。
下面针对于各种方式的数据验证进行一个测试。
if else
结论:这种效率是无疑是最高效的验证代码,优势是效率高,缺点是可能返回状态忘记设置,可能if else判断太多,看代码很烦。
code:
long currentTimeMillis = System.currentTimeMillis();
try
{
Map<String, Object> resultMap = new HashMap<String, Object>();
resultMap.put("status", "y");
resultMap.put("msg", "操作成功!");
for (int i = 0; i < 300; i++)
{
PlatformDevelopers dev = new PlatformDevelopers();
if (null == dev.getAddress() || dev.getAddress().length() == 0)
{
resultMap.put("status", "n");
resultMap.put("msg", "Address 不能为空!");
//这里按照正常流程走的话,应该是 return ;
continue;
}
}
} catch (Exception e)
{
e.printStackTrace();
} finally
{
long l = System.currentTimeMillis();
System.out.println(l - currentTimeMillis);
}
程序执行300次,测试得到的平均时间为:32ms左右。
if else 太多的情况,如:
StringBuilder builder = new StringBuilder(160);
if (getDicMap().containsKey("id")) //如果包含id,则进行处理
{
builder.append(Str.tl(" and id in (:0) ", getMoreParameter("id")));
} else if (this.getId() != null && !"".equals(this.getId()))
{
builder.append(" and id = " + this.getId());
}
if (getDicMap().containsKey("text")) //如果包含text,则进行处理
{
builder.append(Str.tl(" and text in (:0) ", getMoreParameter("text", true)));
} else if (this.getText() != null && !"".equals(this.getText()))
{
builder.append(" and text like '%" + Str.filterSql(this.getText()) + "%'");
}
if (getDicMap().containsKey("realValue")) //如果包含realValue,则进行处理
{
builder.append(Str.tl(" and real_value in (:0) ", getMoreParameter("realValue", true)));
} else if (this.getRealValue() != null && !"".equals(this.getRealValue()))
{
builder.append(" and real_value like '%" + Str.filterSql(this.getRealValue()) + "%'");
}
if (getDicMap().containsKey("fieldName")) //如果包含fieldName,则进行处理
{
builder.append(Str.tl(" and field_name in (:0) ", getMoreParameter("fieldName", true)));
} else if (this.getFieldName() != null && !"".equals(this.getFieldName()))
{
builder.append(" and field_name like '%" + Str.filterSql(this.getFieldName()) + "%'");
}
if (getDicMap().containsKey("remark")) //如果包含remark,则进行处理
{
builder.append(Str.tl(" and remark in (:0) ", getMoreParameter("remark", true)));
} else if (this.getRemark() != null && !"".equals(this.getRemark()))
{
builder.append(" and remark like '%" + Str.filterSql(this.getRemark()) + "%'");
}
if (getDicMap().containsKey("pid")) //如果包含pid,则进行处理
{
builder.append(Str.tl(" and pid in (:0) ", getMoreParameter("pid")));
} else if (this.getPid() != null && !"".equals(this.getPid()))
{
builder.append(" and pid = " + this.getPid());
}
if (getDicMap().containsKey("pname")) //如果包含pname,则进行处理
{
builder.append(Str.tl(" and pname in (:0) ", getMoreParameter("pname", true)));
} else if (this.getPname() != null && !"".equals(this.getPname()))
{
builder.append(" and pname like '%" + Str.filterSql(this.getPname()) + "%'");
}
if (getDicMap().containsKey("sort")) //如果包含sort,则进行处理
{
builder.append(Str.tl(" and sort in (:0) ", getMoreParameter("sort")));
} else if (this.getSort() != null && !"".equals(this.getSort()))
{
builder.append(" and sort = " + this.getSort());
}
Apache Validate
结论:这种判断效率比if else略低,优势是可以阻断程序继续往下执行,缺点是会抛出异常栈。
code:
long currentTimeMillis = System.currentTimeMillis();
try
{
for (int i = 0; i < 300; i++)
{
PlatformDevelopers dev = new PlatformDevelopers();
Validate.notBlank(dev.getAddress(), "错误的参数!");
}
} catch (Exception e)
{
//e.printStackTrace();
} finally
{
long l = System.currentTimeMillis();
System.out.println(l - currentTimeMillis);
}
程序执行300次,测试得到的平均时间为:47ms左右。
如:
java.lang.NullPointerException: Address 不能为空!
at org.apache.commons.lang3.Validate.notBlank(Validate.java:448)
at test.spring.boot.rest.TValidVsJSR.m2(TValidVsJSR.java:59)
at test.spring.boot.rest.TValidVsJSR.main(TValidVsJSR.java:29)
JSR303(Hibernate Validator 5.2.4.Final 提供支持)
结论:这种判断最简单,一个注解搞定,只需处理错误即可。优点是方便,功能强大,可读性,可配置强大,有社区支持,缺点是效率最低,比上面的验证结果慢了10倍有余。
long currentTimeMillis = System.currentTimeMillis();
for (int i = 0; i < 300; i++)
{
PlatformDevelopers dev = new PlatformDevelopers();
//jsr
Map<String, String> validate = ValidateUtil.validate(dev);
if (!validate.isEmpty())
{
// System.out.println(validate);
}
}
long l = System.currentTimeMillis();
System.out.println(l - currentTimeMillis);
PlatformDevelopers.java
public class PlatformDevelopers
{
//id
private java.lang.Integer id;
@NotBlank
@Email
//开发者email
private java.lang.String email;
@NotBlank
@Size(min = 6, max = 32)
//登陆密码
private java.lang.String password;
}
ValidateUtil.java
/**
*
* 项目名称:ej <br><br>
*
* 类名称:ValidateUtil <br><br>
*
* 创建人:LinApex@163.com <br><br>
*
* 创建时间:2014-2-26 下午1:10:03 <br><br>
*
* 版本:1.0 <br><br>
*
* 功能描述:验证工具类,后台校验对象
*/
public class ValidateUtil
{
static Validator validator;
static
{
//消息国际化对象
// ReloadableResourceBundleMessageSource localMessageSource = new ReloadableResourceBundleMessageSource();
// localMessageSource.setBasename("classpath:i18n/messages");
// localMessageSource.setDefaultEncoding("UTF-8");
// localMessageSource.setCacheSeconds(60);
LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
localValidatorFactoryBean.setProviderClass(HibernateValidator.class);
// localValidatorFactoryBean.setValidationMessageSource(localMessageSource); //消息国际化对象
localValidatorFactoryBean.afterPropertiesSet();
validator = localValidatorFactoryBean.getValidator();
}
public static <T> Map<String, String> validate(T t)
{
Map<String, String> resultMap = new HashMap<String, String>(0);
Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);
if (constraintViolations.size() > 0)
{
for (ConstraintViolation<T> constraintViolation : constraintViolations)
{
resultMap.put(constraintViolation.getPropertyPath().toString(), constraintViolation.getMessage());
}
}
return resultMap;
}
}
程序执行300次,测试得到的平均时间为:630ms左右。
有没有更优的解决方式?
你们在开发里一般使用什么方式?
有没有更有经验的朋友来分享一下你的看法?
(adsbygoogle = window.adsbygoogle || []).push({});
