練習 - 建立 Azure 資源與 Java Spring 應用程式

已完成

在本單元中,您將建立基本的 Spring Boot 應用程式。 您將使用 Azure CLI 和所選的整合式開發環境 (IDE) 來編輯程式碼。 使用所選的終端機來執行該程式碼。

準備工作環境

使用下列命令來設定一些環境變數:

AZ_RESOURCE_GROUP=azure-spring-workshop
AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
AZ_LOCATION=<YOUR_AZURE_REGION>
AZ_MYSQL_USERNAME=spring
AZ_MYSQL_PASSWORD=<YOUR_MYSQL_PASSWORD>
AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>

在程式碼中,以下列表中的值取代預留位置。 本課程模組會用到這些值。

變數 描述
<YOUR_DATABASE_NAME> 您 MySQL 伺服器的名稱。 此名稱在 Azure 中必須是唯一。
<YOUR_AZURE_REGION> 您將使用的 Azure 區域。 根據預設,您可使用 eastus,但建議您使用居住位置附近的區域。 您可輸入 az account list-locations 來查看可用區域的完整清單
<YOUR_MYSQL_PASSWORD> 您 MySQL 資料庫伺服器的密碼。 密碼至少要有八個字元。 所用字元必須包含下列類別的其中三種:英文大寫字母、英文小寫字母、數字 0 到 9 和非英數字元 (!、$、#、% 等等)。
<YOUR_LOCAL_IP_ADDRESS> 執行 Spring Boot 應用程式的本機電腦 IP 位址。 若要尋找 IP 位址,請將瀏覽器指向 whatismyip.akamai.com

接著,建立資源群組:

az group create \
    --name $AZ_RESOURCE_GROUP \
    --location $AZ_LOCATION \
    | jq

注意

本課程模組會使用預設安裝在 Azure Cloud Shell 上的 jq 工具,以顯示 JSON 資料並使其更容易閱讀。

如果不想要使用 jq 工具,您可安全移除本課程模組中所有命令的 | jq 部分。

建立適用於 MySQL 的 Azure 資料庫其執行個體

現在將建立受控 MySQL 伺服器。

注意

若要深入了解適用於 MySQL 的 Azure 資料庫,請在本課程模組的結尾處,遵循相關文件的連結。

執行下列指令碼以建立適用於 MySQL 的 Azure 資料庫其小型執行個體。 資料庫有 1 個 CPU 和 2 GB 的 RAM。

az mysql server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME \
    --location $AZ_LOCATION \
    --sku-name B_Gen5_1 \
    --storage-size 5120 \
    --admin-user $AZ_MYSQL_USERNAME \
    --admin-password $AZ_MYSQL_PASSWORD \
    | jq

此指令碼會建立一個使用稍早所設定變數的小型 MySQL 伺服器。

設定 MySQL 伺服器的防火牆規則

適用於 MySQL 的 Azure 資料庫預設會受到保護。 其防火牆不允許連入連線。 請新增防火牆規則,以允許本機 IP 位址存取資料庫伺服器。

執行下列命令來開啟伺服器的防火牆:

az mysql server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME-database-allow-local-ip \
    --server-name $AZ_DATABASE_NAME \
    --start-ip-address $AZ_LOCAL_IP_ADDRESS \
    --end-ip-address $AZ_LOCAL_IP_ADDRESS \
    | jq

執行下列命令以允許從 Azure 資源存取防火牆:

az mysql server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name allAzureIPs \
    --server-name $AZ_DATABASE_NAME \
    --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0 \
    | jq

設定 MySQL 資料庫

您稍早建立的 MySQL 伺服器是空的。 沒有任何可搭配 Spring Boot 應用程式使用的資料庫。 建立名為 demo 的新資料庫:

az mysql db create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name demo \
    --server-name $AZ_DATABASE_NAME \
    | jq

使用 Spring Initializr 產生應用程式

Spring Initializr 是能產生 Spring Boot 專案結構的 Web 應用程式。 Spring Initializr 不會產生任何應用程式程式碼,但能提供基本的專案結構和 Maven 組建規格。

您將使用以下三個相依性以產生應用程式 Scaffold:webmysqldata-jpa。 因為將在本機執行應用程式,所以不需要指定 Azure 相依性。

在命令提示字元中產生應用程式:

curl https://start.spring.io/starter.tgz -d type=maven-project -d dependencies=web,data-jpa,mysql -d baseDir=azure-spring-workshop -d bootVersion=3.1.5.RELEASE -d javaVersion=17 | tar -xzvf -

將 Spring Boot 設定為使用適用於 MySQL 的 Azure 資料庫

開啟 src/main/resources/application.properties 檔案,然後新增一些屬性。 請務必使用稍早設定的值取代兩個 $AZ_DATABASE_NAME 變數和 $AZ_MYSQL_PASSWORD 變數。

logging.level.org.hibernate.SQL=DEBUG

spring.datasource.url=jdbc:mysql://$AZ_DATABASE_NAME.mysql.database.azure.com:3306/demo?serverTimezone=UTC
spring.datasource.username=spring@$AZ_DATABASE_NAME
spring.datasource.password=$AZ_MYSQL_PASSWORD

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop

警告

設定屬性 spring.jpa.hibernate.ddl-auto=create-drop 表示 Spring Boot 會在應用程式啟動時自動建立資料庫結構描述,並在關閉時嘗試刪除該資料庫結構描述。 這個屬性很適合用於測試,但不應用在生產中!

注意

請將 ?serverTimezone=UTC 附加在設定屬性 spring.datasource.url 的後面。 當連線到資料庫時,此設定會通知 Java 資料庫連線 (JDBC) 驅動程式使用國際標準時間 (UTC) 日期格式。 否則,Java 伺服器不會和資料庫使用相同的日期格式,進而導致錯誤。

現在請使用所提供的 Maven 包裝函式來啟動您的應用程式:

./mvnw spring-boot:run

這個螢幕擷取畫面顯示第一次執行的應用程式:

顯示正在執行的應用程式其螢幕擷取畫面。

編碼應用程式

接下來,新增下列 Java 程式碼。 其使用 JAVA 持續性 API (JPA) 在 MySQL 伺服器中儲存及擷取資料。

您將使用 JPA 實體類別直接將 Java Todo 物件對應到 MySQL Todo 資料表。

DemoApplication 類別旁建立新的 Todo 實體類別。 然後,新增下列程式碼:

package com.example.demo;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Todo {

    public Todo() {
    }

    public Todo(String description, String details, boolean done) {
        this.description = description;
        this.details = details;
        this.done = done;
    }

    @Id
    @GeneratedValue
    private Long id;

    private String description;

    private String details;

    private boolean done;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDetails() {
        return details;
    }

    public void setDetails(String details) {
        this.details = details;
    }

    public boolean isDone() {
        return done;
    }

    public void setDone(boolean done) {
        this.done = done;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof Todo)) {
            return false;
        }
        return id != null && id.equals(((Todo) o).id);
    }

    @Override
    public int hashCode() {
        return 31;
    }
}

