使用自定义注解和反射实现参数检查

一、首先定义一个参数检查的注解@RequestParam

package com.daily.java.AnotationAndReflect;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 参数检查注解
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {

    /**
     * 参数名称
     *
     * @return
     */
    String paramName() default "";

    /**
     * 是否可为空
     * - 返回true时,如果此参数为空,则会在调用前抛出异常
     *
     * @return
     */
    boolean notNull() default false;

    /**
     * 是否可为空或空字符串或空集合
     * - 返回true时,如果此参数为空,则会在调用前抛出异常
     *
     * @return
     */
    boolean notEmpty() default false;
}

二、定义一个参数检查的接口

package com.daily.java.AnotationAndReflect;

/**
 * 需要参数检查的POJO必须实现此接口
 */
public interface Request {
}

三、工具类的实现

package com.daily.java.AnotationAndReflect;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;

/**
 * 请求工具类
 * (1). 检查参数非空
 * (2). 从request中提取参数
 */
public class RequestUtils {

    private static final Logger log = LoggerFactory.getLogger(RequestUtils.class);

    /**
     * 请求的全部成员变量Map
     * -- key  : request.getClass().getName();
     * -- value: request.getClass().getFields();
     */
    private static final Map<String, Set<Field>> All_FIELDS_MAP =new ConcurrentHashMap<>();

    private static final Map<String, Set<Field>> NOT_NULL_FIELDS_MAP = new ConcurrentHashMap<>();

    private static final Set<Field> getAllFields(Object request) {
        return getFields(request, All_FIELDS_MAP);
    }

    private static final Set<Field> getNotNullFields(Object request) {
        return getFields(request, NOT_NULL_FIELDS_MAP);
    }


    private static final Set<Field> getFields(Object userCenterRequest, Map<String, Set<Field>> cacheMap) {
        String name = userCenterRequest.getClass().getName();
        Set<Field> fields = cacheMap.get(name);
        if (fields == null) {
            initRequestFields(userCenterRequest);
            fields = cacheMap.get(name);
        }
        return fields;
    }

    private static final void initClassFields(Class clazz, Set<Field> allFields, Set<Field> notNullFields) {
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            RequestParam annotation = field.getAnnotation(RequestParam.class);
            if (annotation != null) {
                field.setAccessible(true);
                allFields.add(field);
                if (annotation.notNull() || annotation.notEmpty()) {
                    notNullFields.add(field);
                }
            }
        }

        Class superclass = clazz.getSuperclass();
        if (superclass != null && !superclass.isInterface()) {
            initClassFields(superclass, allFields, notNullFields);
        }
    }

    private static final void initRequestFields(Object request) {
        String name = request.getClass().getName();
        synchronized (name + "requestUtils") {
            Set<Field> allFields = All_FIELDS_MAP.get(name);
            if (allFields == null) {
                Set<Field> notNullFields = new HashSet<>();
                allFields = new HashSet<>();
                initClassFields(request.getClass(), allFields, notNullFields);
                NOT_NULL_FIELDS_MAP.put(name, notNullFields);
                All_FIELDS_MAP.put(name, allFields);
            }
        }
    }

    /**
     * 从request中提取调用参数(过滤为空的参数)
     *
     * @param request 请求
     * @return
     */
    public static final Map<String, String> getRequestParams(Request request) {
        return getRequestParams(request, true);
    }

    /**
     * 从request中提取调用参数
     *
     * @param request         请求
     * @param filterNullParam 是否过滤非空参数
     * @return
     */
    public static final Map<String, String> getRequestParams(Object request, boolean filterNullParam) {
        Set<Field> allFields = getAllFields(request);
        Map<String, String> requestParamMap = new ConcurrentHashMap<>();
        try {
            for (Field field : allFields) {
                RequestParam annotation = field.getAnnotation(RequestParam.class);
                if (annotation != null) {
                    Object objectValue = field.get(request);
                    if (objectValue == null && filterNullParam) {
                        continue;
                    }

                    String value=objectValue==null?"":objectValue.toString();

                    String paramName = annotation.paramName();
                    if (StringUtils.isEmpty(paramName)) {
                        paramName = field.getName();
                    }
                    requestParamMap.put(paramName, value);
                } else {
                    Object value = field.get(request);
                    if (value == null && filterNullParam) {
                        continue;
                    }
                    Map<String, String> requestParams = getRequestParams(value, filterNullParam);
                    if (requestParams != null && !requestParams.isEmpty()) {
                        requestParamMap.putAll(requestParams);
                    }
                }

            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return requestParamMap;
    }

    /**
     * 对request中的参数进行非空校验
     *
     * @param request
     */
    public static final void checkRequestParams(Object request) {

        Set<Field> notEmptyFields = getNotNullFields(request);
        try {
            for (Field field : notEmptyFields) {
                Object value = field.get(request);
                RequestParam annotation = field.getAnnotation(RequestParam.class);
                if (annotation != null) {
                    if (annotation.notNull() && value == null) {
                        throw new IllegalArgumentException("Parameter " + field.getName() + " expects not to be null : " + request);
                    }
                    if (annotation.notEmpty()) {
                        // -- 2.1. 校验非空
                        if (value == null) {
                            throw new IllegalArgumentException("Parameter " + field.getName() + " expects not to be null : " + request);
                        }
                        // -- 2.2. 判断String类型的属性非空
                        if (value instanceof String && StringUtils.isEmpty((String) value)) {
                            throw new IllegalArgumentException("Parameter " + field.getName() + " expects not to be empty : " + request);
                        }
                        // -- 2.3. 判断集合类型的属性非空
                        if (value instanceof Collection && ((Collection) value).isEmpty()) {
                            throw new IllegalArgumentException("Parameter " + field.getName() + " expects not to be empty : " + request);
                        }
                        // -- 2.4. 判断Map类型的属性非空
                        if (value instanceof Map && ((Map) value).isEmpty()) {
                            throw new IllegalArgumentException("Parameter " + field.getName() + " expects not to be empty : " + request);
                        }
                        // -- 2.5. 判断数组类型的属性非空
                        if (field.getType().isArray() && JSON.toJSONString(value).equals("[]")) {
                            throw new IllegalArgumentException("Parameter " + field.getName() + " expects not to be empty : " + request);
                        }
                    }
                }
            }
        } catch (IllegalAccessException e) {
            log.error("checkRequestParams exception", e);
        }
    }

}

四、定义一个用于测试的POJO

/**
 * 参数检查测试POJO
 */
public class Student implements Request {

    @RequestParam(notEmpty = true)
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

五、测试

/**
 * 使用自定义注解和反射实现参数检查
 */
public class AnotationAndReflectTest {

    @Test
    public void testRequestCheck() {
        Student student = new Student();
        student.setName("张三");
        RequestUtils.checkRequestParams(student);

        student.setName(null);
        RequestUtils.checkRequestParams(student);
    }
}

东瓜
18 声望3 粉丝