欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

自定义元注解将方法上的String类型字段 NULL 转为 ““

程序员文章站 2022-04-15 17:45:05
自定义元注解讲方法上的String类型字段 NULL 转为 “”元注解@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface StringEmptyFilter { String[] values() default {};//方法上的字段名称}AOP处理类import lombok.extern.slf4j.Slf4j;import org.aspect...

自定义元注解将方法上的String类型字段 NULL 转为 “”

为什么博主会想到写这么一个元注解呢,因为博主在实际开发中,使用的是Springboot JPA,在Repository中写HQL或者SQL的时候总会有一些条件查询,String也是必然会用到的类型,但如果数据库没有对String类型的默认值做处理,那么DB的默认值则会是NULL,对于NULL的处理有几种方式。

对于值为NULL的String字段的处理方式

  • 在Controller层的DTO中给默认值
public class UserDTO{
	private String userName = "";
	private String email = "";
	private String address = "";
}
  • 在Service层一个个String类型的字段判空
public List<User> findUserBySearch(String userName,String email,String address){
        userName = StringUtils.isEmpty(userName)?"":userName;
        email = StringUtils.isEmpty(email)?"":email;
        address = StringUtils.isEmpty(address)?"":address;
        return UserRepository.findUserBySearch(userName,email,address);
    }
  • 在Repository层为每一个需要Like且可能为NULL的字段加上额外的条件
@Query(value = "select u from User u where (userName like %?1% or '' like %?1%) and (email like %?1% or '' like %?1%) and (address like %?1% or '' like %?1%)  ")
List<User> findBySearch(String userName,String email,String address)

以上所想到的办法都让代码显示很不美观,对于博主这样有这种有代码洁癖还喜欢“偷懒”的人是一定不能忍的,所以博主想到用元注解来代替这一系列无脑且重复的操作
以下代码基于JDK1.8

元注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface StringEmptyFilter {
    String[] values() default {};//方法上的字段名称
}

AOP处理类

import lombok.extern.slf4j.Slf4j;
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.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Objects;
@Component
@Aspect
@Slf4j
public class StringEmptyFilterAspect {
    @Around("@annotation(StringEmptyFilter)")
    public Object stringEmptyFilterHandler(ProceedingJoinPoint point) throws Throwable {
        Object[] args = point.getArgs();//入参
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();//AOP代理方法
        Method targetMethod = point.getTarget().getClass().getMethod(method.getName(), method.getParameterTypes());//真实方法
        StringEmptyFilter annotation = targetMethod.getAnnotation(StringEmptyFilter.class);//当前方法的注解
        Class<?>[] parameterTypes = targetMethod.getParameterTypes();//获取方法入参字段类型
//            new LocalVariableTableParameterNameDiscoverer().getParameterNames(targetMethod);//获取方法入参真实变量名①
        ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
        String[] parameterNames = pnd.getParameterNames(targetMethod);//获取方法入参真实变量名②
        if (annotation == null) {
            //如果没有@StringEmptyFilter注解 不做处理
            return point.proceed(args);
        }
        if (annotation.values().length != 0) {
            //如果指定了需要过滤的字符串字段,则只过滤指定的字符串字段
            String[] values = annotation.values();
            Arrays.stream(values).forEach(strField -> {
                for (int i = 0; i < parameterNames.length; i++) {
                    if (Objects.equals(parameterNames[i], strField) && parameterTypes[i] == String.class) {
                        args[i] = StringUtils.isEmpty(args[i]) ? "" : args[i];
                        break;
                    }
                }
            });
            return point.proceed(args);
        } else {
            //如果没指定需要过滤的字符串字段,则过滤所有String类型的字段
            for (int i = 0; i < parameterTypes.length; i++) {
                if (parameterTypes[i] == String.class) {
                    args[i] = StringUtils.isEmpty(args[i]) ? "" : args[i];
                }
            }
            return point.proceed(args);
        }
    }
}

Demo

//场景1:直接使用注解 默认将方法上所有的String的NULL转为""
@StringEmptyFilter
public void doSomething(String userName,String eamil,Integer age,Date birth){
    
}
//场景2:指定字段转化(指定字段不存在||指定字段类型不为String则跳过不做处理)
@StringEmptyFilter(values = {"userName"})
public void doSomething(String userName,String eamil,Integer age,Date birth){
    
}

本文地址:https://blog.csdn.net/qq_37957369/article/details/110820538

相关标签: java spring aop