首页 > 其他分享 >springBoot + 工厂模式 实现 快递鸟、顺丰和快递100的物流查询

springBoot + 工厂模式 实现 快递鸟、顺丰和快递100的物流查询

时间:2023-11-25 21:33:05浏览次数:40  
标签:API springBoot 快递 ExpressInfo new 100 expressInfo String

前言:

在Spring Boot中实现快递鸟、顺丰和快递100的物流查询功能通常需要与它们提供的API进行交互。当然使用他们的API 我们是需要申请和注册,从而去拿到 key 来进行调用。所以为注册的必须先进行注册,以下是他们的官网地址,可以快捷到达。

快递鸟官网:快递鸟 - 快递查询接口_免费快递查询api接口 (kdniao.com)

顺丰快递官网:顺丰开放平台 (sf-express.com) 接口名为:物流轨迹查询接口

快递100官网:快递物流接口文档_电子面单接口文档_快递100api接口文档 (kuaidi100.com)

为了实现这一功能,可以创建一个工厂类,用于封装不同快递查询服务的逻辑,并为每个服务创建一个实现类。以下是一个简单的示例,演示如何在Spring Boot中创建这些类和实现快递查询功能。

1. 创建工厂类

首先,创建一个工厂类,该类根据不同的快递服务创建对应的查询实例。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ExpressServiceFactory {

    private final Kuaidi100Service kuaidi100Service;
    private final KdniaoService kdniaoService;
    private final ShunfengService shunfengService;

    @Autowired
    public ExpressServiceFactory(Kuaidi100Service kuaidi100Service, KdniaoService kdniaoService, ShunfengService shunfengService) {
        this.kuaidi100Service = kuaidi100Service;
        this.kdniaoService = kdniaoService;
        this.shunfengService = shunfengService;
    }

    public ExpressService getExpressService(String provider) {
        switch (provider) {
            case "kuaidi100":
                return kuaidi100Service;
            case "kdniao":
                return kdniaoService;
            case "shunfeng":
                return shunfengService;
            default:
                throw new IllegalArgumentException("Invalid provider: " + provider);
        }
    }
}

2. 创建接口和实现类

接下来,为每个快递服务创建一个接口和实现类,分别实现快递查询的逻辑。以下是示例代码:

快递100 (Kuaidi100)

import org.springframework.stereotype.Service;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Map;

@Service
public class Kuaidi100Service implements ExpressService {
    
    @Autowired
    private RestTemplate restTemplate;

    @Override
    public ExpressInfo queryExpress(String trackingNumber) {
        // 调用Kuaidi100的API,查询物流信息
        // 以下是伪代码,实际中需要调用Kuaidi100的API并解析返回的数据
        String apiUrl = "https://api.kuaidi100.com/query";
        String apiKey = "your_api_key";
        
        // 构建请求参数
        Map<String, String> params = new HashMap<>();
        params.put("com", "your_com_code");  // 快递公司编码
        params.put("num", trackingNumber);   // 快递单号
        params.put("key", apiKey);           // API密钥,可以使用@Vaer注解配置在yaml
        
        // 发送HTTP请求并获取响应
        ResponseEntity<String> response = restTemplate.getForEntity(apiUrl, String.class, params);
        
        if (response.getStatusCode() == HttpStatus.OK) {
            // 解析返回的JSON数据,构建ExpressInfo对象
            String responseBody = response.getBody();
            ExpressInfo expressInfo = parseKuaidi100Response(responseBody);
            return expressInfo;
        } else {
            throw new RuntimeException("Failed to query Kuaidi100: " + response.getStatusCode());
        }
    }

    private ExpressInfo parseKuaidi100Response(String responseBody) {
        // 解析Kuaidi100返回的JSON数据并构建ExpressInfo对象的逻辑
        // 以下是示例代码,实际中需要根据API返回的数据结构进行解析
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            Kuaidi100Response kuaidi100Response = objectMapper.readValue(responseBody, Kuaidi100Response.class);
            ExpressInfo expressInfo = new ExpressInfo();
            expressInfo.setTrackingNumber(kuaidi100Response.getTrackingNumber());
            expressInfo.setLogisticsStatus(kuaidi100Response.getLogisticsStatus());
            expressInfo.setLogisticsDetail(kuaidi100Response.getLogisticsDetail());
            return expressInfo;
        } catch (IOException e) {
            throw new RuntimeException("Failed to parse Kuaidi100 response", e);
        }
    }
}

快递鸟 (Kdniao)

import org.springframework.stereotype.Service;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MultiValueMap;

