API网关触发函数计算处理示例教程(runtime=java8)

简介: 本示例对API网关触发函数计算的使用步骤进行详细介绍,并以运行环境为Java为例,对API网关传入的请求参数进行解析。 通过示例,您将了解 1. 如何使用API网关触发函数计算; 2. 如何在函数中获取API网关传入函数的参数,并将处理结果返回给API网关(以Java运行环境为例)。

API网关触发java runtime的函数计算处理示例教程

背景信息

函数计算(Function Compute)是一种事件驱动的服务。函数的执行可以由事件驱动,即当某个事件发生时,触发函数的执行。目前函数计算支持API网关作为事件源,简单说来,当有请求到达已经设置函数计算为后端服务的API网关时,API网关会触发函数的执行,函数计算会将执行结果返回给API网关。

本示例对API网关触发函数计算的使用步骤进行详细介绍,并以运行环境为Java为例,对API网关传入的请求参数进行解析。

通过示例,您将了解

  • 如何使用API网关触发函数计算;
  • 如何在函数中获取API网关传入函数的参数,并将处理结果返回给API网关(以Java运行环境为例)。

本示例分为以下三个步骤

  • 明确API网关和函数计算对接的格式要求(一定要以这个格式,否则互相不认识);
  • 创建服务和需要被API网关触发的函数(已有服务和函数,可跳过此步骤);
  • API网关控制台配置函数计算作为API后端服务。

API网关和函数计算对接的格式要求

API网关调用函数服务时,会将API的相关数据包装为一个Map形式传给函数计算服务,函数计算服务处理后,需要按照返回参数的格式返回statusCodeheadersbody等相关数据,API网关再将函数计算返回的内容映射到statusCodeheaderbody等位置返回给客户端。

API网关的传入参数格式

当以函数计算作为API网关的后端服务时,API网关会把请求参数通过一个固定结构传给函数计算的入参event,函数计算通过如下结构去获取需要的参数,然后进行处理,该结构如下:

{
    "path":"api request path",
    "httpMethod":"request method name",
    "headers":{all headers,including system headers},
    "queryParameters":{query parameters},
    "pathParameters":{path parameters},
    "body":"string of request payload",
    "isBase64Encoded":"true|false, indicate if the body is Base64-encode"
}

函数计算的返回参数格式

函数计算需要将输出内容通过如下JSON格式返回给API网关,方便API网关解析。

{
    "isBase64Encoded":true|false,
    "statusCode":httpStatusCode,
    "headers":{response headers},
    "body":"..."
}

创建服务和函数

创建服务和函数部分分为两个步骤,本示例以Java Runtime为例

  • 首先需要编写Java代码对API网关传入的参数进行处理,并返回符合格式要求的结果给API网关
  • 创建服务和函数,函数计算提供给我们两种方式创建服务和函数,本示例对两种创建函数的方式分别进行介绍。(如果已有服务就无需重新创建服务了,新建函数就可以)

    • 一种是通过控制台上传代码包的方式创建函数;
    • 另一种是通过命令行工具fcli创建函数。

温馨提示:这里提供了两种创建函数的方法,您根据个人喜好任选其一即可。

编写函数代码

用户在使用Java编程时,必须要实现一个类,它要实现函数计算预定义的接口,目前有2个预定义的接口可以实现(您任选其一即可):

  • StreamRequestHandler以流的方式接受调用输入(event)和返回执行结果,用户需要从inputStream中读取调用函数时的输入,处理完成后把函数执行结果写入到outputStream中来返回
  • PojoRequestHandler<I, O>通过泛型的方式,用户可以自定义输入和输出的类型,但是它们必须是POJO类型。下面将举例如何使用这个接口
    API网关触发函数计算的场景更适合使用PojoRequestHandler<I, O>接口,但是本文也提供使用以StreamRequestHandler接口实现的方法
使用PojoRequestHandler<I, O>接口(推荐)

