佳木斯湛栽影视文化发展公司

主頁(yè) > 知識(shí)庫(kù) > XML到Java代碼的數(shù)據(jù)綁定之對(duì)象

XML到Java代碼的數(shù)據(jù)綁定之對(duì)象

熱門標(biāo)簽:銀行業(yè)務(wù) 阿里云 科大訊飛語(yǔ)音識(shí)別系統(tǒng) Linux服務(wù)器 Mysql連接數(shù)設(shè)置 服務(wù)器配置 電子圍欄 團(tuán)購(gòu)網(wǎng)站

  在這個(gè)由四部分組成的系列文章的第一部分,我們將弄清什么是數(shù)據(jù)綁定,與在 Java 應(yīng)用程序中處理 XML 數(shù)據(jù)的其它方法相比它有什么優(yōu)勢(shì),以及如何開始使用它。這一部分將考查為什么使用數(shù)據(jù)綁定,以及如何為各種約束建立模型,使 XML 文檔能轉(zhuǎn)換成 Java 對(duì)象。同時(shí)還涵蓋用于生成數(shù)據(jù)綁定類的輸入和輸出。

  您希望在您的 Java 應(yīng)用程序中使用 XML 嗎?那么好,同成千上萬(wàn)的其他人一起上這條船吧。當(dāng)您深入了解 XML 以后,也許您會(huì)發(fā)現(xiàn) DOM 和 SAX API(請(qǐng)參閱參考資料)不過是唬人的東西。您可能認(rèn)為肯定存在某種簡(jiǎn)單方法可以取得 XML 文檔,并通過 Java 應(yīng)用程序訪問它,對(duì)嗎?不必通過回調(diào)或復(fù)雜的樹狀結(jié)構(gòu),而是使用像 setOwner(Stringowner) 和 int getNumOrders() 這樣的方法,對(duì)嗎?如果您曾經(jīng)沿著這一思路考慮問題,那么數(shù)據(jù)綁定就是您要尋找的解決方案。

  分析各種選擇

  當(dāng)今各種 XML 和 XML 主義正泛濫成災(zāi)(XSL、RDF、命名空間、RSS、XML Schema、XSLT...),您可能認(rèn)為現(xiàn)在會(huì)有很多方法去訪問 Java 應(yīng)用程序中的 XML 數(shù)據(jù)。令人驚訝的是,如果您尋根究底,實(shí)際只存在三種訪問 XML 數(shù)據(jù)的方法。沒錯(cuò) -- 只有三種方法,其中的一種還是最近隨一種新的 Java API 才出現(xiàn)的。

  應(yīng)該這樣來(lái)看待這一問題:選擇范圍小使您更易于選出適合于您的方法。

  回調(diào)

  回調(diào)是作為一種事件驅(qū)動(dòng)模型工作的。當(dāng)分析 XML 文檔時(shí),某些事件 -- 如文檔的起始和某個(gè)元素中的字符數(shù)據(jù)的起始 -- 將觸發(fā)回調(diào)方法。通過使用執(zhí)行邏輯所需的數(shù)據(jù),您可以實(shí)現(xiàn)這些事件的 Java 代碼。要弄清這種方法不能全靠直覺;開發(fā)人員通常要花費(fèi)一段時(shí)間來(lái)理解和掌握回調(diào)模型的使用。SAX,用于 XML 的一種簡(jiǎn)單 API,是這種 XML 使用方法的事實(shí)上的標(biāo)準(zhǔn)。

  樹

  更常見、更流行的是這種 API,它們?nèi)〉靡粋€(gè) XML 文檔,然后創(chuàng)建數(shù)據(jù)的樹狀結(jié)構(gòu)。XML 文檔成為樹首,充當(dāng)一種容器。它有若干子級(jí),如根元素。根元素又有其附加的子級(jí),依此類推,直到(在某種意義上)獲得 XML 數(shù)據(jù)的一幅圖為止。因?yàn)閹缀趺總€(gè)大學(xué)生在某個(gè)階段肯定都處理過樹狀結(jié)構(gòu),所以這就可用作表示 XML 數(shù)據(jù)的一種非常直觀的方法。

  用于 XML 文檔樹狀表示的最流行的 API 就是 W3C 的推薦標(biāo)準(zhǔn),即文檔對(duì)象模型 (DOM)。一種更新的 API,JDOM (這不是首字母縮寫詞)最近也正一直在推廣并流行開來(lái)。(雖然這個(gè)方案是我和 Jason Hunter 建立的,但我還得說(shuō)實(shí)話。)另外,DOM 和 JDOM 都是 Spinnaker 方案設(shè)計(jì)的基本要求,Spinnaker 是一種新的 XML 分析器,它作為 Apache XML 方案的一部分正在開發(fā)之中。

  雖然樹狀 API 看起來(lái)比事件驅(qū)動(dòng)的 SAX 更易于使用,但它們并不總是合適的。非常大的文檔可能需要大量的內(nèi)存(尤其是使用 DOM 時(shí));當(dāng)對(duì)樹結(jié)構(gòu)執(zhí)行轉(zhuǎn)換 (XSLT) 時(shí),系統(tǒng)可能停止運(yùn)轉(zhuǎn)甚至徹底崩潰。雖然更新的 API(如 JDOM)能處理這些問題,但如果您必須處理極大量的數(shù)據(jù),它們?nèi)詫⑹且粋€(gè)問題。并且,有時(shí)開發(fā)人員寧愿將 XML 文檔中的數(shù)據(jù)建模為一個(gè)簡(jiǎn)單的帶有值的讀寫方法的 Java 對(duì)象,而不用樹狀模型工作。例如,開發(fā)人員會(huì)寧愿不去訪問名為 skuNumber 的子節(jié)點(diǎn)并設(shè)置該節(jié)點(diǎn)的文本值,而只想調(diào)用 setSkuNumber("mySKU") 并繼續(xù)進(jìn)行。


  用Java代碼訪問 XML 數(shù)據(jù)的最新方法要依賴于一套新的 Java 方法和相關(guān)的 API,這些 API 仍在開發(fā)之中。數(shù)據(jù)綁定是由 Sun 構(gòu)建的一種“Java 規(guī)范要求”(JSR-031,見參考資料),它設(shè)計(jì)用于使 Java 對(duì)象綁定到 XML 文檔更加方便,這樣就使一種格式能夠容易地轉(zhuǎn)換為另一種格式,反之亦然。綁定引用一個(gè)具有讀寫方法的 Java 對(duì)象,讀寫方法都會(huì)影響到底層的 XML 文檔,并且也都直接映射為 XML 文檔中的元素及特征的名稱。當(dāng)您進(jìn)入到本系列文章下一部分中的某些細(xì)節(jié)時(shí),這一說(shuō)明會(huì)更有意義,但在目前,只說(shuō)一點(diǎn)就夠了:這樣做使 XML 文檔特征 name 能夠通過一個(gè)稱為 setName() 的方法,來(lái)更改它的值,就像我上面暗示的那樣。

  數(shù)據(jù)綁定

  這種訪問方式正在得到普及,并且當(dāng)在 XML 文檔中存儲(chǔ)配置信息時(shí)特別有用。許多開發(fā)人員發(fā)現(xiàn),它非常便于直接訪問所需的參數(shù),而無(wú)須使用更復(fù)雜的樹狀結(jié)構(gòu)。雖然這種訪問對(duì)于文檔轉(zhuǎn)換或消息傳送沒有什么用處,但它對(duì)于簡(jiǎn)單數(shù)據(jù)處理是極其方便的。它是我們?cè)诒疚募氨鞠盗形恼轮嘘P(guān)注的第三種使用 XML 的方法。

 ?。ó?dāng)然,任何方法隨后都會(huì)引出一系列新的術(shù)語(yǔ),所以請(qǐng)查看術(shù)語(yǔ)解釋以了解這些新的行話。)

  是否任何 XML 文檔都可以轉(zhuǎn)換為 Java 對(duì)象?還是僅有某些類型的 XML 文檔才可以?問得好!您很可能只希望將滿足一組約束條件的文檔轉(zhuǎn)換為 Java 對(duì)象。這與定義 Java 接口的方法類似:您確保只實(shí)例化和使用適應(yīng)該接口的對(duì)象,允許就如何操作該對(duì)象作出假定。同樣,您只允許將滿足一組約束條件的 XML 對(duì)象轉(zhuǎn)換成 Java 對(duì)象;這使您能夠按希望的方式來(lái)使用所創(chuàng)建的對(duì)象。

   約束數(shù)據(jù)

  在研究代碼之前,您需要回答幾個(gè)有關(guān)如何表示 XML 數(shù)據(jù)的問題。這是數(shù)據(jù)綁定的最具挑戰(zhàn)性的方面之一。是為每個(gè)文檔創(chuàng)建一個(gè)新類,還是創(chuàng)建某個(gè)現(xiàn)有類的一個(gè)實(shí)例?您要使用哪個(gè)現(xiàn)有類?并且最重要的是,您正在處理的文檔是否適宜轉(zhuǎn)換為 Java 對(duì)象?

  那是一大堆問題,但您將在這里找到全部答案。將這些問題看作一系列決策點(diǎn),一系列選擇。首先,您必須確定您能否從該 XML 文檔創(chuàng)建 Java 對(duì)象(如前面所討論的那樣)。如果能,您就要決定轉(zhuǎn)換應(yīng)該以新 Java 類的形式出現(xiàn),還是僅以現(xiàn)有類的一個(gè)實(shí)例的形式出現(xiàn)。最后,如果選擇了現(xiàn)有類,那么使用哪個(gè)類呢?結(jié)果就是各種各樣的決策樹。

  如果我們考察清單 1 中所示的一個(gè)示例 XML 文檔,然后再來(lái)處理這些問題,則決策樹的意義就更加清楚了。此示例文檔表示 Enhydra Application Server 中某個(gè)服務(wù)(具體說(shuō)就是一個(gè) web 容器)的配置。

  清單 1. 一個(gè)用于配置 Enhydra 中的 web 容器的 XML 文檔 <?xml version="1.0"?>


  <webServiceConfiguration version="1.0" name="My Web Container" >
 ?。紁ort number="80" protocol="http" protected="false" />
  <document root="/usr/local/enhydra/html" index="*.html,*.xml" error="error.html" />
 ?。?webServiceConfiguration>


  此配置文檔包含有關(guān)服務(wù)本身的版本和名稱的信息,以及幾個(gè)嵌套的項(xiàng)目,每個(gè)項(xiàng)目都表示有關(guān)該 web 容器服務(wù)的一些附加信息。它給出了有關(guān)端口的詳細(xì)信息(包括端口號(hào)、協(xié)議和安全性),也給出了文檔服務(wù)信息(包括文檔根、用于索引頁(yè)的默認(rèn)擴(kuò)展名以及錯(cuò)誤頁(yè))。所有這些合在一起,就是配置一個(gè)新的 web 容器服務(wù)所需的全部信息。

  記住這個(gè)示例,您就可以開始回答數(shù)據(jù)表示的各個(gè)問題了。

  是否適合轉(zhuǎn)換?

  絕對(duì)適合!只要看一看清單 1 中的 XML 文檔就會(huì)發(fā)現(xiàn),它表示一個(gè)對(duì)象(總體配置對(duì)象),具有若干特征或變量。其中某些變量又是另外的對(duì)象(端口和文檔),這些對(duì)象又具有它們自己的特征。實(shí)際上,這是適合轉(zhuǎn)換為 Java 對(duì)象的 XML 文檔的一個(gè)極好例子。為了進(jìn)一步保證此對(duì)象是可用的,稍后我將向您展示一種方法來(lái)約束文檔中的數(shù)據(jù)。但是,還是先讓我們繼續(xù)沿著決策樹往下走。

  轉(zhuǎn)換成類還是實(shí)例?

  解決適宜性問題以后,現(xiàn)在就可以作出決定,是將每個(gè) XML 配置文檔都變?yōu)橐粋€(gè)全新的 Java 類呢,還是簡(jiǎn)單地將其變?yōu)槟硞€(gè)現(xiàn)有類的一個(gè)新實(shí)例。換句話說(shuō),就是到底應(yīng)該生成新代碼,還是利用現(xiàn)有的代碼。照這樣來(lái)看,這就變成了一個(gè)簡(jiǎn)單的可重用性問題。更容易且更明智的做法是,為每個(gè) XML 文檔生成現(xiàn)有類的新實(shí)例。如果您一定要嘗試一下從每個(gè)文檔創(chuàng)建一個(gè)新的 Java 類,則得到的各個(gè)類之間可能沒有兼容性 -- 即兩個(gè)完全相同的文檔可能導(dǎo)致兩個(gè)不同的 Java 類!

  不用這個(gè)可能引起混亂的方法,您可以采用一組 XML 約束條件(由一個(gè) DTD 或 XML 方案表示,將在下面講述),并根據(jù)這些約束條件來(lái)生成一個(gè) Java 類(或多個(gè)類,根據(jù)需要)。這個(gè)生成的類將表示符合這些約束條件的任何 XML 文檔;這些 XML 文檔中的每一個(gè)都將被解包到生成的類的一個(gè)實(shí)例中。在這種情況下,就可以為表示 web 服務(wù)配置的文檔定義約束條件。這些約束條件將被映射為一個(gè) Java 類,我們將稱之為 WebServiceConfiguration。然后您就可以獲得任何一種表示特定 web 服務(wù)配置的 XML 文檔,并假定此文檔符合我們的約束條件,由它而創(chuàng)建出前面生成的類的一個(gè)實(shí)例。這將允許應(yīng)用程序?qū)⒉煌?XML 文檔用作相同類型的對(duì)象,只要這些文檔中的數(shù)據(jù)對(duì)于該對(duì)象設(shè)計(jì)時(shí)要達(dá)到目的來(lái)說(shuō)是有效的即可。

  新類還是現(xiàn)有的類?

  現(xiàn)在您也已經(jīng)有條件回答下一個(gè)問題了:您希望創(chuàng)建一個(gè)現(xiàn)有類即 WebServiceConfiguration 類的一個(gè)實(shí)例。剩下需要弄清的全部事情是,這個(gè)類是如何預(yù)先生成的。所以,現(xiàn)在請(qǐng)將您的注意力集中在這樣一個(gè)問題上:如何獲得一組約束條件,用 XML 實(shí)現(xiàn)它們,并保證文檔符合這些約束?再一個(gè)問題就是,您如何再?gòu)倪@些約束條件生成一個(gè)可重用的 Java 類?

  利用文檔約束條件

  既然您知道此文檔將轉(zhuǎn)換成一個(gè) Java 實(shí)例,這就產(chǎn)生了另一個(gè)問題:要考慮到必須以某種方式保證可將此文檔正確地解包到一個(gè)選定的 Java 類中。缺少變量或數(shù)據(jù)類型不正確都可能導(dǎo)致在解包過程中出錯(cuò) -- 或者甚至在客戶機(jī)訪問配置錯(cuò)誤的容器時(shí)出現(xiàn)運(yùn)行時(shí)異常。

  最好的情況是,在實(shí)際的解包過程開始之前,文檔的作者能夠保證,配置文檔對(duì)于他們選擇用來(lái)表示數(shù)據(jù)的類是“合法的”。閱讀到這一方案的 XML 人士說(shuō)不定就會(huì)轉(zhuǎn)動(dòng)他們的眼睛并嘀咕說(shuō),“好吧,當(dāng)然您將使用 XML 文檔約束條件?!贝_認(rèn)數(shù)據(jù)對(duì)選定類的合法性可以通過引用 DTD (文檔類型定義)或 XML 方案來(lái)完成。

  通過使用一組用外部 DTD 或方案文件表示的約束條件,文檔作者就可以在這些數(shù)據(jù)的“接口”上測(cè)試配置數(shù)據(jù)。換句話說(shuō),您可以這樣來(lái)建立應(yīng)用程序,使之能夠?qū)φ账璧臄?shù)據(jù)來(lái)檢查包含在 XML 實(shí)例文檔中的數(shù)據(jù),而所需數(shù)據(jù)則是在文檔約束條件的外部文件中指定的。這樣,您就可以為數(shù)據(jù)創(chuàng)建一個(gè)接口。

  在使用 DTD 方案還是使用 XML 方案之間作出決策是一種相當(dāng)簡(jiǎn)單的選擇:因?yàn)?Java 語(yǔ)言是高度類型化的,所以我們希望能在 XML 文檔中支持類型化。例如,數(shù)據(jù)接口應(yīng)該能夠驗(yàn)證,為web容器的端口號(hào)提供的是整數(shù),而不是字符串,后者在服務(wù)啟動(dòng)時(shí)將引起錯(cuò)誤。DTD 不支持類型檢查,所以我們無(wú)疑應(yīng)該選擇XML方案。雖然XML方案在規(guī)范的領(lǐng)域在有一點(diǎn)不確定性,但它在很大程度上已趨于穩(wěn)定,并可望在年內(nèi)定型。我們可以在一個(gè)XML方案中編寫數(shù)據(jù)約束條件,然后用這個(gè)方案驗(yàn)證可能的實(shí)例文檔,以確保解包能在這些實(shí)例文檔上進(jìn)行。下面的 XML 方案表示我們的web容器服務(wù)的數(shù)據(jù)接口。

  清單 2. 表示一個(gè) web 容器配置文檔的數(shù)據(jù)接口的 XML 方案 <?xml version="1.0"?>


 ?。約chema targetNamespace="http://www.enhydra.org" xmlns="http://www.w3.org/1999/xmlSchema" xmlns:enhydra="http://www.enhydra.org" >

 ?。糲omplexType name="ServiceConfiguration">
  <attribute name="name" type="string" />
 ?。糰ttribute name="version" type="float" />
 ?。?complexType>


  <element name="serviceConfiguration" type="ServiceConfiguration" />

 ?。糲omplexType name="WebServiceConfiguration" baseType="ServiceConfiguration" derivedBy="extension">
 ?。糴lement name="port">
 ?。糲omplexType>
 ?。糰ttribute name="protocol" type="string" />
  <attribute name="number" type="integer" />
 ?。糰ttribute name="protected" type="string" />
 ?。?complexType>
 ?。?element>

 ?。糴lement name="document">
  <complexType>
 ?。糰ttribute name="root" type="string" />
  <attribute name="index" type="string" />
 ?。糰ttribute name="error" type="string" />
 ?。?complexType>
  </element>
 ?。?complexType>

  <element name="webServiceConfiguration" type="WebServiceConfiguration" />

 ?。?schema>


  清單 2 中的 XML 方案定義了幾個(gè)不同的數(shù)據(jù)對(duì)象,它們合起來(lái)表示一個(gè) web 服務(wù)的配置對(duì)象。首先,定義了一個(gè)核心服務(wù)配置(serviceConfiguration),它包含版本和名稱。這可用作所有服務(wù)(如負(fù)載均衡服務(wù)、EJB 容器,當(dāng)然還有我們的 web 服務(wù))的基本對(duì)象。然后,作為此基本服務(wù)的擴(kuò)展,又定義了 web 服務(wù)配置(webServiceConfiguration)。請(qǐng)注意,Java 成型之后,方案就已經(jīng)為數(shù)據(jù)接口建立了模型。我們將附加的 web 服務(wù)屬性 port 和 document 添加到 version 和 name 基本屬性中。這些屬性本身都是對(duì)象,具有它們自己的屬性(protocol、root、error 等)。

  在此方案的定義方式中,特征代表簡(jiǎn)單的 Java 類型,通常是原始 (primitive) 類型。這樣,name 和 version 就分別成為類型 String 和 float 的 Java 原始類型。port 和 document 這樣的元素成為 Java 對(duì)象,它們可以有自己的屬性,還是用特征來(lái)表示。這樣就出現(xiàn)了遞歸現(xiàn)象:元素變成新對(duì)象,并對(duì)它的每個(gè)屬性進(jìn)行檢查。如果屬性是一個(gè)特征,就為此對(duì)象創(chuàng)建一個(gè)簡(jiǎn)單的 Java 原始成員變量;如果屬性是元素,則創(chuàng)建一個(gè)新的對(duì)象,并作為一個(gè)成員變量將其添加,然后在這個(gè)新對(duì)象上又開始同樣的過程,直到全部類都已創(chuàng)建為止。
   從蘿卜 ... 嗯 ... XML 獲得 Java

  一旦創(chuàng)建了 XML 方案,您就需要從這個(gè)方案中提取出必需的信息,來(lái)確定應(yīng)該創(chuàng)建哪些 Java 類。這個(gè)過程的第一步是查看 XML 方案,并嚴(yán)格確定輸出應(yīng)該是什么。對(duì)于簡(jiǎn)單的 serviceConfiguration 對(duì)象,定義了兩個(gè) Java 原始屬性:name 和 version。對(duì)于這樣一個(gè)簡(jiǎn)單的對(duì)象,確定所需的接口并不難。只需將被定義類型的名稱的首字母大寫,并將這些 Java 屬性添加到接口中即可,如清單 3 所示。

  清單 3. 為 ServiceConfiguration 接口而從 XML 方案生成的 Java 代碼 public interface

  ServiceConfiguration {
  public void setVersion(float version);
  public float getVersion();
  public void setName(String name);
  public String getName();
  }

   這是相當(dāng)明白易懂的;清單 3 中的接口為 XML 方案中定義的屬性提供讀方法和寫方法。另外,您將需要生成一個(gè)實(shí)現(xiàn)類來(lái)定義此接口的各個(gè)成員變量,并實(shí)現(xiàn)此接口中的每個(gè)方法。這種使接口從實(shí)現(xiàn)中分離出來(lái)的方法使我們能夠?yàn)樘囟ǖ男枰嶂泄┒喾N實(shí)現(xiàn)。 例如,某個(gè)特定的服務(wù)可能需要執(zhí)行計(jì)算,而不只是接受從寫方法中收到的值?,F(xiàn)在考慮那種更復(fù)雜的情況還有點(diǎn)為時(shí)尚早,但我將在后續(xù)文章中重新提到它。然而,一般說(shuō)來(lái),您仍可以確定實(shí)現(xiàn)類應(yīng)該像什么樣子,如清單 4 所示。

  清單 4. 為 ServiceConfiguration 實(shí)現(xiàn)而從 XML 方案生成的 Java 代碼 public class

  ServiceConfigurationImpl implements ServiceConfiguration {
  private String name;
  private float version;

  public void setVersion(float version) {
  this.version = version;
  }

  public float getVersion() {
  return version;
  }

  public void setName(String name) {
  this.name = name;
  }

  public String getName() {
  return name;
  }
  }

  相同的原則也適用于 XML 方案中定義的其它對(duì)象。您可以在下面查看到其它 Java 類(因?yàn)樗鼈兌际菓?yīng)該生成的):

  PortType.java
  PortTypeImpl.java
  DocumentType.java
  DocumentTypeImpl.java
  WebServiceConfiguration.java
  WebServiceConfigurationImpl.java

  總結(jié)

  到目前為止,您應(yīng)該對(duì)數(shù)據(jù)綁定的各個(gè)方面都比較熟悉了。我已初步介紹了您應(yīng)該使用數(shù)據(jù)綁定的原因,尤其是在配置信息的范圍內(nèi),并概述了為實(shí)現(xiàn)此方法您所需要了解的一些基本概念。

您可能感興趣的文章:
  • 將Java對(duì)象序列化成JSON和XML格式的實(shí)例
  • Java對(duì)象的XML序列化與反序列化實(shí)例解析
  • xml與Java對(duì)象的轉(zhuǎn)換詳解
  • 通過實(shí)例學(xué)習(xí)JAVA對(duì)象轉(zhuǎn)成XML輸出

標(biāo)簽:萍鄉(xiāng) 衢州 棗莊 江蘇 大理 蚌埠 廣元 衡水

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《XML到Java代碼的數(shù)據(jù)綁定之對(duì)象》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    瓮安县| 上思县| 北碚区| 赫章县| 雷州市| 东安县| 德安县| 黄浦区| 磐石市| 扎鲁特旗| 台中市| 库伦旗| 泾源县| 靖西县| 延津县| 兴海县| 邵阳县| 离岛区| 柘荣县| 略阳县| 曲阳县| 南召县| 贵定县| 天长市| 望奎县| 新营市| 巴林右旗| 墨江| 巍山| 绥化市| 新安县| 云安县| 辽宁省| 宁海县| 鄂温| 全南县| 西藏| 镇安县| 宜州市| 湛江市| 八宿县|