全部产品
云市场

Java 运行环境

更新时间:2020-03-31 10:59:37

函数计算目前支持 Java OpenJDK 1.8.0 (runtime = java8) 运行环境,本文介绍了 Java 运行环境的以下内容:

打印日志

函数通过 context.getLogger() 打印的内容会被收集到在创建服务时指定的 LogStore 中。

  1. package example;
  2. import com.aliyun.fc.runtime.Context;
  3. import com.aliyun.fc.runtime.StreamRequestHandler;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. public class HelloFC implements StreamRequestHandler {
  8. @Override
  9. public void handleRequest(
  10. InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
  11. context.getLogger().info("hello world");
  12. outputStream.write(new String("hello world").getBytes());
  13. }
  14. }

执行上面的代码输出的日志内容如下所示。

  1. message:2017-07-05T05:13:35.920Z a72df088-f738-cee3-e0fe-323ad89118e5 [INFO] hello world

使用 context.getLogger().warncontext.getLogger().error 分别可以打包 WARN、ERROR 级别的日志。

错误处理

您的函数如果在执行过程抛出异常,函数计算会把异常捕获并将异常信息返回。

  1. package example;
  2. import com.aliyun.fc.runtime.Context;
  3. import com.aliyun.fc.runtime.StreamRequestHandler;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. public class HelloFC implements StreamRequestHandler {
  8. @Override
  9. public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
  10. throw new IOException("oops");
  11. }
  12. }

调用时收到的响应如下所示。

  1. >>> invk hello-java -f /tmp/a.json
  2. {
  3. "errorMessage" : "oops",
  4. "errorType" : "java.io.IOException",
  5. "errorCause" : "oops",
  6. "stackTrace" : [ "example.HelloFC.handleRequest(HelloFC.java:15)" ]
  7. }
  8. Error: Request id: 45dd8d90-6b78-cce3-087c-8bf4ebc6c9af. Error type: UnhandledInvocationError

发生异常时,函数调用的响应的HTTP header 中会包含 X-Fc-Error-Type: UnhandledInvocationError

错误类型的更多信息,请参见错误类型

使用自定义模块

如果您需要使用自定义的模块,则需要在打包 jar 时,将它们与代码一起打包。下文演示如何将 OSS Java SDK 打包到项目中。

环境准备

确保您已经安装 Java 和 Maven。您可以通过官网下载安装合适您系统的 JDK。
Maven 安装详情请参见 Installing Apache Maven

使用 maven 命令安装依赖并打包上传

1.创建一个 Java 项目,目录结构如下。

  1. test/src/main/java/example/App.java

2.在 App.java 文件内输入如下内容。

  1. package example;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.OutputStream;
  5. import com.aliyun.fc.runtime.Context;
  6. import com.aliyun.fc.runtime.StreamRequestHandler;
  7. import com.aliyun.fc.runtime.FunctionInitializer;
  8. /**
  9. * Hello world!
  10. *
  11. */
  12. public class App implements StreamRequestHandler, FunctionInitializer {
  13. public void initialize(Context context) throws IOException {
  14. }
  15. public void handleRequest(
  16. InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
  17. outputStream.write(new String("hello world\n").getBytes());
  18. }
  19. }

3.在项目文件夹根目录下创建 pom.xml 文件,在 pom.xml 中添加 maven-assembly-plugin 插件内容如下。

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>example</groupId>
  5. <artifactId>Java-example</artifactId>
  6. <packaging>jar</packaging>
  7. <version>1.0-SNAPSHOT</version>
  8. <name>Java-example</name>
  9. <properties>
  10. <maven.compiler.target>1.8</maven.compiler.target>
  11. <maven.compiler.source>1.8</maven.compiler.source>
  12. <maven.test.skip>true</maven.test.skip>
  13. </properties>
  14. <build>
  15. <plugins>
  16. <plugin>
  17. <artifactId>maven-assembly-plugin</artifactId>
  18. <version>3.1.0</version>
  19. <configuration>
  20. <descriptorRefs>
  21. <descriptorRef>jar-with-dependencies</descriptorRef>
  22. </descriptorRefs>
  23. <appendAssemblyId>false</appendAssemblyId> <!-- this is used for not append id to the jar name -->
  24. </configuration>
  25. <executions>
  26. <execution>
  27. <id>make-assembly</id> <!-- this is used for inheritance merges -->
  28. <phase>package</phase> <!-- bind to the packaging phase -->
  29. <goals>
  30. <goal>single</goal>
  31. </goals>
  32. </execution>
  33. </executions>
  34. </plugin>
  35. <plugin>
  36. <groupId>org.apache.maven.plugins</groupId>
  37. <artifactId>maven-compiler-plugin</artifactId>
  38. <configuration>
  39. <source>1.8</source>
  40. <target>1.8</target>
  41. </configuration>
  42. </plugin>
  43. </plugins>
  44. </build>
  45. </project>