本示例演示了在Java Runtime中,通过实现函数计算预定义的接口PojoRequestHandler,对从API网关传入的参数进行处理,并将结果返回给API网关的过程。PojoRequestHandler<I, O>通过泛型的方式接受调用输入和返回执行结果,用户可以自定义输入和输出的类型,但是它们必须是POJO类型。下面将举例如何使用这个接口通过自定义类ApiRequest传入API网关的参数,函数计算获取参数,对参数进行处理,并通过ApiResponse返回函数计算处理结果的过程。
Java Runtime使用请参考Java Runtime

import com.aliyun.fc.runtime.Context;
import com.aliyun.fc.runtime.PojoRequestHandler;
import java.util.HashMap;
import java.util.Map;

public class ApiTriggerDemo implements PojoRequestHandler<ApiRequest, ApiResponse> {

    public ApiResponse handleRequest(ApiRequest request, Context context) {
        // Get ApiRequest info
        context.getLogger().info(request.toString());
        String path = request.getPath();
        String httpMethod = request.getHttpMethod();
        String body = request.getBody();
        context.getLogger().info("path:" + path);
        context.getLogger().info("httpMethod:" + httpMethod);
        context.getLogger().info("body:" + body);

        // Deal with your own logic here

        // ApiResponse example
        Map headers = new HashMap();
        boolean isBase64Encoded = false;
        int statusCode = 200;
        String returnBody = "";
        return new ApiResponse(headers,isBase64Encoded,statusCode,returnBody);
    }
}

两个pojo类,ApiRequest类和ApiResponse类如下。注意pojo类的set()get()方法注意要写全哈

import java.util.Map;

public class ApiRequest {
    private String path;
    private String httpMethod;
    private Map headers;
    private Map queryParameters;
    private Map pathParameters;
    private String body;
    private boolean isBase64Encoded;

