Java
函数计算支持使用Java进行编程,支持以下Java运行环境
- OpenJDK 1.8.0
Java语言由于需要编译以后才可以在JVM虚拟机中运行,因此CFC不支持在线编辑代码,仅仅支持通过web页面上传编译好的zip包和从BOS上传zip包两种方式上传代码。
当前CFC的Java运行时支持两种事件模式,点击下面链接您可以快速查看两种模式的简单开发示例
简单示例(event事件模式)
环境准备
确保您已经安装了JAVA和Maven。
创建项目
本示例使用开源Java项目管理工具Maven进行管理, 使用mvn命令行工具创建了一个groupId为com.baidu.demo,artifactId为bce-cfc-java-demo简单函数项目,命��如下。
1$ mvn archetype:generate \
2 -DgroupId=com.baidu.demo \
3 -DartifactId=bce-cfc-java-demo \
4 -Dversion=1.0 \
5 -DarchetypeArtifactId=maven-archetype-quickstart \
6 -DinteractiveMode=no
运行完成之后,执行 tree 命令查看目录结构,应该是这样的
1.
2├── pom.xml
3└── src
4 ├── main
5 │ └── java
6 │ └── com
7 │ └── baidu
8 │ └── demo
9 │ └── App.java
10 └── test
11 └── java
12 └── com
13 └── baidu
14 └── demo
15 └── AppTest.java
16
1711 directories, 3 files
编写代码
在使用 Java 编程时,您首先需要定义一个函数入口类。创建文件 src/main/java/com/baidu/demo/SimpleHandler.java,写入以下内容,以下是一个最简单的入口函数:
1package com.baidu.demo;
2
3import com.baidubce.cfc.core.CfcContext;
4import com.baidubce.cfc.core.StreamHandler;
5
6import java.io.InputStream;
7import java.io.OutputStream;
8
9public class SimpleHandler implements StreamHandler {
10 @Override
11 public void handler(InputStream input, OutputStream output, CfcContext context) throws Exception {
12 System.out.println("console outlog");
13 System.err.println("console errlog");
14 output.write("hello world!".getBytes());
15 }
16}
一些说明:
-
函数入口类需要继承并实现
com.baidubce.cfc.core.StreamHandler接口,该接口包含一个handler函数,handler函数有三个参数:input表示输入数据output表示输出数据context表示函数运行时信息,使用context需要在代码中导入"com.baidubce.cfc.core.CfcContext"
- 日志输出到stdout和stderr,函数计算服务会自动收集这些日志。
打开文件 src/main/java/com/baidu/demo/App.java,写入以下内容:
1package com.baidu.demo;
2
3import com.baidubce.cfc.core.CfcClient;
4
5public class App {
6 public static void main(String[] args) {
7 CfcClient.main();
8 }
9}
在 main 入口函数中调用 CfcClient.main() 进入函数运行时执行。
maven编译并打包函数代码
在项目文件夹根目录创建pom.xml编译文件,可以在通过编辑pom.xml增加依赖和plugin配置, 以下分别给出示例
增加依赖:
函数计算相关接口定义于cfc-java-core包中,可以通过在pom.xml中增加以下 pom 定义引入该包依赖。在 <dependencies> 标签下加入这一段:
1<dependency>
2 <groupId>com.baidu.cfc</groupId>
3 <artifactId>cfc-java-core</artifactId>
4 <version>2.1.3</version>
5</dependency>
增加 plugin 配置
在 pom.xml 文件中添加 maven-dependency-plugin,构建阶段会将依赖的其他 JAR 包拷贝至 ${project.build.directory}/lib 目录;添加 maven-jar-plugin,用于构建可执行 JAR 包。在 project 标签下增加如下两项:
1<properties>
2 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
3 <maven.compiler.source>1.8</maven.compiler.source>
4 <maven.compiler.target>1.8</maven.compiler.target>
5</properties>
6<build>
7 <plugins>
8 <plugin>
9 <groupId>org.apache.maven.plugins</groupId>
10 <artifactId>maven-dependency-plugin</artifactId>
11 <version>3.1.1</version>
12 <executions>
13 <execution>
14 <id>copy-dependencies</id>
15 <phase>package</phase>
16 <goals>
17 <goal>copy-dependencies</goal>
18 </goals>
19 <configuration>
20 <outputDirectory>${project.build.directory}/lib</outputDirectory>
21 <overWriteReleases>false</overWriteReleases>
22 <overWriteSnapshots>false</overWriteSnapshots>
23 <overWriteIfNewer>true</overWriteIfNewer>
24 </configuration>
25 </execution>
26 </executions>
27 </plugin>
28 <plugin>
29 <!-- Build an executable JAR -->
30 <groupId>org.apache.maven.plugins</groupId>
31 <artifactId>maven-jar-plugin</artifactId>
32 <version>3.0.2</version>
33 <configuration>
34 <archive>
35 <manifest>
36 <addClasspath>true</addClasspath>
37 <classpathPrefix>lib/</classpathPrefix>
38 <mainClass>com.baidu.demo.App</mainClass>
39 <useUniqueVersions>false</useUniqueVersions>
40 </manifest>
41 </archive>
42 </configuration>
43 </plugin>
44 </plugins>
45</build>
发布
1// 打包
2$ mvn clean package
3
4// zip压缩
5$ cd target
6$ zip -r bce-cfc-java-demo.zip bce-cfc-java-demo-1.0.jar lib/
配置函数
创建函数时使用如下配置:
- 在函数管理页面,点击“创建函数”,进入创建函数页面。
- 填写您的函数名称等基本信息,运行时选择"java8",点击 提交。

