你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

适用于 Java 的Azure 应用程序配置客户端库 - 版本 1.4.10

Azure 应用配置是一项托管服务,可帮助开发人员轻松且安全地集中管理其应用程序配置。

新式程序,尤其是在云端运行的程序,通常具有多个事实上已分发的组件。 跨这些组件分散配置设置可能导致应用程序部署过程中出现难以解决的错误。 使用应用程序配置来存储应用程序的所有设置并在一个位置保证其访问权限的安全。

使用客户端库应用程序配置创建和管理应用程序配置设置。

源代码 | 包 (Maven) | API 参考文档 | 产品文档 | 样品

入门

先决条件

包括包

包括 BOM 文件

请将 azure-sdk-bom 包含在项目中,以依赖于库的正式发布 (GA) 版本。 在以下代码段中,将 {bom_version_to_target} 占位符替换为版本号。 若要详细了解 BOM,请参阅 AZURE SDK BOM 自述文件

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.azure</groupId>
            <artifactId>azure-sdk-bom</artifactId>
            <version>{bom_version_to_target}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

然后在依赖项部分中包括直接依赖项,不带版本标记,如下所示。

<dependencies>
  <dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-data-appconfiguration</artifactId>
  </dependency>
</dependencies>

包括直接依赖项

如果要依赖于 BOM 中不存在的特定库版本,请将直接依赖项添加到项目,如下所示。

<dependency>
  <groupId>com.azure</groupId>
  <artifactId>azure-data-appconfiguration</artifactId>
  <version>1.4.10</version>
</dependency>

创建应用程序配置应用商店

若要创建配置存储,可以使用 Azure 门户或 Azure CLI

需要先安装 Azure 应用配置 CLI 扩展,方法是通过执行以下命令:

az extension add -n appconfig

之后,创建配置存储:

az appconfig create --name <config-store-name> --resource-group <resource-group-name> --location eastus

验证客户端

若要与 应用程序配置 服务交互,需要创建 Configuration Client 类的实例。 为此,需要配置存储的连接字符串。 或者,使用 AAD 令牌连接到服务。

使用连接字符串

获取凭据

使用以下 Azure CLI 代码片段从配置存储中获取连接字符串。

az appconfig credential list --name <config-store-name>

或者,从 Azure 门户获取连接字符串。

创建配置客户端

获得 连接字符串值后,可以创建配置客户端:

ConfigurationClient configurationClient = new ConfigurationClientBuilder()
    .connectionString(connectionString)
    .buildClient();

ConfigurationAsyncClient configurationClient = new ConfigurationClientBuilder()
    .connectionString(connectionString)
    .buildAsyncClient();

使用 AAD 令牌

下面我们将演示如何使用 DefaultAzureCredential 作为服务主体进行身份验证。 但是,配置客户端接受任何 azure 标识 凭据。 有关其他凭据的详细信息,请参阅 azure-identity 文档。

(可选) 创建服务主体

Azure CLI 代码片段演示如何创建新的服务主体。 使用前,请将“your-application-name”替换为服务主体的相应名称。

创建服务主体:

az ad sp create-for-rbac --name http://my-application --skip-assignment

输出:

 {
     "appId": "generated app id",
     "displayName": "my-application",
     "name": "http://my-application",
     "password": "random password",
     "tenant": "tenant id"
 }

