使用自定义注解和反射实现参数检查
一、首先定义一个参数检查的注解@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> All_FIELDS_MAP =new ConcurrentHashMap<>();
private static final Map> NOT_NULL_FIELDS_MAP = new ConcurrentHashMap<>();
private static final Set getAllFields(Object request) {
return getFields(request, All_FIELDS_MAP);
}
private static final Set getNotNullFields(Object request) {
return getFields(request, NOT_NULL_FIELDS_MAP);
}
private static final Set getFields(Object userCenterRequest, Map> cacheMap) {
String name = userCenterRequest.getClass().getName();
Set fields = cacheMap.get(name);
if (fields == null) {
initRequestFields(userCenterRequest);
fields = cacheMap.get(name);
}
return fields;
}
private static final void initClassFields(Class clazz, Set allFields, Set 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 allFields = All_FIELDS_MAP.get(name);
if (allFields == null) {
Set 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 getRequestParams(Request request) {
return getRequestParams(request, true);
}
/**
* 从request中提取调用参数
*
* @param request 请求
* @param filterNullParam 是否过滤非空参数
* @return
*/
public static final Map getRequestParams(Object request, boolean filterNullParam) {
Set allFields = getAllFields(request);
Map 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 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 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);
}
}