AOP实现对请求参数的所以字符串去前后空格

在实际的开发过程中,经常会需要客户端输入一些字符串,比如账号、密码,都是以字符串的形式传给后端的。

客户端传给后端的字符串可以说五花八门,"","      ","      123456","123456        ","         123456          "等等。

这就导致后端拿到字符串之后需要做两次操作,第一次判空,第二次去除前后空格。

public String test(String str) {
    if (str != null) {
        str = str.trim();
    }
    return str;
}

这样的后果是,当需要客户端传送许多文本的时候(POST请求发送大量数据),去除空格的代码就会变得很冗余。

public String test(Class class) {
    if (class.p1 != null) {
        class.p1 = class.p1.trim();
    }
    if (class.p2 != null) {
        class.p2 = class.p2.trim();
    }
    if (class.p3 != null) {
        class.p3 = class.p3.trim();
    }
    // 其余去空代码
    ...
    return class;
}

 

使用AOP可以在方法的执行前先统一对字符串去空格,这样在业务逻辑代码里面就不需要对字符串进行去空格操作了。

/**
 * Created with IntelliJ IDEA.
 *
 * @auther: lkz
 * @date: 2021/02/28
 * @version: 1.0
 * @description:
 */
@Component
@Aspect
public class TrimAspect {

    // 定义切点
    // 记录后台接口的操作记录
    // 拦截Controller所在的包
    @Pointcut("execution(* com.xxx.xxx.controller.*.*(..))")
    public void excudeService() {
    }

    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {



        // 数据校验注解优先于此AOP执行

        //重点 这里就是获取@RequestBody参数的关键  调试的情况下 可以看到arr变量已经获取到了请求的参数
        Object[] arr = pjp.getArgs();
        for (int i = 0; i < arr.length; ++i) {
            if (arr[i] instanceof HttpServletRequest) { // 特殊处理
                HttpServletRequest request = (HttpServletRequest) arr[i];
                Map<String, String[]> m = request.getParameterMap();
                Map<String, String[]> newM = new HashMap<String, String[]>();
                if (m != null) {
                    for (Map.Entry<String, String[]> entry : m.entrySet()) {
                        String key = entry.getKey();
                        String[] value = entry.getValue();
                        if (value == null) continue;
                        for (int j = 0; j < value.length; ++j) {
                            String temp = value[i].trim();
                            value[i] = temp.length() == 0 ? null : temp;
                        }
                        newM.put(key, value);
                    }
                }
                // 因为我们无法去改变getParameterMap的返回值
                // 所以对里面的值去除空格是无效的
                // 但是我们可以把参数的值去除空格之后把值放入setAttribute里面
                // 这样request对象就携带了去除空格之后的值
                request.setAttribute("The-result-after-removing-the-space", newM);
                arr[i] = request;
            } else {
                // 考虑到类里面还有类 这里采用递归的方式处理
                arr[i] = dfs(arr[i].getClass(), arr[i]);
            }
        }

        // 把 arr 放回去即可改变参数的值
        return pjp.proceed(arr);
    }

    private Object dfs(Class<?> aClass, Object object) throws IllegalAccessException {
        if (object == null) return null;
        // 如果是Java的基本数据类型就不需要继续递归了
        if (isPrimitive(aClass)) {
            if (object instanceof String) {
                String temp = ((String) object).trim();
                return temp.length() == 0 ? null : temp;
            }
            return object;
        }
        // 返回类所有字段
        // 注意: 会返回静态字段
        // 不要在Dto、Vo定义静态属性
        // 没有获取父类属性 可通过 “object.getClass().getSuperclass()” 获取
        for (Field item : object.getClass().getDeclaredFields()) {
            // static 和 final 修饰的字段忽略
            if (Modifier.isStatic(item.getModifiers()) || Modifier.isStatic(item.getModifiers())) {
                continue;
            }
            // 设置可见性
            item.setAccessible(true);
            // 递归处理
            item.set(object, dfs(item.getType(), item.get(object)));
        }
        return object;
    }

    // 判断是否为Java的基本类型或包装类
    // java.lang.* java.util.* 存放着Java的基本数据类型的包装类和集合类
    // 基本数据类型和包装类是JVM虚拟机运行需要的类,已嵌入到JVM内核
    // 不需要继承ClassLoader 用户自定义的需要
    private boolean isPrimitive(Class<?> aClass) {
        return aClass != null && aClass.getClassLoader() == null;
    }

}

通过了这个AOP之后的字符串都是已经去除前后空格的了,之后的业务代码根据需要去判断字符串是否为空就可以了。上述代码对空格字符串的处理是,把空格字符串的那个字段置为null。可以自己根据需求去修改。

public String test(Class class) {
    if (class.p1 != null) {
        // 已经不需要了
        // class.p1 = class.p1.trim();
    }
    if (class.p2 != null) {
        // 已经不需要了
        // class.p2 = class.p2.trim();
    }
    if (class.p3 != null) {
        // 已经不需要了
        // class.p3 = class.p3.trim();
    }
    // 其余去空代码
    ...
    return class;
}
//  "     " 会变成null
String temp = value[i].trim();
value[i] = temp.length() == 0 ? null : temp;

这个AOP还有一个不足的地方是没有考虑到父类,只向下处理了子类,没有向上处理父类。

可以通过 “object.getClass().getSuperclass()” 获取父类,然后加以改进。

不过,一般Controller层接受参数的类不会很复杂,有父类一般也就只有一层,不需要用到递归,向上处理一层就可以了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值