在 Azure 上使用 Java 开始云开发

本指南逐步讲解如何为 Java 中的 Azure 开发设置开发环境。 然后,创建并连接一些 Azure 资源,以执行一些基本任务,例如,上传文件或部署 Web 应用程序。 完成本指南后,便可以在自己的 Java 应用程序中开始使用 Azure 服务。

先决条件

设置身份验证

Java 应用程序需要 Azure 订阅中的读取和创建权限才能运行本教程中的示例代码。 请创建一个服务主体,并将应用程序配置为通过其凭据运行。 可以通过服务主体创建与标识关联的非交互式帐户,仅向该帐户授予应用运行时所需的权限。

使用 Azure CLI 2.0 创建 Azure 服务主体并捕获输出。 在密码参数而非 MY_SECURE_PASSWORD 中提供安全密码。 密码必须为 8 到 16 个字符,并且至少符合以下 4 个条件中的 3 个:

  • 包含小写字符
  • 包含大写字符
  • 包含数字
  • 包含以下符号之一:@ # $ % ^ & * - _ ! + = [ ] { } | \ : ‘ , . ? / ` ~ “ ( ) ;
az ad sp create-for-rbac --name AzureJavaTest --password "MY_SECURE_PASSWORD"

这会提供采用以下格式的回复:

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

工具

创建新的 Maven 项目

备注

本指南使用 Maven 生成工具来生成并运行示例代码,但其他生成工具(例如 Gradle)也适用于用于 Java 的 Azure 库。

从系统的新目录中的命令行创建 Maven 项目:

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

这样会在 testAzureApp 文件夹中创建基本的 Maven 项目。 将以下条目添加到项目 pom.xml 中,以便导入本教程示例代码中使用的库。

<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure</artifactId>
    <version>1.3.0</version>
</dependency>
<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-storage</artifactId>
    <version>5.0.0</version>
</dependency>
<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>6.2.1.jre8</version>
</dependency>

在顶级 project 元素下添加 build 条目,以便使用 maven-exec-plugin 来运行示例:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <configuration>
                <mainClass>com.fabrikam.AzureApp</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

安装用于 IntelliJ 的 Azure 工具包

若要以编程方式部署 Web 应用或 API,则需要使用 Azure 工具包,但是,该工具包目前不可用于其他任何类型的开发。 下面是安装过程的摘要。 有关详细步骤,请访问安装用于 IntelliJ 的 Azure 工具包

选择“文件”菜单,然后选择“设置...”。

选择“浏览存储库...”,搜索“Azure”,然后安装“用于 Intellij 于 Azure 工具包”。

重启 IntelliJ。

安装用于 Eclipse 的 Azure 工具包

若要以编程方式部署 Web 应用或 API,则需要使用 Azure 工具包,但是,该工具包目前不可用于其他任何类型的开发。 下面是安装过程的摘要。 有关详细步骤,请参阅安装用于 Eclipse 的 Azure 工具包

选择“帮助”菜单,然后选择“安装新软件”。

在“使用:”字段中,输入 http://dl.microsoft.com/eclipse 并按 Enter。

然后,选中“用于 Java 的 Azure 工具包”旁边的复选框,并取消选中“在安装过程中联系所有更新站点以查找所需的软件”对应的复选框。 然后选择“下一步”。

创建 Linux 虚拟机

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

package com.fabrikam;

import com.microsoft.azure.management.Azure;
import com.microsoft.azure.management.compute.VirtualMachine;
import com.microsoft.azure.management.compute.KnownLinuxVirtualMachineImage;
import com.microsoft.azure.management.compute.VirtualMachineSizeTypes;
import com.microsoft.azure.management.appservice.WebApp;
import com.microsoft.azure.management.storage.StorageAccount;
import com.microsoft.azure.management.storage.SkuName;
import com.microsoft.azure.management.storage.StorageAccountKey;
import com.microsoft.azure.management.sql.SqlDatabase;
import com.microsoft.azure.management.sql.SqlServer;
import com.microsoft.azure.management.resources.fluentcore.arm.Region;
import com.microsoft.azure.management.resources.fluentcore.utils.SdkContext;

import com.microsoft.rest.LogLevel;

