springboot利用aop切面实现自定义注解-校验入参

1.先定义一个接口类

springboot利用aop切面实现自定义注解-校验入参

2.接口类具体实现

@Aspect
@Component
public class Checker {
    private static final Logger log = LoggerFactory.getLogger(Checker.class);

    private static final String SPLITTER = ":";
    private ExpressionParser parser = new SpelExpressionParser();
    private LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
    private Function<String, Object> unsuccess;


    private Checker() {

    }

    /**
     * Action performed when check fails
     *
     * @param unsuccess lambda of the action
     */

    public void setUnsuccess(Function<String, Object> unsuccess) {

        this.unsuccess = unsuccess;

    }


    /**
     * checker builder
     */

    public static class Builder {

        private Checker checker = new Checker();


        public Builder unsuccess(Function<String, Object> unsuccess) {

            checker.setUnsuccess(unsuccess);

            return this;

        }


        public Checker build() {

            return checker;

        }

    }


    /**
     * initialize builder
     *
     * @return checker builder
     * @see Builder
     */

    public static Builder builder() {

        return new Builder();

    }


    /**
     * aop around the method
     *
     * @param point ProceedingJoinPoint
     * @return method result
     * @throws Throwable method exception
     */

    @Around(value = "@annotation(com.zhuanzhuan.c2b_offline_recovery.annotion.check.Check)")
    public Object check(ProceedingJoinPoint point) throws Throwable {

        Object obj;

        // check param

        String msg = doCheck(point);

        if (!StringUtils.isEmpty(msg)) {

            return ScfBaseResult.buildError(ParamConstant.REQUEST_PARAM_NULL.getCode(), msg);

        }

        obj = point.proceed();

        return obj;

    }


    /**
     * check param
     *
     * @param point ProceedingJoinPoint
     * @return error message
     */

    private String doCheck(ProceedingJoinPoint point) {

        // get arguments

        Object[] arguments = point.getArgs();

        // get method

        Method method = getMethod(point);

        String methodInfo = StringUtils.isEmpty(method.getName()) ? "" : " while calling " + method.getName();

        String msg = "";

        if (isCheck(method, arguments)) {

            Check annotation = method.getAnnotation(Check.class);

            String[] fields = annotation.value();

            Object vo = arguments[0];

            if (vo == null) {

                msg = "param can not be null";

            } else {

                for (String field : fields) {
                    //字段解析
                    FieldInfo info = resolveField(field, methodInfo);

                    Boolean isValid;

                    if (info.optEnum == Operator.SPEL) {

                        isValid = parseSpel(method, arguments, info.field);

                    } else {

                        String getMethodName = "get" + StringUtils.capitalize(info.field);

                        Method getMethod = ReflectionUtils.findMethod(vo.getClass(), getMethodName);
                        // 获取字段的值
                        Object value = ReflectionUtils.invokeMethod(getMethod, vo);

                        isValid = info.optEnum.fun.apply(value, info.operatorNum);

                    }

                    if (!isValid) {

                        msg = info.innerMsg;

                        break;

                    }

                }

            }

        }

        return msg;

    }


    /**
     * parse spel expression
     *
     * @param method    method
     * @param arguments arguments
     * @param spel      spel expression
     * @return is match
     */

    private Boolean parseSpel(Method method, Object[] arguments, String spel) {

        String[] params = discoverer.getParameterNames(method);

        EvaluationContext context = new StandardEvaluationContext();

        for (int len = 0; len < params.length; len++) {

            context.setVariable(params[len], arguments[len]);

        }

        try {

            Expression expression = parser.parseExpression(spel);

            return expression.getValue(context, Boolean.class);

        } catch (Exception e) {

            log.error("", e);

            return Boolean.FALSE;

        }

    }


    /**
     * parse field
     *
     * @param fieldStr   field string
     * @param methodInfo method info
     * @return the entity contain field's info
     */

