在 Azure 上使用 Java 开始云开发

本文将指导你设置用于 Java 中 Azure 开发的开发环境。 然后,你将创建一些 Azure 资源并连接到它们以执行一些基本任务,例如上传文件或部署 Web 应用程序。 完成后,即可开始在自己的 Java 应用程序中使用 Azure 服务。

先决条件

设置身份验证

Java 应用程序需要 读取在 Azure 订阅中创建 权限,才能在本教程中运行示例代码。 创建服务主体,并将应用程序配置为使用其凭据运行。 服务主体提供了一种创建与标识关联的非交互帐户的方法,你仅授予应用运行所需的特权。

使用 Azure CLI 2.0创建服务主体,并捕获输出:

az ad sp create-for-rbac \
    --name AzureJavaTest \
    --role Contributor \
    --scopes /subscriptions/<your-subscription-ID>

此命令提供以下格式的答复:

{
  "appId": "a487e0c1-82af-47d9-9a0b-af184eb87646d",
  "displayName": "AzureJavaTest",
  "name": "http://AzureJavaTest",
  "password": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
  "tenant": "tttttttt-tttt-tttt-tttt-tttttttttttt"
}

接下来,配置环境变量:

  • AZURE_SUBSCRIPTION_ID:使用 Azure CLI 2.0 中 az account showID 值。
  • AZURE_CLIENT_ID:使用从服务主体输出中获取的输出中的 appId 值。
  • AZURE_CLIENT_SECRET:使用服务主体输出中的 密码 值。
  • AZURE_TENANT_ID:使用服务主体输出中的 租户 值。

有关更多身份验证选项,请参阅适用于 Java 的 Azure 标识客户端库

注意

Microsoft建议使用可用的最安全的身份验证流。 此过程中所述的身份验证流(例如数据库、缓存、消息传送或 AI 服务)需要高度信任应用程序,并且存在其他流中不存在的风险。 仅当更安全的选项(例如无密码连接或无密钥连接的托管标识)不可行时,才使用此流。 对于本地计算机作,首选无密码连接或无密钥连接的用户标识。

工具

创建新的 Maven 项目

注意

本文使用 Maven 生成工具生成并运行示例代码。 其他生成工具(如 Gradle)也适用于用于 Java 的 Azure SDK。

在系统上的新目录中从命令行创建 Maven 项目。

mkdir java-azure-test
cd java-azure-test
mvn archetype:generate -DgroupId=com.fabrikam -DartifactId=AzureApp \
-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

此步骤在 testAzureApp 目录下创建一个基本 Maven 项目。 将以下条目添加到项目的 pom.xml 文件中,以导入本教程中的示例代码中使用的库。

<dependency>
  <groupId>com.azure</groupId>
  <artifactId>azure-identity</artifactId>
  <version>1.3.2</version>
</dependency>
<dependency>
  <groupId>com.azure.resourcemanager</groupId>
  <artifactId>azure-resourcemanager</artifactId>
  <version>2.6.0</version>
</dependency>
<dependency>
  <groupId>com.azure</groupId>
  <artifactId>azure-storage-blob</artifactId>
  <version>12.8.0</version>
</dependency>
<dependency>
  <groupId>com.microsoft.sqlserver</groupId>
  <artifactId>mssql-jdbc</artifactId>
  <version>6.2.1.jre8</version>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-simple</artifactId>
  <version>1.7.33</version>
</dependency>

在顶级 project 元素下添加 build 项,以使用 maven-exec-plugin 运行示例。 maven-compiler-plugin 用于配置源代码和为 Java 8 生成的类。

<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>3.0.0</version>
      <configuration>
        <mainClass>com.fabrikam.App</mainClass>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.8.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>
  </plugins>
</build>

创建 Linux 虚拟机

在项目的 src/main/java/com/fabrikam 目录中创建名为 App.java 的新文件,并粘贴以下代码块。 使用计算机的实际值更新 userNamesshKey 变量。 该代码创建一个新的 Linux 虚拟机(VM),其名称 testLinuxVM 资源组 sampleResourceGroup 在美国东部 Azure 区域中运行。

package com.fabrikam;

import com.azure.core.credential.TokenCredential;
import com.azure.core.http.policy.HttpLogDetailLevel;
import com.azure.core.management.AzureEnvironment;
import com.azure.core.management.Region;
import com.azure.core.management.profile.AzureProfile;
import com.azure.identity.AzureAuthorityHosts;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.resourcemanager.AzureResourceManager;
import com.azure.resourcemanager.compute.models.KnownLinuxVirtualMachineImage;
import com.azure.resourcemanager.compute.models.VirtualMachine;
import com.azure.resourcemanager.compute.models.VirtualMachineSizeTypes;

public class App {

