Java自动在传入参数中对于对象字符串进行trim操作

原文链接

欢迎大家对于本站的访问 - AsterCasc

前言

经常做表单操作的小伙伴都知道,测试没能测出来然后由于种种原因在线上出问题且大概率不能直接定位到问题的BUG,其中没有进行字符串的修剪是一个不少人在初期,甚至中后期都有可能不小心犯的错误。因为这种问题的出现的BUG一般不是本身,而是衍生出来比如字符串不匹配导致的检查错误、认证错误等

前段时间和产品聊天,某产品表示,谁谁谁的技术框架是很烂不能被接受的,问其原因,说是一次线上问题定位很久才定位到:是由于管理员输入用户姓名时,前后端没有进行修剪,导致用户在进行后续操作的时候提示查无此人。但是这种问题,我扪心自问,也很难避免,所以这里我们简化业务trim的处理,统一使用注解实现

实现

创建注解

@Target(ElementType.PARAMETER)  
@Retention(RetentionPolicy.RUNTIME)  
public @interface TrimParam {  
}

创建切面

这里有两种方案,如果你只在数据请求的时候进行修剪操作,那么通过继承RequestBodyAdviceAdapter实现HandlerMethodArgumentResolver的方式,对于指定注解参数进行处理,这里由于我们需要更加通用的操作,所以使用切面实现

package com.aster.yuno.index.utils;

import com.aster.yuno.index.ann.TrimParam;  
import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.ProceedingJoinPoint;  
import org.aspectj.lang.annotation.Around;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.reflect.MethodSignature;  
import org.springframework.stereotype.Component;  
  
import java.lang.annotation.Annotation;  
import java.lang.reflect.Field;  
import java.lang.reflect.Method;

@Aspect  
@Component  
public class TrimParamStringsAspect {  
  
    @Around("execution(* *(.., @com.aster.yuno.index.ann.TrimParam (*), ..))")  
    public Object trimParamStrings(ProceedingJoinPoint joinPoint) throws Throwable {  
        Object[] args = joinPoint.getArgs();  
        Method method = getCurrentMethod(joinPoint);  
        if (method == null) {  
            return joinPoint.proceed(args);  
        }  
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();  
        for (int annCount = 0; annCount < parameterAnnotations.length; annCount++) {  
            for (Annotation annotation : parameterAnnotations[annCount]) {  
                if (annotation instanceof TrimParam) {  
                    Object needTrimParam = args[annCount];  
                    if (needTrimParam instanceof String thisStr) {  
                        args[annCount] = thisStr.trim();  
                    } else {  
                        trimFields(args[annCount]);  
                    }  
                }  
            }  
        }  
        return joinPoint.proceed(args);  
    }  
  
    private void trimFields(Object object) {  
        for (Field field : object.getClass().getDeclaredFields()) {  
            if (field.getType().equals(String.class)) {  
                field.setAccessible(true);  
                try {  
                    String value = (String) field.get(object);  
                    if (value != null) {  
                        field.set(object, value.trim());  
                    }  
                } catch (Exception ignore) {  
                }  
            }  
        }  
    }  
  
    private Method getCurrentMethod(JoinPoint joinPoint) {  
        String methodName = joinPoint.getSignature().getName();  
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();  
        try {  
            return joinPoint.getTarget().getClass().getMethod(methodName, parameterTypes);  
        } catch (NoSuchMethodException ignore) {  
            return null;  
        }  
    }  
}

这里我们注解给到参数,如果是字符串参数,则直接修剪,如果是对象参数,则进入对象,修剪对象中的所有字符串字段

注入

由于我们这里是使用的自建的外部包,方便所有微服务使用,所以需要在注册到当前容器内,如果小伙伴只在当前项目中处理,则不需要进行注入了。注入方式很多,这里使用@ComponentScan

//more
@ComponentScan(basePackages = ["com.aster.yuno.index.utils", "com.aster.yuno.demo"])  
class DemoApplication  
  
fun main(args: Array<String>) {  
    runApplication<DemoApplication>(*args)  
}

使用

@RestController  
@RequestMapping("/test")  
class TestController @Autowired constructor(  
    private val testService: ITestService,  
) {  
  
    @PostMapping("/{projectId}/user/insert/auth")  
    fun new(  
        @PathVariable("projectId") projectId: String,  
        @TrimParam @RequestBody param: InsertProjectUserParam,  
    ): ResultObj<Unit> {  
        testService.new(projectId, adminUserId, param)  
        return ResultObj.success()  
    }  
}

此时我们传入携带首尾空格的字符串字段在InsertProjectUserParam中,即可观察到,该字符串被修剪

源代码位置

原文链接

欢迎大家对于本站的访问 - AsterCasc

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值