網頁

2020/4/11

Angular HttpClient呼叫Spring Boot RESTful API

在Angular使用HttpClient呼叫Spring Boot RESTful API取得資料。

環境:

  • Windows 64 Bit
  • 前端
    • Angular 7
  • 後端
    • Java 11
    • Spring Boot 2.2.4.RELEASE


後端 Spring Boot 設定

建立Spring Boot專案。參考以下:


Spring Boot的application.properties不設定任何參數。所以預設應用程式路徑為http://localhost:8080/

建立類別HelloDto。此類別作為回傳給前端的資料。

HelloDto

package com.abc.demo.dto;

public class HelloDto {

    private String message;

    public HelloDto(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

建立DemoController。提供RESTful API接點。

類別名稱前必須掛上@CrossOrigin(origins = "http://localhost:4200")origins值為前端Angular的domain,這樣才能接受前端Angular的跨來源資源共享(CORS)請求。

DemoController

package com.abc.demo.controller;

import com.abc.demo.dto.HelloDto;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@CrossOrigin(origins = "http://localhost:4200")
@RestController
public class DemoController {

    @GetMapping(value = "/hello")
    public HelloDto getHello() {
        return new HelloDto("Hello! This is from Spring Boot RESTful API!"); // <--這邊的字串最後會顯示在前端頁面
    }

}

呼叫http://localhost:8080/hello時,Response回傳結果如下。

{"message": "Hello! This is from Spring Boot RESTful API!"}

Spring Boot專案../src/main目錄結構如下:

../src/main
├─java
│  └─com
│      └─abc
│          └─demo
│              ├─DemoApplication.java
│              │
│              ├─bean
│              │ └─HelloWorldBean.java
│              │
│              ├─controller
│              │ └─DemoController.java
│              │
│              └─dto
│                └─HelloDto.java
│
└─resources
    ├─application.properties
    ├─static
    └─templates

在Chrome瀏覽器位址直接輸入http://localhost:8080/hello測試結果。





前端 Angular 設定

建立Angular專案,參考「Angular 使用Angular CLI建立一個angular專案」。

建立HelloComponent,參考「Angular 使用Angular CLI建立Component元件」。

建立ApiService,參考「Angular 使用Angular CLI建立Service」。

src/app下新增data目錄,並建立hello-data.ts (HelloData)。

HelloData (hello-data.ts)

export class HelloData {

    message: string;

}

此類別將設為HttpClient.get<T>()的資料型態,對映後端回傳的json結果。


Angular可利用內建的HttpClient呼叫API,使用前需在AppModule(app.module.ts)引入,要放在BrowserModule後面。

AppModule (app.module.ts)

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http' // 引入HttpClientModule

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello/hello.component';

@NgModule({
  declarations: [
    AppComponent,
    HelloComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule // 引入HttpClientModule,放在BrowserModule後面
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

修改app.component.html如下,直接顯示HelloComponenthello.component.html頁面內容。

<app-hello></app-hello> <!-- 顯示HelloComponent -->
<router-outlet></router-outlet>

修改ApiService (app.module.ts)內容如下,負責向後端Spring Boot發出請求。

ApiService (api.service.ts)

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'; // 引入HttpClient
import { HelloData } from '../data/hello-data'; // 引入HelloData

@Injectable({
  providedIn: 'root'
})
export class ApiService {

  // 注入HttpClient
  constructor(
    private http: HttpClient
  ) { }

  /** 從後端取得資料 */
  getHello() {
    // get回傳Observable<HelloData>物件
    return this.http.get<HelloData>('http://localhost:8080/hello'); // 呼叫Spring Boot的DemoController.getHello()
  }

}

HttpClient.get<T>()執行當下並不會送出請求,必須呼叫其回傳物件Observable<T>subscribe()才會送出請求。


修改HelloComponent (hello.component.ts)內容如下,委託ApiService.getHello()取得Observable<T>並呼叫subscribe()送出請求來取得後端回傳的結果。

HelloComponent (hello.component.ts)

import { Component, OnInit } from '@angular/core';
import { ApiService } from '../service/api.service'; // 引入ApiService
import { HelloData } from '../data/hello-data'; // 引入HelloData

@Component({
  selector: 'app-hello',
  templateUrl: './hello.component.html',
  styleUrls: ['./hello.component.css']
})
export class HelloComponent implements OnInit {

  hello: string; // 對映hello.component.html頁面的{{hello}}

  // 注入ApiService
  constructor(
    private apiService: ApiService
  ) { }

  ngOnInit() {
  }

  /** 委託ApiService.getHello()取得內容 */
  getHello() {
    this.apiService.getHello().subscribe(
      value => this.success(value)
    );
  }

  /** API呼叫成功的處理 */
  success(value: HelloData) {
    this.hello = value.message;
  }

  /** 清除頁面{{hello}}內容 */
  clear() {
    this.hello = '';
  }

}

修改hello.component.html如下。

hello.component.html

<div>
  <button (click)="getHello()">Get Hello</button>  <!-- 取得{{hello}}顯示的內容-->
  <button (click)="clear()">Clear</button> <!-- 清除{{hello}}顯示的內容 -->
</div>
<hr>
<h1>{{hello}}</h1>

Get HelloClear按鈕利用事件綁定分別呼叫HelloComponentgetHello()clear()來更改插值符{{hello}}的顯示內容。


Angular專案../src/app目錄結構如下:

../src/app
├─app-routing.module.ts
├─app.component.css
├─app.component.html
├─app.component.spec.ts
├─app.component.ts
├─app.module.ts
│
├─data
│  └─hello-data.ts
│
├─hello
│  ├─hello.component.css
│  ├─hello.component.html
│  ├─hello.component.spec.ts
│  └─hello.component.ts
│
└─service
    ├─api.service.spec.ts
    └─api.service.ts


測試

完成以上後端Spring Boot及前端Angular的設定後啟動兩個專案。

啟動後在瀏覽器輸入前端Angular的應用程式路徑http://localhost:4200/顯示如下。


點擊按鈕效果如下。




沒有留言:

張貼留言