    private FieldInfo resolveField(String fieldStr, String methodInfo) {

        FieldInfo fieldInfo = new FieldInfo();

        String innerMsg = "";

        // parse error message

        if (fieldStr.contains(SPLITTER)) {

            if (fieldStr.split(SPLITTER).length == 2) {

                innerMsg = fieldStr.split(SPLITTER)[1].trim();

                fieldStr = fieldStr.split(SPLITTER)[0].trim();

            } else {

                throw new IllegalArgumentException("@Check annotation error: " + fieldStr);

            }

        }

        // parse operator

        if (fieldStr.startsWith("#")) {

            fieldInfo.optEnum = Operator.SPEL;

        } else if (fieldStr.contains(Operator.GREATER_THAN_EQUAL.value)) {

            fieldInfo.optEnum = Operator.GREATER_THAN_EQUAL;

        } else if (fieldStr.contains(Operator.LESS_THAN_EQUAL.value)) {

            fieldInfo.optEnum = Operator.LESS_THAN_EQUAL;

        } else if (fieldStr.contains(Operator.GREATER_THAN.value)) {

            fieldInfo.optEnum = Operator.GREATER_THAN;

        } else if (fieldStr.contains(Operator.LESS_THAN.value)) {

            fieldInfo.optEnum = Operator.LESS_THAN;

        } else if (fieldStr.contains(Operator.NOT_EQUAL.value)) {

            fieldInfo.optEnum = Operator.NOT_EQUAL;

        } else {

            fieldInfo.optEnum = Operator.NOT_NULL;

        }

        // direct assignment field

        if (fieldInfo.optEnum == Operator.NOT_NULL || fieldInfo.optEnum == Operator.SPEL) {

            fieldInfo.field = fieldStr;

        }

        // other operators, need to separate fields and operands

        else {

            fieldInfo.field = fieldStr.split(fieldInfo.optEnum.value)[0];

            fieldInfo.operatorNum = fieldStr.split(fieldInfo.optEnum.value)[1];

        }

        fieldInfo.operator = fieldInfo.optEnum.value;

        String operatorNum = fieldInfo.operatorNum == null ? "" : " " + fieldInfo.operatorNum;

        String defaultMsg = fieldInfo.field + " must " + fieldInfo.operator + operatorNum + methodInfo;

        fieldInfo.innerMsg = StringUtils.isEmpty(innerMsg) ? defaultMsg : innerMsg;

        return fieldInfo;

    }


    /**
     * is not null
     *
     * @param value       field's value
     * @param operatorNum the num of operator
     * @return is not null
     */

    private static Boolean isNotNull(Object value, String operatorNum) {

        Boolean isNotNull = Boolean.TRUE;

        Boolean isStringNull = (value instanceof String) && StringUtils.isEmpty((CharSequence) value);

        Boolean isCollectionNull = (value instanceof Collection) && CollectionUtils.isEmpty((Collection) value);

        if (value == null) {

            isNotNull = Boolean.FALSE;

        } else if (isStringNull || isCollectionNull) {

            isNotNull = Boolean.FALSE;

        }

        return isNotNull;

    }


    /**
     * is greater than
     *
     * @param value       field value
     * @param operatorNum operatorNum
     * @return is greater than
     */

    private static Boolean isGreaterThan(Object value, String operatorNum) {

        Boolean isGreaterThan = Boolean.FALSE;

        if (value == null) {

            return Boolean.FALSE;

        }

        boolean isStringGreaterThen = (value instanceof String) && ((String) value).length() > Integer.parseInt(operatorNum);

        boolean isLongGreaterThen = (value instanceof Long) && ((Long) value) > Long.parseLong(operatorNum);

        boolean isIntegerGreaterThen = (value instanceof Integer) && ((Integer) value) > Integer.parseInt(operatorNum);

        boolean isShortGreaterThen = (value instanceof Short) && ((Short) value) > Short.parseShort(operatorNum);

        boolean isFloatGreaterThen = (value instanceof Float) && ((Float) value) > Float.parseFloat(operatorNum);

        boolean isDoubleGreaterThen = (value instanceof Double) && ((Double) value) > Double.parseDouble(operatorNum);

        boolean isCollectionGreaterThen = (value instanceof Collection) && ((Collection) value).size() > Integer.parseInt(operatorNum);

        if (isStringGreaterThen || isLongGreaterThen || isIntegerGreaterThen ||

                isShortGreaterThen || isFloatGreaterThen || isDoubleGreaterThen || isCollectionGreaterThen) {

            isGreaterThan = Boolean.TRUE;

        }

        return isGreaterThan;

    }


    /**
     * is greater than or equal to
     *
     * @param value       field value
     * @param operatorNum operatorNum
     * @return is greater than or equal to
     */

