iT邦幫忙

2023 iThome 鐵人賽

DAY 24
0
Modern Web

自己開發一個~?系列 第 24

Springboot~Bootstrap起手式

  • 分享至 

  • xImage
  •  

連假第1天

POSTMAN依照不同專案管理空間
https://ithelp.ithome.com.tw/upload/images/20231110/20119035NKBucDOy4U.png

server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/sakila?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=1234
spring.datasource.dbcp2.driver-class-name=com.mysql.cj.jdbc.Driver
#監控轉譯語法
spring.jpa.show-sql=true
#設定翻譯員風格
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
#外部服務自訂屬性項目
outside.service.ubike=https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json

說明:
這些配置是Spring Boot應用程序的屬性設置,它們用於配置應用程序的行為和連接到其他服務的方式。讓我逐一解釋這些配置:

  1. server.port=8080:這個屬性設置了應用程序的HTTP伺服器端口。默認情況下,Spring Boot應用程序使用8080端口,但你可以在這裡自定義端口號。

  2. spring.datasource.url:這個屬性設置了數據庫的URL。在這個例子中,它配置了一個MySQL數據庫的URL,指定了數據庫的位置(localhost:3306)、數據庫名稱(sakila)、使用的時區(UTC)、字符編碼(utf-8)等等。這些信息用於建立到MySQL數據庫的連接。

  3. spring.datasource.usernamespring.datasource.password:這些屬性分別設置了數據庫的用戶名和密碼。在這個例子中,用戶名為 root,密碼為 1234

  4. spring.datasource.dbcp2.driver-class-name:這個屬性設置了使用的數據庫驅動程式的類名。在這個例子中,使用的是MySQL數據庫,所以設置為 com.mysql.cj.jdbc.Driver

  5. outside.service.ubike:這個屬性設置了一個外部服務的URL,它用於向 https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json 發送HTTP請求。這個URL指向一個JSON檔案,你的應用程序可以通過HTTP訪問它,從中獲取Ubike即時資訊。

這些配置使你的Spring Boot應用程序知道如何連接到MySQL數據庫,設置了伺服器的端口號,並提供了一個外部Ubike服務的URL。這些配置對於應用程序的運行和與其他服務的通信非常重要。根據這些配置,你的應用程序可以建立到MySQL數據庫的連接,並訪問外部Ubike服務以獲取資訊。

/images/emoticon/emoticon06.gif
修改程式碼

package com.tzu2.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

//Ubike服務
	@RestController
	public class UbikeService {
		//Data Field Injection(Attribute)
		@Value("${outside.service.ubike}")
		private String ubkieService;
		
		//服務 提供輸入區域 找出即時資訊
		@GetMapping(path="/api/ubike/{area}/rawdata",produces="application/json")
		public String  ubikeQry(@PathVariable(name="area") String sarea) {
			
			return sarea;
}
		
	}

這段代碼使用Spring Boot實現了一個簡單的UbikeService,提供查詢Ubike即時資訊的API。

代碼解析:

  1. @RestController定義這是一个REST控制器

  2. @Value注入了outside.service.ubike屬性值,可在配置中定義

  3. @GetMapping處理GET請求,PathVariable獲取路徑變量area

  4. ubikeQry方法根據區域參數sarea返回字符串

  5. 可在配置中定義ubikeService值,例如接口URL

  6. 可根據area調用Ubike開放API獲取即時資訊

  7. 返回json格式的Ubike資訊

這實現了一個典型的Spring Boot RESTful Web服务Demo。

可進一步完善ubikeQry方法,調用Ubike API並返回實際數據。

Spring Boot使構建REST API變得非常簡單。


使用POSTMAN抓取政府開放平台的JSON檔
測試https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json
https://ithelp.ithome.com.tw/upload/images/20231110/20119035YLXvWhqwdc.png

線上用JSON轉看欄位數或其他
https://jsoneditoronline.org/#left=local.liditi&right=local.pilaci

https://ithelp.ithome.com.tw/upload/images/20231110/201190359Ti15qPUEH.png

線上用JSON轉JAVA程式碼
https://codebeautify.org/json-to-java-converter
https://ithelp.ithome.com.tw/upload/images/20231110/20119035OzjvQCFP5B.png

新增程式碼檔案

package com.tzu.domain;
//Java bean 
public class UbikeData {
	 private String sno;
	 private String sna;
	 private float tot;
	 private float sbi;
	 private String sarea;
	 private String mday;
	 private float lat;
	 private float lng;
	 private String ar;
	 private String sareaen;
	 private String snaen;
	 private String aren;
	 private float bemp;
	 private String act;
	 private String srcUpdateTime;
	 private String updateTime;
	 private String infoTime;
	 private String infoDate;


	 // Getter Methods 

	 public String getSno() {
	  return sno;
	 }

	 public String getSna() {
	  return sna;
	 }

	 public float getTot() {
	  return tot;
	 }

	 public float getSbi() {
	  return sbi;
	 }

	 public String getSarea() {
	  return sarea;
	 }

	 public String getMday() {
	  return mday;
	 }

	 public float getLat() {
	  return lat;
	 }

	 public float getLng() {
	  return lng;
	 }

	 public String getAr() {
	  return ar;
	 }

	 public String getSareaen() {
	  return sareaen;
	 }

	 public String getSnaen() {
	  return snaen;
	 }

	 public String getAren() {
	  return aren;
	 }

	 public float getBemp() {
	  return bemp;
	 }

	 public String getAct() {
	  return act;
	 }

