java - 访问 python 的 fastapi 搭建的 web 服务

代码

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.course.constants.FileFormatConstants;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;

/**
 * 访问用 python 的 fastapi 搭建的 web 服务
 */
@Slf4j
public class AccessServiceUtil {

    private static final int REQUEST_BODY_NOT_MATCH_ERROR = 422;

    /**
     * 访问服务
     *
     * @param serviceName 服务名
     * @param serviceUrl  服务地址
     * @param dto         服务所需入参
     * @return 服务响应 ( 需要手动关闭 )
     */
    private static <D> HttpResponse post(String serviceName, String serviceUrl, D dto) {

        // 校验 - 服务名不为空, 服务地址不为空
        if (StrUtil.isBlank(serviceName) || StrUtil.isBlank(serviceUrl)) {
            throw new ServiceException("未获取到服务名, 或服务地址");
        }

        // 校验 - 服务地址以 http 开头
        if (!StrUtil.startWith(serviceUrl, "http")) {
            String errorMessage = StrUtil.format("未获取到 {} 服务", serviceName);
            throw new ServiceException(errorMessage);
        }

        // 记录开始时间
        log.info("开始访问 {} 服务", serviceName);
        long start = System.currentTimeMillis();

        // 访问
        String requestBody = JSON.toJSONString(dto);
        String contentType = "application/json";
        HttpResponse resp = HttpUtil.createPost(serviceUrl).contentType(contentType).body(requestBody).execute();

        // 记录结束时间
        long end = System.currentTimeMillis();
        log.info("访问 {} 服务结束, time = {} ms, isOk = {}", serviceName, (end - start), resp.isOk());

        // 访问失败的情况
        if (!resp.isOk()) {
            // 参数错误导致访问失败的情况
            if (REQUEST_BODY_NOT_MATCH_ERROR == resp.getStatus()) {
                log.error("请求参数错误, 应符合 {} 服务要求.", serviceName);
            }

            log.error("url = {}", serviceUrl);
            log.error("requestBody = {}", requestBody);
            log.error("responseBody = {}", resp.body());

            throw new ServiceException("操作失败, 请联系管理员");
        }

        // 返回
        return resp;
    }

    /**
     * 返回 JSON
     *
     * @param serviceName 服务名
     * @param serviceUrl  服务地址
     * @param dto         服务所需入参
     * @param resultClass 服务的返回值的类型
     * @return 返回值实例
     */
    public static <D, R> R postObj(String serviceName, String serviceUrl, D dto, Class<R> resultClass) {
        HttpResponse resp = post(serviceName, serviceUrl, dto);
        String json = resp.body();
        resp.close();
        return JSON.parseObject(json, resultClass);
    }

    /**
     * 下载文件
     *
     * @param serviceName 服务名
     * @param serviceUrl  服务地址
     * @param dto         服务所需入参
     * @return 文件地址
     */
    public static <D> String postDownload(String serviceName, String serviceUrl, D dto, String dir) {

        // 校验 - 存放目录不为空
        if (StrUtil.isBlank(dir)) {
            throw new ServiceException("未指定存放目录");
        }

        // 访问服务
        HttpResponse resp = post(serviceName, serviceUrl, dto);

        // 下载文件
        String fileName = dir + System.currentTimeMillis() + FileFormatConstants.ZIP;
        String filePath = RuoYiConfig.getProfile() + fileName;
        File file = Paths.get(filePath).toFile();
        try (BufferedOutputStream bos = FileUtil.getOutputStream(file)) {
            log.info("开始下载 {} 服务返回的文件", serviceName);
            bos.write(resp.bodyBytes());
            bos.flush();
            resp.close();
            log.info("完成下载 {} 服务返回的文件", serviceName);
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new ServiceException("操作失败, 无法下载文件");
        }

        // 返回
        return Constants.RESOURCE_PREFIX + fileName;
    }
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FastAPI是一个由Python编写的现代高性能Web框架,特别适合构建RESTful APIWeb应用。它基于星lette和Uvicorn,提供了简单易用的API定义、自动文档生成以及类型安全等特性。以下是一些基本步骤来使用FastAPI搭建Web服务器: 1. 安装FastAPI: 首先确保你已经安装了Python和pip,然后在命令行中运行 `pip install fastapi uvicorn` 来安装FastAPI和其依赖的Uvicorn。 2. 创建项目文件结构: 创建一个新的目录,例如`my_api`,并在其中创建`main.py`和`app.py`(如果需要分模块管理)。 3. 编写`main.py` (或app.py): 这里通常导入并启动FastAPI应用程序。例如,一个简单的示例是: ```python from fastapi import FastAPI # 在这里导入你的API路由和配置 from app import app as api if __name__ == "__main__": import uvicorn uvicorn.run(api, host="0.0.0.0", port=8000) ``` 4. 定义路由和处理函数: 在`app.py`中,你需要定义`API Router`,即定义HTTP方法(GET、POST、PUT等)和URL路径,以及对应的处理函数。例如: ```python from fastapi import APIRouter, Depends, HTTPException, status router = APIRouter() @router.get("/items/") async def read_items(): # 这里是返回数据的逻辑,比如查询数据库 return [{"item_id": 1, "item_name": "Example item"}] ``` 5. 文档生成: FastAPI内置了`docs`功能,可以通过`app.include_router(router, tags=["Items"])`来添加文档,并访问`http://localhost:8000/docs`查看API文档。 6. 启动服务: 运行`main.py`(或指定的`app.py`),在指定的主机和端口上(如8000)启动Web服务器。 相关问题-- 1. FastAPI与星lette和Uvicorn的关系是什么? 2. 如何在FastAPI中处理POST请求并解析请求体数据? 3. 如何在FastAPI中设置全局响应头信息? 4. FastAPI中的Depends函数是用来做什么的?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值