1. 程式人生 > >必填引數統一處理

必填引數統一處理

1. 必填引數統一處理

1.1. 需求

  1. 專案使用交易程式碼的形式,反射呼叫執行類,統一入口和出口類,相當於直接呼叫服務層,例如:
 /**
  * 獲取訂單詳情3003101009
  */
 ResponseReport getOrderDetail(RequestReport requestReport);
  1. 我們知道如果後臺呼叫入口在Controller,且入口引數靈活填寫,那麼可以使用SpringMVC自帶的引數驗證方式,通過註解如@NotNull @Size等來限制入參,錯誤直接返回
  2. 現在我呼叫入口引數統一了,也不在controller層,但要實現相同的功能,也就是引數驗證,特別是必填項

1.2. 解決

1.2.1. 服務層

  1. 我的想法同樣是通過註解來解決,只是註解的實現方法需要自己實現
  2. 通過aop切服務層固定入參列表的方法,判斷是否存在註解
@Override
@CheckUnfilled(value={"order_id"})
public ResponseReport getOrderDetail(RequestReport requestReport) {
    ResponseReport responseReport = new ResponseReport();
    Map<String, Object> reqParams = JSON.parseObject(requestReport.getBody().toString(), Map.class);
    Object id = reqParams.get("order_id");
    String orderId = id.toString();
    OrderInfo orderInfo = orderInfoExtDao.selectByPrimaryKey(orderId);
    OrderInfoExt orderInfoExt = new OrderInfoExt();
    orderInfoExt.setAddress(orderInfo.getHospital() + " " + orderInfo.getBed());
    BeanUtils.copyProperties(orderInfo, orderInfoExt);
    return responseReport.returnSuccessResult(orderInfoExt, "獲取訂單詳情成功", requestReport);
}

1.2.2. 註解方法

/**
 * @author laoliangliang
 * @date 2019/1/10 16:57
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckUnfilled {
    String[] value() default {};
}

1.2.3. 註解實現aop

package com.zhiyis.framework.aop;

import com.alibaba.fastjson.JSON;
import com.zhiyis.common.report.RequestReport;
import com.zhiyis.common.report.ResponseReport;
import com.zhiyis.framework.annotation.CheckUnfilled;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author laoliangliang
 * @date 2019/1/10 17:04
 */
@Slf4j
@Component
@Aspect
public class CheckUnfilledAspect {

    @Around("execution(com.zhiyis.common.report.ResponseReport com.zhiyis.framework.service.impl..*.*(com.zhiyis.common.report.RequestReport))")
    public Object checkUnfilled(ProceedingJoinPoint joinPoint) {
        Object clazz = joinPoint.getTarget();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        RequestReport requestReport = (RequestReport) args[0];
        Map<String, Object> reqParams = JSON.parseObject(JSON.toJSONString(requestReport.getBody()), Map.class);

        Method method = ReflectionUtils.findMethod(clazz.getClass(), methodName, RequestReport.class);

        CheckUnfilled annotation = AnnotationUtils.findAnnotation(method, CheckUnfilled.class);
        if(annotation != null){
            String[] value = annotation.value();
            Set<String> keys = reqParams.keySet();
            Set<String> unfilledSet = new HashSet<>();
            for (String key : value) {
                if (!keys.contains(key)) {
                    unfilledSet.add(key);
                }
            }
            if (unfilledSet.size() > 0) {
                ResponseReport responseReport = new ResponseReport();
                return responseReport.returnError("9999", JSON.toJSONString(unfilledSet) + "為必填引數");
            }
        }
        try {
            return joinPoint.proceed();
        } catch (Throwable e) {
            log.error("tradeCode介面錯誤", e);
        }
        return null;
    }


}

1.3. 測試

  1. 帶orderId引數

  2. 不帶orderId引數

  3. 上述介面只為測試所寫,這種沒有任何驗證的在正式環境存在開關關閉執行