logo 范 · 拾光录
网址收集 关于作者 Github Gitee
杂文随笔4
Hexo博客:基础使用Hexo博客:Next主题Hexo博客:Next进阶使用Hexo博客:Next高级配置
前端编程3
前端基础知识16
UniApp15
Vue框架19
Java编程7
Java基础知识14
SpringBoot31
SpringMVC14
MyBatis8
SpringCloud15
RocketMQ1
MyCat1
数据库4
MySQL6
Redis7
MongoDB10
H21
Java技术栈4
知识整理分布式锁的实现方案MySQL事务MySQL的锁
软件工具箱14
IDEAGitMavenGradleNginx安装Nginx配置JMeter压测OllamaPicGoRustFSVSCodeDockerObsidianObs录制
Linux知识11
树莓派安装及使用ArchLinux:常用软件ArchLinux:基础系统安装ArchLinux:深度优化ArchLInux:图形化界面安装ArchLinux:Nirifrp内网穿透Jar启动脚本Linux常用命令VirtualBox安装CentOSVirtualBox安装Ubuntu
Python编程6
Python基础知识Python语法yolo目标检测OpenCV的使用及树莓派平台condauv
创意设计2
Blender:入门知识UI设计基础知识
AI相关9
Claude CodeHermes AgentOpenAI基本使用OpenAI工具调用OpenAI记忆管理OpenAI推理执行OpenAI开发框架Langchainllama.cpp

问题场景

接口参数需要做校验,基于JSR303等框架需要写不同的Vo类来支持,比如添加接口不需要强制ID,而修改接口又必须要ID,就可能需要两个Vo类传入。为了解决这类场景,可以写个参数动态校验工具类

工具代码

import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Objects;
import java.util.function.Function;

/**
 * 参数校验
 */
@Slf4j
public class VerifyUtil {

    /**
     * 使Function获取序列化能力
     */
    @FunctionalInterface
    public interface SFunction<T, R> extends Function<T, R>, Serializable {
    }

    @SafeVarargs
    public static <T> String check(Object params, VerifyUtil.SFunction<T, ?>... fns) {
        Class<?> clazz = params.getClass();
        try {
            for (VerifyUtil.SFunction<T, ?> fn : fns) {
                // 从function取出序列化方法
                Method writeReplaceMethod;
                try {
                    writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace");
                } catch (NoSuchMethodException e) {
                    throw new RuntimeException(e);
                }
                // 从序列化方法取出序列化的lambda信息
                // JDK9以下
                // boolean isAccessible = writeReplaceMethod.isAccessible();
                // JDK9及以上
                boolean isAccessible = writeReplaceMethod.canAccess(fn);
                writeReplaceMethod.setAccessible(true);
                SerializedLambda serializedLambda;
                try {
                    serializedLambda = (SerializedLambda) writeReplaceMethod.invoke(fn);
                } catch (IllegalAccessException | InvocationTargetException e) {
                    throw new RuntimeException(e);
                }
                writeReplaceMethod.setAccessible(isAccessible);
                // 从lambda信息取出method、field、class等
                String fieldName = serializedLambda.getImplMethodName().substring("get".length());
                fieldName = fieldName.replaceFirst(fieldName.charAt(0) + "", (fieldName.charAt(0) + "").toLowerCase());
                // 通过反射直接获取名为username的属性
                Field declaredField = clazz.getDeclaredField(fieldName);
                if (declaredField.getModifiers() == Modifier.PRIVATE) {
                    declaredField.setAccessible(true);
                    Object value = declaredField.get(params);
                    // 判断是否为空
                    if (value instanceof String) {
                        // 字符不能为空字符
                        if (Objects.equals(value, "")) {
                            return declaredField.getName() + "不能为空";
                        }
                    } else {
                        if (Objects.isNull(value)) {
                            return declaredField.getName() + "不能为空";
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("校验失败", e);
        }
        return null;
    }

}

使用方式

public Result<String> login(SysUser params) {
    // 校验
    String check = VerifyUtil.check(params, SysUser::getUsername, SysUser::getPassword);
    if (Objects.nonNull(check)) {
        return Result.failMsg(check);
    }
    // 更复杂的检验在此做
    LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(SysUser::getUsername, params.getUsername());
    wrapper.eq(SysUser::getPassword, params.getPassword());
    wrapper.eq(SysUser::getDeleted, 1);
    SysUser sysUser = this.getOne(wrapper);
    if (Objects.isNull(sysUser)) {
        return Result.failMsg("用户名或密码错误");
    } else {
        return Result.successMsg("登录成功");
    }
}
问题场景
工具代码
使用方式