Funqy HTTP Binding (Standalone)

指南将逐步介绍快速入门代码,向您展示如何部署 Funqy 作为独立服务,以及使用 HTTP 调用 Funqy 函数。

The guide walks through quickstart code to show you how you can deploy Funqy as a standalone service and invoke on Funqy functions using HTTP.

Funqy HTTP 绑定不会替代通过 HTTP 的 REST。由于 Funqy 需要在许多不同的协议和函数提供程序之间实现可移植性,因此其 HTTP 绑定非常极简,您将失去 REST 功能,例如链接以及利用缓存控制和条件 GET 等 HTTP 功能的能力。您可能希望考虑使用 Quarkus 的 Jakarta REST、Spring MVC 或 Vert.x Web Reactive Routes 支持,尽管 Funqy 将比这些替代方案(除了仍然非常快的 Vert.x)具有更少的开销。

The Funqy HTTP binding is not a replacement for REST over HTTP. Because Funqy needs to be portable across a lot of different protocols and function providers its HTTP binding is very minimalistic and you will lose REST features like linking and the ability to leverage HTTP features like cache-control and conditional GETs. You may want to consider using Quarkus’s Jakarta REST, Spring MVC, or Vert.x Web Reactive Routes support instead, although Funqy will have less overhead than these alternatives (except Vert.x which is still super fast).

Prerequisites

include::{includes}/prerequisites.adoc[]* 阅读有关 Funqy Basics 的信息。这是一篇短文!

Unresolved directive in funqy-http.adoc - include::{includes}/prerequisites.adoc[] * Read about Funqy Basics. This is a short read!

The Quickstart

克隆 Git 存储库: git clone {quickstarts-clone-url},或下载 {quickstarts-archive-url}[存档]。

Clone the Git repository: git clone {quickstarts-clone-url}, or download an {quickstarts-archive-url}[archive].

解决方法位于 funqy-http-quickstart directory 中。

The solution is located in the funqy-http-quickstart directory.

The Code

如果您查看 Java 代码,会发现没有 HTTP 特定的 API。它只是用 @Funq 注释过的简单 Java 方法。简单、容易、直接。

If you look at the Java code, you’ll see that there is no HTTP specific API. Its just simple Java methods annotated with @Funq. Simple, easy, straightforward.

Maven Dependencies

要编写 Funqy HTTP 函数,只需将 quarkus-funqy-http 依赖项包含到您的 Quarkus pom.xml 文件中:

To write Funqy HTTP functions, simply include the quarkus-funqy-http dependency into your Quarkus pom.xml file:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-funqy-http</artifactId>
</dependency>

Build Project

mvn clean quarkus:dev

这将在 Quarkus dev 模式下启动您的函数。

This starts your functions in Quarkus dev mode.

Execute Funqy HTTP functions

执行函数的 URL 路径是函数名称。例如,如果您的函数名称为 foo,则执行函数的 URL 路径将为 /foo

The URL path to execute a function is the function name. For example if your function name is foo then the URL path to execute the function would be /foo.

可以使用 HTTP POST 或 GET 方法调用函数。函数的返回值使用 Jackson JSON 库编组到 JSON 中。可以使用 Jackson 注释。如果您的函数有输入参数,POST 调用必须使用 JSON 作为输入类型。Jackson 也用于此处进行取消编组。

The HTTP POST or GET methods can be used to invoke on a function. The return value of the function is marshalled to JSON using the Jackson JSON library. Jackson annotations can be used. If your function has an input parameter, a POST invocation must use JSON as the input type. Jackson is also used here for unmarshalling.

您可以通过将浏览器指向 [role="bare"][role="bare"]http://localhost:8080/hello 来调用在 PrimitiveFunctions.java 中定义的 hello 函数。

You can invoke the hello function defined in PrimitiveFunctions.java by pointing your browser to [role="bare"]http://localhost:8080/hello

调用快速入门中的其他函数需要 HTTP POST。要执行在 GreetingFunction.java 中定义的 greet 函数,请调用此 curl 脚本。

Invoking the other functions in the quickstart requires an HTTP POST. To execute the greet function defined in GreetingFunction.java invoke this curl script.

curl "http://localhost:8080/greet" \
-X POST \
-H "Content-Type: application/json" \
-d '{"name":"Bill"}'

也可以使用标准的 JSON 映射将基本类型传递为输入。若要执行在 PrimitiveFunctions.java 中定义的 toLowerCase 函数,请调用此 curl 脚本:

Primitive types can also be passed as input using the standard JSON mapping for them. To execute the toLowerCase function defined in PrimitiveFunctions.java invoke this curl script:

curl "http://localhost:8080/toLowerCase" \
-X POST \
-H "Content-Type: application/json" \
-d '"HELLO WORLD"'

若要执行在 PrimitiveFunctions.java 中定义的 double 函数,请调用此 curl 脚本:

To execute the double function defined in PrimitiveFunctions.java invoke this curl script:

curl "http://localhost:8080/double" \
-X POST \
-H "Content-Type: application/json" \
-d '2'

GET Query Parameter Mapping