    @Override
    public String toString() {
        return "Request{" +
                "path='" + path + '\'' +
                ", httpMethod='" + httpMethod + '\'' +
                ", headers=" + headers +
                ", queryParameters=" + queryParameters +
                ", pathParameters=" + pathParameters +
                ", body='" + body + '\'' +
                ", isBase64Encoded=" + isBase64Encoded +
                '}';
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getHttpMethod() {
        return httpMethod;
    }

    public void setHttpMethod(String httpMethod) {
        this.httpMethod = httpMethod;
    }

    public Map getHeaders() {
        return headers;
    }

    public void setHeaders(Map headers) {
        this.headers = headers;
    }

    public Map getQueryParameters() {
        return queryParameters;
    }

    public void setQueryParameters(Map queryParameters) {
        this.queryParameters = queryParameters;
    }

    public Map getPathParameters() {
        return pathParameters;
    }

    public void setPathParameters(Map pathParameters) {
        this.pathParameters = pathParameters;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public boolean getIsBase64Encoded() {
        return this.isBase64Encoded;
    }

    public void setIsBase64Encoded(boolean base64Encoded) {
        this.isBase64Encoded = base64Encoded;
    }
}
import java.util.Map;

public class ApiResponse {
    private Map headers;
    private boolean isBase64Encoded;
    private int statusCode;
    private String body;

    public ApiResponse(Map headers, boolean isBase64Encoded, int statusCode, String body) {
        this.headers = headers;
        this.isBase64Encoded = isBase64Encoded;
        this.statusCode = statusCode;
        this.body = body;
    }

    public Map getHeaders() {
        return headers;
    }

    public void setHeaders(Map headers) {
        this.headers = headers;
    }

    public boolean getIsBase64Encoded() {
        return isBase64Encoded;
    }

    public void setIsBase64Encoded(boolean base64Encoded) {
        this.isBase64Encoded = base64Encoded;
    }

    public int getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }
}

pom.xml文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>apiTrigger</groupId>
    <artifactId>apiTrigger</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>com.aliyun.fc.runtime</groupId>
            <artifactId>fc-java-core</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>   
</project>
使用StreamRequestHandler接口

使用StreamRequestHandler接口示例如下,需要将输入的InputStream转换为对应的pojo类,pom文件配置与使用PojoRequestHandler<I, O>接口相同,代码如下

import com.aliyun.fc.runtime.Context;
import com.aliyun.fc.runtime.StreamRequestHandler;
import com.aliyun.fc.runtime.Context;
import com.google.gson.Gson;
import java.io.*;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class ApiTriggerDemo2 implements StreamRequestHandler {

    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) {
        try {
            // Convert InputStream to string
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuffer stringBuffer = new StringBuffer();
            String string = "";
            while ((string = bufferedReader.readLine()) != null) {
                stringBuffer.append(string);
            }
            String input = stringBuffer.toString();
            context.getLogger().info("inputStream: " + input);
            Request req = new Gson().fromJson(input, Request.class);
            context.getLogger().info("input req: ");
            context.getLogger().info(req.toString());
            String bodyReq = req.getBody();
            Base64.Decoder decoder = Base64.getDecoder();
            context.getLogger().info("body: " + new String(decoder.decode(bodyReq)));

            // Deal with your own logic here

            // construct response
            Map headers = new HashMap();
            headers.put("x-custom-header", " ");
            boolean isBase64Encoded = false;
            int statusCode = 200;
            Map body = new HashMap();
            Response resp = new Response(headers, isBase64Encoded, statusCode, body);
            String respJson = new Gson().toJson(resp);
            context.getLogger().info("outputStream: " + respJson);
            outputStream.write(respJson.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    class Request {
        private String path;
        private String httpMethod;
        private Map headers;
        private Map queryParameters;
        private Map pathParameters;
        private String body;
        private boolean isBase64Encoded;

        @Override
        public String toString() {
            return "Request{" +
                    "path='" + path + '\'' +
                    ", httpMethod='" + httpMethod + '\'' +
                    ", headers=" + headers +
                    ", queryParameters=" + queryParameters +
                    ", pathParameters=" + pathParameters +
                    ", body='" + body + '\'' +
                    ", isBase64Encoded=" + isBase64Encoded +
                    '}';
        }

        public String getBody() {
            return body;
        }
    }

    // FC need to return the response to API gateway in the following JSON format
    class Response {
        private Map headers;
        private boolean isBase64Encoded;
        private int statusCode;
        private Map body;

        public Response(Map headers, boolean isBase64Encoded, int statusCode, Map body) {
            this.headers = headers;
            this.isBase64Encoded = isBase64Encoded;
            this.statusCode = statusCode;
            this.body = body;
        }
    }
}

创建服务和函数

打成jar包

Java代码需要打成jar包上传到函数计算。如果您使用IntelliJ IDEA集成开发环境,打包方式如下(可参考IDEA导出可执行jar包)

  • File -> Project Structure -> Artifacts -> + -> Jar -> From modules with dependencies -> 选择函数所在的类 -> Apply -> 确定
  • Build -> Build Artifacts -> 找到对应的Aritifacts -> Build
创建服务和函数

函数计算提供两种方式创建服务和函数,使用控制台创建服务和函数和使用命令行工具fcli创建服务和函数,下面对这两种方式分别进行介绍

1.使用控制台创建服务和函数
使用控制台创建服务和函数图文并茂版请参考如何使用控制台,本示例只给出基本操作步骤

  • 创建服务:左侧服务列表 -> + -> 创建服务 -> 填写服务相关内容 -> 确定
  • 创建函数:进入对应服务 -> 左侧函数列表 -> + -> 新建函数 -> 使用空白模板 -> 不创建触发器 -> 输入函数名称 -> 运行环境选择Java8 -> 代码上传方式选择代码包上传 -> 选择刚刚生成的jar包 -> 设置函数入口,入口形式为[package].[class]::[method],例如我打包后的函数入口为ApiTriggerDemo::handleRequest,其他值选择默认即可
    这样函数就创建好啦

2.使用命令行工具fcli创建服务和函数

  • 创建服务: mks fc-demo,即创建服务,服务名称为fc-demo (在创建服务时可以指定log project等信息,具体内容可参考mks
  • 创建函数:
    mkf apiTrigger -t java8 -h ApiTriggerDemo::handleRequest -d fcDemo/out/artifacts/apiTrigger_jar (其中apiTrigger为函数名称,-t为指定运行环境,-h指定函数入口,-d指定代码包,此路径为代码包路径相对于fcli所在位置的路径,具体内容可参考mkf)

创建API

  1. API网关控制台分组管理 -> 创建分组,新建一个API分组(已经有API分组可跳过这步)
  2. API列表 -> 新建API,步骤如图所示
    创建API

API P1
API P2
API P3
API P4

通过API网关触发函数计算可参考以函数计算作为 API 网关后端服务

测试触发器

测试
测试成功后发布API即可

参考文献

以函数计算作为 API 网关后端服务

That's all,enjoy it~
Any question,可留言,或加入函数计算官方客户群(钉钉群号:11721331)

相关文章
|
11月前
|
JSON Java API
【干货满满】分享京东API接口到手价,用Java语言实现
本示例使用 Java 调用京东开放平台商品价格及优惠信息 API,通过商品详情和促销接口获取到手价(含优惠券、满减等),包含签名生成、HTTP 请求及响应解析逻辑,适用于比价工具、电商系统集成等场景。
|
缓存 监控 负载均衡
如何提升 API 性能:来自 Java 和测试开发者的优化建议
本文探讨了如何优化API响应时间,提升用户体验。通过缓存(如Redis/Memcached)、减少数据负载(REST过滤字段或GraphQL精确请求)、负载均衡(Nginx/AWS等工具)、数据压缩(Gzip/Brotli)、限流节流、监控性能(Apipost/New Relic等工具)、升级基础设施、减少第三方依赖、优化数据库查询及采用异步处理等方式,可显著提高API速度。快速响应的API不仅让用户满意,还能增强应用整体性能。
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
567 2
|
11月前
|
JSON Java API
【干货满满】分享拼多多API接口到手价,用Java语言实现
本方案基于 Java 实现调用拼多多开放平台商品详情 API,通过联盟接口获取商品到手价(含拼团折扣与优惠券),包含签名生成、HTTP 请求及响应解析逻辑,适用于电商比价、导购系统集成。
|
11月前
|
JSON Java API
【干货满满】分享淘宝API接口到手价,用Java语言实现
本文介绍了如何使用 Java 调用淘宝开放平台 API 获取商品到手价,涵盖依赖配置、签名生成、HTTP 请求与响应解析等核心实现步骤。
|
JSON JavaScript 前端开发
Python+JAVA+PHP语言,苏宁商品详情API
调用苏宁商品详情API,可通过HTTP/HTTPS发送请求并解析响应数据,支持多种编程语言,如JavaScript、Java、PHP、C#、Ruby等。核心步骤包括构造请求URL、发送GET/POST请求及解析JSON/XML响应。不同语言示例展示了如何获取商品名称与价格等信息,实际使用时请参考苏宁开放平台最新文档以确保兼容性。
|
前端开发 Cloud Native Java
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
|
缓存 安全 Java
《从头开始学java,一天一个知识点》之:字符串处理:String类的核心API
🌱 **《字符串处理:String类的核心API》一分钟速通!** 本文快速介绍Java中String类的3个高频API:`substring`、`indexOf`和`split`,并通过代码示例展示其用法。重点提示:`substring`的结束索引不包含该位置,`split`支持正则表达式。进一步探讨了String不可变性的高效设计原理及企业级编码规范,如避免使用`new String()`、拼接时使用`StringBuilder`等。最后通过互动解密游戏帮助读者巩固知识。 (上一篇:《多维数组与常见操作》 | 下一篇预告:《输入与输出:Scanner与System类》)
414 11
|
数据采集 存储 Java
Java爬虫获取微店店铺所有商品API接口设计与实现
本文介绍如何使用Java设计并实现一个爬虫程序,以获取微店店铺的所有商品信息。通过HttpClient发送HTTP请求,Jsoup解析HTML页面,提取商品名称、价格、图片链接等数据,并将其存储到本地文件或数据库中。文中详细描述了爬虫的设计思路、代码实现及注意事项,包括反爬虫机制、数据合法性和性能优化。此方法可帮助商家了解竞争对手,为消费者提供更全面的商品比较。
|
缓存 Java 应用服务中间件
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
5122 5

相关产品

  • 函数计算