	 public String getSrcUpdateTime() {
	  return srcUpdateTime;
	 }

	 public String getUpdateTime() {
	  return updateTime;
	 }

	 public String getInfoTime() {
	  return infoTime;
	 }

	 public String getInfoDate() {
	  return infoDate;
	 }

	 // Setter Methods 

	 public void setSno(String sno) {
	  this.sno = sno;
	 }

	 public void setSna(String sna) {
	  this.sna = sna;
	 }

	 public void setTot(float tot) {
	  this.tot = tot;
	 }

	 public void setSbi(float sbi) {
	  this.sbi = sbi;
	 }

	 public void setSarea(String sarea) {
	  this.sarea = sarea;
	 }

	 public void setMday(String mday) {
	  this.mday = mday;
	 }

	 public void setLat(float lat) {
	  this.lat = lat;
	 }

	 public void setLng(float lng) {
	  this.lng = lng;
	 }

	 public void setAr(String ar) {
	  this.ar = ar;
	 }

	 public void setSareaen(String sareaen) {
	  this.sareaen = sareaen;
	 }

	 public void setSnaen(String snaen) {
	  this.snaen = snaen;
	 }

	 public void setAren(String aren) {
	  this.aren = aren;
	 }

	 public void setBemp(float bemp) {
	  this.bemp = bemp;
	 }

	 public void setAct(String act) {
	  this.act = act;
	 }

	 public void setSrcUpdateTime(String srcUpdateTime) {
	  this.srcUpdateTime = srcUpdateTime;
	 }

	 public void setUpdateTime(String updateTime) {
	  this.updateTime = updateTime;
	 }

	 public void setInfoTime(String infoTime) {
	  this.infoTime = infoTime;
	 }

	 public void setInfoDate(String infoDate) {
	  this.infoDate = infoDate;
	 }
	}

這是一個定義Ubike數據的Java Bean類。

從代碼可以看出:

  1. 該類包含了多個屬性,對應Ubike站點的各種信息,如站點編號、名稱、座標等。

  2. 為每個屬性都定義了Getter和Setter方法,可以獲取和設置屬性值。

  3. 這遵循了Java Bean的編碼規範,屬性私有化,通過Getter/Setter訪問。

  4. 沒有任何業務邏輯,僅對數據進行包裝。

  5. 可以在程序中new一個UbikeData對象,設置其屬性,表示一個Ubike站點的信息。

  6. 也可以將從Ubike API獲取的json/xml數據反序列化為UbikeData對象。

這類數據對象是Java Web應用和開發中常見的編碼方式,用於數據傳輸和業務邏輯的分離。遵循Java Bean規範,使代碼更規範化。


修改檔案UbikeService

package com.tzu.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.tzu.domain.UbikeData;

//Ubike服務
@RestController
public class UbikeService {
	//Data Field Injection(Attribute)
	@Value("${outside.service.ubike}")
	private String ubkieService;
	//服務 提供輸入區域 找出即時資訊
	@GetMapping(path="/api/ubike/{area}/rawdata",produces="application/json")
	public List<UbikeData> ubikeQry(@PathVariable(name="area") String sarea) {
		//串結服務架構
		//1.建構HttpClient RestTemplate
		var client=new RestTemplate(); //同步處理機制
		UbikeData[] result=client.getForObject(ubkieService,UbikeData[].class);
		//TODO 進行區域查詢
		//使用Stream篩選機制(JDK 8.0)
		List<UbikeData> lists=Arrays.asList(result);
		//透過集合物件產生Stream 進行篩選 filter(Predicate interface--抽象方法只有一個)
		//var finalResult=lists.stream().filter((u)->u.getSarea().equals(sarea)).toList();
		//使用foreach 逐筆走訪跟判斷
		List<UbikeData> finalResult=new ArrayList<>();
		for(UbikeData ub:result) {
			//判斷區域
			if(ub.getSarea().equals(sarea)) {
				finalResult.add(ub);
			}
		}
		
		return finalResult;
	}

}

這段程式碼是一個Spring Boot應用程序的控制器,它提供了一個Ubike服務,允許使用者根據輸入的區域查詢即時Ubike資訊。讓我解釋一下這個程式碼的功能:

  1. @RestController:這個標記表明這是一個Spring Boot控制器,它會處理HTTP請求。

  2. @Value("${outside.service.ubike}"):這個註釋用於注入應用程序的屬性,特別是outside.service.ubike 的值,這個值是外部Ubike服務的URL。這樣,你可以在程式中使用ubkieService變數來訪問這個URL。

  3. @GetMapping:這是一個HTTP GET請求的處理方法。它處理路徑為/api/ubike/{area}/rawdata的請求,其中{area}是一個區域的參數。

  4. ubikeQry 方法:這是實際的Ubike查詢方法。它接受area作為參數,用於指定要查詢的Ubike區域。

  5. RestTemplate:這是Spring的HTTP客戶端工具,用於發送HTTP請求。你首先建立一個RestTemplate實例,然後使用它來向外部Ubike服務發送GET請求。

  6. client.getForObject(ubkieService, UbikeData[].class):這行代碼使用RestTemplate來發送GET請求到ubkieService URL,然後將響應轉換為UbikeData數組。

  7. 在接收到Ubike資訊後,程式使用一個for 迴圈來遍歷所有的Ubike資料,並篩選出與輸入的區域匹配的資料。篩選後的結果存儲在finalResult列表中。

  8. 最後,將篩選後的Ubike資料列表finalResult返回給客戶端,這是一個包含了特定區域的Ubike資訊的JSON回應。