对于 GET 请求,Funqy HTTP 绑定还具有用于函数输入参数的查询参数映射。只有 bean 样式类和 java.util.Map 可以用于您的输入参数。对于 bean 样式类,查询参数名称映射到 bean 类上的属性。这里有一个简单的 Map 示例:

For GET requests, the Funqy HTTP Binding also has a query parameter mapping for function input parameters. Only bean style classes and java.util.Map can be used for your input parameter. For bean style classes, query parameter names are mapped to properties on the bean class. Here’s an example of a simple Map:

@Funq
public String hello(Map<String, Integer> map) {
...
}

键值必须是基本类型(char 除外)或 String 。值可以是基本类型(char 除外)、StringOffsetDateTime 或复杂 bean 样式类。对于上述示例,以下是相应的 curl 请求:

Key values must be a primitive type (except char) or String. Values can be primitives (except char), String, OffsetDateTime or a complex bean style class. For the above example, here’s the corresponding curl request:

curl "http://localhost:8080/a=1&b=2"

hello 函数的 map 输入参数将具有键值对:a1b2

The map input parameter of the hello function would have the key value pairs: a→1, b→2.

bean 样式类也可以用作输入参数类型。这里有一个示例:

Bean style classes can also be use as the input parameter type. Here’s an example:

public class Person {
    String first;
    String last;

    public String getFirst() { return first; }
    public void setFirst(String first) { this.first = first; }
    public String getLast() { return last; }
    public void setLast(String last) { this.last = last; }
}

public class MyFunctions {
    @Funq
    public String greet(Person p) {
       return "Hello " + p.getFirst() + " " + p.getLast();
    }
}

属性值可以是除 char 以外的任何基本类型。它也可以是 StringOffsetDateTimeOffsetDateTime 查询参数值必须采用 ISO-8601 格式。

Property values can be any primitive type except char. It can also be String, and OffsetDateTime. OffsetDateTime query param values must be in ISO-8601 format.

可以使用 HTTP GET 和查询参数对此进行调用:

You can invoke on this using an HTTP GET and query parameters:

curl "http://localhost:8080/greet?first=Bill&last=Burke"

在上面的请求中,查询参数名称映射到输入类中对应的属性。

In the above request, the query parameter names are mapped to corresponding properties in the input class.

输入类也可以具有嵌套的 bean 类。对上一个示例进行扩展:

The input class can also have nested bean classes. Expanding on the previous example:

public class Family {
    private Person dad;
    private Person mom;

    public Person getDad() { return dad; }
    public void setDad(Person dad) { this.dad = dad; }
    public Person getMom() { return mom; }
    public void setMom(Person mom) { this.mom = mom; }
}

public class MyFunctions {
    @Funq
    public String greet(Family family) {
       ...
    }
}

在这种情况下,嵌套值的查询参数使用 . 表示法。例如:

In this case, query parameters for nested values use the . notation. For example:

curl "http://localhost:8080/greet?dad.first=John&dad.last=Smith&mom.first=Martha&mom.last=Smith"

java.util.ListSet 也支持作为属性值。例如:

java.util.List and Set are also supported as property values. For example:

public class Family {
    ...

    List<String> pets;
}

public class MyFunctions {
    @Funq
    public String greet(Family family) {
       ...
    }
}

若要调用 GET 请求,只需多次列出 pets 查询参数即可。

To invoke a GET request, just list the pets query parameter multiple times.

curl "http://localhost:8080/greet?pets=itchy&pets=scratchy"

对于更复杂类型,ListSet 成员必须在 query 参数中具有一个标识符。例如:

For more complex types, List and Set members must have an identifier in the query parameter. For example:

public class Family {
    ...

    List<Person> kids;
}

public class MyFunctions {
    @Funq
    public String greet(Family family) {
       ...
    }
}

每个 kids 查询参数都必须标识它们引用的 kid,以便运行时能够找出哪些属性值属于列表中哪些成员。以下是 curl 请求:

Each kids query parameter must identify the kid they are referencing so that the runtime can figure out which property values go to which members in the list. Here’s the curl request:

curl "http://localhost:8080/greet?kids.1.first=Buffy&kids.2.first=Charlie"

上述 URL 使用值 12 来标识列表的目标成员,但可以使用任何唯一的字符串。

The above URL uses the value 1 and 2 to identity the target member of the list, but any unique string can be used.

属性也可以是 java.util.Map 。映射的键可以是任何基本类型和 String 。例如:

A property can also be a java.util.Map. The key of the map can be any primitive type and String. For example:

public class Family {
    ...

    Map<String, String> address;
}

public class MyFunctions {
    @Funq
    public String greet(Family family) {
       ...
    }
}

相应的调用将如下所示:

The corresponding call would look like this:

curl "http://localhost:8080/greet?address.state=MA&address.city=Boston"

如果您的 Map 值是复杂类型,那么只需通过在最后添加要设置的属性来继续表示法即可。

If your Map value is a complex type, then just continue the notation by adding the property to set at the end.

public class Family {
    ...

    Map<String, Address> addresses;
}

public class MyFunctions {
    @Funq
    public String greet(Family family) {
       ...
    }
}
curl "http://localhost:8080/greet?addresses.home.state=MA&addresses.home.city=Boston"