    private static Boolean isGreaterThanEqual(Object value, String operatorNum) {

        Boolean isGreaterThanEqual = Boolean.FALSE;

        if (value == null) {

            return Boolean.FALSE;

        }

        boolean isStringGreaterThenEqual = (value instanceof String) && ((String) value).length() >= Integer.parseInt(operatorNum);

        boolean isLongGreaterThenEqual = (value instanceof Long) && ((Long) value) >= Long.parseLong(operatorNum);

        boolean isIntegerGreaterThenEqual = (value instanceof Integer) && ((Integer) value) >= Integer.parseInt(operatorNum);

        boolean isShortGreaterThenEqual = (value instanceof Short) && ((Short) value) >= Short.parseShort(operatorNum);

        boolean isFloatGreaterThenEqual = (value instanceof Float) && ((Float) value) >= Float.parseFloat(operatorNum);

        boolean isDoubleGreaterThenEqual = (value instanceof Double) && ((Double) value) >= Double.parseDouble(operatorNum);

        boolean isCollectionGreaterThenEqual = (value instanceof Collection) && ((Collection) value).size() >= Integer.parseInt(operatorNum);

        if (isStringGreaterThenEqual || isLongGreaterThenEqual || isIntegerGreaterThenEqual ||

                isShortGreaterThenEqual || isFloatGreaterThenEqual || isDoubleGreaterThenEqual || isCollectionGreaterThenEqual) {

            isGreaterThanEqual = Boolean.TRUE;

        }

        return isGreaterThanEqual;

    }


    /**
     * is less than
     *
     * @param value       field value
     * @param operatorNum operatorNum
     * @return is less than
     */

    private static Boolean isLessThan(Object value, String operatorNum) {

        Boolean isLessThan = Boolean.FALSE;

        if (value == null) {

            return Boolean.FALSE;

        }

        boolean isStringLessThen = (value instanceof String) && ((String) value).length() < Integer.parseInt(operatorNum);

        boolean isLongLessThen = (value instanceof Long) && ((Long) value) < Long.parseLong(operatorNum);

        boolean isIntegerLessThen = (value instanceof Integer) && ((Integer) value) < Integer.parseInt(operatorNum);

        boolean isShortLessThen = (value instanceof Short) && ((Short) value) < Short.parseShort(operatorNum);

        boolean isFloatLessThen = (value instanceof Float) && ((Float) value) < Float.parseFloat(operatorNum);

        boolean isDoubleLessThen = (value instanceof Double) && ((Double) value) < Double.parseDouble(operatorNum);

        boolean isCollectionLessThen = (value instanceof Collection) && ((Collection) value).size() < Integer.parseInt(operatorNum);

        if (isStringLessThen || isLongLessThen || isIntegerLessThen ||

                isShortLessThen || isFloatLessThen || isDoubleLessThen || isCollectionLessThen) {

            isLessThan = Boolean.TRUE;

        }

        return isLessThan;

    }


    /**
     * is less than or equal to
     *
     * @param value       field value
     * @param operatorNum operatorNum
     * @return is less than or equal to
     */

    private static Boolean isLessThanEqual(Object value, String operatorNum) {

        Boolean isLessThanEqual = Boolean.FALSE;

        if (value == null) {

            return Boolean.FALSE;

        }

        boolean isStringLessThenEqual = (value instanceof String) && ((String) value).length() <= Integer.parseInt(operatorNum);

        boolean isLongLessThenEqual = (value instanceof Long) && ((Long) value) <= Long.parseLong(operatorNum);

        boolean isIntegerLessThenEqual = (value instanceof Integer) && ((Integer) value) <= Integer.parseInt(operatorNum);

        boolean isShortLessThenEqual = (value instanceof Short) && ((Short) value) <= Short.parseShort(operatorNum);

        boolean isFloatLessThenEqual = (value instanceof Float) && ((Float) value) <= Float.parseFloat(operatorNum);

        boolean isDoubleLessThenEqual = (value instanceof Double) && ((Double) value) <= Double.parseDouble(operatorNum);

        boolean isCollectionLessThenEqual = (value instanceof Collection) && ((Collection) value).size() <= Integer.parseInt(operatorNum);

        if (isStringLessThenEqual || isLongLessThenEqual || isIntegerLessThenEqual ||

                isShortLessThenEqual || isFloatLessThenEqual || isDoubleLessThenEqual || isCollectionLessThenEqual) {

            isLessThanEqual = Boolean.TRUE;

        }

        return isLessThanEqual;

    }


