hadoop2-HBase的Java API操作

来源:https://www.cnblogs.com/hongten/archive/2018/11/08/hongten_hadoop_hbase_java_api.html
-Advertisement-
Play Games

Hbase提供了豐富的Java API,以及線程池操作,下麵我用線程池來展示一下使用Java API操作Hbase。 項目結構如下: ...


Hbase提供了豐富的Java API,以及線程池操作,下麵我用線程池來展示一下使用Java API操作Hbase。

項目結構如下:

我使用的Hbase的版本是

hbase-0.98.9-hadoop2-bin.tar.gz

大家下載後,可以拿到裡面的lib目錄下麵的jar文件,即上所示的hbase-lib資源。

 

介面類:

/hbase-util/src/com/b510/hbase/util/dao/HbaseDao.java

 1 package com.b510.hbase.util.dao;
 2 
 3 import java.util.List;
 4 
 5 import org.apache.hadoop.hbase.client.HTableInterface;
 6 
 7 
 8 /**
 9  * @author Hongten
10  * @created 7 Nov 2018
11  */
12 public interface HbaseDao {
13 
14     // initial table
15     public HTableInterface getHTableFromPool(String tableName);
16 
17     // check if the table is exist
18     public boolean isHTableExist(String tableName);
19 
20     // create table
21     public void createHTable(String tableName, String[] columnFamilys);
22 
23     // insert new row
24     public void addRow(String tableName, String rowKey, String columnFamily, String column, String value);
25 
26     // get row by row key
27     public void getRow(String tableName, String rowKey);
28 
29     public void getAllRows(String tableName);
30 
31     // get rows by giving range
32     public void getRowsByRange(String tableName, String startRowKey, String endRowKey);
33 
34     //delete row
35     public void delRow(String tableName, String rowKey);
36     
37     //delete rows by row keys
38     public void delRowsByRowKeys(String tableName, List<String> rowKeys);
39 
40     // auto flush data when close
41     public void closeAutoFlush(HTableInterface table);
42 
43     // close table
44     public void closeTable(HTableInterface table);
45 
46     // close pool connection
47     public void closePoolConnection();
48 
49     // delete table
50     public void deleteHTable(String tableName);
51 }

 

實現類:

