用Spring JMS使非同步訊息變得簡單
非同步處理通訊是面向服務架構(SOA)的重要部分,因為企業中的許多系統通訊,尤其是跟外部系統通訊本來就是非同步的。Java訊息服務(JMS)就是用來編寫非同步訊息J2EE應用的API。使用JMS API的傳統訊息實現涉及到象這樣的一些步驟:查詢對列連線工廠、佇列資源以及在實際傳送和接受訊息前,建立JMS會話(JMS session)。
Spring framework簡化了用JEE元件(包括JMS)開發JMS應用的工作。它提供了一個模板機制來隱藏典型的JMS實現細節,所以開發者可以專注於訊息處理任務而不用擔心怎樣建立、訪問和釋放JMS資源。
本文用一個執行在JBoss MQ server上的簡單Web應用概述了Spring JMS API和怎樣使用它非同步處理(傳送和接受)訊息。我將對比JMS實現的傳統方法和Spring JMS實現方法,以顯示使用Spring JMS來處理訊息是多麼的簡單和靈活。
非同步訊息和SOA
現實世界中,大多數Web請求是同步處理的。例如,當用戶登陸一個站點,他或她輸入使用者名稱和口令以及伺服器識別登陸憑證。如果身份驗證成功,程式讓使用者進入站點。這裡,登陸請求從客戶端被接受後,立即被處理。信用卡授權也是一個同步處理的例子;僅當伺服器核實了傳送進來的信用卡號是有效並且該客戶的帳號有足夠的信用額度後,才允許客戶繼續進行下一步動作。讓我們來考察一下訂單處理系統中的支付結算步驟。一旦系統核實了那個使用者的信用卡資訊是正確的,而且帳戶上有足夠的資金,那麼不需要等到支付細節和轉帳最終完成。支付結算用非同步方式處理,如此客戶便可以繼續進行結帳處理。
與典型的同步請求相比,非同步處理用於需要長時間來處理的請求。非同步處理的另外一個例子是住房貸款處理應用中,處理提交到AUS(Automated Underwriting System)的貸款請求。貸款人提交貸款申請後,抵押公司傳送請求到AUS取得信用歷史資訊。因為該請求要取得綜合詳細的信用報告如貸款人當前和過去的信用帳戶,最近的支付以及其它金融詳細資訊,所以從請求到獲得響應常常需要很長時間。對客戶端程式來說開一個到伺服器的連線並且長時間等待響應是沒有意義的。於是就有了非同步通訊;也就是,一旦請求被提交,它就被放入佇列裡面並且客戶斷開伺服器連線。然後,AUS服務從特定佇列摘取請求,處理它,把結果訊息放入另外一個訊息佇列。最後客戶程式從訊息佇列摘取響應結果繼續處理信用歷史結果資訊。
JMS
如果用過JMS的話,會發現它類似寫JDBC或JCA程式碼。它有建立或檢索JMS資源的樣板程式碼,每當你需要編寫一個新類來發送或接受訊息時,都得重複編寫那個樣本程式碼。下面列出了傳統JMS實現涉及的步驟:
1、建立JNDI初始上下文context;
2、從JNDI上下文獲得佇列連線工廠;
3、從佇列連線工廠取得佇列Queue;
4、建立一個Session物件;
5、建立一個傳送或接受物件;
6、利用第5部建立的傳送或接受物件傳送或接受訊息;
7、處理完訊息後,關閉所有JMS資源。
如你所見,只有第6步是處理訊息的步驟。其他步驟都只是管理JMS資源,與實際業務需求無關,但開發者不得不編寫和維護那些附加步驟程式碼。
Spring JMS
Spring框架提供一個模板機制來隱藏Java API細節。JEE開發者可用JDBCTemplate 和JNDITemplate類來分別訪問後端資料庫和JEE資源(資料來源,連線池)。JMS沒有異常。Spring提供了JMSTemplate類,所以開發者不必為JMS實現編寫樣本程式碼。當開發JMS應用時,Spring提供了一下一些優勢:
1、提供了一個JMS的抽象API,簡化了JMS的使用。如:訪問目的地(佇列或主體)和出版訊息到特定目的地。
2、JEE開發者不必關心JMS不同版本之間的差異(如JMS 1.0.2 同 JMS 1.1);
3、開發者不必特定地處理JMS異常,因為Spring為JMS程式碼丟擲的任何JMS異常提供了一個unchecked異常。
一旦你在JMS應用中開始使用Spring,你將會欣賞到非同步訊息處理的簡易性。Spring JMS框架提供了各種java類使JMS開發變得簡單。
表1,Spring JMS類
隨後的部分,我將詳細解釋表1中的類(如JmsTemplate, DestinationResolver,和 MessageConverter)。
JMSTemplate
JmsTemplate提供了幾個helper方法來執行基本操作。開始使用JmsTemplate前,有必要知道JMS提供者支援哪種JMS規範。JBoss AS 4.0.2 和 WebLogic 8.1伺服器支援JMS1.0.2規範。WebLogic 伺服器 9.0包含JMS1.1支援。JMS1.1統一了PTP和Pub/Sub程式設計介面。有了這個改變,開發者可以建立一個事務會話,然後在同一個JMS事務中,從Queue(PTP)接受訊息和傳送一個訊息到Topic(Pub/Sub)。JMS1.1向後相容JMS1.0,因此基於JMS1.0編寫的程式碼仍然能跟JMS1.1工作。
JmsTemplate提供各種方法來接收和傳送訊息。表2是方法列表。
表2。JMS模板方法
使用JNDI上下文儲存和檢索目的地。當配置Spring應用上下文時,我們用JndiObjectFactoryBean獲得JMS目的地引用。DestinationResolver用來解析目的地名稱到一個JMS目的地,當應用有許多目的地時,那是很有幫助的。DynamicDestinationResolver(預設DestinationResolver實現)用於解析動態目的地。
MessageConverter介面定義了java物件和JMS訊息之間轉換的契約。使用轉換器,應用程式碼可以專注於業務物件,不用操心它是如何代表JMS訊息的。SimpleMessageConverter(和SimpleMessageConverter102)是預設MessageConverter實現。它們用於將String、位元組陣列((byte[])、Map、Serializable物件分別轉換成JMS TextMessage、JMS BytesMessage,JMS MapMessage,JMS ObjectMessage。你可以編寫MessageConverter介面的定製實現並結合XML繫結框架如JAXB, Castor, Commons Digester, XMLBeans, 或 XStream來轉換XML文件到TextMessage。
樣本應用
我將用一個樣本貸款應用處理系統(叫LoanProc)來說明怎樣在JMS應用中使用Spring。作為貸款處理的一部分,LoanProc傳送貸款詳細資料(loan ID, borrower name, borrower's SSN, loan expiration date, and loan amount)從AUS系統請求信貸歷史。為讓例子簡單一點,我們將基於兩個引數:信用評分和貸款數量來獲得信貸歷史詳細資料。讓我們假定處理信用檢查請求的業務規則如下:
1、如果貸款數量等於或小於$500,000,那麼貸款人必須至少有一個“good”信用(例如,貸款人的信用評分在680到699之間);
2、如果貸款數量超過$500,000,那麼貸款人必須至少要有一個“very good”信用,這意味他/她的信用評分超過700。
貸款應用Use Case
貸款請求處理Use Case由下列步驟組成:
1、使用者在貸款申請web頁面輸入貸款詳細資料並提交貸款申請;
2、然後程式傳送貸款詳細資料到AUS系統取得信用歷史詳細資料。用傳送請求到名叫CreditRequestSendQueue的訊息佇列來完成。
3、AUS系統從佇列摘取貸款詳細資料並用貸款引數來從資料庫檢索信用歷史資訊;
4、然後AUS系統用找到的貸款人信用歷史資訊建立一個新的訊息併發送到名叫CreditRequestReceiveQueue的訊息佇列;
5、最後LoanProc從接收訊息佇列摘取響應訊息並處理貸款申請,決定申請是被核准還是拒絕。
應用中,在同樣的JBoss MQ server中配置了兩個訊息佇列。Use Case用序列圖1表示如下:
圖1:貸款處理應用的序列圖
技術
表3列出了例子應用中用到的一些技術和開源框架
表3,JMS應用中用到的框架
使用Hermes 的JMS資源設定
為非同步處理訊息,首先,我們需要訊息佇列來發送和接收訊息。我們在JBoss中使用xml配置檔案建立訊息佇列並且用JMS控制檯來瀏覽佇列詳細資料。清單1顯示了XML配置檔案JMS配置片斷。(這個片斷可以被新增到%JBOSS_HOME%/server/all/deploy-hasingleton/jms目錄下的jbossmq-destinations-service.xml檔案中。)
清單1,JBoss MQ伺服器中JMS佇列配置
<!-- Credit Request Send Queue -->
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=CreditRequestSendQueue">
<depends optional-attribute-name="DestinationManager">
jboss.mq:service=DestinationManager
</depends>
</mbean>
<!-- Credit Request Receive Queue -->
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=CreditRequestReceiveQueue">
<depends optional-attribute-name="DestinationManager">
jboss.mq:service=DestinationManager
</depends>
</mbean>
現在,讓我們看看怎麼使用一個叫做Hermes的JMS工具瀏覽訊息佇列。Hermes是一個Java Swing應用,它能建立、管理和監控JMS提供者中的JMS destination。這樣的JMS提供者有JBossMQ, WebSphereMQ, ActiveMQ 和 Arjuna。從website下載Hermes並解壓zip檔案到一個本地目錄(如c:/dev/tools/hermes)。一旦安裝,雙擊hermes.bat (在bin目錄)啟動程式。
為在Hermes中配置JBossMQ伺服器,參考Hermes站點上的demo。它一步一步形象說明了JBoss MQ的配置。當配置一個新的JNDI初始上下文時,輸入下面的配置資訊。
•providerURL = jnp://localhost:1099
•initialContextFactory = org.jnp.interfaces.NamingContextFactory
•urlPkgPrefixes = org.jnp.interfaces:org.jboss.naming
•securityCredentials = admin
•securityPrincipal = admin
當建立一個新destinations時,輸入queue/CreditRequestSendQueue 和 queue/CreditRequestReceiveQueue。圖2顯示了JMS控制檯主螢幕,它顯示了為樣本JMS應用建立的新訊息。
圖2.Hermes中所有destinations的截圖
圖3是訊息傳送者傳送一些訊息到CreditRequestSendQueue後,Hermes JMS控制檯顯示的訊息佇列詳細資料。你能看到這裡佇列中有5個訊息並且控制檯顯示了訊息的詳細資訊如message ID、message destination、time stamp、和實際的訊息。
圖3.Hermes中佇列詳細資料截圖
使用Spring JMS,非同步訊息變得簡單
用在樣本應用中的這些訊息佇列名和其它JMS以及JNDI引數如下表4所示。
表4,Spring JMS配置引數
Spring配置
已經有了執行樣本應用所需的JMS destinations,現在該是進入用XML Spring配置檔案(叫做spring-jms.xml)裝配JMS元件的細節的時候了。用IOC設計模式中的setter依賴注入原理裝入這些元件。讓我們仔細看看元件,為每一個JMS元件顯示了一個XML配置片斷。
JNDI上下文是獲取JMS資源的入口,所以我們首先配置一個JNDI模板。清單2顯示了一名為jndiTemplate的Spring bean,它具有取得JNDI初始上下文必須的常用引數。
清單2,JNDI上下文模板
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">
org.jnp.interfaces.NamingContextFactory
</prop>
<prop key="java.naming.provider.url">
localhost
</prop>
<prop key="java.naming.factory.url.pkgs">
org.jnp.interfaces:org.jboss.naming
</prop>
</props>
</property>
</bean>
下一步,我們配置佇列連線工廠。清單3顯示了佇列連線工廠。
清單3,JMS對了連線工廠配置
<bean id="jmsQueueConnectionFactory"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>UIL2ConnectionFactory</value>
</property>
</bean>
我們定義了兩個JMS destinations來發送和接收訊息。清單4和清單5顯示了這些細節。
清單4,傳送佇列配置
<bean id="sendDestination"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>queue/CreditRequestSendQueue</value>
</property>
</bean>
清單5,接收佇列配置
<bean id="receiveDestination"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>queue/CreditReqeustReceiveQueue</value>
</property>
</bean>
然後,我們配置JmsTemplate元件。我們在樣本應用中使用JmsTemplate102。使用defaultDestination屬性來指定JMS destination。
清單6,JMS template配置
<bean id="jmsTemplate"
class="org.springframework.jms.core.JmsTemplate102">
<property name="connectionFactory">
<ref bean="jmsQueueConnectionFactory"/>
</property>
<property name="defaultDestination">
<ref bean="destination"/>
</property>
<property name="receiveTimeout">
<value>30000</value>
</property>
</bean>
最後,我們配置傳送和接收者元件。清單7和清單8顯示了Sender 和Receiver 物件配置。
清單7,JMS Sender配置
Listing 7. JMS Sender configuration
<bean id="jmsSender" class="springexample.client.JMSSender">
<property name="jmsTemplate">
<ref bean="jmsTemplate"/>
</property>
</bean>
清單8,JMS Receiver配置
<bean id="jmsReceiver" class="springexample.client.JMSReceiver">
<property name="jmsTemplate">
<ref bean="jmsTemplate"/>
</property>
</bean>
測試和監控
我些了一個叫做LoanApplicationControllerTest的測試類來測試LoanProc應用。我們使用這個類來設定貸款引數和呼叫那個信用請求服務類。
讓我們看看使用傳統JMS而不用Spring JMS API的訊息傳送者實現。清單9顯示了MessageSenderJMS這個類的sendMessage方法,這個類具備使用JMS API處理訊息的所有必須步驟。
清單9,傳統JMS實現
public void sendMessage() {
queueName = "queue/CreditRequestSendQueue";
System.out.println("Queue name is " + queueName);
/*
* Create JNDI Initial Context
*/
try {
Hashtable env = new Hashtable();
env.put("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
env.put("java.naming.provider.url","localhost");
env.put("java.naming.factory.url.pkgs",
"org.jnp.interfaces:org.jboss.naming");
jndiContext = new InitialContext(env);
} catch (NamingException e) {
System.out.println("Could not create JNDI API " +
"context: " + e.toString());
}
/*
* Get queue connection factory and queue objects from JNDI context.
*/
try {
queueConnectionFactory = (QueueConnectionFactory)
jndiContext.lookup("UIL2ConnectionFactory");
queue = (Queue) jndiContext.lookup(queueName);
} catch (NamingException e) {
System.out.println("JNDI API lookup failed: " +
e.toString());
}
/*
* Create connection, session, sender objects.
* Send the message.
* Cleanup JMS connection.
*/
try {
queueConnection =
queueConnectionFactory.createQueueConnection();
queueSession = queueConnection.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
queueSender = queueSession.createSender(queue);
message = queueSession.createTextMessage();
message.setText("This is a sample JMS message.");
System.out.println("Sending message: " + message.getText());
queueSender.send(message);
} catch (JMSException e) {
System.out.println("Exception occurred: " + e.toString());
} finally {
if (queueConnection != null) {
try {
queueConnection.close();
} catch (JMSException e) {}
}
}
}
現在,讓我們看看用Spring實現的訊息傳送者。清單10顯示了MessageSenderSpringJMS類中send方法程式碼。
清單10,用Spring API 的JMS實現
public void send() {
try {
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] {
"spring-jms.xml"});
System.out.println("Classpath loaded");
JMSSender jmsSender = (JMSSender)appContext.getBean("jmsSender");
jmsSender.sendMesage();
System.out.println("Message sent using Spring JMS.");
} catch(Exception e) {
e.printStackTrace();
}
}
如你所見,所有與管理JMS資源相關的資源步驟都由Spring容器用配置檔案處理。我們僅需要獲取JMSSender引用並且呼叫它上面的sendMessage即可。
結論
本文中,我們看到Spring框架如何簡化了使用JMS API的非同步訊息應用開發的工作。Spring移走了所有JMS訊息處理必須的樣板程式碼,如獲取連線工廠,從Java程式碼建立佇列和會話物件並在執行時用配置檔案裝配它們。由於這個強大的IOC原理,我們可以不必修改Java程式碼便可動態交換JMS資源物件。
因為非同步訊息是構成SOA框架整體所需的一部分,Spring非常適合放入SOA工具集。同樣,JMS管理工具如Hermes使得建立,管理和控制JMS資源變得簡單,尤其對系統管理員。
資源
本文樣本程式碼
Matrix:http://www.matrix.org.cn/
Spring JMS documentation
"1-2-3 Messaging with Spring JMS"
JBoss MQ wiki
Srini Penchikala是Flagstar Bank資訊系統領域問題專家。
相關推薦
用Spring JMS使非同步訊息變得簡單
非同步處理通訊是面向服務架構(SOA)的重要部分,因為企業中的許多系統通訊,尤其是跟外部系統通訊本來就是非同步的。Java訊息服務(JMS)就是用來編寫非同步訊息J2EE應用的API。使用JMS API的傳統訊息實現涉及到象這樣的一些步驟:查詢對列連線工廠、佇列資源以及在實
InfluxData的Chronograf中的預定義儀表板如何使度量標準變得簡單
問題 視覺化資料是一個特別難的問題,但我們不希望在使用視覺化工具時考慮這一點。我們希望儘可能快速,輕鬆地獲取資料。考慮到這一點,我特別興奮地看到最新版本的Chronograf(1.7.3),其中包括改進的入門,這給了我正在尋找的東西。 經驗 我正在使用MySQL作為我的一些Rails應用程式的資
如何使電商APP制作變得簡單易懂,容易上手?
如何使電商APP制作變得簡單易懂,容易上手? 乘著互聯網+的東風,大眾創業、萬眾創新正在蓬勃興起。但是,無論淘寶還是微商,都存在同質化嚴重的問題,想引人註目、脫穎而出困難重重。在人人手機不離手的移動互聯網時代,擁有一款量身定做的APP,一定會讓您的努力事半功倍。APIClo
刪除一個數的K位使原數變得最小
應用 true ++ font 首開 範圍 color 選擇 pre 原創 給定一個n位正整數a, 去掉其中k個數字後按原左右次序將組成一個新的正整數。對給定的a, k尋找一種方案,使得剩下的數字組成的新數最小。 提示:應用貪心算法設計求解 操作對象為n位正整數,有可能超
使Mybatis開發變得更加輕鬆的增強工具 — Ourbatis
一、Mybatis的不足之處 Mybatis是一款優秀的及其靈活的持久層框架,通過XML配置並對映到Mapper介面為Service層提供基礎資料操作入口。 這麼優秀的框架竟然還有不足之處? 俗話說人無完人,因為Mybatis實在是太靈活了,靈活到每個Mappe
RabbitMQ學習(十一)之spring整合傳送非同步訊息
實現使用Exchange型別為DirectExchange. routingkey的名稱預設為Queue的名稱。非同步傳送訊息。 1.配置檔案 [plain] view plain copy print? #============== rabbitmq co
Spring JMS---三種訊息監聽器
訊息監聽器MessageListener 在spring整合JMS的應用中我們在定義訊息監聽器的時候一共可以定義三種類型的訊息監聽器,分別是MessageListener、SessionAwareMessageListener和MessageListenerA
怎麽樣把網站建設變得簡單
jpg isp 的人 .com 好的 創業公司 聯網 想法 美好 每個互聯網創業的人,心中都有一個憧憬!一個夢想!一個念頭!那就是在互聯網這個大板塊上闖出一片天。好了,好了。言歸正傳,不論你懷著什麽樣的目的、什麽樣想法,想要在互聯網這殘酷的舞臺上弄出點東西來,你少不了一樣東
EchoSite---讓內網穿透變得簡單
來到EchoSite官網註冊的都可以獲得三個月免費的域名,續費也就五塊一個月。 下面介紹下方法 (1)、首先你需要拿到你自己的域名,在我的域名裡就能看到了: (2)、下載客戶端和配置檔案。 (3)、把客戶端執行檔案和配置檔案放到同一個目錄下,然後編輯你的配置檔案(e
完美韻腳----讓押韻變得簡單
把押韻的活全部承攬 降低詩詞的創作門檻 本文導言: 用Python+Django+Apache在工作之餘做了一個押韻搜尋的網站:完美韻腳(wanmeiyunjiao.com);這裡借自己的部落格做下推廣,不做技術分享。 完美韻腳用來幫助詞作人、詩人、Rapper歌手和
創新讓IT變得簡單
“我們之所以叫雲庫新技術,是因為這個名字傳遞了我們關注新技術的信念。公司的英文名字是InnoMITS,它是Innovation Makes IT Simple的縮寫,即‘創新讓IT變得更簡單’。我們希望簡化複雜的IT工作,以輕量化的IT運維為客戶提供支援,完成之前IT難以解決的任務,包括人工智慧
Linux下Shell指令碼實現批量重新命名資料夾,批量重新命名檔案(讓原本繁重的工作變得簡單)
最近接了個專案,具體做什麼都不說了,其中有個工作就是批量更改資料夾,然後批量更改資料夾下的檔名字,一會兒先貼程式碼,再詳細解釋步驟。 下面是我的簡化版的目錄結構,實際上有上百個。 project dir1 dir1.py dir2
TestFlight.top 讓 TestFlight 變得簡單
TestFlight.Top 是一款針對於TestFlight的服務,開發者可以在**60秒**內製作一個方便分享的、**可直接下載TestFlight App** 的應用介紹頁。 為什麼要做TestFlight.top因為TestFlight不夠好用,TestFlight
一款能讓Vive開發變得簡單的外掛——Vive Input Utility使用指南
相信各位小夥伴們在使用SteamVR Unity Plugin的過程中應該都遇到過這樣的問題:獲取裝置很麻煩,裝置在重啟後indexID會改變從而導致設定好的左右手裝置出現交錯;無法與UGUI的事件系統連線導致無法使用UGUI等等很多問題。(見圖1) 官
使用C++11讓多執行緒開發變得簡單
#include <iostream> #include <functional> #include <map> #include <vector> #include <algorithm> #incl
自動生成匯出前端頁面的快速開發工具,讓程式碼開發變得簡單
微信小程式自動切片生成佈局軟體是一款根據效果影象畫畫一樣來設計微信小程式,自動生成匯出前端頁面的快速開發工具。可以很方便、快速地生成小程式的wxml,wcss,js檔案。可以大大提高您的工作效率,減少前端佈局的編寫工作。功能如下:1.切片功能:原來手工寫的這部分工作,可以用切
spring的jms:用spring的JmsTemplate傳送和接收訊息
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "http://www.springframework.org/dtd/spring-beans.dtd"><
Spring + JMS + ActiveMQ實現簡單的訊息佇列(監聽器非同步實現)
首先宣告:以下內容均是在網上找別人的部落格綜合學習而成的,可能會發現某些程式碼與其他博主的相同,由於參考的文章比較多,這裡對你們表示感謝,就不一一列舉,如果有侵權的地方,請通知我,我可以把該文章刪除。 1、jms-xml Spring配置檔案 <?xml versi
Django運維後臺的搭建之四:用bootstrap模板讓運維前臺變得更漂亮
html django bootstrap 靜態資源 我對於PHP和ajax是屬於二把刀的水平,所以做網頁前端肯定是比上天還難,但是我又想把網頁做的漂亮可愛,怎麽辦呢?我就只好去download別人的模板,在這裏我使用了bootstrap框架做的模板。各位可以去https://wrapboot
用AOP來讓你的JS程式碼變得更有可維護性吧
此文已由作者吳佳祥授權網易雲社群釋出。 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。 好吧我承認這是篇任務。 最近看到個訊息,ES2017已經定稿了,心想,我去,還完全沒了解ES2016呢,ES8就定稿了,out了,這可咋辦,趕緊Google(Baidu)去! 不過從ES6(2015)之後,tc39的