這個類別是在 Todo 資料表上對應的網域模型。 其將由 JPA 自動建立。

需要有存放庫才能管理該類別。 在相同的套件中定義新的 TodoRepository 介面:

package com.example.demo;

import org.springframework.data.jpa.repository.JpaRepository;

public interface TodoRepository extends JpaRepository<Todo, Long> {
}

此存放庫是 Spring Data JPA 管理的 JPA 存放庫。 透過擴充 JpaRepository,您可取得一大堆的類型泛型建立、讀取、更新和刪除 (CRUD) 方法。 因此可執行一些如儲存和刪除 Todo 物件的動作。

建立能發佈 REST 介面以透過 HTTP 儲存及擷取資料的 RestController 來完成應用程式。 在相同的套件中實作 TodoController 類別。 然後,新增下列程式碼:

package com.example.demo;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/")
public class TodoController {

    private final TodoRepository todoRepository;

    public TodoController(TodoRepository todoRepository) {
        this.todoRepository = todoRepository;
    }

    @PostMapping("/")
    @ResponseStatus(HttpStatus.CREATED)
    public Todo createTodo(@RequestBody Todo todo) {
        return todoRepository.save(todo);
    }

    @GetMapping("/")
    public Iterable<Todo> getTodos() {
        return todoRepository.findAll();
    }
}

最後,停止應用程式,然後使用下列命令再次啟動應用程式:

./mvnw spring-boot:run

Spring Boot 應用程式應該會啟動並連線到您的資料庫。

這個螢幕擷取畫面顯示連線到資料庫的應用程式:

顯示連線到資料庫的執行中應用程式其螢幕擷取畫面。

測試應用程式

您可使用 cURL 以測試應用程式。

首先,在資料庫中建立新的待辦事項:

curl --header "Content-Type: application/json" \
    --request POST \
    --data '{"description":"configuration","details":"congratulations, you have set up your Spring Boot application correctly!","done": "true"}' \
    http://127.0.0.1:8080

此命令應該會傳回已建立的項目:

{"id":1,"description":"configuration","details":"congratulations, you have set up your Spring Boot application correctly!","done":true}

接下來,使用新的 cURL 要求以擷取資料:

curl http://127.0.0.1:8080

此命令會傳回待辦事項清單,包括所建立的項目:

[{"id":1,"description":"configuration","details":"congratulations, you have set up your Spring Boot application correctly!","done":true}]