4.项目需要引用 Maven Central 的外部包,可以根据需要添加依赖,下文以 OSS Java SDK 为例,pom.xml 文件内容如下。

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>example</groupId>
  5. <artifactId>Java-example</artifactId>
  6. <packaging>jar</packaging>
  7. <version>1.0-SNAPSHOT</version>
  8. <name>Java-example</name>
  9. <dependencies>
  10. <dependency>
  11. <groupId>com.aliyun.fc.runtime</groupId>
  12. <artifactId>fc-java-core</artifactId>
  13. <version>1.3.0</version>
  14. </dependency>
  15. <dependency>
  16. <groupId>com.aliyun.oss</groupId>
  17. <artifactId>aliyun-sdk-oss</artifactId>
  18. <version>2.6.1</version>
  19. </dependency>
  20. </dependencies>
  21. <properties>
  22. <maven.compiler.target>1.8</maven.compiler.target>
  23. <maven.compiler.source>1.8</maven.compiler.source>
  24. <maven.test.skip>true</maven.test.skip>
  25. </properties>
  26. <build>
  27. <plugins>
  28. <plugin>
  29. <artifactId>maven-assembly-plugin</artifactId>
  30. <version>3.1.0</version>
  31. <configuration>
  32. <descriptorRefs>
  33. <descriptorRef>jar-with-dependencies</descriptorRef>
  34. </descriptorRefs>
  35. <appendAssemblyId>false</appendAssemblyId> <!-- this is used for not append id to the jar name -->
  36. </configuration>
  37. <executions>
  38. <execution>
  39. <id>make-assembly</id> <!-- this is used for inheritance merges -->
  40. <phase>package</phase> <!-- bind to the packaging phase -->
  41. <goals>
  42. <goal>single</goal>
  43. </goals>
  44. </execution>
  45. </executions>
  46. </plugin>
  47. <plugin>
  48. <groupId>org.apache.maven.plugins</groupId>
  49. <artifactId>maven-compiler-plugin</artifactId>
  50. <configuration>
  51. <source>1.8</source>
  52. <target>1.8</target>
  53. </configuration>
  54. </plugin>
  55. </plugins>
  56. </build>
  57. </project>

5.在项目的根目录下执行mvn package命令打包,编译输出类似如下。

  1. $mvn package
  2. [INFO] Scanning for projects...
  3. ... .... ....
  4. [INFO] --------------------------< example:example >---------------------------
  5. [INFO] Building Java-example 1.0-SNAPSHOT
  6. [INFO] --------------------------------[ jar ]---------------------------------
  7. ... .... ....
  8. [INFO] ------------------------------------------------------------------------
  9. [INFO] BUILD SUCCESS
  10. [INFO] ------------------------------------------------------------------------
  11. [INFO] Total time: 11.681 s
  12. [INFO] Finished at: 2020-03-26T15:55:05+08:00
  13. [INFO] ------------------------------------------------------------------------

如果显示编译失败,请根据输出的编译错误信息调整代码。
编译后的 jar 包位于项目文件夹内的 target 目录内,并根据 pom.xml 内的 artifactId、version 字段命名为 Java-example-1.0-SNAPSHOT.jar
6.您通过函数计算控制台代码执行页面,选择 OSS 上传或者代码包上传方式上传上述步骤打包的 jar 包。

