企業級Java開發,從這裡總覽開啟

牛旦教育it課堂 發佈 2020-04-14T11:56:53+00:00

清單1-3:JSF後端Bean@Namedpublicclass BookController {@Injectprivate BookEJB bookEJB;private Book book = new Book;public String doCreateBook;book

企業如今生活在一個全球化競爭的世界,他們需要應用系統來滿足他們的業務需求,這些需求越來越複雜。 在這個全球化時代,公司分布不同區域,他們通過網際網路實現24*7的全天候模式下跟不同國家進行業務往來。基於多個數據中心以及必須處理不同貨幣和時區的國際化系統,這樣以便降低成本和降低服務的響應時間,並將業務數據存儲在可靠和安全的存儲上,同時為其客戶、員工和供應商提供移動和Web方式的多種交互形式。

大多數公司必須將這些複雜的挑戰與其現有的企業信息系統(EIS)相結合,同時開發企業對企業(Business to Business)應用程式,以便基於移動和地理定位模式的應用程式與合作夥伴或企業對客戶系統進行通信溝通。 這樣,公司不得不協調存儲在不同位置的內部數據,由多種程式語言處理,並通過不同的協議進行路由。 當然,在無損失的情況下,企業必須這樣做,這意味著分布系統具有防止系統崩潰、高可用性、可擴展性和安全性等特性,同時,企業應用必須面對變化和複雜性,並且應該系統必須是健壯的。 這正是Java企業版(Java EE)創建的原因所在。

於1999年發布的Java EE的第一個版本(最初稱為J2EE)側重於企業面臨的問題:分布式組件。 從那時起,軟體應用程式不得不適應新的技術解決方案,如SOAP或RESTful Web服務。Java EE平台已經發展到通過提供各種標準規範的方法來滿足這些技術需求。 多年來,Java EE已經發生變化,變得更加豐富、更簡單、更易於使用、更便攜和更加集成化。

那麼,在本學習教程中,我將給出一個Java EE的總體概述,介紹其內部架構,組件和服務後等,並介紹Java EE 7中的新功能特性。

1Java EE 簡史

圖1-0總結了14年的Java EE演進。 Java EE以前稱為J2EE。 J2EE 1.2是由Sun開發的,並於1999年發布,包含10個JSR的總括規範。 當時人們總在在談論CORBA,所以J2EE 1.2是在分布式系統的基礎上創建的。引入了企業Java Bean(EJB),支持遠程狀態和無狀態服務對象,並支持持久對象(實體bean)。 它們基於使用RMI-IIOP(遠程方法調用 - Internet Inter-ORB協議)作為底層協議的事務和分布式組件模型構建。Web層有servlet和JavaServer Pages(JSP)技術,JMS用於發送消息之用。

圖1-0 Java EE簡史

由J2EE 1.3開始,該規範是由Java社區進程(JCP)根據JSR 58開發的。實體bean的支持是強制性的,EJB引入了XML部署描述符來存儲元數據(在EJB 1.0中的一個文件中被序列化)。 該版本解決了使用遠程接口通過值傳遞參數的開銷,即通過引用本地接口並通過引用傳遞參數。 引入了J2EE連接器架構(JCA)來實現Java EE連接到EIS(企業信息系統)。

2003年發布的J2EE 1.4(JSR 151)在包含20個規範,並增加了對Web服務的支持。 EJB 2.1允許通過SOAP / HTTP調用會話bean。 創建定時服務以允許在指定的時間或間隔調用EJB。該版本為應用程式的裝配和部署提供了更好的支持。 雖然它的支持者預測了它的偉大未來,但並不是所有的J2EE的承諾都實現了。使用它創建的系統太複雜,開發時間常常與用戶需求的複雜性成正比。 J2EE被視為重量級組件模型:難以測試,難以部署,難以運行。 就在那時, Struts,Spring或Hibernate等框架出現並導引出開發企業應用程式的新方法。

幸運的是,2006年第二季度發布了Java EE 5(JSR 244),帶來了顯著的進步。 通過從開源框架中獲得了一些靈感,引入POJO編程模型。可以使用注釋定義元數據,並且XML描述符成為可選的。 從開發人員的角度來看,EJB 3和新的JPA比平台的演變更具有飛躍性。JavaServer Faces(JSF)作為標準的表示層框架被引入,JAX-WS 2.0將JAX-RPC替換為 SOAP Web服務API。

在2009年,Java EE 6(JSR 316)遵循開發的方便之路,在整個平台(包括Web層)中擁抱含註解、POJO編程和例外配置機制的概念。 它擁有豐富的創新,如全新的JAX-RS 1.1,Bean Validation 1.0和CDI 1.0; 它簡化了成熟的API,如EJB 3.1,並豐富了其他的,如JPA 2.0或EJB定時器服務。 但是Java EE 6的主要主題是可移植性(例如通過標準化全局JNDI命名),某些規範(通過修剪)的棄用,以及通過配置文件創建平台的子集。

今天,Java EE 7帶來了許多新的規範(批量處理,websockets,JSON處理)以及改進其他規範。 Java EE 7還通過在大多數規範中採用CDI來提高技術之間的集成。 有機會,將在教程中,我想向您展示這些改進,以及Java Enterprise Edition已經變得更加容易和豐富開發模式。

尤其是從Java EE 7演進到 Java EE 8,最終又轉交Eclipse基金管理,也就促進了現今新的企業級Java 規範的誕生,即Jakarta EE8。需要注意的是Jakarta EE 8完全兼容Java EE8,而Java EE8是在7的基礎上做到增量新特性添加和部分組件的完善,更不行的變化不大,所以,我們還是基於Java EE 7來介紹企業級Java。

2 全局理解Java EE 7

當想處理對的集合時,無需從開發自己的哈希表開始——集合API(應用程式編程接口)就完全滿足需要了。 同樣,如果您需要一個簡單的Web應用程式或支持事務、安全、可互操作和分布式的應用程式,則不需要開發所有低級API:企業版Java就滿足需要。 正如Java標準版(Java SE)提供的處理集合的API一樣,Java EE提供了一種標準的事務API方法來處理Java 事務,使用Java消息服務(JMS)進行消息傳遞,或者使用持久化 API(JPA)進行數據持久化。Java EE是針對企業應用程式的一組規範,它可以被看作是Java SE的擴展,以便於開發分布式、健壯的、強大的和高可用性的應用程式。

Java EE 7是一個重要的里程碑。不僅僅是遵循Java EE 6關注一個更簡單的開發模式,而且還增加了新的規範,並為現有特性增加了新的功能。另外,上下文依賴注入(CDI)正在成為所有這些新規範之間的集成點。 Java EE 7的發布與企業平台發布十三周年緊密相連,將Java語言的優勢與過去13年所獲得的經驗結合起來.Java EE從開源社區的活力中獲益,同時也得益於嚴格的 JCP(Java Community Process)標準化進程。

今天,Java EE早已成為經過驗證的優秀平台,其擁有經驗豐富的開發人員、大型社區以及部署在公司伺服器上運行著的諸多應用系統。Java EE是一套規範的APIs,可用於構建基於標準組件的多層應用程式,這些組件部署在提供一系列服務的不同容器中。

接下來,我們從不同層面理解掌握Java EE 7的不同總體構成。

2.1Java EE總體架構

Java EE是由不同容器實現的一組規範。容器是為其所託管的組件提供某些服務的Java EE運行時環境,例如生命周期管理,依賴注入,並發等。這些組件使用定義良好的規約與Java EE基礎架構以及其他組件進行通信。在部署之前,需要以標準方式打包(按照定義的目錄結構,可壓縮到歸檔文件中)。注意,Java EE是Java SE平台的超集,這意味著Java SE API可以由任何Java EE組件使用。

圖1-1顯示了容器之間的邏輯關係。箭頭表示一個容器訪問另一個容器所使用的協議。 例如,Web容器託管可以通過RMI-IIOP訪問EJB的servlet。

圖1-1 標準Java EE容器架構關係

2.2Java EE構件組成

Java EE運行時環境規範定義了Java EE「實現」(可以看作為中間件)必須支持的四種類型的構件:

  1. ²Applets:瀏覽器小程序是在Web瀏覽器中執行的GUI(圖形用戶介面)應用程式。它們使用豐富的Swing API來提供強大的用戶介面。
  2. ²Applications:應用程式(PC獨立應用程式)是在客戶端上執行的程序。它們通常是可以訪問Java EE中間層所有設施的GUI或批處理程序。
  3. ²Web Applications:Web應用程式(由servlet、servlet過濾器、Web事件偵聽器、JSP和JSF頁面組成)在Web容器中執行,並響應來自Web客戶端的HTTP請求。 Servlet還支持SOAP和RESTful Web服務,Web應用程式還可以包含EJB精簡版(EJBs Lite).
  4. ²Enterprise Applications:企業應用程式(由企業Java Bean、Java消息服務、Java事務API、異步調用、定時服務、RMI / IIOP等構成)在EJB容器中執行。EJBs是用於處理事務性業務邏輯的容器管理組件。它們可以被本地化訪問和通過RMI(或SOAP for SOAP和RESTful Web服務)遠程訪問。

2.3Java EE容器

Java EE基礎架構被劃分為稱為容器的邏輯域(見圖1-1)。每個容器都有一個特定的角色,支持一組API,並為組件提供服務(如安全性,資料庫訪問,事務處理,命名目錄,資源注入等)。容器隱藏技術複雜性並增強可移植性。根據要構建的應用程式的類型,將須了解每個容器的功能和約束,以便使用一個或多個。例如,如果您需要開發一個Web應用,將開發具有EJB Lite層的JSF層,並將其部署到Web容器中。但是,如果您希望Web應用程式能遠程調用業務層並使用消息傳遞和異步調用,那麼您將需要Web和EJB容器。

Java EE標準定義了四種不同的容器:

  1. ²Applet containers:大多數Web瀏覽器提供Applet容器來執行applet組件。 當開發applets時,在容器提供安全的環境中,可以集中精力在應用程式的可視化方面。 小應用程式容器使用沙盒安全模型,其中「沙箱」中執行的代碼不允許「在沙箱外活動」。這意味著該容器可防止下載到本地計算機的任何代碼訪問自由本地系統資源,例如進程或文件。
  2. ²Application client container:應用程式客戶機容器(ACC)包括一組Java類、庫和其他文件等,用於為Java SE應用程式提供注入、完全管理、命名服務(這樣的應用包括Swing應用、批處理或僅使用main()方法的類等)。ACC使用RMI-IIOP和具有HTTP的Web容器(例如,用於Web服務)與EJB容器進行通信。
  3. ²Web container:Web容器提供用於管理和執行Web組件(servlet,EJB Lite,JSP,過濾器,偵聽器,JSF頁面和Web服務)的底層服務。它負責實例化,初始化和調用servlet並支持HTTP和HTTPS 協議。它是用於將網頁反饋到客戶端瀏覽器。
  4. ²EJB container:EJB容器負責管理包含Java EE應用程式的業務邏輯層的企業bean(會話bean和消息驅動的bean)的執行。它創建EJB的新實例,管理其生命周期,並提供諸如 事務,安全性,並發性,分發,命名服務或異步調用的可能性。

2.4Java EE服務

容器為其部署的組件提供基礎服務。 作為開發人員,容器允許您集中精力實施業務邏輯,而不是解決企業應用程式中面臨的技術問題。圖1-2顯示了每個容器提供的服務。 例如,Web和EJB容器提供連接器來訪問EIS,但不提供applet容器或ACC。Java EE提供以下服務:

  1. ²Java Transaction API:此服務提供容器和應用程式使用的事務分界API。 它還提供事務管理器和服務提供者接口(SPI)級別的資源管理器之間的接口。
  2. ²Java Persistence API:用於對象關係映射(ORM)的標準API。使用其持久性查詢語言(JPQL),可以查詢存儲在底層資料庫中的對象。
  3. ²Validation: Bean驗證提供類和方法級約束聲明和驗證功能。
  4. ²Java消息服務:這允許組件通過消息異步通信。它支持可靠的點對點(P2P)消息傳遞以及發布訂閱(pub-sub)模型。
  5. ²Java命名和目錄接口:此API包含在Java SE中,用於訪問命名和目錄系統。應用程式使用此技術將名稱與對象進行關聯(綁定),然後在目錄中查找這些對象(以lookup方式查找)。其可以查找對象包括數據源、JMS工廠、EJB和其他資源等。直到J2EE 1.4,無所不在的JNDI可以更透明的方式通過注入使用。
  6. ²JavaMail:許多應用程式需要發送電子郵件的功能,可以通過使用JavaMail API來實現。
  7. ²JavaBeans激活框架:Java SE中包含的JAF API提供了一種處理不同MIME類型的數據的框架。 它被JavaMail使用。
  8. ²XML處理:大多數Java EE組件可以部署可選的XML部署描述符,應用程式通常必須處理XML文檔。 Java XML處理API(JAXP)提供了對使用SAX和DOM以及XSLT解析文檔的支持。XML流化API(StAX)為XML提供了一個」pull-parsing」(拉式)解析API。
  9. ²JSON處理:Java EE 7中新增的JSON 處理API(JSON-P)允許應用程式解析、生成、轉換和查詢JSON。
  10. ²Java EE連接器體系結構:連接器允許您從Java EE訪問EIS,EIS可以是資料庫,大型機或企業資源計劃(ERP)程序等。
  11. ²安全服務:Java認證和授權服務(JAAS)使服務能夠對用戶進行身份驗證和強制訪問控制。 Java授權服務提供商規約(JACC)定義了Java EE應用程式伺服器和授權服務提供商之間的約束,允許將自定義授權服務提供商插入到任何Java EE產品中。 容器的Java認證服務提供程序接口(JASPIC)定義了一個標準接口,通過該標準接口可以將認證模塊集成到容器中,以便這些模塊可以建立容器使用的認證標識。
  12. ²Web服務:Java EE為SOAP和RESTful Web服務提供支持。用於XML Web服務的Java API(JAX-WS),提供了支持SOAP/HTTP協議的web服務(用於替代基於XML的RPC即JAX-RPC的API)。 RESTful服務API(JAX-RS)提供了對使用REST風格的Web服務的支持。
  13. ²依賴注入:自Java EE 5以來,可以將一些資源(數據源,JMS工廠,持久性單元,EJBs ...)注入到託管組件中。 Java EE 7通過使用CDI以及DI(Java的依賴注入)規範實現了對依賴注入的進一步應用擴展。
  14. ²管理:Java EE使用特殊的管理企業bean定義用於管理容器和伺服器的API。 Java管理擴展(JMX)API也用於提供一些管理支持。
  15. ²部署:Java EE部署規範定義了部署工具和Java EE產品之間的規約,以標準化應用程式部署。

圖1-2 容器提供服務支持及關係圖

而在Jakarta EE 8(原Java EE 8)中,上述的構成關係如下圖所示:


上圖簡要描述如下:

如圖上所示,它描述了Java EE平台架構元素之間的關係。注意,該圖顯示的是組件元素之間的邏輯關係,而並不意味著將元素物理地劃分為單獨的機器、進程、地址空間或虛擬機等。

容器(用單獨的矩形表示)是Java EE運行時環境,為矩形上半部分中表示的應用程式組件提供所需的服務。所提供的服務由矩形下半部分的方框表示,一些由應用伺服器實現的符合規範的組件。例如,應用客戶端容器向應用客戶端提供Java消息服務(JMS) APIs以及所表示的其他服務。下面將解釋所有這些服務。

箭頭表示需要訪問Java EE平台的其他部分。應用客戶端容器通過JDBC API與資料庫系統連接,為應用客戶端提供了對Java EE所需資料庫的直接訪問。由Web容器為JSP頁面、JSF應用和servlet提供類似的資料庫訪問,EJB容器為企業bean提供類似的訪問。

如前所述,Java平台標準版(Java SE)的APIs由Java SE運行時環境為每種類型的應用組件提供支持。

2.5Java EE網絡協議

如圖1-2所示,部署在容器中的組件可以通過不同的協議進行調用。 例如,部署在Web容器中的servlet可以使用HTTP以及在EJB容器中部署EJB端點的Web服務來調用。 以下是Java EE支持的協議列表:

  1. HTTP:HTTP是Web協議,在現代應用程式中是普遍存在的。客戶端API由Java SE中的java.net包定義。HTTP伺服器端API由servlet、JSP和JSF接口定義,就像SOAP和RESTful Web服務一樣。
  2. HTTPS:HTTPS是HTTP和安全套接字層(SSL)協議的組合。
  3. RMI-IIOP:遠程方法調用(RMI)允許您獨立於底層協議調用遠程對象。Java SE本機RMI協議是Java遠程方法協議(JRMP).RMI-IIOP是用於與CORBA集成的RMI的擴展 .Java介面描述語言(IDL)允許Java EE應用程式組件使用IIOP協議調用外部CORBA對象。 CORBA對象可以用許多語言(Ada,C,C ++,Cobol等)以及Java編寫。

2.6Java EE 打包

要部署在容器中,組件首先要封裝在標準的格式化存檔中。 Java SE定義了Java Archive(jar)文件,用於將多個文件(Java類,部署描述符,資源或外部庫)聚合到一個壓縮文件(基於ZIP格式)中。 如圖1-3所示,Java EE定義了基於通用jar格式的具有自己的打包格式的不同類型的模塊。

圖1-3 容器中打包歸檔格式

針對上述歸檔模式,說明如下:

其一,應用程式客戶端模塊包含打包在jar文件中的Java類和其他資源文件。 該jar文件可以在Java SE環境或應用程式客戶端容器中執行。 像任何其他存檔格式一樣,jar文件包含一個可選的META-INF目錄,用於描述歸檔的元信息。 META-INF / MANIFEST.MF文件用於定義擴展和包相關數據。 如果部署在ACC中,則部署描述符可以可選地位於META-INF / application-client.xml。

其二,EJB模塊包含打包在jar文件(通常稱為EJB jar文件)中的一個或多個會話和/或消息驅動的bean(MDB)。 它包含一個可選的META-INF / ejb-jar.xml部署描述符,並且只能部署在EJB容器中。

其三,Web應用程式模塊包含servlet,JSP,JSF頁面和Web服務,以及任何其他Web相關文件(HTML和XHTML頁面,級聯樣式表(CSS),Java腳本,圖像,視頻等)。 從Java EE 6以來,Web應用程式模塊還可以包含EJB Lite bean(EJB API的一個子集)。所有這些工件都封裝在帶有.war擴展名(通常稱為war文件或Web Archive)的jar文件中。可選Web部署描述符在WEB-INF / web.xml文件中定義。 如果war包含EJB Lite bean,則可以在WEB-INF / ejb-jar.xml中設置可選的部署描述符。 Java.class文件放置在WEB-INF / classes目錄和依賴的jar文件的WEB-INF / lib目錄下。

其四,企業模塊可以包含零個或多個Web應用程式模塊,零個或多個EJB模塊以及其他常用或外部庫。所有這些都被打包成企業歸檔(具有.ear擴展名的jar文件),以便各種部署模塊協同進行並發。 可選的企業模塊部署描述符在META-INF / application.xml文件中定義。特殊的lib目錄用於在模塊之間共享公共庫。

2.7註解和部署描述符

在編程範例中,有兩種方法:命令式編程和聲明式編程。語法編程規定了實現目標的算法(必須做的事情),而聲明式編程規定了如何實現這一目標(如何完成)。 在Java EE中,通過使用元數據(即注釋或/和部署描述符)完成聲明式編程。

如圖1-2所示,組件在容器中運行,此容器為組件提供了一組服務.Metadata用於聲明和自定義這些服務,並將附加信息與Java類、接口、構造函數、方法、欄位或參數相關聯 。

自從Java EE 5以來,注釋在企業平台上一直在增長。它們使用元數據信息來修飾代碼(Java類,接口,欄位,方法...)。 清單1-1顯示了一個POJO(普通Java對象),它使用類和屬性上的注釋來聲明某些行為。

@Stateless

@Remote(ItemRemote.class)

@Local(ItemLocal.class)

@LocalBean

public class ItemEJB implements ItemLocal, ItemRemote {

@PersistenceContext(unitName = "chapter01PU")

private EntityManager em;

public Book findBookById(Long id) {

return em.find(Book.class, id);

}

}

代碼清單1-1:註解式EJB

聲明元數據的另一種方式是使用部署描述符。部署描述符(DD)是指與容器中組件一起部署的XML配置文件.Listing 1-2顯示了一個EJB部署描述符。 像大多數Java EE 7部署描述符一樣,它定義了http://xmlns.jcp.org/xml/ns/javaee命名空間,並包含版本屬性

規範。

<ejb-jar xmlns="http://xmlns.jcp.org/xml/ns/javaee" 

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 

http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd" 

version="3.2">

<enterprise-beans>

<session>

<ejb-name>ItemEJB</ejb-name>

<remote>org.agoncal.book.javaee7.ItemRemote</remote>

<local>org.agoncal.book.javaee7.ItemLocal</local>

<local-bean/>

<ejb-class>org.agoncal.book.javaee7.ItemEJB</ejb-class>

<session-type>Stateless</session-type>

<transaction-type>Container</transaction-type>

</session>

</enterprise-beans>

</ejb-jar>

代碼清單1-2:EJB部署描述符

部署描述符需要與特殊的META-INF或WEB-INF目錄中的組件打包在一起,以備參考。 表1-1顯示了Java EE部署描述符和相關規範的列表

表1-1:JavaEE部署描述列表

文件規範路徑application.xmlJava EEMETA-INFapplication-client.xmlJava EEMETA-INFbeans.xmlCDIMETA-INF or WEB-INFra.xmlJCAMETA-INFejb-jar.xmlEJBMETA-INF or WEB-INFfaces-config.xmlJSFWEB -INFpersistence.xmlJPAMETA-INFvalidation.xmlBean ValidationMETA-INF or WEB-INFweb.xmlServletWEB-INFweb-fragment.xmlServletWEB-INFwebservices.xmlSOAP Web ServicesMETA-INF or WEB-INF

由於Java EE 5大多數部署描述符是可選的,應用可以使用注釋。或使用兩者中對應用程式最好的方式即可。 注釋的最大優點是它們顯著減少了開發人員編寫的代碼量,並且通過使用注釋可以避免編寫部署描述符的需要。 另一方面,部署描述符是可以更改的外部XML文件,而不需要修改原始碼和重新編譯。 如果您同時使用這兩者,當部署應用程式或組件時則元數據將被部署描述符覆蓋(即XML優先於注釋)。

2.8編程模型

大多數Java EE 7規範使用相同的編程模型。 它通常是一個POJO,它將一些元數據(注釋或XML)部署到容器中。 大多數時候,POJO甚至沒有實現一個接口或者擴展一個超類。 由於元數據,容器知道應用於此已部署組件的每一個服務。

在Java EE 7中,servlet,JSF支持bean,EJB,實體,SOAP和REST Web服務是帶可選XML部署描述符的注釋類。 清單1-3顯示了一個JSF支持bean,證明是具有單個CDI注釋的Java類。

清單1-3:JSF後端Bean

@Named

public class BookController {

@Inject

private BookEJB bookEJB;

private Book book = new Book();

private List<Book> bookList = new ArrayList<Book>();

public String doCreateBook() {

book = bookEJB.createBook(book);

bookList = bookEJB.findBooks();

return "listBooks.xhtml";

}

// Getters, setters

}

EJB也遵循相同的模式。 如清單1-4所示,如果您需要在本地訪問EJB,則沒有接口的簡單注釋類就足夠了。 EJB也可以直接部署在war文件中,而不會先前封裝在jar文件中。 這使EJB成為可以從簡單的Web應用程式到複雜的企業應用程式使用的最簡單的事務組件。

代碼清單1-4:無狀態EJB

@Stateless

public class BookEJB {

@Inject

private EntityManager em;

public Book findBookById(Long id) {

return em.find(Book.class, id);

}

public Book createBook(Book book) {

em.persist(book);

return book;

}

}

RESTful Web服務已經進入現代應用程式。 Java EE 7通過改進JAX-RS規範來滿足企業的需求。 如清單1-5所示,一個RESTful Web服務是一個響應HTTP操作的帶有注釋的Java類。

代碼清單1-5:RESTFUL web服務

@Path("books")

public class BookResource {

@Inject

private EntityManager em;

@GET

@Produces({"application/xml", "application/json"})

public List<Book> getAllBooks() {

Query query = em.createNamedQuery("findAllBooks");

List<Book> books = query.getResultList();

return books;

}

}


以上,希望對你總體把握和學習企業級Java (Jakarta EE 8)有更好的鋪墊解釋和引導幫助。如果覺得有意義,請點這個贊、轉發和收藏。謝謝^_^

另,這篇教程是在學習Java EE7時的理解和外文翻譯,如有不妥的可以給我留言。

關鍵字: