阿里P8架构师教你kill祖传石山代码重复/大量ifelse( 三 )
通过注解实现了对API参数的描述 。 看反射如何配合注解实现动态的接口参数组装:
【阿里P8架构师教你kill祖传石山代码重复/大量ifelse】private static String remoteCall(AbstractAPI api) throws IOException {// 从类上获得BankAPI注解 , 然后拿到其URL属性 , 后续进行远程调用BankAPI bankAPI = api.getClass().getAnnotation(BankAPI.class);bankAPI.url();StringBuilder stringBuilder = new StringBuilder();// 使用stream快速实现获取类中所有带BankAPIField注解的字段 , 并把字段按order属性排序 , 然后设置私有字段反射可访问 。Arrays.stream(api.getClass().getDeclaredFields()) //获得所有字段//查找标记了注解的字段.filter(field -> field.isAnnotationPresent(BankAPIField.class))// 根据注解中的order对字段排序.sorted(Comparator.comparingInt(a -> a.getAnnotation(BankAPIField.class).order())).peek(field -> field.setAccessible(true)) //设置可以访问私有字段.forEach(field -> {// 实现了反射获取注解的值 , 然后根据BankAPIField拿到的参数类型 , 按照三种标准进行格式化 , 将所有参数的格式化逻辑集中在了这一处// 获得注解BankAPIField bankAPIField = field.getAnnotation(BankAPIField.class);Object valuehttp://kandian.youth.cn/index/= "";try {// 反射获取字段值value = http://kandian.youth.cn/index/field.get(api);} catch (IllegalAccessException e) {e.printStackTrace();}// 根据字段类型以正确的填充方式格式化字符串switch (bankAPIField.type()) {case"S": {stringBuilder.append(String.format("%-" + bankAPIField.length() + "s", value.toString()).replace(' ', '_'));break;}case "N": {stringBuilder.append(String.format("%" + bankAPIField.length() + "s", value.toString()).replace(' ', '0'));break;}case "M": {if (!(value instanceof BigDecimal))throw new RuntimeException(String.format("{} 的 {} 必须是BigDecimal", api, field));stringBuilder.append(String.format("%0" + bankAPIField.length() + "d", ((BigDecimal) value).setScale(2, RoundingMode.DOWN).multiply(new BigDecimal("100")).longValue()));break;}default:break;}});// 实现参数加签和请求调用// 签名逻辑stringBuilder.append(DigestUtils.md2Hex(stringBuilder.toString()));String param = stringBuilder.toString();long begin = System.currentTimeMillis();//发请求String result = Request.Post("http://localhost:45678/reflection" + bankAPI.url()).bodyString(param, ContentType.APPLICATION_JSON).execute().returnContent().asString();log.info("调用银行API {} url:{} 参数:{} 耗时:{}ms", bankAPI.desc(), bankAPI.url(), param, System.currentTimeMillis() - begin);return result;}
所有处理参数排序、填充、加签、请求调用的核心逻辑 , 都汇聚在remoteCall 。 有这方法 , BankService中每一个接口的实现就非常简单了 , 只是参数的组装 , 然后调用remoteCall 。
文章插图
涉及类结构性的通用处理 , 都可按照该模式减少重复代码 。
- 反射使得我们在不知类结构时 , 按固定逻辑处理类成员
- 注解给我们为这些成员补充元数据的能力 , 使得我们利用反射实现通用逻辑的时候 , 可以从外部获得更多我们关心的数据
ComplicatedOrderDTO orderDTO = new ComplicatedOrderDTO();ComplicatedOrderDO orderDO = new ComplicatedOrderDO();orderDO.setAcceptDate(orderDTO.getAcceptDate());orderDO.setAddress(orderDTO.getAddress());orderDO.setAddressId(orderDTO.getAddressId());orderDO.setCancelable(orderDTO.isCancelable());orderDO.setCommentable(orderDTO.isComplainable()); //属性错误orderDO.setComplainable(orderDTO.isCommentable()); //属性错误orderDO.setCancelable(orderDTO.isCancelable());orderDO.setCouponAmount(orderDTO.getCouponAmount());orderDO.setCouponId(orderDTO.getCouponId());orderDO.setCreateDate(orderDTO.getCreateDate());orderDO.setDirectCancelable(orderDTO.isDirectCancelable());orderDO.setDeliverDate(orderDTO.getDeliverDate());orderDO.setDeliverGroup(orderDTO.getDeliverGroup());orderDO.setDeliverGroupOrderStatus(orderDTO.getDeliverGroupOrderStatus());orderDO.setDeliverMethod(orderDTO.getDeliverMethod());orderDO.setDeliverPrice(orderDTO.getDeliverPrice());orderDO.setDeliveryManId(orderDTO.getDeliveryManId());orderDO.setDeliveryManMobile(orderDO.getDeliveryManMobile()); //对象错误orderDO.setDeliveryManName(orderDTO.getDeliveryManName());orderDO.setDistance(orderDTO.getDistance());orderDO.setExpectDate(orderDTO.getExpectDate());orderDO.setFirstDeal(orderDTO.isFirstDeal());orderDO.setHasPaid(orderDTO.isHasPaid());orderDO.setHeadPic(orderDTO.getHeadPic());orderDO.setLongitude(orderDTO.getLongitude());orderDO.setLatitude(orderDTO.getLongitude()); //属性赋值错误orderDO.setMerchantAddress(orderDTO.getMerchantAddress());orderDO.setMerchantHeadPic(orderDTO.getMerchantHeadPic());orderDO.setMerchantId(orderDTO.getMerchantId());orderDO.setMerchantAddress(orderDTO.getMerchantAddress());orderDO.setMerchantName(orderDTO.getMerchantName());orderDO.setMerchantPhone(orderDTO.getMerchantPhone());orderDO.setOrderNo(orderDTO.getOrderNo());orderDO.setOutDate(orderDTO.getOutDate());orderDO.setPayable(orderDTO.isPayable());orderDO.setPaymentAmount(orderDTO.getPaymentAmount());orderDO.setPaymentDate(orderDTO.getPaymentDate());orderDO.setPaymentMethod(orderDTO.getPaymentMethod());orderDO.setPaymentTimeLimit(orderDTO.getPaymentTimeLimit());orderDO.setPhone(orderDTO.getPhone());orderDO.setRefundable(orderDTO.isRefundable());orderDO.setRemark(orderDTO.getRemark());orderDO.setStatus(orderDTO.getStatus());orderDO.setTotalQuantity(orderDTO.getTotalQuantity());orderDO.setUpdateTime(orderDTO.getUpdateTime());orderDO.setName(orderDTO.getName());orderDO.setUid(orderDTO.getUid());
- 王兴称美团优选目前重点是建设核心能力;苏宁旗下云网万店融资60亿元;阿里小米拟增资居然之家|8点1氪 | 美团
- 注册|阿里申请注册“爆改吧!小店”商标,打造线下特色实体小店
- 耽误|被阿里耽误的虾米的一生
- 租赁物业|居然之家(000785)牵手阿里与小米
- IT|信服云为IT基础架构演进提供新思路
- 上市公司|数字化新外贸成为企业巨头新选择 近百家上市公司入驻阿里国际站
- 字节|阿里巴巴、字节跳动、花生日记获“互联网行业公益奖”
- 青山湖|阿里人均年薪百万?95后阿里单身狗陪跑摇号近2年 连青山湖都抛弃他?
- 告诉|阿里大佬告诉你如何一分钟利用Python在家告别会员看电影
- 电商|又一家电商平台倒下惨遭阿里抛弃,负债23亿进入破产重组