- 在创建成功页面,选择进入代码编辑页面

- 选择"上传.zip文件",将上一步中压缩生成的zip文件上传至百度云。
- 处理程序中填写函数入口类名称,本例中为
com.baidu.demo.SimpleHandler。
进阶用法(stream模式)
特别地,对于http trigger请求,除了可以使用普通的event模式进行处理外,还可以使用stream模式进行处理。在stream模式下,将启动一个http server接收并处理http trigger请求。
创建函数
与普通event模式不同,需要将事件模式设置为stream。
编辑代码
下面显示了一个使用 stream 模式处理 HTTP Trigger 请求的例子,项目名称为 httptrigger-demo。您首先需要定义一个函数入口类 Demo。创建文件 src/main/java/com/baidubce/httptrigger/demo/Demo.java,写入以下内容:
1package com.baidubce.httptrigger.demo;
2
3import com.baidubce.cfc.core.http.CfcContext;
4import com.baidubce.cfc.core.http.HttpRequestHandler;
5
6import java.io.IOException;
7import java.util.logging.Logger;
8import javax.servlet.ServletException;
9import javax.servlet.http.HttpServletRequest;
10import javax.servlet.http.HttpServletResponse;
11
12public class Demo implements HttpRequestHandler {
13 private static final Logger LOGGER = Logger.getLogger("java.util.logging.ConsoleHandler");
14
15 @Override
16 public void handleRequest(HttpServletRequest request,
17 HttpServletResponse response,
18 CfcContext context) throws ServletException, IOException {
19 LOGGER.info(String.format("requestid=%s", context.getRequestId()));
20 LOGGER.info(String.format("appid=%s", context.getApiID()));
21 LOGGER.info(String.format("clientip=%s", context.getClientIP()));
22 response.getOutputStream().print("hello world!");
23 }
24}
该类需要实现 com.baidubce.cfc.core.http.HttpRequestHandler 接口,handleRequest 方法的参数说明如下:
| 参数 | 必填 | 说明 |
|---|---|---|
request |
是 | HTTP 请求对象。 |
response |
是 | HTTP 响应对象。 |
context |
是 | 函数运行时信息。使用 context 时需要在代码中导入 com.baidubce.cfc.core.http.CfcContext。 |
因为该模式使用 Jetty,Java 运行时已经集成 main 入口调用,无需单独编写 App.java 调用 CfcClient.main()。
maven打包函数代码
添加依赖。
与event模式不同,stream模式依赖bce-cfc-java-httpcore包。
1<dependencies>
2 <dependency>
3 <groupId>com.baidubce.cfc</groupId>
4 <artifactId>bce-cfc-java-httpcore</artifactId>
5 <version>1.0.0</version>
6 </dependency>
7</dependencies>
添加 plugin配置。
在package阶段增加了copy-dependencies功能,它将函数依赖的所有jar包拷贝到target/lib目录。同时,设置入口点mainClass为com.baidubce.cfc.core.http.CfcClient。
1<build>
2 <plugins>
3 <plugin>
4 <groupId>org.apache.maven.plugins</groupId>
5 <artifactId>maven-dependency-plugin</artifactId>
6 <version>3.1.1</version>
7 <executions>
8 <execution>
9 <id>copy-dependencies</id>
10 <phase>package</phase>
11 <goals>
12 <goal>copy-dependencies</goal>
13 </goals>
14 <configuration>
15 <outputDirectory>${project.build.directory}/lib</outputDirectory>
16 <overWriteReleases>false</overWriteReleases>
17 <overWriteSnapshots>false</overWriteSnapshots>
18 <overWriteIfNewer>true</overWriteIfNewer>
19 </configuration>
20 </execution>
21 </executions>
22 </plugin>
23 <plugin>
24 <!-- Build an executable JAR -->
25 <groupId>org.apache.maven.plugins</groupId>
26 <artifactId>maven-jar-plugin</artifactId>
27 <version>3.0.2</version>
28 <configuration>
29 <archive>
30 <manifest>
31 <addClasspath>true</addClasspath>
32 <classpathPrefix>lib/</classpathPrefix>
33 <mainClass>com.baidubce.cfc.core.http.CfcClient</mainClass>
34 <useUniqueVersions>false</useUniqueVersions>
35 </manifest>
36 </archive>
37 </configuration>
38 </plugin>
39 </plugins>
40</build>
打包
1mvn clean package
2cd target
3zip -r httptrigger-demo.zip httptrigger-demo-1.0.0.jar lib/
上传代码
上传方式与普通 event 模式相同。创建函数时,运行时选择 java8,事件模式设置为 stream,处理程序填写 com.baidubce.httptrigger.demo.Demo,然后上传 httptrigger-demo.zip。
处理POJO
除了StreamHandler外,运行时还支持直接处理POJO,可以通过实现RequestHandler<REQ, RSP>接口处理POJO。
支持的类型有:String,Integer,Boolean和其他可通过json序列化的自定义类型。
日志
使用Logger输出日志
创建logger配置文件
创建logger配置文件 src/main/resources/logger.properties
1handlers = java.util.logging.ConsoleHandler
2
3java.util.logging.ConsoleHandler.level=INFO
4java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
初始化并使用logger
1package com.baidu.demo;
2
3import com.baidubce.cfc.core.CfcContext;
4import com.baidubce.cfc.core.StreamHandler;
5
6import java.io.InputStream;
7import java.io.OutputStream;
8import java.util.logging.LogManager;
9import java.util.logging.Logger;
10
11public class DemoHandler implements StreamHandler {
12 static {
13 try{
14 InputStream input = DemoHandler.class.getResourceAsStream("/logger.properties");
15 LogManager.getLogManager().readConfiguration(input);
16 }catch (Exception e){
17 e.printStackTrace();
18 }
19 }
20 Logger logger = Logger.getLogger(DemoHandler.class);
21 public void handler(InputStream input, OutputStream output, CfcContext context) throws Exception {
22 logger.info("info log");
23 logger.warning("warn log");
24 output.write("hello world!".getBytes());
25 }
26}
使用 log4j 输出日志
增加依赖
在保留前文 cfc-java-core 依赖的基础上,在 pom.xml 文件的 <dependencies> 标签下加入以下内容:
1<dependency>
2 <groupId>log4j</groupId>
3 <artifactId>log4j</artifactId>
4 <version>1.2.17</version>
5</dependency>
6<dependency>
7 <groupId>com.fasterxml.jackson.core</groupId>
8 <artifactId>jackson-databind</artifactId>
9 <version>2.13.5</version>
10</dependency>
配置 log4j
创建配置文件 src/main/resources/log4j.properties。
1log4j.rootLogger = debug,stdout
2
3### 输出信息到控制台 ###
4log4j.appender.stdout = org.apache.log4j.ConsoleAppender
5log4j.appender.stdout.Target = System.out
6log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
7log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
代码中使用 log4j
其余 pom.xml 打包配置和 App.java 均可复用前文 Event 模式示例。创建 src/main/java/com/baidu/demo/log4j/DemoHandler.java,写入以下内容:
1package com.baidu.demo.log4j;
2
3import com.baidubce.cfc.core.CfcContext;
4import com.baidubce.cfc.core.StreamHandler;
5import com.fasterxml.jackson.databind.ObjectMapper;
6import org.apache.log4j.Logger;
7
8import java.io.InputStream;
9import java.io.OutputStream;
10import java.io.PrintStream;
11
12public class DemoHandler implements StreamHandler {
13 private static final Logger LOGGER = Logger.getLogger(DemoHandler.class);
14
15 public static class InvokeEvent {
16 private String event;
17
18 public String getEvent() {
19 return event;
20 }
21
22 public void setEvent(String event) {
23 this.event = event;
24 }
25 }
26
27 @Override
28 public void handler(InputStream input, OutputStream output, CfcContext context) throws Exception {
29 ObjectMapper mapper = new ObjectMapper();
30 InvokeEvent event = mapper.readValue(input, InvokeEvent.class);
31 if (event.getEvent() != null) {
32 LOGGER.info(event.getEvent());
33 }
34
35 PrintStream stream = new PrintStream(output);
36 stream.println("Hello world");
37 stream.close();
38 }
39}
该示例的入口参数与前文 Event 模式中的 StreamHandler 示例一致。上传代码时,将处理程序填写为 com.baidu.demo.log4j.DemoHandler,打包方式与前文 Event 模式一致。
例如,向函数传入 {"event":"hello-from-log4j"} 后,函数返回结果与日志尾部示例如下:
1Hello world
2
3START RequestId: <request-id> Version: $LATEST
4[INFO ] <timestamp> method:com.baidu.demo.log4j.DemoHandler.handler(DemoHandler.java:<line-number>)
5hello-from-log4j
6END RequestId: <request-id>
7REPORT RequestId: <request-id> Duration: <duration-ms> Billed Duration: <billed-duration-ms> Max Memory Used: <memory-used>
代码示例
- 本章节中举例的Event模式的简单示例,请点击下载 简单示例
- 本章节中举例的Stream模式示例,请点击下载使用Stream模式
- 本章节中举例的log4j输出日志示例,请点击下载 使用log4j输出日志
评价此篇文章