    /**
     * is not equal
     *
     * @param value       field value
     * @param operatorNum String
     * @return is not equal
     */

    private static Boolean isNotEqual(Object value, String operatorNum) {

        Boolean isNotEqual = Boolean.FALSE;

        if (value == null) {

            return Boolean.FALSE;

        }

        boolean isStringNotEqual = (value instanceof String) && !value.equals(operatorNum);

        boolean isLongNotEqual = (value instanceof Long) && !value.equals(Long.valueOf(operatorNum));

        boolean isIntegerNotEqual = (value instanceof Integer) && !value.equals(Integer.valueOf(operatorNum));

        boolean isShortNotEqual = (value instanceof Short) && !value.equals(Short.valueOf(operatorNum));

        boolean isFloatNotEqual = (value instanceof Float) && !value.equals(Float.valueOf(operatorNum));

        boolean isDoubleNotEqual = (value instanceof Double) && !value.equals(Double.valueOf(operatorNum));

        boolean isCollectionNotEqual = (value instanceof Collection) && ((Collection) value).size() != Integer.parseInt(operatorNum);

        if (isStringNotEqual || isLongNotEqual || isIntegerNotEqual ||

                isShortNotEqual || isFloatNotEqual || isDoubleNotEqual || isCollectionNotEqual) {

            isNotEqual = Boolean.TRUE;

        }

        return isNotEqual;

    }


    /**
     * is meets the parameter rules
     *
     * @param method    method
     * @param arguments arguments
     * @return is meets
     */

    private Boolean isCheck(Method method, Object[] arguments) {

        Boolean isCheck = Boolean.TRUE;

        if (!method.isAnnotationPresent(Check.class) || arguments == null) {

            isCheck = Boolean.FALSE;

        }

        return isCheck;

    }


    /**
     * get the method
     *
     * @param joinPoint ProceedingJoinPoint
     * @return method
     */

    private Method getMethod(ProceedingJoinPoint joinPoint) {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        Method method = signature.getMethod();

        if (method.getDeclaringClass().isInterface()) {

            try {

                method = joinPoint

                        .getTarget()

                        .getClass()

                        .getDeclaredMethod(joinPoint.getSignature().getName(), method.getParameterTypes());

            } catch (SecurityException | NoSuchMethodException e) {

                log.error("" + e);

            }

        }

        return method;

    }


    /**
     * file info
     */

    static class FieldInfo {

        /**
         * field
         */

        String field;

        /**
         * prompt message
         */

        String innerMsg;

        /**
         * operator
         */

        String operator;

        /**
         * num of operator
         */

        String operatorNum;

        /**
         * enum of operator
         */

        Operator optEnum;

    }


    /**
     * enum of operator
     */

    enum Operator {

        /**
         * spel expression
         */

        SPEL("match spel expression", null),

        /**
         * GreaterThan
         */

        GREATER_THAN(">", Checker::isGreaterThan),

        /**
         * GreaterThanEqual
         */

        GREATER_THAN_EQUAL(">=", Checker::isGreaterThanEqual),

        /**
         * LessThan
         */

        LESS_THAN("<", Checker::isLessThan),

        /**
         * LessThanEqual
         */

        LESS_THAN_EQUAL("<=", Checker::isLessThanEqual),

        /**
         * NotEqual
         */

        NOT_EQUAL("!=", Checker::isNotEqual),

        /**
         * NotNull
         */

        NOT_NULL("not null", Checker::isNotNull);


        private String value;

        private BiFunction<Object, String, Boolean> fun;


        Operator(String value, BiFunction<Object, String, Boolean> fun) {

            this.value = value;

            this.fun = fun;

        }

    }

}

3.使用

springboot利用aop切面实现自定义注解-校验入参

备注:

优点:可以校验参数是否为空,参数大小校验,参数非等校验

缺点:多个参数需要使用bean去放参数

 

上一篇:javascript的哲学,Function构造函数的神奇之处!我生了我!


下一篇:Java编程中数据库中取出的值判断