這個控制器允許客戶端根據區域查詢即時Ubike資訊,並返回符合條件的資料。當用戶訪問/api/ubike/{area}/rawdata端點時,控制器會執行ubikeQry 方法,並返回相應的Ubike資料。

再新增一個檔案

package com.tzu.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UbikeController {
	//提供一個View Page進行區域的Ubike即時資訊查詢
	@GetMapping(path="/ubike/qry")
	public String ubikeQry() {
		
		return "ubikeqry";
	}

	
}

這個程式碼片段是一個Spring控制器,通常用於處理和呈現Web應用程序的視圖。讓我解釋一下它的功能:

  1. @Controller:這個標記表明這是一個Spring MVC控制器,它用於處理HTTP請求並返回視圖。

  2. @GetMapping:這是一個HTTP GET請求處理方法。它處理路徑為/ubike/qry的GET請求。

  3. ubikeQry 方法:這是實際的控制器方法。當用戶訪問/ubike/qry路徑時,這個方法被執行。它返回一個字串 "ubikeqry"

  4. 返回視圖名稱:當這個控制器方法被調用時,它返回一個視圖的名稱,這個名稱通常用於導航到特定的視圖模板。在這個情況下,返回的視圖名稱是 "ubikeqry"

這個控制器的主要功能是提供一個View Page,用戶可以通過訪問/ubike/qry路徑來查詢Ubike的即時資訊。具體的視圖模板文件將根據視圖名稱 "ubikeqry" 來決定。通常,這個視圖將呈現Ubike資訊的查詢界面給用戶。

再新增一個ubikeqry.html檔案

用VSCODE編輯

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
</html>

修改成

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script th:src="@{/js/vue.min.js}"></script>
    <script th:src="@{/js/jquery-3.6.1.min.js}"></script>
    <title>Ubike 區域 即時資訊</title>
</head>
<body>

    <fieldset id="app">
        <legend>區域查詢</legend>
        <div>
            <div>區域</div>
            <input type="text"/>

        <button>查詢</button>
        </div>
    </fieldset>
</body>
</html>

測試Ubike 區域 即時資訊http://localhost:8080/ubike/qry

修改前端程式碼:

[VS Code]自動排版 Alt + Shift + F.

修改前端程式碼:顯示筆數

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script th:src="@{/js/vue.min.js}"></script>
    <script th:src="@{/js/jquery-3.6.1.min.js}"></script>
    <title>Ubike 區域 即時資訊</title>
</head>

<body>

    <fieldset id="app">
        <legend>區域查詢</legend>
        <div>
            <div>區域</div>
            <input type="text" />
            
            <button>查詢</button>
             <div>{{100/5}}</div>
        </div>
    </fieldset>
    <script>
        //建構一個Vue Instance
        //配置Vue物件初始化 使用JS物件
        var app = new Vue();

        //掛載到特定的DOM ID
        app.$mount('#app');
    </script>
</body>

</html>

這是一個HTML模板,它使用Vue.js和jQuery來創建一個簡單的Web頁面,用於Ubike區域即時資訊的查詢。讓我解釋一下這個模板的主要部分:

  1. <!DOCTYPE html>:這是HTML文件的聲明,它指定了這是一個HTML5文檔。

  2. <html lang="en">:HTML文檔的開始,並指定了語言為英語。

  3. <head>:這個部分包含了HTML文檔的元信息,例如字符集、視口設定和連結到JavaScript文件。

  4. <meta charset="UTF-8">:指定字符集為UTF-8,確保正確的文字編碼。

  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">:設定視口,以使頁面適應不同設備的螢幕寬度。

  6. <script th:src="@{/js/vue.min.js}"></script><script th:src="@{/js/jquery-3.6.1.min.js}"></script>:這兩行代碼包括了Vue.js和jQuery的JavaScript文件,以便在頁面上使用這些庫。

  7. <title>Ubike 區域 即時資訊</title>:設定網頁的標題。

  8. <body>:HTML文檔的主體部分,這裡將放置網頁的可見內容。

  9. <fieldset id="app">:這是一個HTML字段集,具有ID "app",它將被Vue實例掛載到這個元素上。

  10. <legend>區域查詢</legend>:這是字段集的標題。

  11. <div>:這個<div>元素包含區域查詢的輸入框和按鈕。

  12. <input type="text" />:這是一個文本輸入框,用戶可以在這裡輸入區域信息。

  13. <button>查詢</button>:這是一個按鈕,用戶可以點擊以執行區域查詢。

  14. <div>{{100/5}}</div>:這個<div>包含了Vue的數據綁定,它顯示了一個簡單的數學表達式的結果。Vue會將結果渲染到這個<div>中。

  15. <script>:這是JavaScript代碼的部分,它創建了一個Vue實例並將其掛載到ID為 "app" 的元素上。

這個模板是一個簡單的示例,用於Ubike區域查詢的前端部分。您可以在Vue實例中添加更多功能,以實現實際的區域查詢操作。

測試:http://localhost:8080/ubike/qry顯示筆數

前端CODE改成

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script th:src="@{/js/vue.min.js}"></script>
    <script th:src="@{/js/jquery-3.6.1.min.js}"></script>
    <title>Ubike 區域 即時資訊</title>
</head>

