必填引數統一處理
阿新 • • 發佈:2019-01-10
1. 必填引數統一處理
1.1. 需求
- 專案使用交易程式碼的形式,反射呼叫執行類,統一入口和出口類,相當於直接呼叫服務層,例如:
/**
* 獲取訂單詳情3003101009
*/
ResponseReport getOrderDetail(RequestReport requestReport);
- 我們知道如果後臺呼叫入口在Controller,且入口引數靈活填寫,那麼可以使用SpringMVC自帶的引數驗證方式,通過註解如@NotNull @Size等來限制入參,錯誤直接返回
- 現在我呼叫入口引數統一了,也不在controller層,但要實現相同的功能,也就是引數驗證,特別是必填項
1.2. 解決
1.2.1. 服務層
- 我的想法同樣是通過註解來解決,只是註解的實現方法需要自己實現
- 通過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. 測試
帶orderId引數
不帶orderId引數
上述介面只為測試所寫,這種沒有任何驗證的在正式環境存在開關關閉執行