函数计算CFC

    Java

    函数计算支持使用Java进行编程,支持以下Java运行环境

    • OpenJDK 1.8.0

    Java语言由于需要编译以后才可以在JVM虚拟机中运行,因此CFC不支持在线编辑代码,仅仅支持通过web页面上传编译好的zip包和从BOS上传zip包两种方式上传代码。

    当前CFC的Java运行时支持两种事件模式,点击下面链接您可以快速查看两种模式的简单开发示例

    • event模式:所有触发器类型均支持该模式
    • stream模式:如果触发器类型是HTTP触发器,还支持stream模式

    简单示例(event事件模式)

    环境准备

    确保您已经安装了JAVA和Maven。

    创建项目

    本示例使用开源Java项目管理工具Maven进行管理, 使用mvn命令行工具创建了一个groupId为com.baidu.demo,artifactId为bce-cfc-java-demo简单函数项目。, 命令如下。

    $ mvn archetype:generate \
      -DgroupId=com.baidu.demo \
      -DartifactId=bce-cfc-java-demo \
      -Dversion=1.0 \
      -DarchetypeArtifactId=maven-archetype-quickstart \
      -DinteractiveMode=no

    运行完成之后,执行 tree 命令查看目录结构,应该是这样的

    .
    ├── pom.xml
    └── src
        ├── main
        │   └── java
        │       └── com
        │           └── baidu
        │               └── demo
        │                   └── App.java
        └── test
            └── java
                └── com
                    └── baidu
                        └── demo
                            └── AppTest.java
    
    11 directories, 3 files

    编写代码

    在使用 Java 编程时,您首先需要定义一个函数入口类。创建文件 src/main/java/com/baidu/demo/SimpleHandler.java,写入以下内容,以下是一个最简单的入口函数:

    package com.baidu.demo;
    
    import com.baidubce.cfc.core.CfcContext;
    import com.baidubce.cfc.core.StreamHandler;
    
    import java.io.InputStream;
    import java.io.OutputStream;
    
    public class SimpleHandler implements StreamHandler {
        @Override
        public void handler(InputStream input, OutputStream output, CfcContext context) throws Exception {
            System.out.println("console outlog");
            System.err.println("console errlog");
            output.write("hello world!".getBytes());
        }
    }

    一些说明:

    • 函数入口类需要继承并实现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,写入以下内容:

    package com.baidu.demo;
    
    import com.baidubce.cfc.core.CfcClient;
    
    public class App
    {
        public static void main(String args[])
        {
            CfcClient.main();
        }
    }

    main入口函数中调用CfcClient.main进入函数运行时执行

    maven编译并打包函数代码

    在项目文件夹根目录创建pom.xml编译文件,可以在通过编辑pom.xml增加依赖和plugin配置, 以下分别给出示例

    增加依赖:

    函数计算相关接口定义于bce-cfc-java-core包中,可以通过在pom.xml中增加以下 pom 定义引入该包依赖。在 <dependencies> 标签下加入这一段:

    <dependency>
        <groupId>com.baidubce.cfc</groupId>
        <artifactId>bce-cfc-java-core</artifactId>
        <version>2.0.0</version>
    </dependency>

    增加 plugin 配置

    在 pom.xml文件中添加 maven-assembly-plugin,构建一个可执行jar包。添加maven-dependency-plugin,将jar包所依赖的其他jar包拷贝至${project.build.directory}/lib目录。 在 project 标签下增加如下的两项:

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>3.1.1</version>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                            <overWriteReleases>false</overWriteReleases>
                            <overWriteSnapshots>false</overWriteSnapshots>
                            <overWriteIfNewer>true</overWriteIfNewer>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <!-- Build an executable JAR -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.0.2</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>com.baidu.demo.App</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

    发布

    // 打包
    $ mvn package
    
    // zip压缩
    $ cd target
    $ zip -r bce-cfc-java-demo.zip bce-cfc-java-demo-1.0.jar lib/

    配置函数

    创建函数时使用如下配置:

    1. 在函数管理页面,点击“创建函数”,进入创建函数页面。
    2. 填写您的函数名称等基本信息,运行时选择"java8",点击 提交image.png
    3. 在创建成功页面,选择进入代码编辑页面 image.png
    4. 选择"上传.zip文件",将上一步中压缩生成的zip文件上传至百度云。
    5. 处理程序中填写函数入口类名称,本例中为com.baidu.demo.SimpleHandlerimage.png

    进阶用法(stream模式)

    特别地,对于http trigger请求,除了可以使用普通的event模式进行处理外,还可以使用stream模式进行处理。在stream模式下,将启动一个http server接收并处理http trigger请求。

    创建函数

    与普通event模式不同,需要将事件模式设置为stream

    编辑代码

    下面显示了一个使用stream模式处理http trigger请求的例子,项目名称为httptrigger-demo。您首先需要定义一个函数入口类Demo, 需要继承并实现com.baidubce.cfc.core.http.HttpRequestHandler接口, 接口包含一个函数handleRequest,该函数包含三个参数 handler函数有三个参数:

    • request表示请求
    • response表示响应
    • context表示函数运行时信息,使用context需要在代码中导入"com.baidubce.cfc.core.CfcContext"
    package com.baidubce.httptrigger.demo;
    
    import com.baidubce.cfc.core.http.CfcContext;
    import com.baidubce.cfc.core.http.HttpRequestHandler;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.logging.Logger;
    
    public class Demo implements HttpRequestHandler {
        Logger logger =  Logger.getLogger("java.util.logging.ConsoleHandler");
    
        public void handleRequest(HttpServletRequest request,
                                  HttpServletResponse response,
                                  CfcContext context) throws ServletException, IOException {
            logger.info(String.format("requestid=%s", context.getRequestId()));
            logger.info(String.format("appid=%s", context.getApiID()));
            logger.info(String.format("clientip=%s", context.getClientIP()));
            response.getOutputStream().print("hello world!");
        }
    }

    因为该模式使用jetty, java runtime已经集成main函调用,无需单独写main调用cfcclient.main。

    maven打包函数代码

    添加依赖。

    与event模式不同,stream模式依赖bce-cfc-java-httpcore包。

    <dependencies>
        <dependency>
            <groupId>com.baidubce.cfc</groupId>
            <artifactId>bce-cfc-java-httpcore</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>

    添加 plugin配置。

    在package阶段增加了copy-dependencies功能,它将函数依赖的所有jar包拷贝到target/lib目录。同时,设置入口点mainClass为com.baidubce.cfc.core.http.CfcClient

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>3.1.1</version>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                            <overWriteReleases>false</overWriteReleases>
                            <overWriteSnapshots>false</overWriteSnapshots>
                            <overWriteIfNewer>true</overWriteIfNewer>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <!-- Build an executable JAR -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.0.2</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>com.baidubce.cfc.core.http.CfcClient</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

    打包

    $ cd target/
    $ zip -r httptrigger-demo.zip httptrigger-demo-1.0.0.jar lib/

    上传代码

    在函数编辑页面上传代码,步骤与普通event模式上传方式相同

    处理POJO

    除了StreamHandler外,运行时还支持直接处理POJO,可以通过实现RequestHandler<REQ, RSP>接口处理POJO。 支持的类型有:String,Integer,Boolean和其他可通过json序列化的自定义类型。

    日志

    使用Logger输出日志

    创建logger配置文件

    创建logger配置文件 src/main/resources/logger.properties

    handlers = java.util.logging.ConsoleHandler
    
    java.util.logging.ConsoleHandler.level=INFO
    java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter

    初始化并使用logger

    package com.baidu.demo;
    
    import com.baidubce.cfc.core.CfcContext;
    import com.baidubce.cfc.core.StreamHandler;
    
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.logging.LogManager;
    import java.util.logging.Logger;
    
    public class DemoHandler implements StreamHandler {
     static {
           try{
            InputStream input = DemoHandler.class.getResourceAsStream("/logger.properties");
                LogManager.getLogManager().readConfiguration(input);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        Logger logger = Logger.getLogger(DemoHandler.class);
        public void handler(InputStream input, OutputStream output, CfcContext context) throws Exception {
           logger.info("info log");
           logger.warning("warn log");
           output.write("hello world!".getBytes());
        }
    }

    使用log4j输出日志

    增加依赖:

    在pom.xml文件中,> 标签下加入这一段:

    <dependency>
    	<groupId>log4j</groupId>
    	<artifactId>log4j</artifactId>
    	<version>1.2.17</version>
    </dependency>

    配置log4j

    创建配置文件src/main/resources/log4j.properties

    log4j.rootLogger = debug,stdout
    
    ### 输出信息到控制台 ###
    log4j.appender.stdout = org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target = System.out
    log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

    代码中使用log4j

    package com.baidu.demo.log4j;
    
    import com.baidubce.cfc.core.StreamHandler;
    import org.apache.log4j.Logger;
    import com.baidubce.cfc.core.CfcContext;
    import com.baidubce.cfc.core.StsCredential;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.PrintStream;
    
    public class DemoHandler  implements StreamHandler {
        Logger logger = Logger.getLogger(DemoHandler.class);
    
        public DemoHandler() {
        }
    
        public void handler(InputStream input, OutputStream output, CfcContext context) throws Exception {
            ObjectMapper mapper = new ObjectMapper();
            InvokeEvent event = mapper.readValue(input, InvokeEvent.class);
            if (event.getEvent() != null) {
                logger.info(event.getEvent());
            }
    
            PrintStream stream = new PrintStream(output);
            stream.println("Hello world");
            stream.close();
        }
    }

    代码示例

    上一篇
    Golang
    下一篇
    C#