<body>

    <fieldset id="app">
        <legend>區域查詢</legend>
        <div>
            <div>區域</div>
            <input type="text" v-model.lazy:value="sarea"/>
            <button v-on:click="ubikeqryHandler">查詢</button>
           <div>您查詢的區域:{{sarea}}</div>
        </div>
    </fieldset>
    <script>
        //建構一個Vue Instance
        //配置Vue物件初始化 使用JS物件
        var app = new Vue(
//配置初始化物件
{
                //資料模組
                data:{
                    sarea:'', //空字串
                    result:[] //空陣列
                },
                //事件程序或者函數模組
                methods:{
                    ubikeqryHandler:function(){
                        
                        console.log(this.sarea);

                    }
                }
            }
        );
        //掛載到特定的DOM ID
        app.$mount('#app');
    </script>
</body>

</html>

這是一個HTML模板,它使用Vue.js和jQuery來創建一個簡單的Web頁面,用於Ubike區域即時資訊的查詢。讓我解釋一下這個模板的主要部分,特別是Vue.js相關的部分:

  1. <!DOCTYPE html>:這是HTML文件的聲明,它指定了這是一個HTML5文檔。

  2. <html lang="en">:HTML文檔的開始,並指定了語言為英語。

  3. <head>:這個部分包含了HTML文檔的元信息,例如字符集、視口設定和連結到JavaScript文件。

  4. <meta charset="UTF-8">:指定字符集為UTF-8,確保正確的文字編碼。

  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">:設定視口,以使頁面適應不同設備的螢幕寬度。

  6. <script th:src="@{/js/vue.min.js}"></script><script th:src="@{/js/jquery-3.6.1.min.js}"></script>:這兩行代碼包括了Vue.js和jQuery的JavaScript文件,以便在頁面上使用這些庫。

  7. <title>Ubike 區域 即時資訊</title>:設定網頁的標題。

  8. <body>:HTML文檔的主體部分,這裡將放置網頁的可見內容。

  9. <fieldset id="app">:這是一個HTML字段集,具有ID "app",它將被Vue實例掛載到這個元素上。

  10. <legend>區域查詢</legend>:這是字段集的標題。

  11. <div>:這個<div>元素包含區域查詢的輸入框、按鈕和顯示查詢結果的區域。

  12. <input type="text" v-model.lazy:value="sarea"/>:這是一個文本輸入框,並使用Vue的v-model指令來實現雙向數據綁定,它將輸入的值綁定到Vue實例的sarea屬性。

  13. <button v-on:click="ubikeqryHandler">查詢</button>:這是一個按鈕,當被點擊時,它執行名為ubikeqryHandler的方法,該方法定義在Vue實例的methods中。

  14. <div>您查詢的區域:{{sarea}}</div>:這個<div>顯示了查詢的區域,它使用Vue的模板語法將sarea的值插入到文本中。

  15. <script>:這是Vue.js的JavaScript代碼,它創建了一個Vue實例,配置了資料和方法,並將其掛載到ID為 "app" 的元素上。

Vue.js使您能夠實現數據綁定和事件處理,以實現互動性的Web頁面。在這個模板中,當用戶輸入區域並點擊查詢按鈕時,ubikeqryHandler方法將在控制台中輸出區域的值。您可以根據需要擴展這個示例,以實現更複雜的功能。

測試http://localhost:8080/ubike/qry 顯示

再修改前端資料

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script th:src="@{/js/vue.min.js}"></script>
    <script th:src="@{/js/jquery-3.6.1.min.js}"></script>
    <title>Ubike 區域 即時資訊</title>
</head>

<body>

    <fieldset id="app">
        <legend>區域查詢</legend>
        <div>
            <div>區域</div>
            <input type="text" v-model.lazy:value="sarea"/>
            <button v-on:click="ubikeqryHandler">查詢</button>
           <div>您查詢的區域:{{sarea}}</div>
        </div>
    </fieldset>
    <script>
        //建構一個Vue Instance
        //配置Vue物件初始化 使用JS物件
        var app = new Vue(
//配置初始化物件
{
                //資料模組
                data:{
                    sarea:'', //空字串
                    result:[] //空陣列
                },
                //事件程序或者函數模組
                methods:{
                    ubikeqryHandler:function(){
                        
                        //TODO進行非同步處理 指向自行定義的服務端點
                        let ubikeService='../api/ubike/'+this.sarea+'/rawdata';
                        console.log(ubikeService);

                    }
                }
            }
        );
        //掛載到特定的DOM ID
        app.$mount('#app');
    </script>
</body>

</html>

這是一個HTML模板,使用Vue.js和jQuery來創建一個簡單的Web頁面,用於Ubike區域即時資訊的查詢。以下是HTML模板的主要部分,特別是Vue.js相關的部分:

  1. <!DOCTYPE html>:這是HTML文件的聲明,它指定了這是一個HTML5文檔。

  2. <html lang="en">:HTML文檔的開始,並指定了語言為英語。

  3. <head>:這個部分包含了HTML文檔的元信息,例如字符集、視口設定和連結到JavaScript文件。

  4. <meta charset="UTF-8">:指定字符集為UTF-8,確保正確的文字編碼。

  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">:設定視口,以使網頁適應不同設備的螢幕寬度。

  6. <script th:src="@{/js/vue.min.js}"></script><script th:src="@{/js/jquery-3.6.1.min.js}"></script>:這兩行代碼包括了Vue.js和jQuery的JavaScript文件,以便在頁面上使用這些庫。

  7. <title>Ubike 區域 即時資訊</title>:設定網頁的標題。

  8. <body>:HTML文檔的主體部分,這裡將放置網頁的可見內容。

  9. <fieldset id="app">:這是一個HTML字段集,具有ID "app",它將被Vue實例掛載到這個元素上。

  10. <legend>區域查詢</legend>:這是字段集的標題。

  11. <div>:這個<div>元素包含區域查詢的輸入框、按鈕和顯示查詢結果的區域。

  12. <input type="text" v-model.lazy:value="sarea"/>:這是一個文本輸入框,並使用Vue的v-model指令來實現雙向數據綁定,它將輸入的值綁定到Vue實例的sarea屬性。

  13. <button v-on:click="ubikeqryHandler">查詢</button>:這是一個按鈕,當被點擊時,它執行名為ubikeqryHandler的方法,該方法定義在Vue實例的methods中。

  14. <div>您查詢的區域:{{sarea}}</div>:這個<div>顯示了查詢的區域,它使用Vue的模板語法將sarea的值插入到文本中。

  15. <script>:這是Vue.js的JavaScript代碼,它創建了一個Vue實例,配置了資料和方法,並將其掛載到ID為 "app" 的元素上。