/hbase-util/src/com/b510/hbase/util/dao/impl/HbaseDaoImpl.java

  1 package com.b510.hbase.util.dao.impl;
  2 
  3 import java.io.IOException;
  4 import java.util.List;
  5 
  6 import org.apache.hadoop.conf.Configuration;
  7 import org.apache.hadoop.hbase.Cell;
  8 import org.apache.hadoop.hbase.CellUtil;
  9 import org.apache.hadoop.hbase.HBaseConfiguration;
 10 import org.apache.hadoop.hbase.HColumnDescriptor;
 11 import org.apache.hadoop.hbase.HTableDescriptor;
 12 import org.apache.hadoop.hbase.MasterNotRunningException;
 13 import org.apache.hadoop.hbase.TableName;
 14 import org.apache.hadoop.hbase.ZooKeeperConnectionException;
 15 import org.apache.hadoop.hbase.client.Delete;
 16 import org.apache.hadoop.hbase.client.Get;
 17 import org.apache.hadoop.hbase.client.HBaseAdmin;
 18 import org.apache.hadoop.hbase.client.HTableInterface;
 19 import org.apache.hadoop.hbase.client.HTablePool;
 20 import org.apache.hadoop.hbase.client.Put;
 21 import org.apache.hadoop.hbase.client.Result;
 22 import org.apache.hadoop.hbase.client.ResultScanner;
 23 import org.apache.hadoop.hbase.client.Scan;
 24 
 25 import com.b510.hbase.util.dao.HbaseDao;
 26 
 27 /**
 28  * @author Hongten
 29  * @created 7 Nov 2018
 30  */
 31 @SuppressWarnings("deprecation")
 32 public class HbaseDaoImpl implements HbaseDao {
 33 
 34     private static Configuration conf = null;
 35     private static HBaseAdmin hAdmin;
 36     private static HTablePool pool;
 37 
 38     private static int defaultPoolSize = 5;
 39 
 40     public HbaseDaoImpl(int poolSize) {
 41         conf = HBaseConfiguration.create();
 42         conf.set("hbase.zookeeper.quorum", "node1:2888,node2:2888,node3:2888");
 43         try {
 44             hAdmin = new HBaseAdmin(conf);
 45             // the default pool size is 5.
 46             pool = new HTablePool(conf, poolSize <= 0 ? defaultPoolSize : poolSize);
 47         } catch (MasterNotRunningException e) {
 48             e.printStackTrace();
 49         } catch (ZooKeeperConnectionException e) {
 50             e.printStackTrace();
 51         } catch (IOException e) {
 52             e.printStackTrace();
 53         }
 54     }
 55 
 56     @Override
 57     public HTableInterface getHTableFromPool(String tableName) {
 58         HTableInterface table = pool.getTable(tableName);
 59         return table;
 60     }
 61 
 62     @Override
 63     public boolean isHTableExist(String tableName) {
 64         try {
 65             return hAdmin.tableExists(tableName);
 66         } catch (IOException e) {
 67             e.printStackTrace();
 68         }
 69         return false;
 70     }
 71 
 72     @Override
 73     public void createHTable(String tableName, String[] columnFamilys) {
 74         if (!isHTableExist(tableName)) {
 75             HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(tableName));
 76             // The Hbase suggested the number of column family should be less than 3.
 77             // Normally, there only have 1 column family.
 78             for (String cfName : columnFamilys) {
 79                 HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(cfName);
 80                 tableDescriptor.addFamily(hColumnDescriptor);
 81             }
 82             try {
 83                 hAdmin.createTable(tableDescriptor);
 84             } catch (IOException e) {
 85                 e.printStackTrace();
 86             }
 87             System.out.println("The table [" + tableName + "]  is created.");
 88         } else {
 89             System.out.println("The table [" + tableName + "]  is existing already.");
 90         }
 91 
 92     }
 93 
 94     @Override
 95     public void addRow(String tableName, String rowKey, String columnFamily, String column, String value) {
 96         if (isHTableExist(tableName)) {
 97             HTableInterface table = getHTableFromPool(tableName);
 98             Put put = new Put(rowKey.getBytes());
 99             put.add(columnFamily.getBytes(), column.getBytes(), value.getBytes());
100             try {
101                 table.put(put);
102             } catch (IOException e) {
103                 e.printStackTrace();
104             }
105             System.out.println("Insert into table [" + tableName + "], Rowkey=[" + rowKey + "], Column=[" + columnFamily + ":" + column + "], Vlaue=[" + value + "].");
106             closeTable(table);
107         } else {
108             System.out.println("The table [" + tableName + "] does not exist.");
109         }
110     }
111 
112     @Override
113     public void getRow(String tableName, String rowKey) {
114         if (isHTableExist(tableName)) {
115             HTableInterface table = getHTableFromPool(tableName);
116             Get get = new Get(rowKey.getBytes());
117             Result result;
118             try {
119                 result = table.get(get);
120                 String columnName = "";
121                 String timeStamp = "";
122                 String columnFamily = "";
123                 String value = "";
124                 for (Cell cell : result.rawCells()) {
125                     timeStamp = String.valueOf(cell.getTimestamp());
126                     columnFamily = new String(CellUtil.cloneFamily(cell));
127                     columnName = new String(CellUtil.cloneQualifier(cell));
128                     value = new String(CellUtil.cloneValue(cell));
129 
130                     System.out.println("Get from table [" + tableName + "], Rowkey=[" + rowKey + "], Column=[" + columnFamily + ":" + columnName + "], Timestamp=[" + timeStamp + "], Vlaue=[" + value + "].");
131                 }
132             } catch (IOException e) {
133                 e.printStackTrace();
134             }
135             closeTable(table);
136         } else {
137             System.out.println("The table [" + tableName + "] does not exist.");
138         }
139     }
140 
141     @Override
142     public void getAllRows(String tableName) {
143         if (isHTableExist(tableName)) {
144             Scan scan = new Scan();
145             scanHTable(tableName, scan);
146         } else {
147             System.out.println("The table [" + tableName + "] does not exist.");
148         }
149     }
150 
151     private void scanHTable(String tableName, Scan scan) {
152         try {
153             HTableInterface table = getHTableFromPool(tableName);
154             ResultScanner results = table.getScanner(scan);
155             for (Result result : results) {
156                 String rowKey = "";
157                 String columnName = "";
158                 String timeStamp = "";
159                 String columnFamily = "";
160                 String value = "";
161                 for (Cell cell : result.rawCells()) {
162                     rowKey = new String(CellUtil.cloneRow(cell));
163                     timeStamp = String.valueOf(cell.getTimestamp());
164                     columnFamily = new String(CellUtil.cloneFamily(cell));
165                     columnName = new String(CellUtil.cloneQualifier(cell));
166                     value = new String(CellUtil.cloneValue(cell));
167 
168                     System.out.println("Get from table [" + tableName + "], Rowkey=[" + rowKey + "], Column=[" + columnFamily + ":" + columnName + "], Timestamp=[" + timeStamp + "], Vlaue=[" + value + "].");
169                 }
170             }
171             closeTable(table);
172         } catch (IOException e) {
173             e.printStackTrace();
174         }
175     }
176 
177     @Override
178     public void getRowsByRange(String tableName, String startRowKey, String endRowKey) {
179         if (isHTableExist(tableName)) {
180             Scan scan = new Scan();
181             scan.setStartRow(startRowKey.getBytes());
182             // not equals Stop Row Key, it mean the result does not include the stop row record(exclusive).
183             // the hbase version is 0.98.9
184             scan.setStopRow(endRowKey.getBytes());
185             scanHTable(tableName, scan);
186         } else {
187             System.out.println("The table [" + tableName + "] does not exist.");
188         }
189     }
190 
191     @Override
192     public void delRow(String tableName, String rowKey) {
193         if (isHTableExist(tableName)) {
194             HTableInterface table = getHTableFromPool(tableName);
195             deleteRow(table, rowKey);
196         } else {
197             System.out.println("The table [" + tableName + "] does not exist.");
198         }
199     }
200 
201     private void deleteRow(HTableInterface table, String rowKey) {
202         Delete del = new Delete(rowKey.getBytes());
203         try {
204             table.delete(del);
205             System.out.println("Delete from table [" + new String(table.getTableName()) + "], Rowkey=[" + rowKey + "].");
206             closeTable(table);
207         } catch (IOException e) {
208             e.printStackTrace();
209         }
210     }
211 
212     @Override
213     public void delRowsByRowKeys(String tableName, List<String> rowKeys) {
214         if (rowKeys != null && rowKeys.size() > 0) {
215             for (String rowKey : rowKeys) {
216                 delRow(tableName, rowKey);
217             }
218         }
219     }
220 
221     @Override
222     public void deleteHTable(String tableName) {
223         if (isHTableExist(tableName)) {
224             try {
225                 hAdmin.disableTable(tableName.getBytes());
226                 hAdmin.deleteTable(tableName.getBytes());
227                 System.out.println("The table [" + tableName + "] is deleted.");
228             } catch (IOException e) {
229                 e.printStackTrace();
230             }
231         } else {
232             System.out.println("The table [" + tableName + "] does not exist.");
233         }
234 
235     }
236 
237     @Override
238     public void closeAutoFlush(HTableInterface table) {
239         table.setAutoFlush(false, false);
240     }
241 
242     @Override
243     public void closeTable(HTableInterface table) {
244         try {
245             table.close();
246         } catch (IOException e) {
247             e.printStackTrace();
248         }
249     }
250 
251     @Override
252     public void closePoolConnection() {
253         try {
254             pool.close();
255         } catch (IOException e) {
256             e.printStackTrace();
257         }
258     }
259 
260 }

 