使用输出将 AZURE_CLIENT_ID (“appId”设置为高于 ) ,AZURE_CLIENT_SECRET) 上方 (“password ”,AZURE_TENANT_ID () 环境变量上方的“tenant”。 以下示例演示了在 Bash 中执行此操作的方法:

export AZURE_CLIENT_ID="generated app id"
export AZURE_CLIENT_SECRET="random password"
export AZURE_TENANT_ID="tenant id"

将一个适用的应用程序配置角色分配给服务主体。

创建客户端

设置 AZURE_CLIENT_IDAZURE_CLIENT_SECRETAZURE_TENANT_ID 环境变量后, DefaultAzureCredential 将能够对配置客户端进行身份验证。

构造客户端还需要配置存储的 URL,可以从 Azure CLI 或 Azure 门户获取该 URL。 在 Azure 门户中,URL 可以作为服务“终结点”列出。

DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
ConfigurationClient configurationClient = new ConfigurationClientBuilder()
    .credential(credential)
    .endpoint(endpoint)
    .buildClient();

关键概念

配置设置

配置设置是配置存储区中的基本资源。 在最简单的形式中,它是一个键和一个值。 但是,还有其他属性,例如可修改的内容类型和标记字段,它们允许以不同方式解释或关联值。

配置设置的 Label 属性提供了一种将配置设置分为不同维度的方法。 这些维度是用户定义的,可以采用任何形式。 用于标签的维度的一些常见示例包括区域、语义版本或环境。 许多应用程序都有一组必需的配置键,这些键具有不同的值,因为应用程序存在于不同的维度中。 例如,MaxRequests 在“NorthAmerica”中可能是 100,在“WestEurope”中可能是 200。 通过在“WestEurope”标签中创建一个名为 MaxRequests 的配置设置,其标签为“NorthAmerica”,另一个仅具有不同值的配置设置,可以实现一种解决方案,使应用程序能够在这两个维度中运行时无缝检索配置设置。

配置客户端

客户端执行与应用程序配置服务的交互,获取、设置、删除和选择配置设置。 SDK 中存在异步 ConfigurationAsyncClient、 和 同步 ConfigurationClient客户端,允许根据应用程序的用例选择客户端。

需要检索启动配置的应用程序更适合使用同步客户端,例如设置 SQL 连接。

ConfigurationClient configurationClient = new ConfigurationClientBuilder()
    .connectionString(connectionString)
    .buildClient();

// urlLabel is optional
String url = configurationClient.getConfigurationSetting(urlKey, urlLabel).getValue();
Connection conn = null;
try {
    conn = DriverManager.getConnection(url);
} catch (SQLException ex) {
    System.out.printf("Failed to get connection using url %s", url);
} finally {
    if (conn != null) {
        try {
            conn.close();
        } catch (SQLException ex) {
            System.out.printf("Failed to close connection, url %s", url);
        }
    }
}

具有需要定期更新的大量配置的应用程序更适合使用异步客户端,例如,具有特定标签的所有设置都会定期更新。

ConfigurationAsyncClient configurationClient = new ConfigurationClientBuilder()
    .connectionString(connectionString)
    .buildAsyncClient();

configurationClient.listConfigurationSettings(new SettingSelector().setLabelFilter(periodicUpdateLabel))
    .subscribe(setting -> updateConfiguration(setting));

示例

以下部分提供了几个代码片段,涵盖了一些最常见的配置服务任务,包括:有关“功能标志”和“机密参考”配置设置,请参阅 示例 了解更多详细信息。

创建配置客户端

通过使用 ConfigurationClientBuilder 传递连接字符串来创建配置客户端。

ConfigurationClient configurationClient = new ConfigurationClientBuilder()
    .connectionString(connectionString)
    .buildClient();

创建配置设置

创建要存储在配置存储中的配置设置。 可通过两种方法来存储配置设置:

  • addConfigurationSetting 仅当存储中尚不存在该设置时,才会创建设置。
ConfigurationSetting setting = configurationClient.addConfigurationSetting("new_key", "new_label", "new_value");

  • setConfigurationSetting 如果设置不存在,则创建一个设置,或者重写现有设置。
ConfigurationSetting setting = configurationClient.setConfigurationSetting("some_key", "some_label", "some_value");

创建要存储在配置存储中的功能标志配置设置或机密引用配置设置。

String key = "some_key";
String filterName = "{filter_name}"; // such as "Microsoft.Percentage"
String filterParameterKey = "{filter_parameter_key}"; // "Value"
Object filterParameterValue = 30; // Any value. Could be String, primitive value, or Json Object
FeatureFlagFilter percentageFilter = new FeatureFlagFilter(filterName)
                                         .addParameter(filterParameterKey, filterParameterValue);
FeatureFlagConfigurationSetting featureFlagConfigurationSetting =
    new FeatureFlagConfigurationSetting(key, true)
        .setClientFilters(Arrays.asList(percentageFilter));

FeatureFlagConfigurationSetting setting = (FeatureFlagConfigurationSetting)
    configurationClient.addConfigurationSetting(featureFlagConfigurationSetting);
String key = "{some_key}";
String keyVaultReference = "{key_vault_reference}";

SecretReferenceConfigurationSetting referenceConfigurationSetting =
    new SecretReferenceConfigurationSetting(key, keyVaultReference);

SecretReferenceConfigurationSetting setting = (SecretReferenceConfigurationSetting)
    configurationClient.addConfigurationSetting(referenceConfigurationSetting);

检索配置设置

通过调用 getConfigurationSetting检索以前存储的配置设置。

ConfigurationSetting setting = configurationClient.setConfigurationSetting("some_key", "some_label", "some_value");
ConfigurationSetting retrievedSetting = configurationClient.getConfigurationSetting("some_key", "some_label");

对于条件请求,如果要有条件地提取配置设置,请将 设置为 ifChanged true。 如果 ifChanged 为 true,则仅当配置设置与给定 setting的 不同时,才会检索配置设置。 这是通过将 的 setting ETag 与服务中的 ETag 进行比较来确定的,以查看它们是否相同。 如果 ETag 不相同,则表示配置设置不同,并且会检索其值。

ConfigurationSetting setting = configurationClient.setConfigurationSetting("some_key", "some_label", "some_value");
Response<ConfigurationSetting> settingResponse = configurationClient.getConfigurationSettingWithResponse(setting, null, true, Context.NONE);

在配置存储中检索功能标志配置设置或机密引用配置设置。

FeatureFlagConfigurationSetting setting = (FeatureFlagConfigurationSetting)
    configurationClient.getConfigurationSetting(featureFlagConfigurationSetting);
SecretReferenceConfigurationSetting setting = (SecretReferenceConfigurationSetting)
    configurationClient.getConfigurationSetting(referenceConfigurationSetting);

更新现有配置设置

通过调用 setConfigurationSetting更新现有配置设置。

ConfigurationSetting setting = configurationClient.setConfigurationSetting("some_key", "some_label", "some_value");
ConfigurationSetting updatedSetting = configurationClient.setConfigurationSetting("some_key", "some_label", "new_value");

对于条件请求,如果要有条件地更新配置设置,请将 ifUnchanged 参数设置为 true。 如果 ifUnchanged 为 true,则仅当配置设置与给定 setting的 相同时,才会更新配置设置。 这是通过将 的 setting ETag 与服务中的 ETag 进行比较来确定的,以查看它们是否相同。 如果 ETag 相同,则表示配置设置相同,并且更新其值。

ConfigurationSetting setting = configurationClient.setConfigurationSetting("some_key", "some_label", "some_value");
Response<ConfigurationSetting> settingResponse = configurationClient.setConfigurationSettingWithResponse(setting, true, Context.NONE);

更新配置存储中的功能标志配置设置或机密引用配置设置。

FeatureFlagConfigurationSetting setting = (FeatureFlagConfigurationSetting)
    configurationClient.setConfigurationSetting(featureFlagConfigurationSetting);
SecretReferenceConfigurationSetting setting = (SecretReferenceConfigurationSetting)
    configurationClient.setConfigurationSetting(referenceConfigurationSetting);

删除配置设置

通过调用 deleteConfigurationSetting删除现有配置设置。

ConfigurationSetting setting = configurationClient.setConfigurationSetting("some_key", "some_label", "some_value");
ConfigurationSetting deletedSetting = configurationClient.deleteConfigurationSetting("some_key", "some_label");

对于条件请求,如果要有条件地删除配置设置,请将 ifUnchanged 参数设置为 true。 当 ifUnchanged 参数为 true 时。 如果 ifUnchanged 为 true,则仅当配置设置与给定 setting的 相同时,才会删除配置设置。 这是通过将 的 setting ETag 与服务中的 ETag 进行比较来确定的,以查看它们是否相同。 如果 ETag 相同,则表示配置设置相同,并且会删除其值。

ConfigurationSetting setting = configurationClient.setConfigurationSetting("some_key", "some_label", "some_value");
Response<ConfigurationSetting> settingResponse = configurationClient.deleteConfigurationSettingWithResponse(setting, true, Context.NONE);

删除配置存储中的功能标志配置设置或机密引用配置设置。

FeatureFlagConfigurationSetting setting = (FeatureFlagConfigurationSetting)
    configurationClient.deleteConfigurationSetting(featureFlagConfigurationSetting);
SecretReferenceConfigurationSetting setting = (SecretReferenceConfigurationSetting)
    configurationClient.deleteConfigurationSetting(referenceConfigurationSetting);

列出具有多个密钥的配置设置

通过调用 listConfigurationSettings列出多个配置设置。 如果要提取所有配置设置及其字段,请将 null SettingSelector 传递给 方法。

String key = "some_key";
String key2 = "new_key";
configurationClient.setConfigurationSetting(key, "some_label", "some_value");
configurationClient.setConfigurationSetting(key2, "new_label", "new_value");
SettingSelector selector = new SettingSelector().setKeyFilter(key + "," + key2);
PagedIterable<ConfigurationSetting> settings = configurationClient.listConfigurationSettings(selector);

列出多个配置设置的修订

通过调用 listRevisions列出配置设置的所有修订。

String key = "revisionKey";
configurationClient.setConfigurationSetting(key, "some_label", "some_value");
configurationClient.setConfigurationSetting(key, "new_label", "new_value");
SettingSelector selector = new SettingSelector().setKeyFilter(key);
PagedIterable<ConfigurationSetting> settings = configurationClient.listRevisions(selector);

将配置设置设置为只读

将配置设置设置为只读状态。

configurationClient.setConfigurationSetting("some_key", "some_label", "some_value");
ConfigurationSetting setting = configurationClient.setReadOnly("some_key", "some_label", true);

从配置设置中清除只读

从配置设置中清除只读。

ConfigurationSetting setting = configurationClient.setReadOnly("some_key", "some_label", false);

使用代理选项创建客户端

使用代理选项创建配置客户端。

// Proxy options
final String hostname = "{your-host-name}";
final int port = 447; // your port number

ProxyOptions proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP,
    new InetSocketAddress(hostname, port));