import com.microsoft.azure.storage.*;
import com.microsoft.azure.storage.blob.*;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class AzureApp {

    public static void main(String[] args) {

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

        try {
            String clientId = "YOUR_CLIENT_ID";
            String tennantId = "YOUR_TENANT_ID";
            String secret = "YOUR_SECRET";
               
            //AzureEnvironment.AZURE_CHINA, use azure China environment
            AzureTokenCredentials credentials = new ApplicationTokenCredentials(clientId,tennantId,secret,AzureEnvironment.AZURE_CHINA);
            Azure azure = Azure.authenticate(credentials).withDefaultSubscription();
           
            // create a Ubuntu virtual machine in a new resource group 
            VirtualMachine linuxVM = azure.virtualMachines().define("testLinuxVM")
                    .withRegion(Region.CHINA_NORTH)
                    .withNewResourceGroup("sampleVmResourceGroup")
                    .withNewPrimaryNetwork("10.0.0.0/24")
                    .withPrimaryPrivateIpAddressDynamic()
                    .withoutPrimaryPublicIpAddress()
                    .withPopularLinuxImage(KnownLinuxVirtualMachineImage.UBUNTU_SERVER_16_04_LTS)
                    .withRootUsername(userName)
                    .withSsh(sshKey)
                    .withUnmanagedDisks()
                    .withSize(VirtualMachineSizeTypes.Standard_A1)
                    .create();   

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

从命令行运行示例:

mvn compile exec:java

此时会在控制台中看到一些 REST 请求和响应,因为 SDK 会对 Azure REST API 进行基础调用,以便配置虚拟机及其资源。 在程序完成后,请使用 Azure CLI 2.0 验证订阅中的虚拟机:

az vm list --resource-group sampleVmResourceGroup

验证代码可以正常运行以后,请使用 CLI 删除 VM 及其资源。

az group delete --name sampleVmResourceGroup

从 GitHub 存储库部署 Web 应用

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

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

            final File credFile = new File(System.getenv("AZURE_AUTH_LOCATION"));
            final String appName = "YOUR_APP_NAME";

            Azure azure = Azure.configure()
                    .withLogLevel(LogLevel.BASIC)
                    .authenticate(credFile)
                    .withDefaultSubscription();

            WebApp app = azure.webApps().define(appName)
                    .withRegion(Region.CHINA_NORTH)
                    .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 appservice web browse --resource-group sampleWebResourceGroup --name YOUR_APP_NAME

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

az group delete --name sampleWebResourceGroup

## 连接到 Azure SQL 数据库

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


    public static void main(String args[])
    {
        // create the db using the management libraries
        try {
            final File credFile = new File(System.getenv("AZURE_AUTH_LOCATION"));
            Azure azure = Azure.configure()
                    .withLogLevel(LogLevel.BASIC)
                    .authenticate(credFile)
                    .withDefaultSubscription();

            final String adminUser = SdkContext.randomResourceName("db",8);
            final String sqlServerName = SdkContext.randomResourceName("sql",10);
            final String sqlDbName = SdkContext.randomResourceName("dbname",8);
            final String dbPassword = "YOUR_PASSWORD_HERE";


            SqlServer sampleSQLServer = azure.sqlServers().define(sqlServerName)
                            .withRegion(Region.CHINA_NORTH)
                            .withNewResourceGroup("sampleSqlResourceGroup")
                            .withAdministratorLogin(adminUser)
                            .withAdministratorPassword(dbPassword)
                            .withNewFirewallRule("0.0.0.0","255.255.255.255")
                            .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.chinacloudapi.cn;loginTimeout=30;";

            // connect to the database, create a table and insert a entry into it
            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";
            Statement createStatement = conn.createStatement();
            createStatement.execute(createTable);
            Statement insertStatement = conn.createStatement();
            insertStatement.execute(insertValues);
            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 写入新的存储帐户中

将当前在 AzureApp.java 中的 main 方法替换为以下代码。 此代码创建一个 Azure 存储帐户,然后通过用于 Java 的 Azure 存储库在云中创建新的文本文件。

    public static void main(String[] args) {

        try {

            // use the properties file with the service principal information to authenticate
            // change the name of the environment variable if you used a different name in the previous step
            final File credFile = new File(System.getenv("AZURE_AUTH_LOCATION"));
            Azure azure = Azure.configure()
                    .withLogLevel(LogLevel.BASIC)
                    .authenticate(credFile)
                    .withDefaultSubscription();

            // create a new storage account
            String storageAccountName = SdkContext.randomResourceName("st",8);
            StorageAccount storage = azure.storageAccounts().define(storageAccountName)
                        .withRegion(Region.CHINA_NORTH)
                        .withNewResourceGroup("sampleStorageResourceGroup")
                        .create();

            // create a storage container to hold the file
            List<StorageAccountKey> keys = storage.getKeys();
            final String storageConnection = "DefaultEndpointsProtocol=https;"
                   + "AccountName=" + storage.name()
                   + ";AccountKey=" + keys.get(0).value()
                    + ";EndpointSuffix=core.chinacloudapi.cn";

            CloudStorageAccount account = CloudStorageAccount.parse(storageConnection);
            CloudBlobClient serviceClient = account.createCloudBlobClient();

            // Container name must be lower case.
            CloudBlobContainer container = serviceClient.getContainerReference("helloazure");
            container.createIfNotExists();

            // Make the container public
            BlobContainerPermissions containerPermissions = new BlobContainerPermissions();
            containerPermissions.setPublicAccess(BlobContainerPublicAccessType.CONTAINER);
            container.uploadPermissions(containerPermissions);

            // write a blob to the container
            CloudBlockBlob blob = container.getBlockBlobReference("helloazure.txt");
            blob.uploadText("hello Azure");

        } 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

参考和发行说明

所有包都提供参考

获取帮助和提供反馈

将问题发布到社区的 Stack Overflow。 在项目 GitHub 上报告用于 Java 的 Azure 库的 Bug 并提出问题。