在Vue實例中,當用戶在輸入框中輸入區域並點擊查詢按鈕時,ubikeqryHandler方法將在控制台中輸出查詢的URL。您可以根據需要擴展這個示例,以實現更複雜的功能,例如發送HTTP請求以獲取Ubike區域的即時資訊。

axios官網https://axios-http.com/zh/

下載axios從github:https://github.com/axios/axios

找到四個框架

解壓縮後放到專案下面

再修改前端程式碼

VS CODE安裝延伸模組Axios Snippets

https://ithelp.ithome.com.tw/upload/images/20231110/20119035ExzVwguiEx.png

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script th:src="@{/js/vue.min.js}"></script>
    <script th:src="@{/js/jquery-3.6.1.min.js}"></script>
    <script th:src="@{/js/axios.min.js}"></script>
    <title>Ubike 區域 即時資訊</title>
</head>

<body>

    <fieldset id="app">
        <legend>區域查詢</legend>
        <div>
            <div>區域</div>
            <input type="text" v-model.lazy:value="sarea"/>
            <button v-on:click="ubikeqryHandler">查詢</button>
           <div>您查詢的區域:{{sarea}}</div>
        </div>
    </fieldset>
    <script>
        //建構一個Vue Instance
        //配置Vue物件初始化 使用JS物件
        var app = new Vue(
//配置初始化物件
{
                //資料模組
                data:{
                    sarea:'', //空字串
                    result:[] //空陣列
                },
                //事件程序或者函數模組
                methods:{
                    ubikeqryHandler:function(){
                        
                        //TODO進行非同步處理 指向自行定義的服務端點
                        let ubikeService='../api/ubike/'+this.sarea+'/rawdata';
                        console.log(ubikeService);
                        //採用axios framework進行非同步(ajax)
                        axios.get(ubikeService)
                        //success callback Http status 2xx 傳遞近來Resonse
                        .then(res => {
                            console.log(res);
                        })
                        //Error callback 產生狀態碼為4xx or 5xx
                        .catch(err => {
                            console.log(err); 
                        })

                    }
                }
            }
        );
        //掛載到特定的DOM ID
        app.$mount('#app');
    </script>
</body>

</html>

你的HTML代碼看起來已經修正正確。這個代碼應該正確地引入Vue.js、jQuery、axios和Bootstrap,並且Vue實例的綁定也正確。

當用戶輸入區域並單擊"查詢"按鈕時,Vue應該能夠發出一個非同步請求到指定的服務端點,並根據回應更新結果。

這個HTML模板在之前的基礎上添加了 Axios 框架,以實現更高級的非同步HTTP請求。以下是更新的部分:

  1. <script th:src="@{/js/axios.min.js}"></script>:這一行引入 Axios JavaScript庫,它是一個用於發送HTTP請求的強大庫。

  2. 在Vue實例中的ubikeqryHandler方法中,使用axios.get方法來發送HTTP GET請求。您創建了一個變數ubikeService,其中包含了要訪問的Ubike服務的URL,並將區域(this.sarea)添加到URL中以查詢特定區域的即時資訊。

  3. .then(res => {...}):這是當HTTP請求成功完成時的回調函數,它將請求的響應存儲在res變數中,您可以在此處處理響應數據。在這個示例中,只是將響應輸出到控制台。

  4. .catch(err => {...}):這是當HTTP請求遇到錯誤(例如,狀態碼為4xx或5xx)時的回調函數,它將錯誤信息存儲在err變數中,您可以在此處處理錯誤情況。在這個示例中,只是將錯誤信息輸出到控制台。

這樣,您可以使用Axios來發送HTTP GET請求,查詢指定區域的Ubike即時資訊,並根據響應進行處理。請確保Ubike服務的URL正確,以便正確訪問資料。

測試http://localhost:8080/ubike/qry 顯示狀態號碼

查看data部分

到台北市資料大平台:https://data.taipei/dataset/detail?id=c6bc8aed-557d-41d5-bfb1-8da24f78f2fb

加入主要:欄位說明 sno(站點代號)、sna(場站中文名稱)、tot(場站總停車格)、sbi(場站目前車輛數量)、sarea(場站區域)、mday(資料更新時間)、lat(緯度)、lng(經度)、ar(地點)、sareaen(場站區域英文)、snaen(場站名稱英文)、aren(地址英文)、bemp(空位數量)、act(全站禁用狀態)、srcUpdateTime(YouBike2.0系統發布資料更新的時間)、updateTime(大數據平台經過處理後將資料存入DB的時間)、infoTime(各場站來源資料更新時間)、infoDate(各場站來源資料更新時間)