    public static void main(String[] args) {

        final String userName = "YOUR_VM_USERNAME";
        final String sshKey = "YOUR_PUBLIC_SSH_KEY";

        try {
            TokenCredential credential = new DefaultAzureCredentialBuilder()
                    .authorityHost(AzureAuthorityHosts.AZURE_PUBLIC_CLOUD)
                    .build();

            // If you don't set the tenant ID and subscription ID via environment variables,
            // change to create the Azure profile with tenantId, subscriptionId, and Azure environment.
            AzureProfile profile = new AzureProfile(AzureEnvironment.AZURE);

            AzureResourceManager azureResourceManager = AzureResourceManager.configure()
                    .withLogLevel(HttpLogDetailLevel.BASIC)
                    .authenticate(credential, profile)
                    .withDefaultSubscription();

            // Create an Ubuntu virtual machine in a new resource group.
            VirtualMachine linuxVM = azureResourceManager.virtualMachines().define("testLinuxVM")
                    .withRegion(Region.US_EAST)
                    .withNewResourceGroup("sampleVmResourceGroup")
                    .withNewPrimaryNetwork("10.0.0.0/24")
                    .withPrimaryPrivateIPAddressDynamic()
                    .withoutPrimaryPublicIPAddress()
                    .withPopularLinuxImage(KnownLinuxVirtualMachineImage.UBUNTU_SERVER_18_04_LTS)
                    .withRootUsername(userName)
                    .withSsh(sshKey)
                    .withSize(VirtualMachineSizeTypes.STANDARD_D3_V2)
                    .create();

        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }
}

从命令行运行示例。

mvn compile exec:java

当 SDK 对 Azure REST API 进行基础调用以配置 VM 及其资源时,你将在控制台中看到一些 REST 请求和响应。 程序完成后,使用 Azure CLI 2.0 验证订阅中的 VM。

az vm list --resource-group sampleVmResourceGroup

验证代码是否正常工作后,请使用 CLI 删除 VM 及其资源。

az group delete --name sampleVmResourceGroup

从 GitHub 存储库部署 Web 应用

App.java 中的 main 方法替换为以下方法。 在运行代码之前,将 appName 变量更新为唯一值。 此代码将公共 GitHub 存储库中的 master 分支中的 Web 应用程序部署到在免费定价层中运行的新的 Azure 应用服务 Web 应用