測試類:

/hbase-util/src/com/b510/hbase/util/dao/test/HbaseDaoTest.java

 1 package com.b510.hbase.util.dao.test;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 import org.junit.Test;
 7 
 8 import com.b510.hbase.util.dao.HbaseDao;
 9 import com.b510.hbase.util.dao.impl.HbaseDaoImpl;
10 
11 /**
12  * @author Hongten
13  * @created 7 Nov 2018
14  */
15 public class HbaseDaoTest {
16 
17     HbaseDao dao = new HbaseDaoImpl(4);
18 
19     public static final String tableName = "t_test";
20     public static final String columnFamilyName = "cf1";
21     public static final String[] CFs = { columnFamilyName };
22 
23     public static final String COLUMN_NAME_NAME = "name";
24     public static final String COLUMN_NAME_AGE = "age";
25 
26     @Test
27     public void main() {
28         createTable();
29         addRow();
30         getRow();
31         getAllRows();
32         getRowsByRange();
33         delRow();
34         delRowsByRowKeys();
35         deleteHTable();
36     }
37 
38     public void createTable() {
39         System.out.println("=== create table ====");
40         dao.createHTable(tableName, CFs);
41     }
42 
43     public void addRow() {
44         System.out.println("=== insert record ====");
45         dao.addRow(tableName, "12345566", columnFamilyName, COLUMN_NAME_NAME, "Hongten");
46         dao.addRow(tableName, "12345566", columnFamilyName, COLUMN_NAME_AGE, "22");
47 
48         dao.addRow(tableName, "12345567", columnFamilyName, COLUMN_NAME_NAME, "Tom");
49         dao.addRow(tableName, "12345567", columnFamilyName, COLUMN_NAME_AGE, "25");
50 
51         dao.addRow(tableName, "12345568", columnFamilyName, COLUMN_NAME_NAME, "Jone");
52         dao.addRow(tableName, "12345568", columnFamilyName, COLUMN_NAME_AGE, "30");
53 
54         dao.addRow(tableName, "12345569", columnFamilyName, COLUMN_NAME_NAME, "Jobs");
55         dao.addRow(tableName, "12345569", columnFamilyName, COLUMN_NAME_AGE, "24");
56     }
57 
58     public void getRow() {
59         System.out.println("=== get record ====");
60         dao.getRow(tableName, "12345566");
61     }
62 
63     public void getAllRows() {
64         System.out.println("=== scan table ====");
65         dao.getAllRows(tableName);
66     }
67 
68     public void getRowsByRange() {
69         System.out.println("=== scan record by giving range ====");
70         // it will return the '12345567' and '12345568' rows.
71         dao.getRowsByRange(tableName, "12345567", "12345569");
72     }
73 
74     public void delRow() {
75         System.out.println("=== delete record ====");
76         dao.delRow(tableName, "12345568");
77         // only '12345567' row.
78         getRowsByRange();
79     }
80 
81     public void delRowsByRowKeys() {
82         System.out.println("=== delete batch records ====");
83         List<String> rowKeys = new ArrayList<String>();
84         rowKeys.add("12345566");
85         rowKeys.add("12345569");
86         dao.delRowsByRowKeys(tableName, rowKeys);
87         // can not find the '12345566' and '12345569'
88         getAllRows();
89     }
90 
91     public void deleteHTable() {
92         System.out.println("=== delete table ====");
93         dao.deleteHTable(tableName);
94     }
95 }

 