修改前端程式碼:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script th:src="@{/js/vue.min.js}"></script>
    <script th:src="@{/js/jquery-3.6.1.min.js}"></script>
    <script th:src="@{/js/axios.min.js}"></script>
    <title>Ubike 區域 即時資訊</title>
</head>

<body>

    <fieldset id="app">
        <legend>區域查詢</legend>
        <div>
            <div>區域</div>
            <input type="text" v-model.lazy:value="sarea"/>
            <button v-on:click="ubikeqryHandler">查詢</button>
            <div>您查詢的區域:{{sarea}}</div>
        </div>
        <fieldset>
            <legend>{{sarea}} 區域及時狀態</legend>
            <table class="table table-dark table-hover">
                <thead>
                    <tr>
                        <td>區域</td>
                        <td>場站</td>
                        <td>總停車數</td>
                        <td>目前車數</td>
                        <td>空位數</td>
                        <td>時間點</td>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="item in result">
                     
                        <td>{{item.sarea}}</td>
                        <td>{{item.sna}}</td>
                        <td>{{item.tot}}</td>
                        <td>{{item.sbi}}</td>
                        <td>{{item.bemp}}</td>
                        <td>{{item.srcUpdateTime}}</td>
                    </tr>
                </tbody>
            </table>
        </fieldset>
    </fieldset>
    <script>
        //建構一個Vue Instance
        //配置Vue物件初始化 使用JS物件
        var app = new Vue(
//配置初始化物件
{
                //資料模組
                data:{
                    sarea:'', //空字串
                    result:[] //空陣列
                },
                //事件程序或者函數模組
                methods:{
                    ubikeqryHandler:function(){
                        
                        //TODO進行非同步處理 指向自行定義的服務端點
                        let ubikeService='../api/ubike/'+this.sarea+'/rawdata';
                        console.log(ubikeService);
                        //採用axios framework進行非同步(ajax)
                        axios.get(ubikeService)
                        //success callback Http status 2xx 傳遞近來Resonse
                        .then(res => {
                            console.log(res);
                            this.result=res.data; //回應資料物件
                            //TODO 進行UI Render渲染

                        })
                        //Error callback 產生狀態碼為4xx or 5xx
                        .catch(err => {
                            console.log(err); 
                        })

                    }
                }
            }
        );
        //掛載到特定的DOM ID
        app.$mount('#app');
    </script>
</body>

</html>

這個HTML模板已經被擴展,以便在接收到Ubike服務的響應後呈現即時資訊。以下是更新的部分:

  1. <fieldset>中添加了一個嵌套的<fieldset>,用來顯示區域的即時狀態。這個嵌套<fieldset>包含一個<table>,其中的<thead><tbody>用來呈現即時資訊的表格。

  2. <thead>中,定義了表格的列標題,分別是"區域"、"場站"、"總停車數"、"目前車數"、"空位數"和"時間點"。

  3. <tbody>中,使用v-for指令迭代result數組中的每個item,然後呈現各個項目的值。

  4. ubikeqryHandler方法的then回調中,將Ubike服務的回應資料存儲在this.result中,以便在表格中呈現即時資訊。

現在,當您在文本框中輸入區域並點擊"查詢"按鈕時,Ubike服務的即時資訊將顯示在表格中。請確保Ubike服務返回的資料結構與表格中的項目相符,以便正確呈現。如果資料結構不同,您需要相應地調整模板以匹配Ubike服務的響應。

測試http://localhost:8080/ubike/qry

https://ithelp.ithome.com.tw/upload/images/20231110/201190358deltksTbH.png
下載Bootstrap :https://getbootstrap.com/docs/4.6/getting-started/download/

解壓縮後

複製貼上後端
https://ithelp.ithome.com.tw/upload/images/20231110/20119035LFIVkvJI4S.png
查詢顯示
https://ithelp.ithome.com.tw/upload/images/20231110/20119035GN7o0iaDt0.png

修飾版面,修改前端CODE

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script th:src="@{/js/vue.min.js}"></script>
    <script th:src="@{/js/jquery-3.6.1.min.js}"></script>
    <script th:src="@{/js/axios.min.js}"></script>
    <script th:src="@{/js/bootstrap.bundle.min.js}"></script>
    <script th:src="@{/js/bootstrap.min.js}"></script>
    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
    <title>Ubike 區域 即時資訊</title>
    
</head>

<body>

    <fieldset id="app">
        <legend>區域查詢</legend>
        <div>
            <div>區域</div>
            <input type="text" v-model.lazy:value="sarea"/>
            <button v-on:click="ubikeqryHandler">查詢</button>
            <div>您查詢的區域:{{sarea}}</div>
        </div>
        <fieldset>
            <legend>{{sarea}} 區域及時狀態</legend>
            <table class="table table-dark table-hover">
                <thead>
                    <tr>
                        <td>區域</td>
                        <td>場站</td>
                        <td>總停車數</td>
                        <td>目前車數</td>
                        <td>空位數</td>
                        <td>時間點</td>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="item in result">
                     
                        <td>{{item.sarea}}</td>
                        <td>{{item.sna}}</td>
                        <td>{{item.tot}}</td>
                        <td>{{item.sbi}}</td>
                        <td>{{item.bemp}}</td>
                        <td>{{item.srcUpdateTime}}</td>
                    </tr>
                </tbody>
            </table>
        </fieldset>
    </fieldset>
    <script>
        //建構一個Vue Instance
        //配置Vue物件初始化 使用JS物件
        var app = new Vue(
//配置初始化物件
{
                //資料模組
                data:{
                    sarea:'', //空字串
                    result:[] //空陣列
                },
                //事件程序或者函數模組
                methods:{
                    ubikeqryHandler:function(){
                        
                        //TODO進行非同步處理 指向自行定義的服務端點
                        let ubikeService='../api/ubike/'+this.sarea+'/rawdata';
                        console.log(ubikeService);
                        //採用axios framework進行非同步(ajax)
                        axios.get(ubikeService)
                        //success callback Http status 2xx 傳遞近來Resonse
                        .then(res => {
                            console.log(res);
                            this.result=res.data; //回應資料物件
                            //TODO 進行UI Render渲染

                        })
                        //Error callback 產生狀態碼為4xx or 5xx
                        .catch(err => {
                            console.log(err); 
                        })

                    }
                }
            }
        );
        //掛載到特定的DOM ID
        app.$mount('#app');
    </script>
