消息中間件--ActiveMQ&JMS消息服務

来源:https://www.cnblogs.com/soul-wonder/archive/2018/04/22/8910220.html
-Advertisement-
Play Games

### 消息中間件 ### **消息中間件** 1. 消息中間件的概述 2. 消息中間件的應用場景(查看大綱文檔,瞭解消息隊列的應用場景) * 非同步處理 * 應用解耦 * 流量削峰 * 消息通信 ### JMS消息服務 ### **JMS的概述** 1. JMS消息服務的概述 2. JMS消息模型 ...


### 消息中間件 ###

----------

**消息中間件**

1. 消息中間件的概述 2. 消息中間件的應用場景   * 非同步處理   * 應用解耦   * 流量削峰   * 消息通信   ----------

### JMS消息服務 ###

----------

**JMS的概述**

1. JMS消息服務的概述 2. JMS消息模型   * P2P模式   * Pub/Sub模式   3. 消息消費的方式   * 同步的方式---手動   * 非同步的方式---listener監聽   4. JMS編程模型 ----------

### 消息中間件:ActiveMQ ###

----------

**ActiveMQ的下載與安裝**

1. ActiveMQ的下載與安裝   * 下載ActiveMQ的壓縮文件,解壓apache-activemq-5.14.5-bin.zip文件   * 雙擊運行:activemq.bat文件,啟動服務   2. 測試ActiveMQ是否安裝成功   * 打開瀏覽器,輸入:http://localhost:8161   3. 點擊Manage ActiveMQ broker連接,可以查看ActiveMQ中已經發佈的消息等   * 用戶名密碼都是:admin ----------

**ActiveMQ的消息隊列方式入門**(P2P模式)

1. 在父工程的pom.xml文件中引入ActiveMQ和Spring整合JMS的坐標依賴
<!-- activemq start -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.2.0</version>
</dependency>
<!-- activemq end -->
<!-- spring 與 mq整合 start -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>3.7</version>
</dependency>
<!-- spring 與 mq整合 end -->
  2. ActiveMQ的向消息隊列中發送消息的入門程式(沒有使用Spring整合JMS的方式)
@Test
public void sendQueueMessage() throws JMSException {
// 1 創建連接工廠
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
 
// 2 使用工廠,創建連接
Connection connection = factory.createConnection();
 
// 3 啟動連接
connection.start();
 
// 4 使用連接,創建會話,true表示開始事務,代碼執行後需要提供事務
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
 
// 5 創建隊列隊形(myQueue--隊列的名字)/topic-----------session創建
Queue queue = session.createQueue("myQueue");
// 6 創建生產者-----------session創建
MessageProducer producer = session.createProducer(queue);
// 7 創建消息----文本消息-------session創建
TextMessage message = session.createTextMessage();
message.setText("helloworld!!!");
 
// 8 發送消息
producer.send(message);
 
// 9 提交事務
session.commit();
session.close();
connection.close();
}
3. ActiveMQ從消息隊列中獲取消息
@Test
public void receiverQueueMessage() throws JMSException {
// 1 創建連接工廠
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
// 2 使用工廠,創建連接
Connection connection = factory.createConnection();
// 3 啟動連接
connection.start();
// 4 使用連接,創建會話,true表示開始事務,代碼執行後需要提供事務
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
// 5 創建隊列隊形(hello--隊列的名字)/topic-----------session創建
Queue queue = session.createQueue("myQueue");
// 6 創建消費者-----------session創建
MessageConsumer consumer = session.createConsumer(queue);
 
// 7 接收消息----text格式
TextMessage receive = (TextMessage) consumer.receive();
String text = receive.getText();
System.out.println("接收到的消息====" + text);
 
// 8 提交事務
session.commit();
session.close();
connection.close();
 
}
4. 使用監聽器的方式,從隊列中消費消息
/**
*非同步方式
Queue接受用Listener方式接受,多用
如果有多個監聽listener,則交替執行
* @throws Exception
*/
@Test
public void receiverQueueListener() throws Exception{
// 1 創建連接工廠
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
// 2 使用工廠,創建連接
Connection connection = factory.createConnection();
// 3 啟動連接
connection.start();
// 4 使用連接,創建會話,true表示開始事務,代碼執行後需要提供事務//死迴圈的不能用事物
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 5 創建隊列隊形(hello--隊列的名字)/topic-----------session創建
Queue queue = session.createQueue("myQueue");
// 6 創建消費者-----------session創建
MessageConsumer consumer = session.createConsumer(queue);
 
//7 // 給消費者添加監聽器
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message msg) {
TextMessage message = (TextMessage) msg;
try {
System.out.println("Listener1111111111接收到的消息是=="+message.getText());
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
 
while(true){}
// 使用監聽器的方式不能關閉,需要監聽器一直工作
// session.commit();
// session.close();
// connection.close();
}

 

**ActiveMQ的消息訂閱方式入門**(Pub/Sub模式

/**
* Topic發送
* @throws JMSException
*/
@Test
public void sendTopicMessage() throws JMSException {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
 
// 創建消息訂閱
Topic topic = session.createTopic("myTopic");
// 創建生產者
MessageProducer producer = session.createProducer(topic);
// 創建消息,一組可以存儲key value的消息
MapMessage message = session.createMapMessage();
message.setString("username", "cgx");
message.setString("password", "123456");
// 發送消息
producer.send(message);
// 提交事務
session.commit();
session.close();
connection.close();
}
/**
* Topic接受
*
* @throws JMSException
*/
@Test
public void testReceiverMessage() throws JMSException {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
 
// 創建消息訂閱
Topic topic = session.createTopic("myTopic");
// 創建消費者
MessageConsumer consumer = session.createConsumer(topic);
// 接收消息
MapMessage message = (MapMessage) consumer.receive();
System.out.println(message.getString("username"));
System.out.println(message.getString("password"));
 
session.commit();
session.close();
connection.close();
}
/**
* Topic接受Listener監聽方式
*
* @throws Exception
*/
@Test
public void receiverQueueListener() throws Exception {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 創建消息訂閱
Topic topic = session.createTopic("myTopic");
// 創建消費者
MessageConsumer consumer = session.createConsumer(topic);
 
// 給消費者添加監聽器consumer添加監聽
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message msg) {
MapMessage message = (MapMessage) msg;
try {
System.out.println(message.getString("username"));
System.out.println(message.getString("password"));
} catch (JMSException e) {
e.printStackTrace();
}
}
});
 
