package message.validate.core;
import message.utils.ObjectUtils;
import message.utils.StringUtils;
import message.validate.annotations.ValidateEntity;
import message.validate.constants.ValidateConstants;
import message.validate.exception.DefaultExceptionHandler;
import message.validate.exception.ExceptionHandler;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 验证引擎核心组件.
*
* @author sunhao(sunhao.java@gmail.com)
* @version V1.0
* @createTime 12-11-26 下午9:53
*/
@Aspect
@Component
public class ValidateEngine implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(ValidateEngine.class);
//是否开启验证引擎?默认是开启
private boolean openValidate = true;
//放置验证注解和其对应的处理类
private List<BeanHandler> beanHandlers;
//key-value(注解名称-beanHandler)
private Map<String, BeanHandler> beanHandlerMap;
//异常处理类,默认使用DefaultExceptionHandler
private ExceptionHandler exceptionHandler = new DefaultExceptionHandler();
//注解的集合(集合的名称)
private List<String> annotations;
/**
* 需要验证的类--需要验证的字段(内存中的缓存)
*/
private Map<String, List<Field>> validateFields;
//验证引擎的注解所在classpath下的包路径
private static final String ANNOTATION_PATH = "message.validate.annotations";
//验证引擎的注解对应的处理类所在classpath下的包路径
private static final String VALIDATE_HANDLER_PATH = "message.validate.handler";
//处理类的后缀名(类名)
private static final String HANDLER_CLASS_SUFFIX = "Handler";
/******************************************************验证引擎初始化--开始***********************************************************/
/**
* 初始化验证引擎
*/
private void initValidateEngine() throws Exception {
this.getBeanHandler();
putBeanHandleToMap();
}
/**
* 从jar包中获取验证的beanHandler
*
* @throws Exception
*/
private void getBeanHandler() {
String[] validateAnnotations = ValidateConstants.VALIDATE_ANNOTATIONS;
if (validateAnnotations == null || validateAnnotations.length == 0) {
logger.debug("there is no validate annotations in jars!");
return;
}
for (String va : validateAnnotations) {
if (StringUtils.isEmpty(va)) continue;
String packagePath = ANNOTATION_PATH + "." + va;
Class<?> annotation = null;
try {
annotation = ClassUtils.forName(packagePath, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
logger.error("can't get annotation for name '{}'!", packagePath);
logger.error(e.getMessage(), e);
continue;
}
String handlerPath = VALIDATE_HANDLER_PATH + "." + va + HANDLER_CLASS_SUFFIX;
Class<?> handler = null;
try {
handler = ClassUtils.forName(handlerPath, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
logger.error("can't get handler for name '{}'!", handlerPath);
logger.error(e.getMessage(), e);
continue;
}
if (annotation == null || handler == null || !ValidateHandler.class.equals(handler.getSuperclass())) {
logger.error("no annotation or handler!");
continue;
}
BeanHandler beanHandler = new BeanHandler(annotation.getSimpleName(), annotation, (ValidateHandler) BeanUtils.instantiate(handler));
beanHandlers.add(beanHandler);
}
}
/**
* 将beanHandlers中的注解-处理类放入beanHandlerMap中(并将注解中文名放入内存中-annotations)
*/
private void putBeanHandleToMap() {
if (!this.beanHandlers.isEmpty()) {
for (BeanHandler bh : this.beanHandlers) {
if (bh.getKey() != null && bh.getAnnotation() != null && bh.getValidateHandler() != null) {
logger.debug("validate key is '{}', annotation is '{}', validateHandler is '{}'!", new Object[]{
bh.getKey(), bh.getAnnotation(), bh.getValidateHandler()
});
//TODO 需要处理这里key值
this.beanHandlerMap.put(bh.getKey(), bh);
//将所有的注解放入内存中
String annName = bh.getAnnotation().getSimpleName();
this.annotations.add(annName);
}
}
}
}
@Override
public void afterPropertiesSet() throws Exception {
if (!this.openValidate) {
logger.debug("this web project is not open validate engine!");
return;
}
if (beanHandlers == null) {
beanHandlers = new ArrayList<BeanHandler>();
}
if (beanHandlerMap == null) {
beanHandlerMap = new HashMap<String, BeanHandler>();
}
if (this.validateFields == null) {
validateFields = new HashMap<String, List<Field>>();
}
if (this.annotations == null) {
this.annotations = new ArrayList<String>();
}
initValidateEngine();
}
/******************************************************验证引擎初始化--结束**************************************************************/
/************************************************************神奇的分隔符***************************************************************/
/*******************************************************验证引擎开始工作--开始***********************************************************/
/**
* 基于spring AOP的"环绕"验证开始
*
* @param proceedingJoinPoint 切面
* @throws Exception
*/
@Around("@annotation(message.validate.core.NeedValidate)")
public Object validate(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
if (!this.openValidate) {
logger.debug("this web project is no open validate engine!");
}
if (logger.isDebugEnabled())
logger.debug("start validate..., proceedingJoinPoint is '{}'!", proceedingJoinPoint);
//获取所有参数
Object[] args = proceedingJoinPoint.getArgs();
boolean result = true;
if (logger.isDebugEnabled())
logger.debug("get args is '{}'!", args);
for (Object arg : args) {
if (arg == null) continue;
Class clazz = arg.getClass();
if (clazz.isAnnotationPresent(ValidateEntity.class)) {
result = validateEntityFields(arg);
if (!result) {
logger.debug("validate class '{}' is error!", clazz);
break;
}
}
}
if (result) {
return proceedingJoinPoint.proceed();
}
return null;
}
/**
* 对entity每个字段进行验证
*
* @param entity 要验证的entity
* @return
*/
private boolean validateEntityFields(Object entity) throws Exception {
if (entity == null) {
logger.error("given empty entity!");
return false;
}
List<Field> fieldList = this.getValidateFields(entity.getClass());
if (fieldList == null || fieldList.isEmpty()) {
logger.debug("given entity class is '{}' has no validate fields!", entity.getClass());
return true;
}
boolean result = false;
for (Field f : fieldList) {
result = this.validateField(f, entity);
if (!result) {
break;
}
}
return result;
}
/**
* 验证字段
*
* @param f 待验证字段
* @param entity 待验证实体
* @return
*/
private boolean validateField(final Field f, final Object entity) throws Exception {
if (f == null || entity == null) {
logger.error("given field is null or entity is null!");
return false;
}
Annotation[] as = f.getAnnotations();
boolean result = false;
for (Annotation a : as) {
//TODO 需要处理这里key值
BeanHandler bh = this.beanHandlerMap.get(a.annotationType().getSimpleName());
if (bh != null) {
ValidateHandler handler = bh.getValidateHandler();
if (handler == null) {
logger.error("handler is null for annotation '{}'", a);
//仅结束本次循环
continue;
}
Object value = ObjectUtils.getFieldValue(entity, f.getName());
result = handler.validate(a, value);
if (!result) {
logger.debug("validate field is error for class '{}'! field is '{}', value is '{}'!", new Object[]{
entity.getClass(), f.getName(), value
});
//执行异常处理类
this.exceptionHandler.doHandleException(entity.getClass(), f, value, a);
}
}
}
return result;
}
/**
* 获取指定类需要验证的字段,如果内存中没有做缓存,则循环取出来,否则取内存中的
*
* @param clazz 指定类
* @return
* @throws Exception
*/
private List<Field> getValidateFields(Class<?> clazz) throws Exception {
if (clazz == null) {
logger.error("given empty class!");
return Collections.emptyList();
}
String key = "validate-" + clazz.getName();
List<Field> fieldList = this.validateFields.get(key);
//内存中不存在这个类的需要验证字段
if (fieldList == null || fieldList.isEmpty()) {
fieldList = new ArrayList<Field>();
Field[] fields = ObjectUtils.getFields(BeanUtils.instantiate(clazz));
for (Field f : fields) {
Annotation[] ans = f.getAnnotations();
for (Annotation a : ans) {
if (this.annotations.contains(a.annotationType().getSimpleName())) {
fieldList.add(f);
//这个字段只要有一个注解是符合条件的,立马放入待验证字段中
break;
}
}
}
if (fieldList != null && !fieldList.isEmpty()) {
//放入内存中
this.validateFields.put(key, fieldList);
}
}
return fieldList;
}
/**
* *************************************************验证引擎开始工作--结束*********************************************************
*/
public void setBeanHandlers(List<BeanHandler> beanHandlers) {
this.beanHandlers = beanHandlers;
}
public void setValidateFields(Map<String, List<Field>> validateFields) {
this.validateFields = validateFields;
}
public void setExceptionHandler(ExceptionHandler exceptionHandler) {
this.exceptionHandler = exceptionHandler;
}
public void setOpenValidate(boolean openValidate) {
this.openValidate = openValidate;
}
}