HttpClient httpClient = new NettyAsyncHttpClientBuilder()
    .proxy(proxyOptions)
    .build();
ConfigurationAsyncClient configurationAsyncClient = new ConfigurationClientBuilder()
    .connectionString("{your_connection_string}")
    .httpClient(httpClient)
    .buildAsyncClient();

疑难解答

常规

使用此 Java 客户端库与应用程序配置交互时,服务返回的错误对应于为 REST API 请求返回的相同 HTTP 状态代码。 例如,如果尝试检索配置存储中不存在的配置设置,则会返回错误 404 ,指示 Not Found

应用程序配置提供了一种通过Context公共 API 中的 对象定义自定义标头的方法。

// Add your headers
HttpHeaders headers = new HttpHeaders();
headers.set("my-header1", "my-header1-value");
headers.set("my-header2", "my-header2-value");
headers.set("my-header3", "my-header3-value");
// Call API by passing headers in Context.
configurationClient.addConfigurationSettingWithResponse(
    new ConfigurationSetting().setKey("key").setValue("value"),
    new Context(AddHeadersFromContextPolicy.AZURE_REQUEST_HTTP_HEADERS_KEY, headers));
// Above three HttpHeader will be added in outgoing HttpRequest.

有关更多详细信息,检查 AddHeadersFromContextPolicy