測試結果:

log4j:WARN No appenders could be found for logger (org.apache.hadoop.metrics2.lib.MutableMetricsFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
=== create table ====
The table [t_test]  is created.
=== insert record ====
Insert into table [t_test], Rowkey=[12345566], Column=[cf1:name], Vlaue=[Hongten].
Insert into table [t_test], Rowkey=[12345566], Column=[cf1:age], Vlaue=[22].
Insert into table [t_test], Rowkey=[12345567], Column=[cf1:name], Vlaue=[Tom].
Insert into table [t_test], Rowkey=[12345567], Column=[cf1:age], Vlaue=[25].
Insert into table [t_test], Rowkey=[12345568], Column=[cf1:name], Vlaue=[Jone].
Insert into table [t_test], Rowkey=[12345568], Column=[cf1:age], Vlaue=[30].
Insert into table [t_test], Rowkey=[12345569], Column=[cf1:name], Vlaue=[Jobs].
Insert into table [t_test], Rowkey=[12345569], Column=[cf1:age], Vlaue=[24].
=== get record ====
Get from table [t_test], Rowkey=[12345566], Column=[cf1:age], Timestamp=[1541652952697], Vlaue=[22].
Get from table [t_test], Rowkey=[12345566], Column=[cf1:name], Timestamp=[1541652952626], Vlaue=[Hongten].
=== scan table ====
Get from table [t_test], Rowkey=[12345566], Column=[cf1:age], Timestamp=[1541652952697], Vlaue=[22].
Get from table [t_test], Rowkey=[12345566], Column=[cf1:name], Timestamp=[1541652952626], Vlaue=[Hongten].
Get from table [t_test], Rowkey=[12345567], Column=[cf1:age], Timestamp=[1541652952779], Vlaue=[25].
Get from table [t_test], Rowkey=[12345567], Column=[cf1:name], Timestamp=[1541652952743], Vlaue=[Tom].
Get from table [t_test], Rowkey=[12345568], Column=[cf1:age], Timestamp=[1541652952834], Vlaue=[30].
Get from table [t_test], Rowkey=[12345568], Column=[cf1:name], Timestamp=[1541652952807], Vlaue=[Jone].
Get from table [t_test], Rowkey=[12345569], Column=[cf1:age], Timestamp=[1541652952928], Vlaue=[24].
Get from table [t_test], Rowkey=[12345569], Column=[cf1:name], Timestamp=[1541652952869], Vlaue=[Jobs].
=== scan record by giving range ====
Get from table [t_test], Rowkey=[12345567], Column=[cf1:age], Timestamp=[1541652952779], Vlaue=[25].
Get from table [t_test], Rowkey=[12345567], Column=[cf1:name], Timestamp=[1541652952743], Vlaue=[Tom].
Get from table [t_test], Rowkey=[12345568], Column=[cf1:age], Timestamp=[1541652952834], Vlaue=[30].
Get from table [t_test], Rowkey=[12345568], Column=[cf1:name], Timestamp=[1541652952807], Vlaue=[Jone].
=== delete record ====
Delete from table [t_test], Rowkey=[12345568].
=== scan record by giving range ====
Get from table [t_test], Rowkey=[12345567], Column=[cf1:age], Timestamp=[1541652952779], Vlaue=[25].
Get from table [t_test], Rowkey=[12345567], Column=[cf1:name], Timestamp=[1541652952743], Vlaue=[Tom].
=== delete batch records ====
Delete from table [t_test], Rowkey=[12345566].
Delete from table [t_test], Rowkey=[12345569].
=== scan table ====
Get from table [t_test], Rowkey=[12345567], Column=[cf1:age], Timestamp=[1541652952779], Vlaue=[25].
Get from table [t_test], Rowkey=[12345567], Column=[cf1:name], Timestamp=[1541652952743], Vlaue=[Tom].
=== delete table ====
The table [t_test] is deleted.

 

源碼下載:

hbase-util.zip

 

========================================================

More reading,and english is important.

I'm Hongten

 

大哥哥大姐姐,覺得有用打賞點哦!你的支持是我最大的動力。謝謝。
Hongten博客排名在100名以內。粉絲過千。
Hongten出品,必是精品。

E | [email protected]  B | http://www.cnblogs.com/hongten

========================================================


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 有以下存儲過程: 有這個表: 調用存儲過程: 結果: ...
  • redis事務 1.redis事務介紹 redis的事務可以理解為一系列串列命令的集合。redis的事務和單條命令一樣,都是redis的最小執行單位,因此一個事務內的命令,要麼全部執行,要麼全部不執行。事務的概念對於熟悉資料庫的人們並不陌生,而redis作為一個資料庫系統,必然會對事務進行一定的支持 ...
  • 當需要從資料庫查詢的表有上萬條記錄的時候,一次性查詢所有結果會變得很慢,特別是隨著數據量的增加特別明顯,這時需要使用分頁查詢。對於資料庫分頁查詢,也有很多種方法和優化的點。下麵簡單說一下我知道的一些方法。 準備工作 為了對下麵列舉的一些優化進行測試,下麵針對已有的一張表進行說明。 表名:order_ ...
  • 一. DECODE方法 (Oracle公司獨家) decode(條件,值1,返回值1,值2,返回值2,...值n,返回值n,預設值) 二. CASE WHEN Case函數只返回第一個符合條件的值,剩下的Case部分將會被自動忽略 Case具有兩種格式,簡單Case函數的寫法相對比較簡潔,但是和Ca ...
  • 一. 監控概述 Tempdb庫空間使用的一大特點,是只有一部分對象,例如用戶創建的臨時表、table變數等,可以用sys.allocation_units和sys.partitions這樣的管理視圖來管理,許多內部對象和版本存儲在這些管理視圖中沒有體現,所以sp_spaceused的結果和真實的使用 ...
  • [20181108]12c sqlplus rowfetch參數4.txt--//12cR2 可以改變預設rowfetch參數.11g之前預設是1.通過一些測試說明問題.--//前幾天做的測試有點亂,鏈接http://blog.itpub.net/267265/viewspace-2219004/. ...
  • Redis的哨兵機制中,如果是多哨兵模式,哨兵節點之間也是可以相互感知的,各種搜索之後出來的是千篇一律的一個基礎配置文件,在配置當前哨兵節點的配置文件中,並沒有配置其他哨兵節點的任何信息。如下是一個哨兵節點的配置信息,可以看到,哨兵與哨兵之間沒有任何配置,死活想不明白,哨兵之間是如何自動識別的。 參 ...
  • MapReduce執行流程及單詞統計WordCount示例 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...