
# 使用已有SpringBoot项目构建HTTP函数
#### 方案概述
本章节主要指导使用Springboot开发应用的用户，部署业务到FunctionGraph。
用户通常可以使用[SpringInitializr](https://start.spring.io/)或者IntelliJ IDEA新建等多种方式构建SpringBoot，本章节以Spring.io 的[RESTful Web Service](https://spring.io/guides/gs/rest-service/)项目为例，使用HTTP函数的方式部署到FunctionGraph上。
#### 操作流程
将既有项目部署到FunctionGraph通常只需要：修改项目监听端口号为8000，然后在jar包同目录创建bootstrap文件写入执行jar包的命令。
本案例使用IntelliJ IDEA，Maven项目。
**构建代码包**
1. 打开Springboot项目，在maven插件处单击package，生成jar包。
   图1生成jar包   
   ![](https://support.huaweicloud.com/bestpractice-functiongraph/zh-cn_image_0000002165305677.png "点击放大") 
2. 配置工程web端口。HTTP函数当前支持8000端口，需配置工程web端口为 8000**（此端口请勿修改）** , 可以使用application.properties文件来配置，也可以在启动时指定端口号。
   图2配置8000端口   
   ![](https://support.huaweicloud.com/bestpractice-functiongraph/zh-cn_image_0000002165184125.png "点击放大") 
3. 在jar包同目录创建bootstrap文件，输入启动参数。
   ```
   /opt/function/runtime/java11/rtsp/jre/bin/java -jar -Dfile.encoding=utf-8 /opt/function/code/rest-service-complete-0.0.1-SNAPSHOT.jar
   ```
   ![](https://support.huaweicloud.com/bestpractice-functiongraph/public_sys-resources/note_3.0-zh-cn.png)
   函数中可直接调用Java运行环境，无需另外安装。
   图3输入启动参数   
   ![](https://support.huaweicloud.com/bestpractice-functiongraph/zh-cn_image_0000002129786170.png "点击放大")
   
   
4. 选中jar包和bootstrap文件，打包成zip包。
**创建HTTP函数并上传代码**
创建1个HTTP函数，并上传已打包的zip包。请参见[创建HTTP函数](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_1441.html)。
**验证结果**
- 使用函数测试事件验证
  1. 在函数详情页，选择函数版本，单击"配置测试事件"，弹出"配置测试事件"页。
  
  2. 选择事件模板，修改测试事件中的path、pathParameters参数，构建一个简单的Get请求。
     图4配置测试事件   
     ![](https://support.huaweicloud.com/bestpractice-functiongraph/zh-cn_image_0000002165305669.png "点击放大") 
  
  3. 单击"创建"，完成测试事件创建。
  
  4. 单击"测试"，获取响应。 **建议在测试时函数内存规格、超时时间调大，如512MB、5s。**
     图5查看函数返回结果   
     ![](https://support.huaweicloud.com/bestpractice-functiongraph/zh-cn_image_0000002129786182.png "点击放大") 
   
- 配置APIG触发器测试
  1. 请参见[使用APIG触发器](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_0204.html)，创建APIG专享版触发器，"安全认证"建议选择"None"，方便调试。
  
  2. 复制生成的调用URL在浏览器进行访问。如[图 调用函数]所示，在URL后添加请求参数*greeting?name=fg_user* ，响应如下。
     图6调用函数   
     ![](https://support.huaweicloud.com/bestpractice-functiongraph/zh-cn_image_0000002129944342.png "点击放大")
     默认生成的APIG触发器的调用URL为"域名/函数名"，在本案例中即：https://your_host.com/springboot_demo，URL中包含了函数名springboot_demo作为path的第一部分。如果直接Get https://your_host.com/springboot_demo/greeting，springboot接收到的请求地址将包含springboot_demo/greeting两部分。此处需注意： 如果用户直接把已有的工程上传，会因为path里多了函数名而无法直接访问自己的服务。因此，请参考以下两种方法注解或去除函数名。
     - 方法一：修改代码中的Mapping地址，例如在GetMapping注解或者类注解上添加默认的path第一部分。
       图7修改Mapping地址   
       ![](https://support.huaweicloud.com/bestpractice-functiongraph/zh-cn_image_0000002165184113.png "点击放大") 
     
     - 方法二：单击触发器名称，跳转至API网关服务，直接修改path去除函数名。
      
   
 
#### 常见问题
1. 我的代码可以访问哪些目录？ 根据上文中的bootstrap文件里的命令，可以看出上传的代码包最终被存在函数实例（指函数运行的环境/计算资源，可以理解为容器）/opt/function/code/ 路径。但是该目录只可以读，不可以写入。 如果您希望在代码运行期间写入一些数据到实例里，打印日志到本地，或者您使用的依赖默认写入jar所在的目录，请对/tmp目录进行写入操作。
   
2. 我的日志如何被收集，应该怎么输出日志？ 函数实例在一段时间内没有请求会被销毁，写入到本地日志会同时被销毁，当前用户也无法在函数运行中查看函数本地日志，所以建议不要仅将日志写入到本地。产生的日志建议输出到控制台，如配置log4j输出target为System.out，或直接用print函数打印日志等。
   输出到控制台的日志，会被函数系统收集，如果用户开通LTS服务，日志会被放入LTS 可以进行较为实时的日志分析。
   调测建议：建议在调测时候[开通LTS日志](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_1834.html#section2)，单击"到LTS进行日志分析"，在实时日志中进行观察分析。
   图8到LTS进行日志分析   
   ![](https://support.huaweicloud.com/bestpractice-functiongraph/zh-cn_image_0000002129786186.png "点击放大") 
3. 我的代码具有什么用户的执行权限？ 和普通事件函数一样，代码执行时并没有root权限，因此需要root权限的代码或者命令都无法在HTTP函数里执行。
   
4. 如何为多个模块的springboot项目进行打包配置？
   您需要为多个模块的springboot项目设置以下打包配置：
   ```
   <build>
           <plugins>
               <plugin>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-maven-plugin</artifactId>
                   <configuration>
                       <mainClass>com.example.YourServiceMainClass</mainClass>
                   </configuration>
                   <executions>
                       <execution>
                           <goals>
                               <goal>repackage</goal>
                           </goals>
                       </execution>
                   </executions>
               </plugin>
           </plugins>
   </build>
   ```
   
 