@Service
public class KdniaoService implements ExpressService {

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public ExpressInfo queryExpress(String trackingNumber) {
        // 调用快递鸟的API,查询物流信息
        // 以下是伪代码,实际中需要调用Kdniao的API并解析返回的数据
        String apiUrl = "https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";
        String apiKey = "your_api_key";

        // 构建请求参数
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("ShipperCode", "your_shipper_code");  // 快递公司编码
        params.add("LogisticCode", trackingNumber);       // 快递单号
        params.add("RequestType", "1002");               // 查询方式
        params.add("apiKey", apiKey);

        // 发送HTTP请求并获取响应
        ResponseEntity<String> response = restTemplate.postForEntity(apiUrl, params, String.class);

        if (response.getStatusCode() == HttpStatus.OK) {
            // 解析返回的XML数据,构建ExpressInfo对象
            String responseBody = response.getBody();
            ExpressInfo expressInfo = parseKdniaoResponse(responseBody);
            return expressInfo;
        } else {
            throw new RuntimeException("Failed to query Kdniao: " + response.getStatusCode());
        }
    }

    private ExpressInfo parseKdniaoResponse(String responseBody) {
        // 解析Kdniao返回的XML数据并构建ExpressInfo对象的逻辑
        // 以下是示例代码,实际中需要根据API返回的数据结构进行解析
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
        Document doc;

        try {
            builder = factory.newDocumentBuilder();
            doc = builder.parse(new InputSource(new StringReader(responseBody)));
        } catch (Exception e) {
            throw new RuntimeException("Failed to parse Kdniao response", e);
        }

        // 解析XML数据并构建ExpressInfo对象
        ExpressInfo expressInfo = new ExpressInfo();
        // 根据XML结构解析数据并设置到ExpressInfo对象中
        return expressInfo;
    }
}

顺丰 (Shunfeng)

import org.springframework.stereotype.Service;

@Service
public class ShunfengService implements ExpressService {

    @Override
    public ExpressInfo queryExpress(String trackingNumber) {
        // 调用顺丰的API,查询物流信息
        // 以下是伪代码,实际中需要调用顺丰的API并解析返回的数据
        String apiUrl = "https://api.sf-express.com/std/service";
        String apiKey = "your_api_key";
        
        // 构建请求参数
        Map<String, Object> params = new HashMap<>();
        params.put("tracking_number", trackingNumber);
        params.put("api_key", apiKey);
        
        // 发送HTTP请求并获取响应
        ResponseEntity<String> response = restTemplate.postForEntity(apiUrl, params, String.class);
        
        if (response.getStatusCode() == HttpStatus.OK) {
            // 解析返回的JSON数据,构建ExpressInfo对象
            String responseBody = response.getBody();
            // 解析JSON数据并构建ExpressInfo对象
            ExpressInfo expressInfo = parseShunfengResponse(responseBody);
            return expressInfo;
        } else {
            throw new RuntimeException("Failed to query Shunfeng: " + response.getStatusCode());
        }
    }

    private ExpressInfo parseShunfengResponse(String responseBody) {
        // 解析顺丰API响应的JSON数据
        try {
            // 解析JSON数据,具体字段和格式需要根据顺丰API文档来定义
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode root = objectMapper.readTree(responseBody);

            // 检查响应状态
            String status = root.get("status").asText();
            if ("OK".equals(status)) {
                // 从响应中提取物流信息
                JsonNode dataNode = root.get("data");
                String trackingNumber = dataNode.get("tracking_number").asText();
                String deliveryStatus = dataNode.get("delivery_status").asText();
                String lastUpdateTime = dataNode.get("last_update_time").asText();

                // 构建ExpressInfo对象
                ExpressInfo expressInfo = new ExpressInfo();
                expressInfo.setTrackingNumber(trackingNumber);
                expressInfo.setDeliveryStatus(deliveryStatus);
                expressInfo.setLastUpdateTime(lastUpdateTime);

                return expressInfo;
            } else {
                // 响应中包含错误信息
                String errorMsg = root.get("message").asText();
                throw new RuntimeException("Shunfeng API error: " + errorMsg);
            }
        } catch (IOException e) {
            // 处理解析错误
            throw new RuntimeException("Failed to parse Shunfeng API response", e);
        }
    }
}

3. 创建接口

创建一个通用的快递查询服务接口,以便在工厂类中使用。

public interface ExpressService {

    /**
     * 根据快递单号查询快递物流信息
     * @param trackingNumber  快递单号
     * @return 快递物流信息
     */
    ExpressInfo queryExpress(String trackingNumber);
}

4. 使用工厂类查询物流信息

在你的控制器或服务类中,使用工厂类来获取适当的快递查询服务实例,并查询物流信息。

@RestController
public class ExpressController {

    private final ExpressServiceFactory expressServiceFactory;

    @Autowired
    public ExpressController(ExpressServiceFactory expressServiceFactory) {
        this.expressServiceFactory = expressServiceFactory;
    }