默认的 HTTP 客户端

默认情况下,所有客户端库都使用 Netty HTTP 客户端。 添加上述依赖项会自动将客户端库配置为使用 Netty HTTP 客户端。 HTTP 客户端 Wiki 中详述了如何配置或更改 HTTP 客户端。

默认 SSL 库

默认情况下,所有客户端库均使用 Tomcat 原生 Boring SSL 库来为 SSL 操作启用原生级别性能。 Boring SSL 库是一个 uber jar,其中包含适用于 Linux/macOS/Windows 的原生库。与 JDK 内的默认 SSL 实现相比,它提供更好的性能。 有关详细信息(包括如何减小依赖项大小),请参阅 Wiki 的性能优化部分。

后续步骤

贡献

本项目欢迎贡献和建议。 大多数贡献要求你同意贡献者许可协议 (CLA),并声明你有权(并且确实有权)授予我们使用你的贡献的权利。

提交拉取请求时,CLA 机器人将自动确定你是否需要提供 CLA,并相应地修饰 PR(例如标签、注释)。 直接按机器人提供的说明操作。 只需使用 CLA 对所有存储库执行一次这样的操作。

此项目采用了 Microsoft 开放源代码行为准则。 有关详细信息,请参阅行为准则常见问题解答,或如果有任何其他问题或意见,请与 联系。

曝光数