您也可以使用 maven-shade-plugin 插件进行打包。
通常上述的打包能够满足大多数的使用场景。但是如果您想把某些没有被 Maven 管理 JAR 包打入到最终的 JAR 中,比如您在 resources/lib 下引入的其他非 Maven 仓库中的 JAR,此时可以使用 maven-jar-pluginmaven-dependency-plugin 插件将其打入最终的 JAR 中。

使用 IDEA 安装依赖并打包上传

  1. 本地创建 Java 项目,pom.xml 文件内容如下。
  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>example</groupId>
  5. <artifactId>Java-example</artifactId>
  6. <packaging>jar</packaging>
  7. <version>1.0-SNAPSHOT</version>
  8. <name>Java-example</name>
  9. <dependencies>
  10. <dependency>
  11. <groupId>com.aliyun.fc.runtime</groupId>
  12. <artifactId>fc-java-core</artifactId>
  13. <version>1.3.0</version>
  14. </dependency>
  15. <dependency>
  16. <groupId>com.aliyun.oss</groupId>
  17. <artifactId>aliyun-sdk-oss</artifactId>
  18. <version>2.6.1</version>
  19. </dependency>
  20. </dependencies>
  21. </project>

2.IDEA 导出 jar 包相关配置。

  • 选择 File -> Project Structure
  • 在弹出的窗口中左侧选中 Artifacts,单击 + 选择 JAR,然后选择 from modules with dependencies
  • 在配置窗口中使用默认配置就好,直接单击 OK
  • 回到 IDEA 的主菜单,选择 Build - Build Artifacts 下的Build 或者 Rebuild 即可生成 jar 包。

3.您可以在项目根目录下 out/artifacts/example_jar 目录中将导出的 jar 包上传函数计算。
您通过函数计算控制台代码执行页面,选择 OSS 上传或者代码包上传方式上传导出的 jar 包。

使用 Fun 工具打包部署

如果您使用 Fun 部署应用,可以使用 fun build 命令来构建。fun build 的详细信息,请参见使用 fun build 构建代码包

1.在工程的根目录下创建 template.yml 文件,内容如下。

  1. ROSTemplateFormatVersion: '2015-09-01'
  2. Transform: 'Aliyun::Serverless-2018-04-03'
  3. Resources:
  4. JavaDemo:
  5. Type: 'Aliyun::Serverless::Service'
  6. Properties:
  7. Description: 'helloworld'
  8. test:
  9. Type: 'Aliyun::Serverless::Function'
  10. Properties:
  11. Handler: example.App::handleRequest
  12. Initializer: example.App::initialize
  13. Runtime: java8
  14. CodeUri: './'

2.执行以下命令将工程打包。

  1. $fun build
  2. using template: template.yml
  3. start building function dependencies without docker
  4. building JavaDemo/test
  5. running task flow MavenTaskFlow
  6. running task: MavenCompileTask
  7. running task: MavenCopyDependencies
  8. running task: CopyMavenArtifacts
  9. Build Success
  10. Built artifacts: .fun/build/artifacts
  11. Built template: .fun/build/artifacts/template.yml
  12. Tips for next step
  13. ======================
  14. * Invoke Event Function: fun local invoke
  15. * Invoke Http Function: fun local start
  16. * Deploy Resources: fun deploy

3.执行以下命令部署函数。

  1. $fun deploy -y
  2. using template: .fun/build/artifacts/template.yml
  3. using region: cn-qingdao
  4. using accountId: ***********3743
  5. using accessKeyId: ***********Ptgk
  6. using timeout: 60
  7. Collecting your services information, in order to caculate devlopment changes...
  8. Resources Changes(Beta version! Only FC resources changes will be displayed):
  9. ***********
  10. Waiting for service JavaDemo to be deployed...
  11. Waiting for function test to be deployed...
  12. Waiting for packaging function test code...
  13. The function test has been packaged. A total of 3 files were compressed and the final size was 330.35 KB
  14. function test deploy success
  15. service JavaDemo deploy success


登录函数计算控制台,即可看到相关的服务、函数被创建成功,且触发执行可以返回正确的结果。