     /**
     * 根据快递类型和单号查询快递物流信息
     * @param provider 快递类型
     * @param trackingNumber  快递单号
     * @return 快递物流信息
     */
    @GetMapping("/query-express")
    public ExpressInfo queryExpress(@RequestParam String provider, @RequestParam String trackingNumber) {
        ExpressService expressService = expressServiceFactory.getExpressService(provider);
        return expressService.queryExpress(trackingNumber);
    }
}

到这里代码就写好!!!接下来就可以进行测试或者前端调用接口!!!

如果对你有用就点个赞或者关注一下吧!

标签:API,springBoot,快递,ExpressInfo,new,100,expressInfo,String
From: https://www.cnblogs.com/blbl-blog/p/17856150.html

相关文章

  • Java基于协同过滤算法开发的springboot+vue服装商城
    演示视频https://www.bilibili.com/video/BV1oH4y127fq/?share_source=copy_web&vd_source=11344bb73ef9b33550b8202d07ae139b主要功能:用户可以浏览商品和特价商品,加入购物车,直接下单支付,在我的个人中心里可以管理自己的订单,收货地址,编辑资料等。管理员可以发布商品,上下架商品,处......
  • SpringBoot2 仿B站的文章示例代码简介
    SpringBoot2仿B站的文章示例代码简介SpringBoot2是一个基于Java的开源框架,它可以帮助开发者快速构建应用程序。本文将介绍一个仿B站的文章示例代码,展示如何使用SpringBoot2构建一个简单的文章发布和展示平台。项目结构项目结构如下:java复制代码├──pom.xml......
  • springboot学习之——SpringApplication.run方法
    springboot学习之——SpringApplication.run方法目录springboot学习之——SpringApplication.run方法第一步第二步ConfigurableApplicationContextspringboot版本3.1.5第一步 /** *Statichelperthatcanbeusedtoruna{@linkSpringApplication}fromthe *spe......
  • 龙芯发布 .NET 8 SDK 8.0.100-ea1(试用版)
    随着.NET8的发布,国内的社区朋友们也很关心龙芯.NET团队对于Loongarch.NET8的发布时间,目前从龙芯.NET编译器团队已经在龙芯.NET官网上发布龙芯.NET8SDK-8.0.100-ea1版本发布(试用版),从龙芯2019年启动.NET的研发工作,2022年完成了LoongArch64架构代码合并到.NET社区主干分......
  • 【SpringBoot应用篇】SpringBoot: 事件的发布和监听
    【SpringBoot应用篇】SpringBoot:事件的发布和监听应用场景概述自定义事件发布和监听pom自定义事件源和实体发布事件监听类使用ApplicationListener方式监听类使用@EventListener方式Spring事件最佳实践通用泛型类事件发布事件类事件监听类异步监听处理事......
  • P1002题解
    思路设\(dp_{i,j}\)表示第\(i\)行\(j\)列卒走到这里有多少种方式。卒是可以向右和下走,所以到这个点只能从左或上来,不难得出转移公式:\(dp_{i,j}=dp_{i-1,j}+dp_{i,j-1}\)。如果马在这个点上或者说马能到这个点上,那么卒不能到这个点,也就是卒到这个点的方式为\(0\)。如......
  • P1003题解
    简单模拟题。思路枚举每一个地毯,因为后面的会覆盖前面的,所以从正序枚举。如果要求的点的坐标在当前地毯上,则将答案赋值为当前地毯编号。最后输出答案。那如果这个点没有地毯呢?答案初始设为\(-1\),这样没有地毯覆盖的话,答案不会改变,这样输出答案就会是\(-1\)。注意:记得赋初......
  • 初中英语优秀范文100篇-007 A Model Student in My Class
    记忆树1Mygoodfriend,Marry,isourmonitor.翻译我的好朋友玛丽是我们的班长。简化记忆我好朋友句子结构主语:MygoodfriendMarry(我的好朋友玛丽)。其中,主语是一个名词短语,由代词“my”(我的)和名词“goodfriendMarry”(好朋友玛丽)组成。谓语:is(是)。这是一......
  • P1002 [NOIP2002 普及组] 过河卒
    [NOIP2002普及组]过河卒题目描述棋盘上\(A\)点有一个过河卒,需要走到目标\(B\)点。卒行走的规则:可以向下、或者向右。同时在棋盘上\(C\)点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。棋盘用坐标表示,\(A\)点\((0......
  • 10.配置优先级,bean的管理,SpringBoot原理
    配置优先级,bean的管理,SpringBoot原理配置优先级:优先级(低->高):application.ymlapplication.ymlapplication.propertiesjava系统属性(-Dxxx=xxx)命令行参数(--xxx=xxx)例子-设置springboot项目端口号:java系统属性:-Dserver.port=9000命令行参数:--server.por......