Browse Source

完善切面 继承判断

王智勇 5 years ago
parent
commit
5d0f4a488c
1 changed files with 198 additions and 88 deletions
  1. 198 88
      source/_posts/aop.md

+ 198 - 88
source/_posts/aop.md

@@ -186,92 +186,202 @@ public class ParamCheckAspect {
 
     /**
      * 是否数字类型
-     *
-     * @param typeName
-     * @return
-     */
-    private boolean isNumberType(String typeName) {
-        if ("integer".equalsIgnoreCase(typeName) || ParamType.INT.name().equalsIgnoreCase(typeName)) {
-            return true;
-        } else if ("long".equalsIgnoreCase(typeName) || ParamType.LONG.name().equalsIgnoreCase(typeName)) {
-            return true;
-        } else if ("double".equalsIgnoreCase(typeName) || ParamType.DOUBLE.name().equalsIgnoreCase(typeName)) {
-            return true;
-        } else if ("float".equalsIgnoreCase(typeName) || ParamType.FLOAT.name().equalsIgnoreCase(typeName)) {
-            return true;
-        } else if ("byte".equalsIgnoreCase(typeName) || ParamType.BYTE.name().equalsIgnoreCase(typeName)) {
-            return true;
-        } else if ("short".equalsIgnoreCase(typeName) || ParamType.SHORT.name().equalsIgnoreCase(typeName)) {
-            return true;
-        } else if ("character".equalsIgnoreCase(typeName) || ParamType.CHAR.name().equalsIgnoreCase(typeName)) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * 检查String类型的参数
-     * 包括 size/根据 type 检查 min/max/pattern
-     *
-     * @param value
-     * @param paramCheck
-     */
-    private void checkString(String value, ParamCheck paramCheck) throws AtdsException {
-        // 检查长度
-        if (paramCheck.size() < value.length()) {
-            throw new AtdsException("parameter %s is too long. (" + value.length() + " of " + paramCheck.size() + ")");
-        }
-        // 日期时
-        if (ParamType.DATE.equals(paramCheck.type())) {
-            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(paramCheck.pattern());
-            try {
-                formatter.parse(value);
-            } catch (Exception e) {
-                throw new AtdsException("parameter %s needs correct pattern. (" + paramCheck.pattern() + ")");
-            }
-        } else if (ParamType.BOOLEAN.equals(paramCheck.type())) {
-            if (!"true".equals(value) && !"false".equals(value)) {
-                throw new AtdsException("parameter %s is not a " + paramCheck.type());
-            }
-        } else if (isNumberType(paramCheck.type().name())) {
-            checkNumber(value, paramCheck);
-        }
-
-    }
-
-    /**
-     * 检查数字类型(BYTE/SHORT/INT/LONG/FLOAT/DOUBLE)以及字符类型的参数
-     * 包括 min/max
-     *
-     * @param value
-     * @param paramCheck
-     */
-    private void checkNumber(Object value, ParamCheck paramCheck) {
-        BigDecimal numberValue;
-        try {
-            String stringValue = value.toString();
-            if (ParamType.CHAR.equals(paramCheck.type())) {
-                if (stringValue.length() != 1) {
-                    throw new NumberFormatException();
-                }
-                numberValue = new BigDecimal(stringValue.toCharArray()[0]);
-            } else {
-                numberValue = new BigDecimal(stringValue);
-            }
-        } catch (NumberFormatException e) {
-            throw new AtdsException("parameter %s is not a " + paramCheck.type());
-        }
-        // 检查最大值
-        BigDecimal min = new BigDecimal(paramCheck.min());
-        if (numberValue.compareTo(min) < 0) {
-            throw new AtdsException("parameter %s is out of range. (min: " + paramCheck.min() + ")");
-        }
-        // 检查最小值
-        BigDecimal max = new BigDecimal(paramCheck.max());
-        if (numberValue.compareTo(max) > 0) {
-            throw new AtdsException("parameter %s is out of range. (max: " + paramCheck.max() + ")");
-        }
-    }
-
-}
+     */**
+       * @author : wangzhiyong
+       * @date : 2018/11/12 17:58
+       * description : 参数校验
+       */
+      @Aspect
+      @Component
+      public class ParamCheckAspect {
+      
+          private static final Logger logger = Logger.getLogger(ParamCheckAspect.class);
+      
+          //todo 暂时使用 方法扫描 以 O 结尾的方法 标识对外的接口 后期改为 @args
+      //    @Pointcut("@args(com.ys.atds.annotation.ParamCheck)")
+          @Pointcut("execution(* com.ys.*.api.impl..*.*O(..))")
+          public void paramPointcut() {
+          }
+      
+          @Before("paramPointcut()")
+          public void before(JoinPoint joinPoint) {
+              Object[] args = joinPoint.getArgs();
+              if (args == null || args.length == 0) {
+                  return;
+              }
+              // 方法的参数
+              Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterTypes();
+              for (int i = 0; i < parameterTypes.length; i++) {
+                  Class<?> parameterType = parameterTypes[i];
+                  // 若参数未注解ParamCheck, 忽略验证
+                  if (parameterType.getAnnotation(ParamCheck.class) == null) {
+                      continue;
+                  }
+                  // 传入的参数
+                  Object arg = args[i];
+                  if (arg == null) {
+                      throw new AtdsException("parameter should not be null or empty");
+                  }
+                  //获取所有变量
+                  List<Field> fieldList = new ArrayList<>();
+                  Class<?> argClass = arg.getClass();
+                  // 去重临时变量
+                  Set<String> temp = new HashSet<>();
+                  //当父类为null的时候说明到达了最上层的父类(Object类).
+                  while (argClass != null && !argClass.getName().toLowerCase().equals("java.lang.object")) {
+                      for (Field field : argClass.getDeclaredFields()) {
+                          if (!temp.contains(field.getName())) {
+                              fieldList.add(field);
+                              temp.add(field.getName());
+                          }
+                      }
+                      //得到父类,然后赋给自己
+                      argClass = argClass.getSuperclass();
+                  }
+                  // 获取注解
+                  for (Field field : fieldList) {
+                      // 获取注解
+                      ParamCheck annotationsByType = field.getAnnotation(ParamCheck.class);
+                      // 只检查@ParamCheck注解字段
+                      if (annotationsByType == null) {
+                          continue;
+                      }
+                      // 设置字段可访问并取值
+                      field.setAccessible(true);
+                      Object argValue = null;
+                      try {
+                          argValue = field.get(arg);
+                      } catch (IllegalAccessException e) {
+                          e.printStackTrace();
+                          logger.error("ParamCheckAspect: " + e.getMessage());
+                      }
+                      // 字段类型
+                      Class type = field.getType();
+                      // 字段为null或空string
+                      if (argValue == null || (String.class.equals(type) && "".equals(argValue))) {
+                          // 若注解声明非空, 抛出异常, 否则忽略本字段
+                          if (annotationsByType.require()) {
+                              throw new AtdsException("parameter " + field.getName() + " should not be null or empty");
+                          } else {
+                              continue;
+                          }
+                      }
+                      // 字段类型非数字 且非String, 忽略本字段, 不深入检查
+                      if (!isNumberType(type) && !String.class.equals(type)) {
+                          continue;
+                      }
+                      try {
+                          // 字段类型为 String 或 数字, 走各自验证
+                          if (String.class.equals(type)) {
+                              checkString(String.valueOf(argValue), annotationsByType);
+                          } else {
+                              checkNumber(argValue, annotationsByType);
+                          }
+                      } catch (AtdsException e) {
+                          throw new AtdsException(String.format(e.getMessage(), field.getName()));
+                      }
+                  }
+              }
+          }
+      
+          /**
+           * 是否数字类型
+           *
+           * @param type
+           * @return
+           */
+          private boolean isNumberType(Class type) {
+              return isNumberType(type.getSimpleName());
+          }
+      
+          /**
+           * 是否数字类型
+           *
+           * @param typeName
+           * @return
+           */
+          private boolean isNumberType(String typeName) {
+              if ("integer".equalsIgnoreCase(typeName) || ParamType.INT.name().equalsIgnoreCase(typeName)) {
+                  return true;
+              } else if ("long".equalsIgnoreCase(typeName) || ParamType.LONG.name().equalsIgnoreCase(typeName)) {
+                  return true;
+              } else if ("double".equalsIgnoreCase(typeName) || ParamType.DOUBLE.name().equalsIgnoreCase(typeName)) {
+                  return true;
+              } else if ("float".equalsIgnoreCase(typeName) || ParamType.FLOAT.name().equalsIgnoreCase(typeName)) {
+                  return true;
+              } else if ("byte".equalsIgnoreCase(typeName) || ParamType.BYTE.name().equalsIgnoreCase(typeName)) {
+                  return true;
+              } else if ("short".equalsIgnoreCase(typeName) || ParamType.SHORT.name().equalsIgnoreCase(typeName)) {
+                  return true;
+              } else if ("character".equalsIgnoreCase(typeName) || ParamType.CHAR.name().equalsIgnoreCase(typeName)) {
+                  return true;
+              }
+              return false;
+          }
+      
+          /**
+           * 检查String类型的参数
+           * 包括 size/根据 type 检查 min/max/pattern
+           *
+           * @param value
+           * @param paramCheck
+           */
+          private void checkString(String value, ParamCheck paramCheck) throws AtdsException {
+              // 检查长度
+              if (paramCheck.size() < value.length()) {
+                  throw new AtdsException("parameter %s is too long. (" + value.length() + " of " + paramCheck.size() + ")");
+              }
+              // 日期时
+              if (ParamType.DATE.equals(paramCheck.type())) {
+                  DateTimeFormatter formatter = DateTimeFormatter.ofPattern(paramCheck.pattern());
+                  try {
+                      formatter.parse(value);
+                  } catch (Exception e) {
+                      throw new AtdsException("parameter %s needs correct pattern. (" + paramCheck.pattern() + ")");
+                  }
+              } else if (ParamType.BOOLEAN.equals(paramCheck.type())) {
+                  if (!"true".equals(value) && !"false".equals(value)) {
+                      throw new AtdsException("parameter %s is not a " + paramCheck.type());
+                  }
+              } else if (isNumberType(paramCheck.type().name())) {
+                  checkNumber(value, paramCheck);
+              }
+      
+          }
+      
+          /**
+           * 检查数字类型(BYTE/SHORT/INT/LONG/FLOAT/DOUBLE)以及字符类型的参数
+           * 包括 min/max
+           *
+           * @param value
+           * @param paramCheck
+           */
+          private void checkNumber(Object value, ParamCheck paramCheck) {
+              BigDecimal numberValue;
+              try {
+                  String stringValue = value.toString();
+                  if (ParamType.CHAR.equals(paramCheck.type())) {
+                      if (stringValue.length() != 1) {
+                          throw new NumberFormatException();
+                      }
+                      numberValue = new BigDecimal(stringValue.toCharArray()[0]);
+                  } else {
+                      numberValue = new BigDecimal(stringValue);
+                  }
+              } catch (NumberFormatException e) {
+                  throw new AtdsException("parameter %s is not a " + paramCheck.type());
+              }
+              // 检查最大值
+              BigDecimal min = new BigDecimal(paramCheck.min());
+              if (numberValue.compareTo(min) < 0) {
+                  throw new AtdsException("parameter %s is out of range. (min: " + paramCheck.min() + ")");
+              }
+              // 检查最小值
+              BigDecimal max = new BigDecimal(paramCheck.max());
+              if (numberValue.compareTo(max) > 0) {
+                  throw new AtdsException("parameter %s is out of range. (max: " + paramCheck.max() + ")");
+              }
+          }
+      
+      }
 ```