我们的测试大神提出了问题单,输入%和_会查询到所有数据,需要修改。如果不修改,严重问题,版本转测试不通过!!在我看来测试能提出这种问题真的是挺“业余”的,那我就给他改一下。
解决方式很简单,无非就是在查询前将可能带有%和_的字段进行转义。例如:
if (StringUtils.isNotBlank(logInfo.getAccount())) {
String account = logInfo.getAccount();
if (account.contains("%")) {
account = account.replaceAll("\\%","\\\\%");
}
if (account.contains("%")) {
account = account.replaceAll("\\%","\\\\%");
}
if (account.contains("_")) {
account = account.replaceAll("\\_","\\\\_");
}
logInfo.setAccount(account);
}
以上例子中,account为带查询的字段。
但是!如果每个方法都这样查询,难免太繁琐了,而且容易遗忘!为了不让我们的测试提问题单,我决定优化一下。
注解+反射+commons-beanutils
本篇采用java注解+反射机制和引入commons-beanutils包来解决。
定义注解@SpecChar
/**
* 特殊字符处理注解,主要用来解决测试大神提的%和_查询问题
* 希望我司测试大神能满意
* 希望我司测试大神增强自己的实力,不要只会体验
* 真正的测试比开发要牛
* 共勉!
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SpecChar {
}
当我们在定义实体类的时候,在需要查询的字段上面加上这个注解!例如:
@Data
public class OrgManageSceneDto extends OrgManageScene{
@SpecChar
private String sceneName;
}
引入commons-beanutils包,记得引入1.9.3,否则会报错哦
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
以上完事后,编写统一方法,查询的时候只需要调用统一方法即可!
/**
* 处理特殊字符‘%’、‘_’
* @param object
* @return
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws NoSuchMethodException
*/
public static Object setSpecChar(Object object) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
if (object == null) {
return object;
}
for (Field field : getAllFields(object)) {
if (field.getAnnotation(SpecChar.class) != null) {
String name = field.getName();
Object value = PropertyUtils.getSimpleProperty(object, name);
if (value != null) {
String valueStr = (String) value;
if (valueStr.contains("%")) {
valueStr = valueStr.replaceAll("\\%","\\\\%");
}
if (valueStr.contains("_")) {
valueStr = valueStr.replaceAll("\\_","\\\\_");
}
PropertyUtils.setProperty(object, name, valueStr);
}
}
}
return object;
}
/**
* 获取类的所有属性,包括父类
*
* @param object
* @return
*/
public static Field[] getAllFields(Object object) {
Class<?> clazz = object.getClass();
List<Field> fieldList = new ArrayList<>();
while (clazz != null) {
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
clazz = clazz.getSuperclass();
}
Field[] fields = new Field[fieldList.size()];
fieldList.toArray(fields);
return fields;
}
在调用DAO层之前先调用此方法:
//调用一下
orgManageSceneDto = (OrgManageSceneDto) StructureUtil.setSpecChar(orgManageSceneDto);
List<OrgManageVo> list = orgManageMapper.getOrgManageScene(orgManageSceneDto);
以上解决问题,我们不用再每次都自己去转义了。
当然我们既然定义了注解,还可以用切面和mybatis拦截器去做,这样会更方便,但是原理是一样的!
写在最后
最后希望我司的测试能多在架构、业务和性能优化上多发现问题和提出建议,不要当个体验官,这样在公司优化的时候你才能避免被淘汰。共勉!