while (true) {
 
}
 
}

 

### Spring整合ActiveMQ ###★★★★★

----------   **Spring整合ActiveMQ**★★★★★   1. 創建applicationContext-mq.xml的配置文件,導入約束★★★★★
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd">
 
</beans>

 

2. 具體的配置如下★★★★★ applicationContext-mq.xml===================mq的消息發送(消息生產者)
<!-- 配置連接工廠 -->
<!-- ActiveMQ 連接工廠 -->
<!-- 真正可以產生Connection的ConnectionFactory,由對應的 JMS服務廠商提供-->
<!-- 如果連接網路:tcp://ip:61616;未連接網路:tcp://localhost:61616 以及用戶名,密碼-->
<amq:connectionFactory id="amqConnectionFactory"
brokerURL="tcp://localhost:61616" userName="admin" password="admin" />
 
<!-- Spring Caching連接工廠 -->
<!-- Spring用於管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<!-- 目標ConnectionFactory對應真實的可以產生JMS Connection的ConnectionFactory -->
<property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
<!-- Session緩存數量和鏈接數有關 -->
<property name="sessionCacheSize" value="100" />
</bean>
 
<!-- 定義JmsTemplate的Queue類型★★★★★ -->
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->
<constructor-arg ref="connectionFactory" />
<!-- 非pub/sub模型(發佈/訂閱),即隊列模式 -->
<property name="pubSubDomain" value="false" />
</bean>
 
<!-- 定義JmsTemplate的Topic類型★★★★★ -->
<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate" >
<!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->
<constructor-arg ref="connectionFactory" />
<!-- pub/sub模型(發佈/訂閱) -->
<property name="pubSubDomain" value="true" />
</bean>

 

  3. 發送消息的代碼如下★★★★★   3.1.Queue方式:★★★★★
@Autowired
@Qualifier(value="jmsQueueTemplate")
private JmsTemplate queueTemplate;//Queue
 
 
/**
* Queue發送消息---spring框架
*/
@Test
public void sendQueueMessage() {
// 發送消息 構造參數指定目標,因為配置文件中的隊列和訂閱模式是通過id與false和true進行區分
queueTemplate.send("myQueue", new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
// 使用session創建消息,發送
TextMessage textMessage = session.createTextMessage("測試結合spring框架發送queue消息");
return textMessage;
}
});
}
  3.2.Topic方式:★★★★★
@Autowired
@Qualifier(value = "jmsTopicTemplate")
private JmsTemplate topicTemplate;//Topic
 