</body>

</html>

用了Bootstrap來改善外觀和風格。現在,當輸入區域並點擊"查詢"按鈕時,Ubike服務的即時資訊將以表格形式顯示在頁面上。這樣的網頁將提供更好的用戶體驗。

請確保所有JavaScript庫和CSS文件(如Vue.js、jQuery、axios和Bootstrap)已被正確引入,並且相關的路徑(@{/js/vue.min.js}@{/js/jquery-3.6.1.min.js}@{/js/axios.min.js}@{/js/bootstrap.bundle.min.js}@{/js/bootstrap.min.js}@{/css/bootstrap.min.css})都被設定為正確的位置。

請記住,Ubike服務的響應應該與表格的項目相匹配,以便正確呈現資訊。如果Ubike服務返回的資料結構不同,則需要相應調整Vue.js的模板以匹配。這個模板已經設定好,當接收到Ubike服務的回應後,它將根據服務的回應自動更新表格中的資料。

繼續設計按鈕顯示的字,

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script th:src="@{/js/vue.min.js}"></script>
    <script th:src="@{/js/jquery-3.6.1.min.js}"></script>
    <script th:src="@{/js/axios.min.js}"></script>
    <script th:src="@{/js/bootstrap.bundle.min.js}"></script>
    <script th:src="@{/js/bootstrap.min.js}"></script>
    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
    <title>Ubike 區域 即時資訊</title>
    
</head>

<body>

    <fieldset id="app">
        <legend>區域查詢</legend>
        <div>
            <div>區域</div>
            <input type="text" v-model.lazy:value="sarea" class="text text-primary"/>
            <button v-on:click="ubikeqryHandler" class="btn-sucess">查詢</button>
           <div>您查詢的區域:{{sarea}}</div>
        </div>
        <fieldset>
            <legend>{{sarea}} 區域及時狀態</legend>
            <table class="table table-dark table-hover">
                <thead>
                    <tr>
                        <td>區域</td>
                        <td>場站</td>
                        <td>總停車數</td>
                        <td>目前車數</td>
                        <td>空位數</td>
                        <td>時間點</td>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="item in result">
                     
                        <td>{{item.sarea}}</td>
                        <td>{{item.sna}}</td>
                        <td>{{item.tot}}</td>
                        <td>{{item.sbi}}</td>
                        <td>{{item.bemp}}</td>
                        <td>{{item.srcUpdateTime}}</td>
                    </tr>
                </tbody>
            </table>
        </fieldset>
    </fieldset>
    <script>
        //建構一個Vue Instance
        //配置Vue物件初始化 使用JS物件
        var app = new Vue(
//配置初始化物件
{
                //資料模組
                data:{
                    sarea:'', //空字串
                    result:[] //空陣列
                },
                //事件程序或者函數模組
                methods:{
                    ubikeqryHandler:function(){
                        
                        //TODO進行非同步處理 指向自行定義的服務端點
                        let ubikeService='../api/ubike/'+this.sarea+'/rawdata';
                        console.log(ubikeService);
                        //採用axios framework進行非同步(ajax)
                        axios.get(ubikeService)
                        //success callback Http status 2xx 傳遞近來Resonse
                        .then(res => {
                            console.log(res);
                            this.result=res.data; //回應資料物件
                            //TODO 進行UI Render渲染

                        })
                        //Error callback 產生狀態碼為4xx or 5xx
                        .catch(err => {
                            console.log(err); 
                        })

                    }
                }
            }
        );
        //掛載到特定的DOM ID
        app.$mount('#app');
    </script>
</body>

</html>

你的HTML代碼看起來很不錯,但有一些小問題需要處理:

<button> 元素的 class 中,你正在使用 "btn-sucess",但正確的是 "btn-success",這樣按鈕應該顯示為綠色。

<input> 元素的 v-model.lazy 屬性可以被簡化為 v-model="sarea"

如果你使用Bootstrap,你應該確保你的頁面中包括了Bootstrap的CSS樣式文件,以便正確渲染Bootstrap元素和樣式。

這裡是經過修正的代碼:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script th:src="@{/js/vue.min.js}"></script>
    <script th:src="@{/js/jquery-3.6.1.min.js}"></script>
    <script th:src="@{/js/axios.min.js}"></script>
    <script th:src="@{/js/bootstrap.bundle.min.js}"></script>
    <script th:src="@{/js/bootstrap.min.js}"></script>
    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
    <title>Ubike 區域 即時資訊</title>
    
</head>