    public static void main(String[] args) {
        try {

            final String appName = "YOUR_APP_NAME";

            TokenCredential credential = new DefaultAzureCredentialBuilder()
                    .authorityHost(AzureAuthorityHosts.AZURE_PUBLIC_CLOUD)
                    .build();

            // If you don't set the tenant ID and subscription ID via environment variables,
            // change to create the Azure profile with tenantId, subscriptionId, and Azure environment.
            AzureProfile profile = new AzureProfile(AzureEnvironment.AZURE);
            
            AzureResourceManager azureResourceManager = AzureResourceManager.configure()
                    .withLogLevel(HttpLogDetailLevel.BASIC)
                    .authenticate(credential, profile)
                    .withDefaultSubscription();

            WebApp app = azureResourceManager.webApps().define(appName)
                    .withRegion(Region.US_WEST2)
                    .withNewResourceGroup("sampleWebResourceGroup")
                    .withNewWindowsPlan(PricingTier.FREE_F1)
                    .defineSourceControl()
                    .withPublicGitRepository(
                            "https://github.com/Azure-Samples/app-service-web-java-get-started")
                    .withBranch("master")
                    .attach()
                    .create();

        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }

像使用 Maven 之前一样运行代码。

mvn clean compile exec:java

使用 CLI 打开指向应用程序的浏览器。

az webapp browse --resource-group sampleWebResourceGroup --name YOUR_APP_NAME

验证部署后,请从订阅中删除 Web 应用和计划。

az group delete --name sampleWebResourceGroup

连接到 Azure SQL 数据库

App.java 中的当前主方法替换为以下代码。 设置变量的实际值。 此代码使用允许远程访问的防火墙规则创建新的 SQL 数据库。 然后,代码使用 SQL 数据库 JBDC 驱动程序连接到它。

    public static void main(String args[]) {
        // Create the db using the management libraries.
        try {
            TokenCredential credential = new DefaultAzureCredentialBuilder()
                    .authorityHost(AzureAuthorityHosts.AZURE_PUBLIC_CLOUD)
                    .build();

            // If you don't set the tenant ID and subscription ID via environment variables,
            // change to create the Azure profile with tenantId, subscriptionId, and Azure environment.
            AzureProfile profile = new AzureProfile(AzureEnvironment.AZURE);

            AzureResourceManager azureResourceManager = AzureResourceManager.configure()
                    .withLogLevel(HttpLogDetailLevel.BASIC)
                    .authenticate(credential, profile)
                    .withDefaultSubscription();

            final String adminUser = "YOUR_USERNAME_HERE";
            final String sqlServerName = "YOUR_SERVER_NAME_HERE";
            final String sqlDbName = "YOUR_DB_NAME_HERE";
            final String dbPassword = "YOUR_PASSWORD_HERE";
            final String firewallRuleName = "YOUR_RULE_NAME_HERE";

            SqlServer sampleSQLServer = azureResourceManager.sqlServers().define(sqlServerName)
                    .withRegion(Region.US_EAST)
                    .withNewResourceGroup("sampleSqlResourceGroup")
                    .withAdministratorLogin(adminUser)
                    .withAdministratorPassword(dbPassword)
                    .defineFirewallRule(firewallRuleName)
                        .withIpAddressRange("0.0.0.0","255.255.255.255")
                        .attach()
                    .create();

            SqlDatabase sampleSQLDb = sampleSQLServer.databases().define(sqlDbName).create();

            // Assemble the connection string to the database.
            final String ___domain = sampleSQLServer.fullyQualifiedDomainName();
            String url = "jdbc:sqlserver://"+ ___domain + ":1433;" +
                    "database=" + sqlDbName +";" +
                    "user=" + adminUser+ "@" + sqlServerName + ";" +
                    "password=" + dbPassword + ";" +
                    "encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;";

            // Connect to the database, create a table, and insert an entry into it.
            try (Connection conn = DriverManager.getConnection(url)) {
                String createTable = "CREATE TABLE CLOUD (name varchar(255), code int);";
                String insertValues = "INSERT INTO CLOUD (name, code) VALUES ('Azure', 1);";
                String selectValues = "SELECT * FROM CLOUD";
                try (Statement createStatement = conn.createStatement()) {
                    createStatement.execute(createTable);
                }
                try (Statement insertStatement = conn.createStatement()) {
                    insertStatement.execute(insertValues);
                }
                try (Statement selectStatement = conn.createStatement();
                     ResultSet rst = selectStatement.executeQuery(selectValues)) {
                    while (rst.next()) {
                        System.out.println(rst.getString(1) + " " + rst.getString(2));
                    }
                }
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.out.println(e.getStackTrace().toString());
        }
    }

从命令行运行示例。

mvn clean compile exec:java

然后使用 CLI 清理资源。

az group delete --name sampleSqlResourceGroup

将 Blob 写入新存储帐户

App.java 中的当前主方法替换为以下代码。 此代码创建 Azure 存储帐户。 然后,该代码使用适用于 Java 的 Azure 存储库在云中创建新的文本文件。

    public static void main(String[] args) {

        try {
            TokenCredential tokenCredential = new DefaultAzureCredentialBuilder()
                    .authorityHost(AzureAuthorityHosts.AZURE_PUBLIC_CLOUD)
                    .build();

            // If you don't set the tenant ID and subscription ID via environment variables,
            // change to create the Azure profile with tenantId, subscriptionId, and Azure environment.
            AzureProfile profile = new AzureProfile(AzureEnvironment.AZURE);

            AzureResourceManager azureResourceManager = AzureResourceManager.configure()
                    .withLogLevel(HttpLogDetailLevel.BASIC)
                    .authenticate(tokenCredential, profile)
                    .withDefaultSubscription();

            // Create a new storage account.
            String storageAccountName = "YOUR_STORAGE_ACCOUNT_NAME_HERE";
            StorageAccount storage = azureResourceManager.storageAccounts().define(storageAccountName)
                    .withRegion(Region.US_WEST2)
                    .withNewResourceGroup("sampleStorageResourceGroup")
                    .create();

            // Create a storage container to hold the file.
            List<StorageAccountKey> keys = storage.getKeys();
            PublicEndpoints endpoints = storage.endPoints();
            String accountName = storage.name();
            String accountKey = keys.get(0).value();
            String endpoint = endpoints.primary().blob();

            StorageSharedKeyCredential credential = new StorageSharedKeyCredential(accountName, accountKey);

            BlobServiceClient storageClient = new BlobServiceClientBuilder()
                    .endpoint(endpoint)
                    .credential(credential)
                    .buildClient();

            // Container name must be lowercase.
            BlobContainerClient blobContainerClient = storageClient.getBlobContainerClient("helloazure");
            blobContainerClient.create();

            // Make the container public.
            blobContainerClient.setAccessPolicy(PublicAccessType.CONTAINER, null);

            // Write a blob to the container.
            String fileName = "helloazure.txt";
            String textNew = "Hello Azure";

            BlobClient blobClient = blobContainerClient.getBlobClient(fileName);
            InputStream is = new ByteArrayInputStream(textNew.getBytes());
            blobClient.upload(is, textNew.length());

        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }

从命令行运行示例。

mvn clean compile exec:java

可以通过 Azure 门户或通过 Azure 存储资源管理器浏览存储帐户中的 helloazure.txt 文件。

使用 CLI 清理存储帐户。

az group delete --name sampleStorageResourceGroup

浏览更多示例

若要详细了解如何使用适用于 Java 的 Azure 管理库来管理资源和自动执行任务,请参阅我们的示例代码,虚拟机Web 应用,以及 SQL 数据库

参考和发行说明

引用 适用于所有包。

获取帮助并提供反馈

将问题发布到 Stack Overflow上的社区。 在 GitHub 存储库中报告针对 Azure SDK for Java 的 bug 和打开问题。