/**
* Topic發送消息---spring框架
*/
@Test
public void sendTopicMessage() {
topicTemplate.send("spring_topic", new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
MapMessage mapMessage = session.createMapMessage();
mapMessage.setString("username", "mdzz");
return mapMessage;
}
});
}

 

4. 接收消息的代碼如下==========不提倡手動,要用監聽器非同步獲取
/**
* Queue接收消息---spring框架
* 同步手動:不提倡
* receive("myQueue")要寫目標,不寫目標的話會報找不到目標的錯誤NO defaultDestination
*/
@Test
public void receiverMessage() {
//接收消息textMessage類型
TextMessage textMessage = (TextMessage) queueTemplate.receive("myQueue");
 
try {
System.out.println(textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
  **Spring配置監聽器**★★★★★★★★★★★★★★★   1. 自定義監聽器代碼的編寫----接收消息---spring框架---實現MessageListener介面★★★★★   1.1.Queue:★★★★★
@Component(value="queueConsumer1")
public class QueueListener implements MessageListener {
 
@Override
public void onMessage(Message arg0) {
// 把arg0強轉
TextMessage textMessage = (TextMessage) arg0;
try {
// 輸出消息
System.out.println(textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
 
}
    1.2.Topic:發送一個,兩個都會接受★★★★★topic特點:有幾個監聽幾個都會同時收到
@Component
public class TopicConsumer1 implements MessageListener {
 
@Override
public void onMessage(Message arg0) {
MapMessage mapMessage = (MapMessage) arg0;
try {
System.out.println("TopicConsumer1===="+mapMessage.getString("username"));
} catch (JMSException e) {
e.printStackTrace();
}
}
 
}
 
@Component
public class TopicConsumer2 implements MessageListener {
    //...
}
  2. 編寫配置文件 applicationContext-mq-consumer.xml=============mq的消息接受(負責監聽接受消息)
<!-- 掃描包 -->
<context:component-scan base-package="com.my.jms.consumer" />
 
<!-- ActiveMQ 連接工廠 -->
<amq:connectionFactory id="amqConnectionFactory"
brokerURL="tcp://localhost:61616" userName="admin" password="admin" />
 
<!-- Spring Caching連接工廠 -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
<property name="sessionCacheSize" value="100" />
</bean>
 
<!-- Spring JmsTemplate 的消息生產者 start-->
<jms:listener-container destination-type="queue" container-type="default" connection-factory="connectionFactory">
<jms:listener destination="myQueue" ref="queueConsumer1"/>
</jms:listener-container>
 
<jms:listener-container destination-type="topic" container-type="default" connection-factory="connectionFactory">
<jms:listener destination="spring_topic" ref="topicConsumer1"/>
<jms:listener destination="spring_topic" ref="topicConsumer2" />
</jms:listener-container>
  3.不用啟動項目,把spring配置文件applicationContext-mq-consumer.xml啟動起來,可以用採用下麵方法 新建一個test類,讓他一直啟動著,這樣就一直載入spring的配置文件
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-mq-consumer.xml")
public class SpringQueueListenerTest {
 
@Test
public void test(){
while(true);
}
}

 

4.只要發送端(發送消息---spring框架)一啟動,監聽器就會監聽到,就會輸出:測試結合spring框架發送queue消息★★★★★

spring整合總結:

消息發送
  1. 創建spring容器
  2. 從容器中獲取JMSTemplate對象,發送消息
  3. 定義Destination
  4. 使用JMSTemplate對象發送消息
消息接受
  1. 創建一個類實現MessageListener 介面。業務處理在此類中實現。
  2.在spring容器中配置DefaultMessageListenerContainer對象,引用MessageListener 實現類對象接收消息。

項目整合ActiveMQ:

1. 消息生產者整合ActiveMQ
  消息生產者只需要發送消息
  需要把JMSTemplate和Destination交給spring進行管理

 部分代碼:
/**===========================activeMQ消息發送========================================*/
// 發送消息!!!
this.send("save", item.getId());
}

@Autowired
private JmsTemplate jmsTemplate;

@Autowired
private Destination destination;

/**
* 此方法就是用來發送消息的
* 考慮:1、發送什麼數據?2、我需要什麼數據?
* 在消息中需要:1、消息的標識:save,delete,update;2、商品的ID
*/
private void send(final String type, final Long itemId) {
// TODO Auto-generated method stub
jmsTemplate.send(destination, new MessageCreator() {

@Override
public Message createMessage(Session session) throws JMSException {
//創建消息體
TextMessage textMessage = new ActiveMQTextMessage();
//設置消息內容
Map<String, Object> map = new HashMap<>();
map.put("type", type);
map.put("itemId", itemId);
try {
ObjectMapper mapper = new ObjectMapper();
textMessage.setText(mapper.writeValueAsString(map));
} catch (Exception e) {
e.printStackTrace();
}
return textMessage;
}
});
}

 


2. 消息消費改造
  在search-service添加
  ItemMessageListener:

/**===========================activeMQ消息發送========================================*/
@Autowired
private SearchService searchService;

@Override
public void onMessage(Message message) {
//先判斷此消息類型是否是TextMessage
if(message instanceof TextMessage){
//如果是,強轉
TextMessage textMessage = (TextMessage)message;
try {
//獲取消息:json
String json = textMessage.getText();
//傑克遜第三作用:直接解析json數據
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(json);
String type = jsonNode.get("type").asText();
Long itemId = jsonNode.get("itemId").asLong();
//根據解析出來的type,判斷此type=save的時候我應該調用indexSearch方法
if("save".equals(type)){
searchService.indexItem(itemId);
}

} catch (Exception e) {
e.printStackTrace();
}
}

}

索引庫增加商品會觸發mq:

SearchServiceImpl:

@Override
public void indexItem(Long itemId) throws Exception {
Item item = this.itemMapper.selectByPrimaryKey(itemId);

SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", item.getId());
doc.addField("item_title", item.getTitle());
doc.addField("item_image", item.getImage());
doc.addField("item_cid", item.getCid());
doc.addField("item_price", item.getPrice());
doc.addField("item_status", item.getStatus());

this.cloudSolrServer.add(doc);

this.cloudSolrServer.commit();

}

 

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

-Advertisement-
Play Games
更多相關文章
  • Lesson Eight 2018-04-23 02:07:01 封裝與隱藏:問題:當創建了類的對像以後,如果直接通過“對象.屬性”的方式對相應的對像屬性賦值的話,可能會出來不滿足實際情況的意外。 引出:通過“對像 .方法”的形式,來控制對像對屬性的訪問。對屬性的要求術可以通過方法來體現。 解決:1 ...
  • 集合的操作 集合是一個無序的,不重覆的數據組合,它的主要作用如下: 去重,把一個列表變成集合,就自動去重了 關係測試,測試兩組數據之間的交集,差集,並集等關係 集合的寫法 list_1 = set([1, 3, 4, 6, 7, 12, 5]) 集合的關係 list_1 = set([1, 3, 5 ...
  • 問題:在使用連接池和線程綁定之後需要關閉其他的參數麽(stat? con?...) ...
  • 多線程併發與線程安全相關知識整理如下: 一、線程怎麼保證安全性。 什麼是線程安全性 當多個線程訪問某個類時,不管運行時環境採用何種調度方式或者這些進程將如何交替執行,並且在主調代碼中不需要任何額外的同步或協同,這個類都能表現出正確的行為,那麼就稱這個類是線程安全的。 線程安全性的三大特征 原子性、有 ...
  • 1. 併發編程的3個概念 併發編程時,要想併發程式正確地執行,必須要保證原子性、可見性和有序性。只要有一個沒有被保證,就有可能會導致程式運行不正確。 1.1. 原子性 原子性:即一個或多個操作要麼全部執行並且執行過程中不會被打斷,要麼都不執行。 一個經典的例子就是銀行轉賬:從賬戶A向賬戶B轉賬100 ...
  • 再次整理了一下這個日誌收集系統的框,如下圖 這次要實現的代碼的整體邏輯為: 完整代碼地址為: https://github.com/pythonsite/logagent etcd介紹 高可用的分散式key-value存儲,可以用於配置共用和服務發現 類似的項目:zookeeper和consul 開 ...
  • Java中的IO流 分類 根據流的方向:輸入流和輸出流 根據讀取文字的大小:位元組流和字元流(位元組按照位元組讀取,讀取中文容易亂碼,字元流按照字元讀取,通常用於讀取中文) 根據讀取的方式:節點流和緩存流 分類 根據流的方向:輸入流和輸出流 根據讀取文字的大小:位元組流和字元流(位元組按照位元組讀取,讀取中文容 ...
  • 一、基礎概念 抽象事物,是若沒有具體的信息可以描述這個事物,這個事物可以稱為抽象事物。 抽象類,是不斷的向上抽取而來。抽取方法聲明而不確定具體的方法內容。由不同的子類來完成具體的方法內容。 (一)抽象類的特點: 1、抽象方法沒有方法體,必須由抽象關鍵字abstract來修飾。 1、抽象方法一定是存在 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...