
# Java SDK使用指导
本章节介绍了Java SDK的使用说明，您可以参考本章节进行快速集成开发。
 #### 开发前准备
- 已[注册](https://reg.huaweicloud.com/registerui/public/custom/register.html?locale=zh-cn#/register)华为账号并开通华为云，完成[实名认证](https://support.huaweicloud.com/usermanual-account/account_auth_00001.html)。
- 具备已备案的域名用于直播推流和播放，并在视频直播控制台[添加推流和播放域名](https://support.huaweicloud.com/iLive-live/live010002.html)，且已完成[域名关联](https://support.huaweicloud.com/iLive-live/live_01_0026.html)。
- 已具备开发环境 ，支持Java JDK 1.8及以上版本。
- 已获取华为云账号对应的Access Key（AK）和Secret Access Key（SK）。请在华为云控制台"我的凭证 \> 访问密钥"页面上创建和查看您的AK/SK。具体请参见[访问密钥](https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html)。
- 已获取直播服务对应区域的项目ID，请在华为云控制台"我的凭证 \> API凭证"页面上查看项目ID。具体请参见[API凭证](https://support.huaweicloud.com/usermanual-ca/ca_01_0002.html)。
 
#### 注意事项
当用户自己引入的三方库版本和Live业务依赖的三方库版本发生冲突时，例如Jackson，okhttp3版本冲突等。可以引入如下bundle包(3.0.40-rc版本后)，重定向SDK依赖的第三方库版本，解决版本冲突问题。详情请访问[SDK开发中心](https://console.huaweicloud.com/apiexplorer/#/sdkcenter)，查看视频直播Java SDK的"整个SDK Bundle包"内容。
注意：bundle包已经包含了core包和云服务集合包，不需要再单独引入core包和服务包。否则根据maven依赖的解析顺序，可能会导致bundle包不生效。
```
<dependency>
    <groupId>com.huaweicloud.sdk</groupId>
    <artifactId>huaweicloud-sdk-bundle</artifactId>
    <version>${version}</version>
</dependency>
```
#### 安装SDK
您可以通过Maven方式获取和安装SDK，首先需要在您的操作系统中[下载](https://maven.apache.org/download.cgi)并[安装Maven](https://maven.apache.org/install.html) ，安装完成后您只需要在Java项目的pom.xml文件中加入相应的依赖项即可。
使用服务端SDK前，您需要安装"huaweicloud-sdk-core"和"huaweicloud-sdk-live"，具体的SDK版本号请参见[SDK开发中心](https://console.huaweicloud.com/apiexplorer/#/sdkcenter)。
![](https://support.huaweicloud.com/ssdk-live/public_sys-resources/caution_3.0-zh-cn.png)
以下代码示例中的**version**值，请根据实际的SDK版本号进行替换。
```
<dependency>
    <groupId>com.huaweicloud.sdk</groupId>
    <artifactId>huaweicloud-sdk-core</artifactId>
    <version>3.1.11</version>
</dependency>
<dependency>
    <groupId>com.huaweicloud.sdk</groupId>
    <artifactId>huaweicloud-sdk-live</artifactId>
    <version>3.1.11</version>
</dependency>
```
#### 开始使用
1. 导入依赖模块。 
   ```
   // 用户身份认证
   import com.huaweicloud.sdk.core.auth.BasicCredentials;
   // 请求异常类
   import com.huaweicloud.sdk.core.exception.ClientRequestException;
   import com.huaweicloud.sdk.core.exception.ServerResponseException;
   // Http配置
   import com.huaweicloud.sdk.core.http.HttpConfig;
   // 导入live的客户端
   import com.huaweicloud.sdk.live.v1.LiveClient;
   // 导入待请求接口的request和response类
   import com.huaweicloud.sdk.live.v1.model.ShowTranscodingsTemplateRequest;
   import com.huaweicloud.sdk.live.v1.model.ShowTranscodingsTemplateResponse;
   // 日志打印
   import org.slf4j.Logger;
   import org.slf4j.LoggerFactory;
   ```
   
   
2. 配置客户端属性。 
   1. 默认配置。
      ```
      // 使用默认配置
      HttpConfig config = HttpConfig.getDefaultHttpConfig();
      ```
      
   
   2. （可选操作）配置代理。
      ```
      // （可选）使用代理服务器
      // 代理服务器的password直接写入代码，会有很大安全风险。建议密文形式存储在配置文件或者环境变量中，待使用时再解密，以确保安全。
      // 代理配置设置前，请先在本地环境中设置环境变量PROXY_PASSWORD
      config.withProxyHost("http://proxy.huaweicloud.com")
          .withProxyPort(8080)
          .withProxyUsername("test")
          .withProxyPassword(System.getenv("PROXY_PASSWORD"));
      ```
      
   
   3. （可选操作）配置连接。
      ```
      // （可选）配置连接超时
      config.withTimeout(3);
      ```
      
   
   4. （可选操作）配置SSL。
      ```
      // （可选）配置跳过服务端证书校验
      config.withIgnoreSSLVerification(true);
      ```
      
   
   
   
   
3. 初始化认证信息。 
   支持以下两种认证方式，您可以根据实际情况进行选择。
   - 使用永久AK/SK 需要先获取永久AK和SK，以及projectId，您可以参考[开发前准备]获取。
     ```
     BasicCredentials credentials = new BasicCredentials()
         .withAk(ak)
         .withSk(sk)
         .withProjectId(projectId)
     ```
     
   
   - 使用临时AK/SK 首先需要获取临时AK、SK和SecurityToken，您可以[通过token获取](https://support.huaweicloud.com/api-iam/iam_04_0002.html)或者[通过委托授权获取](https://support.huaweicloud.com/api-iam/iam_04_0101.html)。
     ```
     BasicCredentials credentials = new BasicCredentials()
             .withAk(ak)
             .withSk(sk)
             .withSecurityToken(securityToken)
             .withProjectId(projectId)
     ```
     
   
   
   相关参数说明如下所示：
   - **ak**：华为云账号Access Key，建议以密文形式存储在配置文件或者环境变量中，待使用时再解密，以确保安全。
   
   - **sk**：华为云账号Secret Access Key，建议以密文形式存储在配置文件或者环境变量中，待使用时再解密，以确保安全。
   
   - **projectId**：云服务所在区域的项目ID ，根据您需要操作的项目所属区域选择对应的项目ID。
   
   - **securityToken**：采用临时AK/SK认证场景下的安全票据。
    
   
   
4. 初始化客户端。 
   ```
   //初始化直播服务的客户端
   LiveClient liveClient = LiveClient.newBuilder()
       .withHttpConfig(config)
       .withCredential(credentials)
       .withRegion(region)
       .build();
   ```
   **region：** 直播服务应用区域和各服务的终端节点，具体请参见[地区和终端节点](https://developer.huaweicloud.com/endpoint?Live)。
   
   
5. 发送请求并查看响应。 
   ```
   // 初始化请求，以调用查询转码模板接口为例
   ShowTranscodingsTemplateResponse showTranscodingsTemplateResponse = liveClient.showTranscodingsTemplate(
       new ShowTranscodingsTemplateRequest().withDomain(domain) // domain 为需要查询的域名 
   );
   logger.info(showTranscodingsTemplateResponse.toString());
   ```
   
   
6. 异常处理。 
   表1异常处理 
   | 一级分类                     | 一级分类说明  | 二级分类                     | 二级分类说明                      |
   |:---|:---|:---|:---|
   | ConnectionException      | 连接类异常   | HostUnreachableException | 网络不可达、被拒绝                   |
   | ConnectionException      | 连接类异常   | SslHandShakeException    | SSL认证异常                     |
   | RequestTimeoutException  | 响应超时异常  | CallTimeoutException     | 单次请求，服务器处理超时未返回             |
   | RequestTimeoutException  | 响应超时异常  | RetryOutageException     | 在重试策略消耗完成以后，仍无有效的响应         |
   | ServiceResponseException | 服务器响应异常 | ServerResponseException  | 服务端内部错误，Http响应码：\[500,\]    |
   | ServiceResponseException | 服务器响应异常 | ClientRequestException   | 请求参数不合法，Http响应码：\[400， 500) |
      
   ```
   // 异常处理
   try {
       ShowTranscodingsTemplateResponse showTranscodingsTemplateResponse = liveClient.showTranscodingsTemplate(
           new ShowTranscodingsTemplateRequest().withDomain("play.example.huaweicloud.com")
       );
   } catch(ServiceResponseException e) {
       logger.error("HttpStatusCode: " + e.getHttpStatusCode());
       logger.error("RequestId: " + e.getRequestId());
       logger.error("ErrorCode: " + e.getErrorCode());
       logger.error("ErrorMsg: " + e.getErrorMsg());
   }
   ```
   
   
7. 异步客户端使用。 
   ```
   // 初始化异步客户端
   LiveAPIAsyncClient liveAsyncClient = LiveAPIAsyncClient.newBuilder()
       .withHttpConfig(config)
       .withCredential(credentials)
       .withRegion(region)
       .build();
   // 发送异步请求
   CompletableFuture<ShowTranscodingsTemplateResponse> future = LiveAPIAsyncClient.showTranscodingsTemplate(
       new ShowTranscodingsTemplateRequest().withDomain("play.example.huaweicloud.com")
   );
   // 获取异步请求结果
   showTranscodingsTemplateResponse response = future.get();
   logger.info(response.toString());
   ```
   
   
8. 访问日志。 
   SDK在运行的时候采用了slf4j进行日志打印，如果在运行代码实例时，未配置日志实现库，会有提示如下：
   ```
   SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
   SLF4J: Defaulting to no-operation (NOP) logger implementation
   SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
   ```
   您可以根据目标项目实际情况引入对应的日志实现，请在对应的工程项目的pom.xml文件中引入日志实现的依赖，如下所示：
   - slf4j
     ```
     <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-simple</artifactId>
          <version>1.7.21</version>
      </dependency>
     logback
     <dependency>
         <groupId>ch.qos.logback</groupId>
         <artifactId>logback-classic</artifactId>
         <version>1.2.3</version>
     </dependency>
     <dependency>
         <groupId>ch.qos.logback</groupId>
         <artifactId>logback-core</artifactId>
         <version>1.2.3</version>
     </dependency>
     ```
     
   
   - log4j
     ```
     <dependency>
         <groupId>log4j</groupId>
         <artifactId>log4j</artifactId>
         <version>1.2.17</version>
     </dependency>
     ```
     
   
   
   SDK默认会打印访问日志，每次请求都会有一条记录，日志名称为"HuaweiCloud-SDK-Access"，日志格式如下所示：
   ```
   "{httpMethod} {uri}" {httpStatusCode} {responseContentLength} {requestId}
   ```
   其中"requestId"是华为云APIG返回的请求ID，可以用于问题跟踪。
   可以根据项目情况在对应的日志配置文件中对访问日志进行屏蔽，或者单独打印到独立文件中。例如在logback中关闭访问日志：
   ```
   <logger name="HuaweiCloud-SDK-Access" level="OFF"> </logger>
   ```
   
   
9. 原始HTTP侦听器。 
   在某些场景下可能对业务发出的HTTP请求进行Debug，需要看到原始的HTTP请求和返回信息，SDK提供侦听器功能获取原始的和加密的HTTP请求和返回信息。
   ![](https://support.huaweicloud.com/ssdk-live/public_sys-resources/caution_3.0-zh-cn.png)
   原始信息打印仅在debug阶段使用，请不要在生产系统中将原始的Http头和Body信息打印到日志中，这些信息并未加密且其中包含敏感数据；当Body体为二进制内容，即Content-Type标识为二进制时，body为"\*\*\*"，详细内容不输出。
   ```
   HttpConfig config = new HttpConfig().addHttpListener(HttpListener.forRequestListener(requestListener ->
       // 注册侦听器后打印Http Request原始信息，请勿在生产系统中使用
       logger.debug("REQUEST: {} {} {} {}",
           requestListener.httpMethod(),
           requestListener.uri(),
           requestListener.headers().entrySet().stream().flatMap(entry ->
               entry.getValue().stream().map(value -> entry.getKey() + " : " + value))
               .collect(Collectors.joining(";")),
           requestListener.body().orElse(""))));
       .addHttpListener(HttpListener.forResponseListener(responseListener ->
       // 注册侦听器后打印Http Request原始信息，请勿在生产系统中使用
       logger.debug("RESPONSE: {} {} {} {} {}",
           responseListener.httpMethod(),
           responseListener.uri(),
           responseListener.statusCode(),
           responseListener.headers().entrySet().stream().flatMap(entry ->
               entry.getValue().stream().map(value -> entry.getKey() + " : " + value))
               .collect(Collectors.joining(";")),
           responseListener.body().orElse(""))));
   LiveClient liveClient = LiveClient.newBuilder()
       .withHttpConfig(config)
       .withCredential(auth)
       .withRegion(region)
       .build();
   ```
   
   
 
#### 代码示例
调用前请根据实际情况替换如下变量：{your endpoint string} 和 {your project id}。
认证用的AK、SK直接写入代码，会有很大安全风险，建议密文形式存放在配置文件或者环境变量中，待使用时再解密，以确保安全。
本示例以AK、SK保存在环境变量中为例。运行本示例前，请先在本地环境中设置环境变量HUAWEICLOUD_SDK_AK和HUAWEICLOUD_SDK_SK。
```
package com.huaweicloud.sdk.test;
// 用户身份认证
import com.huaweicloud.sdk.core.auth.BasicCredentials;
// 请求异常类
import com.huaweicloud.sdk.core.exception.ClientRequestException;
import com.huaweicloud.sdk.core.exception.ServerResponseException;
// HTTP配置
import com.huaweicloud.sdk.core.http.HttpConfig;
// 导入直播服务的客户端
import com.huaweicloud.sdk.live.v1.LiveClient;
// 导入待请求接口的request和response类
import com.huaweicloud.sdk.live.v1.model.ShowTranscodingsTemplateRequest;
import com.huaweicloud.sdk.live.v1.model.ShowTranscodingsTemplateResponse;
// 日志打印
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Application {
    private static final Logger logger = LoggerFactory.getLogger(Application.class);
    public static void showTranscodingsTemplate(LiveClient client) {
        try {
            // 初始化请求，以调用查询转码模板接口为例
            ShowTranscodingsTemplateResponse showTranscodingsTemplateResponse = client.showTranscodingsTemplate(
                new ShowTranscodingsTemplateRequest().withDomain("play.example.huaweicloud.com")
            );
            // 输出json格式的字符串响应
            logger.info(showTranscodingsTemplateResponse.toString());
        } catch (ClientRequestException e) {
            logger.error("HttpStatusCode: " + e.getHttpStatusCode());
            logger.error("RequestId: " + e.getRequestId());
            logger.error("ErrorCode: " + e.getErrorCode());
            logger.error("ErrorMsg: " + e.getErrorMsg());
        }
    }
    public static void main(String[] args) {
        String ak = System.getenv("HUAWEICLOUD_SDK_AK");
        String sk = System.getenv("HUAWEICLOUD_SDK_SK");
        String endpoint = "{your endpoint string}";
        String projectId = "{your project id}";
        // 配置客户端属性
        HttpConfig config = HttpConfig.getDefaultHttpConfig();
        config.withIgnoreSSLVerification(true);
        // 创建认证
        BasicCredentials auth = new BasicCredentials()
            .withAk(ak)
            .withSk(sk)
            .withProjectId(projectId);
        // 创建liveClient实例并初始化
        LiveClient liveClient = LiveClient.newBuilder()
            .withHttpConfig(config)
            .withCredential(auth)
            .withRegion(region)
            .build();
        showTranscodingsTemplate(liveClient);
    }
}
```
