Velocity空間

          快速構(gòu)建JAVA應(yīng)用
          隨筆 - 11, 文章 - 15, 評論 - 5, 引用 - 0
          數(shù)據(jù)加載中……

          CHAPTER 11 Velocity、XML和 Anakia

          可擴(kuò)展標(biāo)記語言(XML)是過去幾年里談?wù)摰米疃嗟募夹g(shù)。剛開始的時候,這個技術(shù)的潛能可能被夸大了。但不要懷疑它基于文本格式來表現(xiàn)數(shù)據(jù)的能力。在這一章里,我們將著眼于兩個XML主題,以及考慮這兩個主題是如何涉及到Velocity的:從Velocity模板里的DOM對象訪問XML數(shù)據(jù)和使用Anakia來處理XML數(shù)據(jù)轉(zhuǎn)換。

          Velocity模板里訪問XML

          你大概知道,Sun正努力為Java開發(fā)者提供一個處理XML數(shù)據(jù)的工具。起初,XML只得到很少的支持,一些如JDOM(一個開源API)、XercesApache軟件基金組織提供)的產(chǎn)品被用于向開發(fā)者提供處理XML數(shù)據(jù)的能力。很快,SunJava 1.3里提供了支持XML的附加包,在Java 1.4版本里,SunXML支持直接構(gòu)建到語言里。

          如果你想在你的Velocity模板里使用XML,你需要在控制器Java類里處理XML文件,并且需要向上下文對象中附加必需的信息。現(xiàn)在,讓我們來看一示例。首先看一下Listing 11.1里的XML文件。目的是為了讓Velocity控制器能夠讀取這個XML文件,并且將其解析到一個對象里,以便得到Velocity模板的支持。Listing 11.2顯示了控制器處理這個XML文件的示例。

          <?xml version="1.0"?>

          <cds>

          <cd>

          <title>2112</title>

          <artist>Rush</artist>

          </cd>

          </cds>

          Listing 11.1 An XML document.

          import java.util.Vector;

          import javax.servlet.http.*;

          import org.apache.velocity.Template;

          import org.apache.velocity.context.Context;

          import org.apache.velocity.servlet.VelocityServlet;

          import org.apache.velocity.exception.*;

          import org.apache.xerces.parsers.*;

          public class VelocityServletExample extends VelocityServlet {

          public Template handleRequest( HttpServletRequest request,

          HttpServletResponse response,

          Context context ) {

          try {

          SAXBuilder builder = new SAXBuilder(

          "org.apache.xerces.parsers.SAXParser" );

          Document root = builder.build("cds.xml");

          VelocityContext context = new VelocityContext();

          context.put("root", root );

          } catch(Exception e){

          e.printStackTrace();

          }

          Template template = null;

          try {

          template = getTemplate("displayxml.vm");

          } catch( Exception e ) {

          System.out.println("Error " + e);

          }

          return template;

          }

          }

          Listing 11.2 The Velocity controller.

          在這里,Listing 11.2里的Servlets和任何一個你在前面章節(jié)里看到的Servlets控制器類似。唯一的改變只涉及XML文件。我們假定這個在Listing 11.1里的XML被保存在一個名叫cds.xml的文件里,并且它和Servlets在同上目錄。

          第一個任務(wù)是把這個文檔放到應(yīng)用程序里,并把它解析到一個你很容易操作的格式。如果你熟悉XML處理的話,你應(yīng)該知道這里有兩條主要的途徑來把這個基于文本的XML文檔解析到數(shù)據(jù)結(jié)構(gòu),以便在應(yīng)用程序里能夠使用,這兩條途徑是:SAXDOM。最后,采用哪種方法對你來說并不是難事,然而SAX比較適合用處理大型文檔。

          在這里,我們選擇使用Xerces里的SAXParser類作為這個示例的控制器。Xerces是一個XML解析包,是Apache旗下的一個產(chǎn)品,你可以在http://xml.apache.org/xerces2-j/index.html下找到它。使用Xerces相當(dāng)容易。首先,初始化一個新的SAXBuilder對象,并指定你想要使用的Xerces家族中的一個解析器。正如你在Listing 11.2看到的一樣,我們使用了SAXParser類。這個SAXBuilder類允許你傳遞原始(raw)XML并返回一個文檔對象。這個文檔對象是一個用XML表示的數(shù)據(jù)結(jié)構(gòu)。這點(diǎn)非常重要,因?yàn)槟阒溃魏螌ο箢愋涂梢员患尤氲?/span>Velocity上下文里,并能夠?qū)⑺鼈鬟f給模板。

          在這些代碼里,你通過名叫“root”的引用把XML數(shù)據(jù)結(jié)構(gòu)附加到上下文里。接著,控制器通過調(diào)用displayxml. vm加載模板,并且返回模板給VelocityServlet進(jìn)行處理。這個displayxml.vm(見Listing 11.3)完成了所有的輸出工作。

          <html>

          <body>

          CD title is $root.getChild("cds").getChild("cd").getChild("title").get-

          Text()

          CD artist is $root.getChild("cds").getChild("cd").getChild("artist").get-

          Text()

          </body>

          </html>

          Listing 11.3 The displayxml.vm template file.

          Listing 11.3的模板被設(shè)計(jì)用于放置來自控制器處理XML后產(chǎn)生的文章和標(biāo)題數(shù)據(jù)。正如你看到的一樣,你正在使用一個普通的XML方法去訪問數(shù)據(jù)結(jié)構(gòu)里面的數(shù)據(jù)。因?yàn)?/span>Velocity可以讓你完全訪問上下文里的對象,你可以使用在Document類或其父類節(jié)點(diǎn)里定義的任何方法。

          例如,你可以使用(帶有所有<cd>元素)的getChildNodes()方法來返回一個NodeList(節(jié)點(diǎn)列表)對象,也就是“NodeList list = $root.getChild (“cds”).getChildNodes();”。現(xiàn)在,你就可以使用#foreach指令來遍歷節(jié)點(diǎn),并且顯示他們每一個節(jié)點(diǎn)的信息。

          VelocityAnakia

          我們剛才描述的處理過程其實(shí)是Anakia項(xiàng)目(支持Velocity的部分)的一個功能庫。Anakia是一個Ant任務(wù),用于把XML轉(zhuǎn)換到一個你選擇好的輸出介質(zhì),以用于代替Velocity模擬的擴(kuò)展層疊語言(XSL)。Ant任務(wù)代碼可以在org.apache.velocity.anakia.AnakiaTask類里找到,同時你也可以在/examples/anakia目錄下找到一個完整的示例。

          The Ant Build Task

          你在自行嘗試之前,讓我們看一個示例。我們之前曾經(jīng)提及,Anakia基本上是一個Ant任務(wù),用于合并Velocity模板和XML文檔。這個Ant任務(wù)代碼見Listing 11.4。

          <project name="build-site" default="docs" basedir=".">

          <property name="docs.src" value="../xdocs"/>

          <property name="docs.dest" value="../docs"/>

          <target name="prepare">

          <available classname="org.apache.velocity.anakia.AnakiaTask"

          property="AnakiaTask.present"/>

          </target>

          <target depends="prepare" name="prepare-error"

          unless="AnakiaTask.present">

          <echo>

          AnakiaTask is not present! Please check to make sure that

          velocity.jar is in your classpath.

          </echo>

          </target>

          <target name="docs" depends="prepare-error" if="AnakiaTask.present">

          <taskdef name="anakia" classname="org.apache.velocity.anakia.AnakiaTask"/>

          <anakia basedir="${docs.src}" destdir="${docs.dest}/"

          extension=".html" style="./site.vsl"

          projectFile="./stylesheets/project.xml"

          excludes="**/stylesheets/**"

          includes="**/*.xml"

          lastModifiedCheck="false"

          velocityPropertiesFile="velocity.properties">

          </anakia>

          <copy todir="${docs.dest}/images" filtering="no">

          <fileset dir="${docs.src}/images">

          <include name="**/*.gif"/>

          <include name="**/*.jpeg"/>

          <include name="**/*.jpg"/>

          </fileset>

          </copy>

          </target>

          </project>

          Listing 11.4 The Anakia Ant task.

          這個Ant任務(wù)首先嘗試定位AnakiaTask類,同時設(shè)置源和目的文件的目錄。在這個示例里,/xdocs目錄用于容納源文件,/docs目錄用于容納目的文件。表11.1解釋了這個Ant任務(wù)的每一個元素。


          Table 11.1
          Anakia Ant Task Definitions

           

          源文檔

          示例程序包含了一兩個源文檔。第一個叫index.xml,在/xdocs目錄,見Listing 11.5;第二個也叫index.xml,在/xdocs/about目錄下,它將被用于根層index文檔的鏈接。

          <?xml version="1.0" encoding="UTF-8"?>

          <document>

          <properties>

          <author email="jon@latchkey.com">Jon S. Stevens</author>

          <title>The Jakarta Project</title>

          </properties>

          <body>

          <section name="Section 1">

          <p>This is an example template that gets processed.</p>

          <img src="/images/velocity.gif" width="329" height="105"/>

          <table border="1">

          <tr>

          <td>It even has a table in it!</td>

          </tr>

          </table>

          <h3>And an h3 tag</h3>

          </section>

          <section name="Section 2">

          <p> here is another section </p>

          </section>

          <section name="section 3">

          <p>

          <a href="./about/index.html">A link to a sub page</a>

          </p>

          </section>

          </body>

          </document>

          Listing 11.5 The index.xml source document.

          Listing 11.5里的XML文檔提供了一個你將用于Velocity模板的信息。正如你看見的一樣,它包括傳統(tǒng)的HTML標(biāo)記和用戶自定義標(biāo)記。當(dāng)Anakia Ant任務(wù)合并這兩個文檔時,這些用戶自定義標(biāo)記將靠著(againstVelocity模板進(jìn)行匹配。注意,在頁面里有一個指向index.html的鏈接。

          在某些情況下,你或許想要有一個描述導(dǎo)航的項(xiàng)目文件。該項(xiàng)目文件看來起來和下面的代碼類似。當(dāng)處理projectFile時,<menu>元素被用作頁面左邊部分的導(dǎo)航菜單里的實(shí)體。

          <?xml version="1.0" encoding="ISO-8859-1"?>

          <project name="Jakarta Site"

          >

          <title>Jakarta Site</title>

          <body>

          <menu name="Home">

          <item name="Front Page" href="/index.html"/>

          </menu>

          <menu name="About">

          <item name="About" href="/about/index.html"/>

          </menu>

          </body>

          </project>

          現(xiàn)在,讓我們來看一下Velocity模板里的這些標(biāo)記將要產(chǎn)生什么結(jié)果。

          Anakia Velocity Stylesheets

          Listing 11.6是一個示例模板,用于處理Listing 11.5index.xml文件。這個模板使用了許多我們曾經(jīng)學(xué)習(xí)的Velocity特性,包括和宏。讓我們遍歷發(fā)生在模板里的處理過程。首先讓我們來關(guān)注一下Anakia自動為模板提供的不同上下文引用。我們將在下一節(jié)討論變量。為了理解這個模板,你必須熟悉以下這些引用:

          $xpath所提供的XML的節(jié)點(diǎn)列表

          $root所解析的XML的根

          $project項(xiàng)目文件的根

          模板從用于模板自身的本地定義開始,接著,一個名叫document()的方法用于產(chǎn)生宏。模板基本上由許多不同的宏構(gòu)成,每一個都用于輸出XML文件特定的部分,以用于它的HTML呈現(xiàn)。Anakia Ant任務(wù)不了解模板文件里的宏,因此,必須從他們中的一個調(diào)用開始。在這種情況下,document()宏定義了主要的HTML輸出部分。

          document()宏的代碼中可以看到,和在大多數(shù)Web頁面一樣,該代碼由所有主要的HTML標(biāo)記組成。第一個不同之處在<title>元素,標(biāo)題的值由以下代碼獲得:

          $root.getChild("properties").getChild("title").getText()

          這個代碼使用$root引用并通過該引用的子節(jié)點(diǎn)標(biāo)題來查找屬性元素,這個$root引用是在Velocity上下文里構(gòu)建的,與你打算用于模板輸入的XML文檔相關(guān)。它通過標(biāo)題元素獲得文本,并在新創(chuàng)建的頁面中將這個文本輸出?;仡櫼幌?/span>XML數(shù)據(jù),你可以發(fā)現(xiàn)通過getText()調(diào)用的輸出將是“The Jakarta Project”。接著,這個宏開始在這個頁面上創(chuàng)建一個表。表的左面部分是一個導(dǎo)航菜單,右面部分顯示了輸入的XML信息(如果你回憶一下就可以知道,這個導(dǎo)航菜單是由之前討論的projectFile構(gòu)建的)。

          為了構(gòu)建導(dǎo)航菜單,document()調(diào)用了makeProject()宏。這個makeProject()宏從項(xiàng)目XML里找到所有的菜單成員,并且按次序把他們輸出到一個列表中。當(dāng)makeProject()宏運(yùn)行結(jié)束,控制將返回到document()宏。

          document()宏創(chuàng)建的表的左面部分由所有輸入的XML元素組成。這些元素的不同部分被提?。?/span>extract),同時提取從子元素中提取出信息,用于產(chǎn)生表的信息。最后,所有HTML關(guān)閉標(biāo)記被輸出,從而產(chǎn)生一個完整的頁面,見Listing 11.7Figure 11.1顯示了最后的Web頁面在瀏覽器里的樣子。

          ## Defined variables

          #set ($bodybg = "#ffffff")

          #set ($bodyfg = "#000000")

          #set ($bodylink = "#525D76")

          #set ($bannerbg = "#525D76")

          #set ($bannerfg = "#ffffff")

          #set ($tablethbg = "#039acc")

          #set ($tabletdbg = "#a0ddf0")

          <!-- start the processing -->

          #document()

          <!-- end the processing -->

          ## This is where the macros live

          #macro ( makeProject )

          #set ($menus = $xpath.applyTo("body/menu", $project))

          #foreach ( $menu in $menus )

          <strong>$menu.getAttributeValue("name")</strong>

          <ul>

          #foreach ( $item in $menu.getChildren() )

          #set ($name = $item.getAttributeValue("name"))

          <li>

          #projectanchor($name $item.getAttributeValue("href"))

          </li>

          #end

          </ul>

          #end

          #end

          #macro ( image $value )

          #if ($value.getAttributeValue("width"))

          #set ($width=$value.getAttributeValue("width"))

          #end

          #if ($value.getAttributeValue("height"))

          #set ($height=$value.getAttributeValue("height"))

          #end

          #if ($value.getAttributeValue("align"))

          #set ($align=$value.getAttributeValue("align"))

          #end

          <img src="$relativePath$value.getAttributeValue("src")"

          width="$!width" height="$!height" align="$!align">

          #end

          #macro ( projectanchor $name $value )

          <a href="$relativePath$value">$name</a>

          #end

          #macro ( metaauthor $author $email )

          <meta name="author" value="$author">

          <meta name="email" value="$email">

          #end

          #macro (document)

          <html>

          <head>

          <title>

          $root.getChild("properties").getChild("title").getText()

          </title>

          </head>

          <body bgcolor="$bodybg" text="$bodyfg" link="$bodylink">

          <table border="1">

          <tr>

          <td>#makeProject()</td>

          <td>

          #set ($allSections = $xpath.applyTo("body/section",

          $root))

          #foreach ( $section in $allSections )

          #foreach ( $item in $section.getChildren() )

          #if ($item.getName().equals("img"))

          #image ($item)

          #else

          $xmlout.outputString($item)

          #end

          #end

          #end

          </td>

          </tr>

          </table>

          </body>

          </html>

          #end

          Listing 11.6 The example stylesheet.

          <!-- Content Stylesheet for Site -->

          <!-- start the processing -->

          <!--================== -->

          <!-- Main Page Section -->

          <!--================== -->

          <html>

          <head>

          <meta http-equiv="Content-Type"

          content="text/html; charset=iso-8859-1"/>

          <meta name="author" value="Jon S. Stevens">

          <meta name="email" value="jon@latchkey.com">

          <title>The Jakarta Project</title>

          </head>

          <body bgcolor="#ffffff" text="#000000" link="#525D76">

          <table border="1">

          <tr>

          <td>

          <strong>Home</strong>

          <ul>

          <li> <a href="./index.html">Front Page</a></li>

          </ul>

          <strong>About</strong>

          <ul>

          <li> <a href="./about/index.html">About</a></li>

          </ul>

          </td>

          <td>

          <p>

          This is an example template that gets processed.

          </p>

          <img src="./images/velocity.gif" width="329"

          height="105" align="">

          <table border="1">

          <tr>

          <td>

          It even has a table in it!

          </td>

          </tr>

          </table>

          <h3>And an h3 tag</h3>

          <p> here is another section </p>

          <p><a href="./about/index.html">A link to a sub page</a></p>

          </td>

          </tr>

          </table>

          </body>

          </html>

          <!-- end the processing -->

          Listing 11.7 The completed Web page.

           


          Figure 11.1
          The Web page output.

          上下文引用

          當(dāng)Anakia Ant任務(wù)合并XML和模板時,它為上下文增加了一些引用,以便Velocity模板可以使用數(shù)據(jù)進(jìn)行工作。你已經(jīng)看到了一些將要進(jìn)入上下文里的對象。表11.2描述了所有可能的對象。


          Table 11.2
          Anakia Context References

          注意帶有任何元素引用的XPath表達(dá)式。比如,你可以用$root.selectNodes(“cds/cd”)來獲得一個和<cd>元素類型匹配的節(jié)點(diǎn)列表。

          Velocity輸出XML

          如果在你擁有一些存儲在數(shù)據(jù)庫或通過Servlets應(yīng)用程序產(chǎn)生的數(shù)據(jù),那么你可能會遇到一種情形,那就是你想要輸出XML給用戶,不管是通過瀏覽器還是通過下載文件。這里有一個在之前章節(jié)里開發(fā)的CD應(yīng)用程序示例,這個應(yīng)用程序提供了增加CD和記錄查詢數(shù)據(jù)庫操作功能。你即可查詢一條單獨(dú)的文章,也可顯示特定CD的歌曲(track)信息。你極有可能想生成一個XML格式的輸出,現(xiàn)在就來看一看如何來實(shí)現(xiàn)。

          在這個部分,讓我們考慮兩個不同的情形:XML用于文章查詢和XML用于數(shù)據(jù)里所有CDs的報(bào)表。

          文章XML查詢

          你回憶一下就可以發(fā)現(xiàn),我們的CD應(yīng)用程序利用一個Servlets控制來解釋主屏上的不同提交按鈕。在文章查詢窗體里,提交按鈕調(diào)用這個Servlets控制,并向其傳遞得到的值。Servlets執(zhí)行的代碼見Listing 11.8。

          else if (req.getParameter("submit").equals("obtain")) {

          try {

          if (cdHome == null) {

          context.put("message", "Sorry we had an error");

          } else {

          Collection cds = cdHome.findByArtist(req.getParameter("artist"));

          context.put ("cds", cds);

          try {

          template = getTemplate("displaycds.vm");

          } catch( Exception e ) {

          e.printStackTrace();

          }

          }

          } catch(Exception e) {

          e.printStackTrace();

          }

          }

          Listing 11.8 The artist query code.

          非常簡單,代碼使用CD Bean調(diào)用了一個查詢,返回的集合通過Velocity模板displaycds.vm進(jìn)行顯示。讓我們改動一下代碼來提交obtainxml的值,其作用是從數(shù)據(jù)庫中取出相同的信息。然而,我們用的不是displaycds.vm模板,而用的是producecdxml. vm模板。新代碼見Listing 11.9。

          else if ((req.getParameter("submit").equals("obtain")) ||

          (req.getParameter("submit").equals("obtainxml"))) {

          try {

          if (cdHome == null) {

          context.put("message", "Sorry we had an error");

          } else {

          Collection cds = cdHome.findByArtist(req.getParameter("artist"));

          context.put ("cds", cds);

          try {

          if (req.getParameter("submit").equals("obtainxml")) {

          template = getTemplate("producecdxml.vm");

          } else {

          template = getTemplate("displaycds.vm");

          } catch( Exception e ) {

          e.printStackTrace();

          }

          }

          } catch(Exception e) {

          e.printStackTrace();

          }

          }

          Listing 11.9 The artist query code with XML output.

          正如你看到的一樣,要相進(jìn)入這個代碼塊,需要把“obtain”或“obtainxml”提交按鈕的值傳遞到Servlets才行。所有相同的CD將從查詢中返回,但依賴于提交的值,不管是用producecdxml. vm還是用displaycds.vm Velocity模板。為了使用這些代碼,首先你得定義producec dxml.vm,代碼見Listing 11.10

          <?xml version="1.0" ?>

          <cds>

          #foreach($value in $cds)

          <cd id="$value.id">

          <title>$value.title</title>

          </cd>

          #end

          </cds>

          Listing 11.10 The producecdxml.vm Velocity template.

          Listing 11.10里的Velocity模板為文章查詢產(chǎn)生一個XML文件。要注意,CDID和標(biāo)題是如何作為屬性和元素被分別捕獲的。

          完整CD XML報(bào)表

          在之前的示例里,所有的輸出都產(chǎn)生在用戶瀏覽器上。你是否想過去下載一個包含所有數(shù)據(jù)庫里CD信息的XML文件?其實(shí)只需要改變一點(diǎn)代碼就可以實(shí)現(xiàn)這個愿望。讓我們在CD主頁面加一個按鈕,用于調(diào)用Servlets控制器來請求一個完整的CD數(shù)據(jù)庫報(bào)表。代碼如下:

          <form action="http://localhost:8080/cd/cdVelocityHandler" method="post">

          <input type="submit" name="submit" value="fullreport"> -

          download 'report.txt' to your local system

          </form>

          當(dāng)用戶單擊FullReport按鈕時,控制被傳遞到Servlets,在這里fullreport值將進(jìn)行驗(yàn)證。Listing 11.11的是之后將要執(zhí)行的代碼。

          else if (req.getParameter("submit").equals("fullreport")) {

          try {

          if (cdHome == null) {

          context.put("message", "Sorry we had an error");

          } else {

          Collection cds = cdHome.findAllCDs();

          context.put ("cds", cds);

          try {

          res.setContentType("APPLICATION/OCTET-STREAM");

          res.setHeader("Content-Disposition","attachment;

          filename=report.txt");

          template = getTemplate("fullreport.vm");

          } catch( Exception e ) {

          e.printStackTrace();

          }

          }

          } catch(Exception e) {

          e.printStackTrace();

          }

          Listing 11.11 The fullreport code.

          注意Listing 11.11里的兩種改變,第一處是一個被加入到CDRecordBean類、名叫findAll-CDs()的新查詢,詳見Listing 11.12。

          <query>

          <query-method>

          <method-name>findAllCDs</method-name>

          </query-method>

          <ejb-ql>SELECT o FROM CDTable o</ejb-ql>

          </query>

          Listing 11.12 The CDRecordBean All CD query.

          第二處改變由下面兩行代碼組成:

          Res.setContentType("APPLICATION/OCTET-STREAM");

          res.setHeader("Content-Disposition","attachment;filename=report.txt");

          這個代碼用于告訴用戶的瀏覽器,有一個名叫report.txt的文件將出現(xiàn)在窗體里,并且是一個附件,因此,在用戶瀏覽器應(yīng)該會出現(xiàn)另存為對話框。這點(diǎn)很重要,因?yàn)槲覀兊?/span>Velocity模板將用于產(chǎn)生一個可下載的文件。Listing 11.13展示了這個模板。

          <cds>

          #foreach($value in $cds)

          <cd id="$value.id">

          <artist>$value.artist</artist>

          <title>$value.title</title>

          </cd>

          #end

          </cds>

          Listing 11.13 The Velocity template for the XML output.

          現(xiàn)在,用戶可以瀏覽這個CD應(yīng)用程序的index頁,并且可以單擊Full-Report按鈕。代碼將把所有的CD從數(shù)據(jù)里取出,并用Velocityfullreport.vm文件進(jìn)行格式化,結(jié)果見Figure 11.2


          Figure 11.2
          The XML output.

          本章小節(jié)和下間介紹

          在這一章里,我們重點(diǎn)介紹了使用Velocity來處理和使用XML數(shù)據(jù)。開發(fā)者可以為設(shè)計(jì)者的模板提供一個標(biāo)準(zhǔn)格式的數(shù)據(jù),并且設(shè)計(jì)者可以使用方法的包容集來訪問數(shù)據(jù)。在下一章里,我們將討論如何混合VelocityServlets。

          posted on 2008-10-22 17:53 KINGWEE 閱讀(991) 評論(0)  編輯  收藏 所屬分類: Velocity

          主站蜘蛛池模板: 远安县| 白水县| 钟山县| 东平县| 武安市| 犍为县| 高青县| 潼关县| 贺州市| 宜宾市| 岱山县| 中山市| 永寿县| 湟中县| 前郭尔| 黄大仙区| 郯城县| 禹州市| 嘉善县| 孟津县| 秦皇岛市| 定兴县| 台北县| 桂东县| 师宗县| 佳木斯市| 涞源县| 东兴市| 东港市| 旅游| 建始县| 江城| 阳信县| 康马县| 黄浦区| 郁南县| 雷山县| 甘泉县| 射阳县| 莱西市| 连江县|