Java Votary

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            48 隨筆 :: 1 文章 :: 80 評(píng)論 :: 0 Trackbacks

          將 Java Swing 應(yīng)用程序連接到 Geronimo 服務(wù)器

          創(chuàng)建可以與 Geronimo EJB 應(yīng)用程序?qū)υ挼莫?dú)立客戶端

          developerWorks
          文檔選項(xiàng)
          將此頁(yè)作為電子郵件發(fā)送

          將此頁(yè)作為電子郵件發(fā)送

          未顯示需要 JavaScript 的文檔選項(xiàng)

          討論

          樣例代碼


          對(duì)此頁(yè)的評(píng)價(jià)

          幫助我們改進(jìn)這些內(nèi)容


          級(jí)別: 初級(jí)

          Neal Sanche , Java 開(kāi)發(fā)人員, Pure Technologies

          2005 年 8 月 24 日

          在前兩篇 developerWorks 文章(參閱 參考資料) 中,作者 Neal Sanche 使用簡(jiǎn)單的電話簿應(yīng)用程序來(lái)展示如何將 Apache Geronimo 應(yīng)用服務(wù)器連接到數(shù)據(jù)庫(kù),以及如何使用 Geronimo 創(chuàng)建具有 Enterprise JavaBeans (EJB) 后端的基于 Struts 的 Web 應(yīng)用程序。本文進(jìn)一步使用電話簿應(yīng)用程序來(lái)展示如何創(chuàng)建獨(dú)立客戶端應(yīng)用程序以操作電話號(hào)碼數(shù)據(jù)庫(kù)。您還將學(xué)習(xí)如何配置 Geronimo 以允許來(lái)自特定客戶端的安全訪問(wèn)。

          簡(jiǎn)介

          本文將展示如何開(kāi)發(fā)可以與運(yùn)行在 Geronimo 應(yīng)用服務(wù)器內(nèi)部的 EJB 應(yīng)用程序通信的獨(dú)立(胖)客戶端。基于我的前兩篇文章 ——“將數(shù)據(jù)庫(kù)連接到 Geronimo 應(yīng)用服務(wù)器的三種方法”(developerWorks,2005 年 6 月)和“利用 Geronimo 深入 EJB Web 應(yīng)用程序” (developerWorks,2005 年 7 月)—— 本文向您展示一個(gè)連接到使用 Geronimo EJB 應(yīng)用程序構(gòu)建的小型電話簿數(shù)據(jù)庫(kù)的 Swing 客戶端。您將閱讀簡(jiǎn)要的設(shè)計(jì)說(shuō)明,然后閱讀有關(guān)運(yùn)行該應(yīng)用程序所需的客戶端庫(kù)的信息。接下來(lái)我將介紹聯(lián)系服務(wù)器并對(duì)服務(wù)器上遠(yuǎn)程無(wú)狀態(tài)會(huì)話 bean 執(zhí)行操作的方法。最后,您將學(xué)習(xí)如何開(kāi)發(fā)、編譯并運(yùn)行客戶端應(yīng)用程序,以及如何配置服務(wù)器以允許來(lái)自網(wǎng)絡(luò)中特定客戶端的安全訪問(wèn)。

          要最有效地利用本文,您需要熟悉用于構(gòu)建 Java 桌面應(yīng)用程序的 Java Swing API 以及 Apache Maven 構(gòu)建系統(tǒng)(參閱 參考資料 以鏈接到 Maven Web 站點(diǎn))。



          回頁(yè)首


          設(shè)計(jì)概述

          首先簡(jiǎn)要介紹一下示例應(yīng)用程序設(shè)計(jì) —— 一個(gè)描述電話簿客戶端應(yīng)用程序的統(tǒng)一建模語(yǔ)言 (Unified Modeling Language, UML) 部署圖 —— 如 圖 1 所示。客戶端應(yīng)用程序通過(guò)其 EJB 端口連接到 Geronimo,并與 PhoneBook Session EJB 對(duì)話以通過(guò) PhoneBook Entry Container-Managed Persistence (CMP) 操作數(shù)據(jù)庫(kù)中的數(shù)據(jù)。


          圖 1. 電話簿客戶端部署圖
          電話簿客戶端部署圖

          Geronimo 的默認(rèn)發(fā)行版對(duì) EJB 端口有限制。僅當(dāng)客戶端應(yīng)用程序運(yùn)行在同一機(jī)器上并且通過(guò)環(huán)回地址(localhost 或 127.0.0.1) 連接時(shí)才能連接到該端口。本文稍后的 配置 Geronimo 的 EJB 端口 一節(jié)提供了有關(guān)如何讓其他機(jī)器上的客戶端訪問(wèn)服務(wù)器的詳細(xì)信息。



          回頁(yè)首


          用于連接到 Geronimo 的客戶端庫(kù)

          要讓客戶端應(yīng)用程序能夠連接到 Geronimo 的 EJB 端口并與 EJB 層通信,客戶端類路徑中必須要有下列 Java 庫(kù):

          • geronimo-spec-j2ee-1.4-rc4.jar
          • geronimo-kernel-1.0-SNAPSHOT.jar
          • geronimo-j2ee-1.0-SNAPSHOT.jar
          • geronimo-security-1.0-SNAPSHOT.jar
          • cglib-nodep-2.1.jar
          • openejb-core-2.0-SNAPSHOT.jar
          對(duì)構(gòu)建結(jié)構(gòu)的備注

          因?yàn)閷?duì)前面文章中代碼的構(gòu)建結(jié)構(gòu)進(jìn)行了一些小的修改,所以本文的代碼包含了電話簿應(yīng)用程序和電話簿客戶端應(yīng)用程序。下載 包括了有關(guān)如何使用 Maven 構(gòu)建這兩個(gè)應(yīng)用程序的詳細(xì)說(shuō)明。

          從源代碼編譯 Geronimo 時(shí),當(dāng)您使用 Maven 構(gòu)建腳本來(lái)編譯電話簿客戶端應(yīng)用程序時(shí),這些庫(kù)被放置到本地 Maven 資源庫(kù)中且可供訪問(wèn)。您可以在 project.xml 文件的依賴關(guān)系部分中查看所有這些庫(kù)位于 Maven 資源庫(kù)的哪個(gè)位置。

          其中一些庫(kù)在客戶端與服務(wù)器的通信中起著非常重要的作用。Geronimo 使用 CGLib 庫(kù)來(lái)執(zhí)行動(dòng)態(tài)代理生成。這使得服務(wù)器動(dòng)態(tài)生成遠(yuǎn)程調(diào)用服務(wù)器端組件的代碼。如果在調(diào)試器中檢查客戶端上 InitialContext 對(duì)象的 lookup() 方法返回的一個(gè)對(duì)象,可以看到動(dòng)態(tài)生成的對(duì)象的類名包括 CGLib。geronimo-spec-j2ee.jar 文件包含所有的 Sun Java 2 Platform, Enterprise Edition (J2EE) 接口和類。沒(méi)有該文件,客戶端將無(wú)法理解任何動(dòng)態(tài)代理實(shí)例。openejb-core.jar 文件是與服務(wù)器的 EJB 端口進(jìn)行對(duì)話所必需的。用于在 Geronimo 服務(wù)器中執(zhí)行遠(yuǎn)程目錄查詢的 Java Naming and Directory Interface (JNDI) 類就在該 .jar 文件中。最后的三個(gè) .jar 文件提供了其他支持類,比如與 Geronimo 對(duì)話的安全主體。



          回頁(yè)首


          執(zhí)行遠(yuǎn)程會(huì)話本地查詢

          客 戶端通信部分的實(shí)現(xiàn)十分簡(jiǎn)單。將客戶端連接到服務(wù)器時(shí),Geronimo 與其他任何 J2EE 服務(wù)器沒(méi)有任何不同,遵守健全的通過(guò) JNDI 查詢和遠(yuǎn)程方法調(diào)用 (RMI) 進(jìn)行的通信標(biāo)準(zhǔn)。JNDI 查詢是獲得對(duì)遠(yuǎn)程對(duì)象的引用的標(biāo)準(zhǔn)訪問(wèn)。要通過(guò) JNDI 進(jìn)行連接,必須使用大量特定于 Geronimo 的屬性來(lái)創(chuàng)建 InitialContext 實(shí)例,該實(shí)例用于執(zhí)行查詢。 清單 1 展示了有關(guān)如何創(chuàng)建會(huì)話的示例。


          清單 1. 創(chuàng)建到 Geronimo 托管會(huì)話 bean 的遠(yuǎn)程會(huì)話
          import java.util.Properties;
          import javax.naming.Context;
          import javax.naming.InitialContext;
          import javax.rmi.PortableRemoteObject;

          public void Connect() {
          String hostName = getHostName();
          String port = getPort();

          Properties props = new Properties();

          props.setProperty("java.naming.factory.initial",
          "org.openejb.client.RemoteInitialContextFactory");
          props.setProperty("java.naming.provider.url", hostName+":"+port);
          props.setProperty("java.naming.security.principal", "username");
          props.setProperty("java.naming.security.credentials", "passwd");

          Context ic;
          try {
          ic = new InitialContext(props);
          PhoneBookSessionHome sessionHome = (PhoneBookSessionHome)
          PortableRemoteObject.narrow(
          ic.lookup(PhoneBookSessionHome.JNDI_NAME),
          PhoneBookSessionHome.class);
          phoneBookSession = sessionHome.create();
          } catch (Throwable ex) {
          ex.printStackTrace();
          } finally {
          if (ic != null) {
          ic.close();
          }
          }
          }

          清單 1 所示,創(chuàng)建了 Properties 對(duì)象并設(shè)置了四個(gè)屬性。第一個(gè)并且是最重要的屬性是 java.naming.factory.initial 屬性,它必須設(shè)置為 org.openejb.client.RemoteInitialContextFactory。其他屬性指定提供者 URL 以及安全主體和憑證。提供者 URL 是用冒號(hào)隔開(kāi)的主機(jī)名和端口。

          前已提及,EJB 端口當(dāng)前只接受從客戶端連接到 127.0.0.1 或 localhost 的連接。默認(rèn)端口是 4201。盡管如此,主機(jī)名和端口都可以進(jìn)行配置。有關(guān)詳細(xì)信息,請(qǐng)參閱 配置 Geronimo 的 EJB 端口 一節(jié)。

          創(chuàng)建好屬性之后,就可以創(chuàng)建并使用 InitialContext 實(shí)例了。通過(guò)將屬性傳遞給構(gòu)造函數(shù)完成這一操作。創(chuàng)建好實(shí)例之后,可以執(zhí)行查詢。清單 1 包括一行復(fù)雜的代碼,該行執(zhí)行查詢并對(duì)結(jié)果執(zhí)行 PortableRemoteObject.narrow()。對(duì)于向用戶隱藏有關(guān)協(xié)議傳輸 —— RMI 或者可能是 Internet Inter-ORB Protocol (IIOP)—— 的詳細(xì)信息,這是必需的。完成之后,遠(yuǎn)程會(huì)話就可供使用了。在 清單 1 中,該行只創(chuàng)建了新 PhoneBookSession,并將其存儲(chǔ)在一個(gè)字段中以供將來(lái)使用。

          具有對(duì)遠(yuǎn)程會(huì)話的引用之后,該引用可用于所有操縱電話簿數(shù)據(jù)庫(kù)信息的操作?,F(xiàn)在只需要一個(gè)應(yīng)用程序來(lái)練習(xí)該遠(yuǎn)程會(huì)話。



          回頁(yè)首


          客戶端的設(shè)計(jì)和開(kāi)發(fā)

          現(xiàn) 在我們來(lái)深入研究一個(gè)小 Swing 應(yīng)用程序的設(shè)計(jì)和開(kāi)發(fā),這個(gè)小應(yīng)用程序用來(lái)瀏覽、創(chuàng)建、刪除和修改電話簿數(shù)據(jù)庫(kù)條目。我盡量將 Swing 行話減到最少,以防您比較熟悉的是另一種 GUI 技術(shù),比如 Standard Widget Toolkit (SWT)。事實(shí)上,如果需要的話,應(yīng)用程序架構(gòu)已經(jīng)使得將顯示從應(yīng)用程序內(nèi)部邏輯分離出來(lái)并將其連接到另一種 GUI 技術(shù)變得非常容易。

          應(yīng)用程序架構(gòu)如 圖 2 所示,這是一個(gè)詳細(xì)顯示應(yīng)用程序靜態(tài)結(jié)構(gòu)的 UML 類圖。


          圖 2. 客戶端應(yīng)用程序的 UML 類圖
          客戶端應(yīng)用程序的 UML 類圖

          圖 2 中帶綠色陰影的類是主要的應(yīng)用程序類。Main 類是包含菜單和拆分窗格(其左側(cè)是 PhoneNumberListPanel,右側(cè)是 PhoneBookEditorPanel)的框架。該菜單還允許用戶設(shè)置連接到哪個(gè)服務(wù)器的首選項(xiàng),連接到服務(wù)器,并退出程序。Application 類是一個(gè)單身類(singleton class),用作應(yīng)用程序的所有操作的控制器。它是惟一一個(gè)執(zhí)行 EJB 操作的類,并保存對(duì) PhoneBookSession 無(wú)狀態(tài)會(huì)話 bean 的引用。

          橙色的兩個(gè)接口定義系統(tǒng)中的主要事件。每當(dāng) Application 決定電話號(hào)碼列表需要更新時(shí),就會(huì)激活 DataChangeEventPhoneNumberListModel 注冊(cè)該事件。因?yàn)樗?PhoneNumberListPanel 中的主要數(shù)據(jù)模型列表視圖,所以列表是通過(guò)模型更改來(lái)更新的。這與 Swing 應(yīng)用程序的設(shè)計(jì)方法一致。

          PhoneNumberListPanelPhoneBookEditorPanel 類都實(shí)現(xiàn) PhoneBookSelectionListener 接口并注冊(cè)來(lái)自 Application 單身類的事件。當(dāng)它們收到事件時(shí),它們相應(yīng)地更新當(dāng)前的選擇。如果是 PhoneBookEditorPanel,當(dāng)前選擇導(dǎo)致 Name 和 Number 字段由來(lái)自當(dāng)前選擇的電話簿條目中的數(shù)據(jù)填充。

          如果希望節(jié)省編寫用戶接口代碼的時(shí)間,通??梢栽?Internet 上找到高質(zhì)量的免費(fèi)工具。優(yōu)秀的工具有 JGoodies Forms 1.0.5 和 FormLayoutMaker,F(xiàn)ormLayoutMaker 是一個(gè)用于可視化創(chuàng)建窗體的小工具(參閱 參考資料 以獲得到這些工具的鏈接)。FormLayoutMaker 工具生成代表 JGoodies 窗體布局約束的 XML 文件。這些工具幫助我快速創(chuàng)建了 Phone Number 編輯面板和 Preferences 面板的窗體。



          回頁(yè)首


          構(gòu)建應(yīng)用程序

          編 譯應(yīng)用程序有兩種方法。我使用 Eclipse Visual Editor (VE) 插件 1.2 版本在 Eclipse 中開(kāi)發(fā)了該應(yīng)用程序。它生成應(yīng)用程序的大部分代碼框架,但它是以一種非入侵的方式完成的(沒(méi)有代碼標(biāo)記和不可訪問(wèn)的代碼塊),所以如果沒(méi)有安裝 VE 的話也應(yīng)該沒(méi)有問(wèn)題??梢灾患虞d項(xiàng)目并嘗試運(yùn)行它。

          您可能需要設(shè)置 MAVEN_REPO 構(gòu)建變量以指向本地 Maven 資源庫(kù)。還需要構(gòu)建與本文一起提供的源代碼中包括的 Geronimo 和 PhoneBook 服務(wù)器應(yīng)用程序(參閱 下載)。這是因?yàn)?,要編譯客戶端應(yīng)用程序,包含服務(wù)器應(yīng)用程序中 EJB 接口的 .jar 文件必須發(fā)布到本地 Maven 資源庫(kù)中。PhoneBook 的 Maven 構(gòu)建腳本通過(guò)下列 Maven 構(gòu)建腳本段完成該操作:


          清單 2. Maven 構(gòu)建腳本段
          <goal name="client" prereqs="java:compile">
          <ant:jar destfile="target/${pom.artifactId}-client.jar">
          <fileset dir="target/classes">
          <include name="**/*.class"/>
          </fileset>
          </ant:jar>
          <artifact:install artifact="target/${pom.artifactId}-client.jar"
          type="jar" project="${pom}"/>
          </goal>

          用于構(gòu)建應(yīng)用程序的第二種方法就是使用 Maven。在 PhoneBook 目錄中解壓文件并運(yùn)行 maven 命令。然后在 PhoneBookClient 目錄中進(jìn)行相同操作。如果一切順利,就已經(jīng)在目標(biāo)子目錄中創(chuàng)建了 UberJar —— 一個(gè)包含運(yùn)行客戶端所需的所有內(nèi)容的 JAR 文件。

          兩種構(gòu)建方法運(yùn)行得同樣好。使用 Maven 方法的優(yōu)點(diǎn)是如果您尚未下載依賴關(guān)系,則它會(huì)自動(dòng)從 ibiblio Web 站點(diǎn)(參閱 參考資料)上的遠(yuǎn)程 Maven 資源庫(kù)中下載這些依賴關(guān)系。所以如果 Eclipse 中的依賴關(guān)系有問(wèn)題,就在項(xiàng)目上至少運(yùn)行一次 Maven 來(lái)校正缺少的庫(kù)。



          回頁(yè)首


          運(yùn)行應(yīng)用程序

          確保 PhoneBook 服務(wù)器應(yīng)用程序部署到 Geronimo 服務(wù)器中且正在運(yùn)行。然后鍵入下列命令:

          java -jar phonebook-client-uber.jar

          將會(huì)看到應(yīng)用程序彈出,如 圖 3 所示。


          圖 3. Geronimo 電話簿客戶端應(yīng)用程序
          Geronimo 電話簿客戶端應(yīng)用程序

          首先,從 File 菜單中選擇 Connect。如果是連接到 localhost:4201 端口,則應(yīng)該獲得一個(gè)連接;否則,控制臺(tái)窗口將會(huì)顯示錯(cuò)誤消息??梢酝ㄟ^(guò)選擇 Edit > Preferences、更改信息并嘗試重新連接來(lái)更改連接的服務(wù)器和端口。一旦連接上之后,可以通過(guò)在電話號(hào)碼編輯器中鍵入姓名和號(hào)碼并單擊 Save 來(lái)創(chuàng)建新記錄。該記錄將顯示在姓名列表中。通過(guò)選擇條目并單擊 Delete 來(lái)刪除條目。通過(guò)選擇條目、進(jìn)行修改并單擊 Save 來(lái)更改條目。



          回頁(yè)首


          配置 Geronimo 的 EJB 端口

          當(dāng) 前,配置 Geronimo 的 EJB 端口的方法需要編輯 XML 文件,然后重新編譯 Geronimo。Tom McQueeney 的大型 Geronimo Live blog 上的一篇短文清楚介紹了如何使用 openejb\modules\assembly\src\plan\j2ee-server-plan.xml 文件更改 Geronimo Jetty 監(jiān)聽(tīng)端口的詳細(xì)信息(參閱 參考資料 以鏈接到該 blog)。同一文件還包含 EJB 端口的配置信息(參閱 清單 3)。


          清單 3. j2ee-server-plan.xml 文件中的代碼段
          <gbean name="EJBNetworkService" 
          class="org.openejb.server.StandardServiceStackGBean">
          <attribute name="name">EJB</attribute>
          <attribute name="port">4201</attribute>
          <attribute name="address">127.0.0.1</attribute>
          <attribute name="allowHosts">127.0.0.1</attribute>
          <attribute name="logOnSuccess">HOST,NAME,THREADID,USERID</attribute>
          <attribute name="logOnFailure">HOST,NAME</attribute>
          <reference name="Executor"><name>DefaultThreadPool</name></reference>
          <reference name="Server">
          <gbean-name>openejb.server:name=EJBServer,*</gbean-name>
          </reference>
          </gbean>

          您需要編輯 j2ee-server-plan.xml 文件并更改 allowHosts 屬性。Geronimo 支持許多不同類型的地址。必須用下列模式之一輸入逗號(hào)分隔的地址列表:

          • 最后一格為 0 的 IP 地址。例如,192.168.10.0 允許 192.168.10 網(wǎng)絡(luò)上的任何機(jī)器與服務(wù)器通信。
          • 任何完全指定的 IP 地址。
          • 分解的 IP 地址。這是一種特殊模式,允許指定地址的網(wǎng)絡(luò)部分和以大括號(hào)擴(kuò)住的主機(jī)地址列表。例如,192.168.10.{5,6,7} 允許以下三個(gè)機(jī)器訪問(wèn)服務(wù)器:192.168.10.5、192.168.10.6 和 192.168.10.7。
          • 網(wǎng)絡(luò)掩碼 IP 地址。這是網(wǎng)絡(luò)管理員熟悉的一種地址。基于精確的位模式匹配規(guī)則(超出本文范圍),IP 地址與網(wǎng)絡(luò)掩碼相匹配。例如,192.168.255.255 允許 192.168.* 網(wǎng)絡(luò)中的所有地址訪問(wèn)服務(wù)器。
          • 準(zhǔn)確的 IPv6 地址。當(dāng)將來(lái)的 IP 網(wǎng)絡(luò)到來(lái)時(shí),Geronimo 將準(zhǔn)備好服務(wù),允許列出特定的 IP 地址。
          • 網(wǎng)絡(luò)掩碼 IPv6 地址。

          有 關(guān)服務(wù)器接受的特定模式的詳細(xì)信息,請(qǐng)咨詢?cè)创a文件 —— ServiceAccessController.java —— 位于來(lái)源的 openejb\modules\core\src\java\org\openejb\server 目錄中。在此將會(huì)找到與支持的每個(gè)地址類型相匹配的明確的正則表達(dá)式。

          對(duì) j2ee-server-plan.xml 文件進(jìn)行修改之后,重新編譯并更新服務(wù)器部署,您將具有一個(gè)專門滿足您需要的服務(wù)器。(如果只想查看針對(duì)同一機(jī)器上的服務(wù)器運(yùn)行的客戶端,則無(wú)需這樣做。默認(rèn)情況下,Geronimo 被配置來(lái)完成這些操作。)



          回頁(yè)首


          結(jié)束語(yǔ)

          本 文提供了一個(gè)構(gòu)建獨(dú)立(胖)客戶端的具體示例,該客戶端可以與運(yùn)行在 Geronimo 應(yīng)用服務(wù)器內(nèi)部的 EJB 應(yīng)用程序進(jìn)行對(duì)話。Geronimo 團(tuán)隊(duì)已經(jīng)認(rèn)真實(shí)現(xiàn)了健全的標(biāo)準(zhǔn),推廣用簡(jiǎn)單的 JNDI 查詢方法獲得與無(wú)狀態(tài)會(huì)話 bean 的遠(yuǎn)程連接。如果只想讓簡(jiǎn)單的應(yīng)用程序運(yùn)行,那么這是一個(gè)好消息,因?yàn)樗恍枰帉懮倭看a。

          按照我所介紹的模式,您能夠?qū)⒃S多比較大的 數(shù)據(jù)庫(kù)連接到與 Geronimo 服務(wù)器位于同一機(jī)器上的客戶端應(yīng)用程序。使用本文提供的指示,您還能夠配置 Geronimo 服務(wù)器以允許從連接到您的網(wǎng)絡(luò)或 Internet 上的其他機(jī)器訪問(wèn)服務(wù)器 EJB 端口。不妨嘗試一下。




          回頁(yè)首


          下載

          描述名字大小 下載方法
          Source code for the phonebook applicationPhonebookClient.zip227 KB  FTP
          關(guān)于下載方法的信息獲取 Adobe? Reader?


          回頁(yè)首


          參考資料



          回頁(yè)首


          關(guān)于作者

          作者照片

          Neal Sanche 是一位最近才涉足 Microsoft? .NET 世界的 Java 開(kāi)發(fā)人員,他正在克服困難脫離他原來(lái)習(xí)慣了的開(kāi)發(fā)環(huán)境。他的經(jīng)驗(yàn)包括開(kāi)發(fā)多個(gè)商業(yè) J2EE 應(yīng)用程序和多個(gè)獨(dú)立 Java 應(yīng)用程序。在業(yè)余時(shí)間,他作曲、攝影并撰寫技術(shù)文章。訪問(wèn)他的 Web 站點(diǎn) 可以看到相應(yīng)的多個(gè)示例。您可以通過(guò) neal@nsdev.org 與 Neal 聯(lián)系。

          posted on 2005-12-09 23:22 Dion 閱讀(1255) 評(píng)論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 萨迦县| 昭觉县| 建平县| 镇远县| 元氏县| 富民县| 奈曼旗| 巧家县| 吉水县| 华容县| 茌平县| 荣昌县| 密云县| 桃源县| 宿松县| 思茅市| 开封市| 仁寿县| 汝南县| 天台县| 宝坻区| 堆龙德庆县| 呈贡县| 通化市| 海原县| 沙田区| 普兰县| 胶南市| 新巴尔虎左旗| 德保县| 秀山| 建阳市| 普安县| 沂水县| 盈江县| 石景山区| 五常市| 九江市| 龙口市| 慈溪市| 栾川县|