<body>

    <fieldset id="app">
        <legend>區域查詢</legend>
        <div>
            <div>區域</div>
            <input type="text" v-model="sarea" class="form-control text-primary"/>
            <button v-on:click="ubikeqryHandler" class="btn btn-success">查詢</button>
           <div>您查詢的區域: {{sarea}}</div>
        </div>
        <fieldset>
            <legend>{{sarea}} 區域及時狀態</legend>
            <table class="table table-dark table-hover">
                <thead>
                    <tr>
                        <td>區域</td>
                        <td>場站</td>
                        <td>總停車數</td>
                        <td>目前車數</td>
                        <td>空位數</td>
                        <td>時間點</td>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="item in result">
                        <td>{{item.sarea}}</td>
                        <td>{{item.sna}}</td>
                        <td>{{item.tot}}</td>
                        <td>{{item.sbi}}</td>
                        <td>{{item.bemp}}</td>
                        <td>{{item.srcUpdateTime}}</td>
                    </tr>
                </tbody>
            </table>
        </fieldset>
    </fieldset>
    <script>
        //建構一個Vue Instance
        //配置Vue物件初始化 使用JS物件
        var app = new Vue(
            //配置初始化物件
            {
                //資料模組
                data:{
                    sarea:'', //空字串
                    result:[] //空陣列
                },
                //事件程序或者函數模組
                methods:{
                    ubikeqryHandler:function(){
                        
                        //TODO進行非同步處理 指向自行定義的服務端點
                        let ubikeService='../api/ubike/'+this.sarea+'/rawdata';
                        console.log(ubikeService);
                        //採用axios framework進行非同步(ajax)
                        axios.get(ubikeService)
                        //success callback Http status 2xx 傳遞近來Resonse
                        .then(res => {
                            console.log(res);
                            this.result=res.data; //回應資料物件
                            //TODO 進行UI Render渲染

                        })
                        //Error callback 產生狀態碼為4xx or 5xx
                        .catch(err => {
                            console.log(err); 
                        })

                    }
                }
            }
        );
        //掛載到特定的DOM ID
        app.$mount('#app');
    </script>
</body>

</html>

你的HTML代碼看起來已經修正正確。這個代碼應該正確地引入Vue.js、jQuery、axios和Bootstrap,並且Vue實例的綁定也正確。

當用戶輸入區域並單擊"查詢"按鈕時,Vue應該能夠發出一個非同步請求到指定的服務端點,並根據回應更新結果。

現在,這個HTML代碼應該會正確渲染,並且按鈕和輸入框的外觀和功能都是正確的。

測試http://localhost:8080/ubike/qry

https://ithelp.ithome.com.tw/upload/images/20231110/20119035y121io3jo7.png

在新增一個檔案service.properties放在src/main/resources下面

https://ithelp.ithome.com.tw/upload/images/20231110/20119035ibtxWE8dVI.png

#app service url
app.service.ubikeqry=http://localhost:8080/api/ubike/%s/rawdata
app.service.ubike=https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json

您可以定義應用程序服務的URL,以便在前端JavaScript中使用。對於不同的服務,您可以在JavaScript中根據需要使用這些URL。以下是如何使用它們的示例:

// 區域查詢服務的URL
var ubikeQryService = 'http://localhost:8080/api/ubike/%s/rawdata';

// Ubike服務的URL
var ubikeService = 'https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json';

// 使用ubikeQryService來構建特定區域的Ubike查詢URL
var sarea = 'your_area'; // 這是區域名稱
var ubikeQryURL = ubikeQryService.replace('%s', sarea);

// 現在ubikeQryURL包含了完整的Ubike查詢URL,您可以使用它來發出非同步請求
axios.get(ubikeQryURL)
  .then(res => {
    console.log(res);
    // 在這裡處理回應
  })
  .catch(err => {
    console.log(err);
    // 在這裡處理錯誤
  });

這樣,您可以使用ubikeQryServiceubikeService的值來動態構建URL,以便發出相應的HTTP請求。當您需要使用不同的URL時,只需更改這些變數的值即可。

再修改UbikeController

package com.tzu.controllers;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
@PropertySource("classpath:service.properties") //註冊resource 來源
public class UbikeController {
	//Data Field
	@Value("${app.service.ubikeqry}")
	private String ubikeQryService;
	//提供一個View Page進行區域的Ubike即時資訊查詢
	@GetMapping(path="/ubike/qry")
	public String ubikeQry() {
		System.out.println(this.ubikeQryService);
		return "ubikeqry";
	}

}

這個控制器已經配置了讀取屬性文件 "service.properties" 並將其中的 "app.service.ubikeqry" 屬性值注入到 ubikeQryService 字段中。當在 "service.properties" 文件中設定了 app.service.ubikeqry 的值,它會被注入到控制器中。當您訪問 "/ubike/qry" 路由時,它將打印出 ubikeQryService 的值。

這個設定允許您輕鬆地配置不同的服務 URL,而不需要硬編碼它們在控制器中。這樣,您可以在不更改代碼的情況下變更服務的 URL。當您需要切換到不同的服務 URL 時,只需更新 "service.properties" 文件中的屬性即可。
refresh網站http://localhost:8080/ubike/qry

後端顯示
https://ithelp.ithome.com.tw/upload/images/20231110/20119035DLD5BZLcCS.png
謝謝大家收看
/images/emoticon/emoticon41.gif


上一篇
Springboot~練習與外部資料連結
下一篇
Springboot~配置JPA
系列文
自己開發一個~?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言