Rising Sun

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            148 隨筆 :: 0 文章 :: 22 評論 :: 0 Trackbacks

          #

          filter的用法,的確是比較有擴展性的一種方法...可以通過filter結合讀取web.xml中的filter參數來完成一系列的動作,做法如下:

          首先,實現javax.servlet.Filter接口,編寫一個處理request編碼的過濾器類...

          package?tutorial.struts.filter;
          import?javax.servlet.Filter;
          import?javax.servlet.FilterConfig;
          import?javax.servlet.ServletException;
          import?javax.servlet.ServletRequest;
          import?javax.servlet.ServletResponse;
          import?javax.servlet.FilterChain;
          import?java.io.IOException;
          public?class?SetCharacterEncodingFilter?implements?Filter?{
          ??protected?FilterConfig?filterConfig;
          ??protected?String?encodingName;
          ??protected?boolean?enable;
          ??public?SetCharacterEncodingFilter()?{
          ????this.encodingName?=?"UTF-8";
          ????this.enable?=?false;
          ??}
          ??public?void?init(FilterConfig?filterConfig)?throws?ServletException?{
          ????this.filterConfig?=?filterConfig;
          ????loadConfigParams();
          ??}
          ??private?void?loadConfigParams()
          ?{
          ????//encoding
          ????this.encodingName?=?this.filterConfig.getInitParameter("encoding");
          ????//filter?enable?flag...
          ????String?strIgnoreFlag?=?this.filterConfig.getInitParameter("enable");
          ????if?(strIgnoreFlag.equalsIgnoreCase("true"))
          ?{
          ??????this.enable?=?true;
          ????}
          ?else
          ?{
          ??????this.enable?=?false;
          ????}
          ??}
          ??public?void?doFilter(ServletRequest?request,?ServletResponse?response,
          ???????????????????????FilterChain?chain)?throws?IOException,?ServletException
          ?{
          ????if(this.enable)?
          {
          ??????request.setCharacterEncoding(this.encodingName);
          ????}
          ????chain.doFilter(request,?response);
          ??}
          ??public?void?destroy()
          ?{
          ??}
          }
          ?

          然后,需要在web.xml中注冊我們的過濾器類:

          ??<filter>
          ????<filter-name>Set?Character?Encoding</filter-name>
          ????<filter-class>tutorial.struts.filter.SetCharacterEncodingFilter</filter-class>
          ????<init-param>
          ??????<param-name>encoding</param-name>
          ??????<param-value>UTF-8</param-value>
          ????</init-param>
          ????<init-param>
          ??????<param-name>enable</param-name>
          ??????<param-value>true</param-value>
          ????</init-param>
          ??</filter>
          ??<filter-mapping>
          ????<filter-name>Set?Character?Encoding</filter-name>
          ????<servlet-name>Action?Servlet</servlet-name>
          ??</filter-mapping>
          ??<filter-mapping>
          ????<filter-name>Set?Character?Encoding</filter-name>
          ????<servlet-name>Faces?Servlet</servlet-name>
          ??</filter-mapping>
          ?

          這樣,任何通過Struts,或是JSF的Controller?Servlet處理的request,都會在過濾器中先行處理,才把控制權交還給Struts或是JSF,而且Filter中有一個Process?Chain的概念,是一個很吸引人的東東~~!
          posted @ 2006-07-27 15:14 brock 閱讀(370) | 評論 (0)編輯 收藏

          ?1 package?cn.com.jsp;
          ?2
          ?3 import?java.io.IOException;
          ?4 import?javax.servlet.Filter;
          ?5 import?javax.servlet.FilterChain;
          ?6 import?javax.servlet.FilterConfig;
          ?7 import?javax.servlet.ServletException;
          ?8 import?javax.servlet.ServletRequest;
          ?9 import?javax.servlet.ServletResponse;
          10 import?javax.servlet.UnavailableException;
          11
          12 public ? class ?SetCharacterEncodingFilter?implements?Filter? {
          13 ???? protected ?String?encoding? = ? null ;
          14 ???? protected ?FilterConfig?filterConfig? = ? null ;
          15 ???? protected ?boolean?ignore? = ? true ;
          16
          17 ???? public ? void ?destroy()? {
          18 ???????? this .encoding? = ? null ;
          19 ???????? this .filterConfig? = ? null ;
          20 ????}

          21
          22 ???? public ? void ?doFilter(ServletRequest?request,?ServletResponse?response,
          23 ?????????????????????????FilterChain?chain)?throws?IOException,
          24 ????????????ServletException? {
          25
          26 ???????? // ?Conditionally?select?and?set?the?character?encoding?to?be?used
          27 ???????? if ?(ignore? || ?(request.getCharacterEncoding()? == ? null ))? {
          28 ????????????String?encoding? = ?selectEncoding(request);
          29 ???????????? if ?(encoding? != ? null )? {
          30 ????????????????request.setCharacterEncoding(encoding);
          31 ????????????}

          32 ????????}

          33
          34 ???????? // ?Pass?control?on?to?the?next?filter
          35 ????????chain.doFilter(request,?response);
          36
          37 ????}

          38
          39 ???? public ? void ?init(FilterConfig?filterConfig)?throws?ServletException? {
          40
          41 ???????? this .filterConfig? = ?filterConfig;
          42 ???????? this .encoding? = ?filterConfig.getInitParameter( " encoding " );
          43 ????????String?value? = ?filterConfig.getInitParameter( " ignore " );
          44 ???????? if ?(value? == ? null )? {
          45 ???????????? this .ignore? = ? true ;
          46 ????????}
          ? else ? if ?(value.equalsIgnoreCase( " true " ))? {
          47 ???????????? this .ignore? = ? true ;
          48 ????????}
          ? else ? if ?(value.equalsIgnoreCase( " yes " ))? {
          49 ???????????? this .ignore? = ? true ;
          50 ????????}
          ? else ? {
          51 ???????????? this .ignore? = ? false ;
          52 ????????}

          53
          54 ????}

          55
          56 ???? protected ?String?selectEncoding(ServletRequest?request)? {
          57 ???????? return ?( this .encoding);
          58 ????}

          59
          60 }


          相應的web.xml文件里的配置如下:

          ?1<web-app>
          ?2??<display-name>wwwrootSPAN style="COLOR: #800000">display-name>
          ?3??<description>MySQL?Test?AppSPAN style="COLOR: #800000">description>
          ?4??<filter>
          ?5????<filter-name>setCharacterEncodingFilterSPAN style="COLOR: #800000">filter-name>
          ?6????<display-name>setCharacterEncodingFilterSPAN style="COLOR: #800000">display-name>
          ?7????<description>setCharacterEncodingFilterSPAN style="COLOR: #800000">description>
          ?8????<filter-class>cn.com.jsp.SetCharacterEncodingFilterSPAN style="COLOR: #800000">filter-class>
          ?9????<init-param>
          10??????<param-name>encodingSPAN style="COLOR: #800000">param-name>
          11??????<param-value>GBKSPAN style="COLOR: #800000">param-value>
          12????SPAN style="COLOR: #800000">init-param>
          13??SPAN style="COLOR: #800000">filter>
          14??<filter-mapping>
          15????<filter-name>setCharacterEncodingFilterSPAN style="COLOR: #800000">filter-name>
          16????<url-pattern>/*SPAN style="COLOR: #800000">url-pattern>
          17??SPAN style="COLOR: #800000">filter-mapping>
          18……
          19SPAN style="COLOR: #800000">web-app>

          上面的代碼我也沒更改什么,看了后,了解了其中的些許流程。放入blog,留以備學吧
          posted @ 2006-07-27 15:11 brock 閱讀(372) | 評論 (0)編輯 收藏

               摘要: 將此頁作為電子郵件發送'); //--> ? ?未顯示需要 JavaScript 的文檔選項 ...  閱讀全文
          posted @ 2006-07-27 13:33 brock 閱讀(178) | 評論 (0)編輯 收藏

          JDOM是一個開源項目,它基于樹型結構,利用純JAVA的技術對XML文檔實現解析、生成、序列化以及多種操作。

          一、JDOM 簡介

          JDOM是一個開源項目,它基于樹型結構,利用純JAVA的技術對XML文檔實現解析、生成、序列化以及多種操作。

          JDOM 直接為JAVA編程服務。它利用更為強有力的JAVA語言的諸多特性(方法重載、集合概念以及映射),把SAX和DOM的功能有效地結合起來。

          在使用設計上盡可能地隱藏原來使用XML過程中的復雜性。利用JDOM處理XML文檔將是一件輕松、簡單的事。

          JDOM 在2000年的春天被Brett McLaughlin和Jason Hunter開發出來,以彌補DOM及SAX在實際應用當中的不足之處。

          這些不足之處主要在于SAX沒有文檔修改、隨機訪問以及輸出的功能,而對于DOM來說,JAVA程序員在使用時來用起來總覺得不太方便。

          DOM的缺點主要是來自于由于Dom是一個接口定義語言(IDL),它的任務是在不同語言實現中的一個最低的通用標準,并不是為JAVA特別設計的。JDOM的最新版本為JDOM Beta
          ?9。最近JDOM被收錄到JSR-102內,這標志著JDOM成為了JAVA平臺組成的一部分。

          二、JDOM 包概覽

          JDOM是由以下幾個包組成的
          org.jdom??????????????? 包含了所有的xml文檔要素的java類

          ?

          org.jdom.adapters???????? 包含了與dom適配的java類

          ?

          org.jdom.filter??????????? 包含了xml文檔的過濾器類

          ?

          org.jdom.input??????????? 包含了讀取xml文檔的類

          ?

          org.jdom.output?????????? 包含了寫入xml文檔的類

          ?

          org.jdom.transform??????? 包含了將jdom xml文檔接口轉換為其他xml文檔接口

          ?

          org.jdom.xpath??????????? 包含了對xml文檔xpath操作的類三、JDOM 類說明

          1、org.JDOM這個包里的類是你J解析xml文件后所要用到的所有數據類型。

          Attribute

          CDATA

          Coment

          DocType

          Document

          Element

          EntityRef

          Namespace

          ProscessingInstruction

          Text

          2、org.JDOM.transform在涉及xslt格式轉換時應使用下面的2個類

          JDOMSource

          JDOMResult

          org.JDOM.input

          3、輸入類,一般用于文檔的創建工作

          SAXBuilder

          DOMBuilder

          ResultSetBuilder

          org.JDOM.output

          4、輸出類,用于文檔轉換輸出

          XMLOutputter

          SAXOutputter

          DomOutputter

          JTreeOutputter

          使用前注意事項:

          1.JDOM對于JAXP 以及 TRax 的支持

          JDOM 支持JAXP1.1:你可以在程序中使用任何的parser工具類,默認情況下是JAXP的parser。

          制定特別的parser可用如下形式

          SAXBuilder parser

          ? = new SAXBuilder("org.apache.crimson.parser.XMLReaderImpl");

          ?Document doc = parser.build("

          ?// work with the document...

          JDOM也支持TRaX:XSLT可通過JDOMSource以及JDOMResult類來轉換(參見以后章節)

          2.注意在JDOM里文檔(Document)類由org.JDOM.Document 來表示。這要與org.w3c.dom中的Document區別開,這2種格式如何轉換在后面會說明。

          以下如無特指均指JDOM里的Document。

          四、JDOM主要使用方法

          1.Ducument類

          (1)Document的操作方法:

          Element root = new Element("GREETING");

          Document doc = new Document(root);

          root.setText("Hello JDOM!");

          或者簡單的使用Document doc = new Document(new Element("GREETING").setText("Hello JDOM!t"));

          這點和DOM不同。Dom則需要更為復雜的代碼,如下:

          DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();

          DocumentBuilder builder =factory.newDocumentBuilder();

          Document doc = builder.newDocument();

          Element root =doc.createElement("root");

          Text text = doc.createText("This is the root");

          root.appendChild(text);

          doc.appendChild(root);

          注意事項:JDOM不允許同一個節點同時被2個或多個文檔相關聯,要在第2個文檔中使用原來老文檔中的節點的話。首先需要使用detach()把這個節點分開來。

          (2)從文件、流、系統ID、URL得到Document對象:

          DOMBuilder builder = new DOMBuilder();

          Document doc = builder.build(new File("jdom_test.xml"));

          SAXBuilder builder = new SAXBuilder();

          Document doc = builder.build(url);

          在新版本中DOMBuilder 已經Deprecated掉 DOMBuilder.builder(url),用SAX效率會比較快。

          這里舉一個小例子,為了簡單起見,使用String對象直接作為xml數據源:

          ?public jdomTest() {

          ??? String textXml = null;

          ??? textXml = "<note>";

          ??? textXml = textXml +

          ??????? "<to>aaa</to><from>bbb</from><heading>ccc</heading><body>ddd</body>";

          ??? textXml = textXml + "</note>";

          ??? SAXBuilder builder = new SAXBuilder();

          ??? Document doc = null;

          ??? Reader in= new StringReader(textXml);

          ??? try {

          ????? doc = builder.build(in);

          ????? Element root = doc.getRootElement();

          ????? List ls = root.getChildren();//注意此處取出的是root節點下面的一層的Element集合

          ????? for (Iterator iter = ls.iterator(); iter.hasNext(); ) {
          ?/*for(int i=0;i<ls.size; i++)
          ?Element el = (Element) list.get(i);
          ?*/
          ??????? Element el = (Element) iter.next();

          ??????? if(el.getName().equals("to")){

          ???????? System.out.println(el.getText());

          ??????? }

          ????? }

          ??? }

          ??? catch (IOException ex) {

          ????? ex.printStackTrace();

          ??? }

          ??? catch (JDOMException ex) {

          ????? ex.printStackTrace();

          ??? }

          ? }

          (3)DOM的document和JDOM的Document之間的相互轉換使用方法,簡單!

          DOMBuilder builder = new DOMBuilder();

          org.jdom.Document jdomDocument = builder.build(domDocument);

          DOMOutputter converter = new DOMOutputter();// work with the JDOM document…

          org.w3c.dom.Document domDocument = converter.output(jdomDocument);

          // work with the DOM document…

          2.XML文檔輸出

          XMLOutPutter類:

          JDOM的輸出非常靈活,支持很多種io格式以及風格的輸出

          Document doc = new Document(...);

          XMLOutputter outp = new XMLOutputter();

          outp.output(doc, fileOutputStream); // Raw output

          outp.setTextTrim(true); // Compressed output

          outp.output(doc, socket.getOutputStream());

          outp.setIndent(" ");// Pretty output

          outp.setNewlines(true);

          outp.output(doc, System.out);

          詳細請參閱最新的JDOM API手冊

          3.Element 類:

          (1)瀏覽Element樹

          Element root = doc.getRootElement();//獲得根元素element

          List allChildren = root.getChildren();// 獲得所有子元素的一個list

          List namedChildren = root.getChildren("name");// 獲得指定名稱子元素的list

          Element child = root.getChild("name");//獲得指定名稱的第一個子元素

          JDOM給了我們很多很靈活的使用方法來管理子元素(這里的List是java.util.List)

          List allChildren = root.getChildren();

          allChildren.remove(3); // 刪除第四個子元素

          allChildren.removeAll(root.getChildren("jack"));// 刪除叫“jack”的子元素

          root.removeChildren("jack"); // 便捷寫法

          allChildren.add(new Element("jane"));// 加入

          root.addContent(new Element("jane")); // 便捷寫法

          allChildren.add(0, new Element("first"));

          (2)移動Elements:

          在JDOM里很簡單

          Element movable = new Element("movable");

          parent1.addContent(movable); // place

          parent1.removeContent(movable); // remove

          parent2.addContent(movable); // add

          在Dom里

          Element movable = doc1.createElement("movable");

          parent1.appendChild(movable); // place

          parent1.removeChild(movable); // remove

          parent2.appendChild(movable); // 出錯!

          補充:糾錯性

          JDOM的Element構造函數(以及它的其他函數)會檢查element是否合法。

          而它的add/remove方法會檢查樹結構,檢查內容如下:

          1.在任何樹中是否有回環節點

          2.是否只有一個根節點

          3.是否有一致的命名空間(Namespaces)

          (3)Element的text內容讀取

          <description>

          A cool demo

          </description>

          // The text is directly available

          // Returns "\n A cool demo\n"

          String desc = element.getText();

          // There's a convenient shortcut

          // Returns "A cool demo"

          String desc = element.getTextTrim();

          (4)Elment內容修改

          element.setText("A new description");

          3.可正確解釋特殊字符

          element.setText("<xml> content");

          4.CDATA的數據寫入、讀出

          element.addContent(new CDATA("<xml> content"));

          String noDifference = element.getText();

          混合內容

          element可能包含很多種內容,比如說

          <table>

          <!-- Some comment -->

          Some text

          <tr>Some child element</tr>

          </table>

          取table的子元素tr

          String text = table.getTextTrim();

          Element tr = table.getChild("tr");

          也可使用另外一個比較簡單的方法

          List mixedCo = table.getContent();

          Iterator itr = mixedCo.iterator();

          while (itr.hasNext()) {

          Object o = i.next();

          if (o instanceof Comment) {...}

          // 這里可以寫成Comment, Element, Text, CDATA,ProcessingInstruction, 或者是EntityRef的類型

          }

          // 現在移除Comment,注意這里游標應為1。這是由于回車鍵也被解析成Text類的緣故,所以Comment項應為1。

          mixedCo.remove(1);

          4.Attribute類

          <table width="100%" border="0"> </table>

          String width = table.getAttributeValue("width");//獲得attribute

          int border = table.getAttribute("width").getIntValue();

          table.setAttribute("vspace", "0");//設置attribute

          table.removeAttribute("vspace");// 刪除一個或全部attribute

          table.getAttributes().clear();

          5.處理指令(Processing Instructions)操作

          一個Pls的例子

          <?br?>

          <?cocoon-process type="xslt"?>

          ????????? |??????? |

          ????????? |??????? |

          ??????? 目標???? 數據

          處理目標名稱(Target)

          String target = pi.getTarget();

          獲得所有數據(data),在目標(target)以后的所有數據都會被返回。

          String data = pi.getData();

          String type = pi.getValue("type");獲得指定屬性的數據

          List ls = pi.getNames();獲得所有屬性的名稱

          6.命名空間操作

          <xhtml:html

          ?xmlns:xhtml="

          <xhtml:title>Home Page</xhtml:title>

          </xhtml:html>

          Namespace xhtml = Namespace.getNamespace("xhtml", "

          List kids = html.getChildren("title", xhtml);

          Element kid = html.getChild("title", xhtml);

          kid.addContent(new Element("table", xhtml));

          7.XSLT格式轉換

          使用以下函數可對XSLT轉換

          最后如果你需要使用w3c的Document則需要轉換一下。

          public static Document transform(String stylesheet,Document in)

          ??????????????????????????????????????? throws JDOMException {

          ???? try {

          ?????? Transformer transformer = TransformerFactory.newInstance()

          ???????????????????????????? .newTransformer(new StreamSource(stylesheet));

          ?????? JDOMResult out = new JDOMResult();

          ?????? transformer.transform(new JDOMSource(in), out);

          ?????? return out.getDeocument();

          ???? }

          ???? catch (TransformerException e) {

          ?????? throw new JDOMException("XSLT Trandformation failed", e);

          ???? }

          ?? }

          五、用例:

          1、生成xml文檔:

          ?

          ?

          public class WriteXML{

          ??? public void BuildXML() throws Exception {

          ??????? Element root,student,number,name,age;????????

          ??????? root = new Element("student-info"); //生成根元素:student-info

          ??????? student = new Element("student"); //生成元素:student(number,name,age)????????????????????????????

          ??????? number = new Element("number");

          ??????? name = new Element("name");

          ??????? age = new Element("age");

          ??????? Document doc = new Document(root); //將根元素植入文檔doc中

          ??????? number.setText("001");

          ??????? name.setText("lnman");

          ??????? age.setText("24");

          ??????? student.addContent(number);

          ??????? student.addContent(name);

          ??????? student.addContent(age);

          ??????? root.addContent(student);

          ??????? Format format = Format.getCompactFormat();

          ??????? format.setEncoding("gb2312"); //設置xml文件的字符為gb2312

          ??????? format.setIndent("??? "); //設置xml文件的縮進為4個空格

          ??????? XMLOutputter XMLOut = new XMLOutputter(format);//元素后換行一層元素縮四格

          ??????? XMLOut.output(doc, new FileOutputStream("studentinfo.xml"));?

          }

          ??? public static void main(String[] args) throws Exception {

          ??????? WriteXML w = new WriteXML();

          ??????? System.out.println("Now we build an XML document .....");

          ??????? w.BuildXML();

          ??????? System.out.println("finished!");

          }

          }

          生成的xml文檔為:

          <?xml version="1.0" encoding="gb2312"?>

          <student-info>

          ??? <student>

          ??????? <number>001</number>

          ??????? <name>lnman</name>

          ??????? <age>24</age>

          ??? </student>

          </student-info>

          ?

          ?

          創建XML文檔2:

          ?public class CreateXML {

          ? public void Create() {

          ?? try {

          ??? Document doc = new Document();??

          ??? ProcessingInstruction pi=new ProcessingInstruction("xml-stylesheet","type="text/xsl" href="test.xsl"");

          ??? doc.addContent(pi);???

          ??? Namespace ns = Namespace.getNamespace("

          ??? Namespace ns2 = Namespace.getNamespace("other", "

          ??? Element root = new Element("根元素", ns);

          ??? root.addNamespaceDeclaration(ns2);

          ??? doc.setRootElement(root);

          ??? Element el1 = new Element("元素一");

          ??? el1.setAttribute("屬性", "屬性一");???

          ??? Text text1=new Text("元素值");

          ???????????? Element em = new Element("元素二").addContent("第二個元素");

          ??? el1.addContent(text1);

          ???????????? el1.addContent(em);????????????

          ???????????? Element el2 = new Element("元素三").addContent("第三個元素");

          ???????????? root.addContent(el1);

          ???????????? root.addContent(el2);????????????

          ???????????? //縮進四個空格,自動換行,gb2312編碼

          ???????????? XMLOutputter outputter = new XMLOutputter("? ", true,"GB2312");

          ???????????? outputter.output(doc, new FileWriter("test.xml"));

          ???????? }catch(Exception e)? {

          ????????? System.out.println(e);

          ???????? }

          ???? }????

          ???? public static void main(String args[]) {

          ????? new CreateXML().Create();

          ???? }????

          ?}

          2、讀取xml文檔的例子:

          import org.jdom.output.*;

          import org.jdom.input.*;

          import org.jdom.*;

          import java.io.*;

          import java.util.*;

          public class ReadXML{

          ??? public static void main(String[] args) throws Exception {

          ??????? SAXBuilder builder = new SAXBuilder();

          ??????? Document read_doc = builder.build("studentinfo.xml");

          ??????? Element stu = read_doc.getRootElement();

          ??????? List list = stu.getChildren("student");

          ??????? for(int i = 0;i < list.size();i++) {

          ??????????? Element e = (Element)list.get(i);

          ??????????? String str_number = e.getChildText("number");

          ??????????? String str_name = e.getChildText("name");

          ??????????? String str_age = e.getChildText("age");

          ??????????? System.out.println("---------STUDENT--------------");

          ??????????? System.out.println("NUMBER:" + str_number);

          ??????????? System.out.println("NAME:" + str_name);

          ??????????? System.out.println("AGE:" + str_age);

          ??????????? System.out.println("------------------------------");

          ??????????? System.out.println();

          ??????? }?

          ?????? }

          }

          3、DTD驗證的:

          ?public class XMLWithDTD {

          ? public void validate()? {

          ?? try {

          ??? SAXBuilder builder = new SAXBuilder(true);

          ??? builder.setFeature(");

          ??? Document doc = builder.build(new FileReader("author.xml"));???

          ??? System.out.println("搞掂");

          ??? XMLOutputter outputter = new XMLOutputter();

          ??? outputter.output(doc, System.out);

          ?? }catch(Exception e) {

          ??? System.out.println(e);

          ?? }??

          ? }

          ? public static void main(String args[]) {

          ?? new XMLWithDTD().validate();

          ? }?

          ?}

          ?  需要說明的是,這個程序沒有指明使用哪個DTD文件。DTD文件的位置是在XML中指定的,而且DTD不支持命名空間,一個XML只能引用一個DTD,所以程序直接讀取XML中指定的DTD,程序本身不用指定。不過這樣一來,好象就只能使用外部式的DTD引用方式了?高人指點。

          ?

          ?

          4、XML Schema驗證的:

          ?public class XMLWithSchema {

          ? String xml="test.xml";

          ? String schema="test-schema.xml";

          ? public void validate() {

          ?? try {

          ??? SAXBuilder builder = new SAXBuilder(true);

          ??? //指定約束方式為XML schema

          ??? builder.setFeature("

          ??? //導入schema文件

          builder.setProperty(");

          ??? Document doc = builder.build(new FileReader(xml));???

          ??? System.out.println("搞掂");

          ??? XMLOutputter outputter = new XMLOutputter();

          ??? outputter.output(doc, System.out);

          ?? }catch(Exception e) {

          ??? System.out.println("驗證失敗:"+e);

          ?? }?

          ? }

          ?}

          ?上面的程序就指出了要引入的XML Schema文件的位置。

          ?

          ?

          ?系統默認輸出是UTF-8,這有可能導致出現亂碼。

          5、Xpath例子:

          JDOM的關于XPATH的api在org.jdom.xpath這個包里。這個包下,有一個抽象類XPath.java和實現類JaxenXPath.java,
          使用時先用XPath類的靜態方法newInstance(String xpath)得到XPath對象,
          然后調用它的selectNodes(Object context)方法或selectSingleNode(Object context)方法,
          前者根據xpath語句返回一組節點(List對象);后者根據一個xpath語句返回符合條件的第一個節點(Object類型)。
          請看jdom-1.0自帶的范例程序:

          ???? 它分析在web.xml文件中的注冊的servlet的個數及參數個數,并輸出角色名。

          web.xml文件:

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

          <!--

          <!DOCTYPE web-app

          ??? PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"

          ??? "

          -->

          <web-app>

          ??? <servlet>

          ??????? <servlet-name>snoop</servlet-name>

          ??????? <servlet-class>SnoopServlet</servlet-class>

          ??? </servlet>

          ??? <servlet>

          ??????? <servlet-name>file </servlet-name>

          ??????? <servlet-class>ViewFile</servlet-class>

          ??????? <init-param>

          ??????????? <param-name>initial</param-name>

          ??????????? <param-value>1000</param-value>

          ??????????? <description>The initial value for the counter? <!-- optional --></description>

          ??????? </init-param>

          ??? </servlet>

          ??? <servlet-mapping>

          ??????? <servlet-name>mv</servlet-name>

          ??????? <url-pattern>*.wm</url-pattern>

          ??? </servlet-mapping>

          ??? <distributed/>

          ??? <security-role>

          ????? <role-name>manager</role-name>

          ????? <role-name>director</role-name>

          ????? <role-name>president</role-name>

          ??? </security-role>

          </web-app>

          處理程序:

          import java.io.*;

          import java.util.*;?

          public class XPathReader {?????

          ??? public static void main(String[] args) throws IOException, JDOMException {

          ??????? if (args.length != 1) {

          ??????????? System.err.println("Usage: java XPathReader web.xml");

          ??????????? return;

          ??????? }

          ??????? String filename = args[0];//從命令行輸入web.xml

          ??????? PrintStream out = System.out;

          ??????? SAXBuilder builder = new SAXBuilder();

          ??????? Document doc = builder.build(new File(filename));//得到Document對象

          ?

          ?

          ??????? // Print servlet information

          ??????? XPath servletPath = XPath.newInstance("http://servlet");//,選擇任意路徑下servlet元素

          ??????? List servlets = servletPath.selectNodes(doc);//返回所有的servlet元素。

          ??????? out.println("This WAR has "+ servlets.size() +" registered servlets:");

          ??????? Iterator i = servlets.iterator();

          ??????? while (i.hasNext()) {//輸出servlet信息

          ??????????? Element servlet = (Element) i.next();

          ??????????? out.print("\t" + servlet.getChild("servlet-name")

          ??????????????????????????????????? .getTextTrim() +

          ????????????????????? " for " + servlet.getChild("servlet-class")

          ?????????????????????????????????????? .getTextTrim());

          ??????????? List initParams = servlet.getChildren("init-param");

          ??????????? out.println(" (it has " + initParams.size() + " init params)");?

          ??????? }?????????????

          ??????? // Print security role information

          ??????? XPath rolePath = XPath.newInstance("http://security-role/role-name/text()");

          ??????? List roleNames = rolePath.selectNodes(doc);//得到所有的角色名

          ??????? if (roleNames.size() == 0) {

          ??????????? out.println("This WAR contains no roles");

          ??????? } else {

          ??????????? out.println("This WAR contains " + roleNames.size() + " roles:");

          ??????????? i = roleNames.iterator();

          ??????????? while (i.hasNext()) {//輸出角色名

          ??????????????? out.println("\t" + ((Text)i.next()).getTextTrim());

          ??????????? }

          ??????? }

          ??? }????

          }

          ?

          ?

          輸出結果:

          C:\java>java?? XPathReader web.xml

          This WAR has 2 registered servlets:

          ??????? snoop for SnoopServlet (it has 0 init params)

          ??????? file for ViewFile (it has 1 init params)

          This WAR contains 3 roles:

          ??????? manager

          ??????? director

          ??????? president

          ?

          ?

          6、數據輸入要用到XML文檔要通過org.jdom.input包,反過來需要org.jdom.output。如前面所說,關是看API文檔就能夠使用。

          我們的例子讀入XML文件exampleA.xml,加入一條處理指令,修改第一本書的價格和作者,并添加一條屬性,然后寫入文件exampleB.xml:

          //exampleA.xml

          <?xml version="1.0" encoding="GBK"?>

          <bookList>

          <book>

          <name>Java編程入門</name>

          <author>張三</author>

          <publishDate>2002-6-6</publishDate>

          <price>35.0</price>

          </book>

          <book>

          <name>XML在Java中的應用</name>

          <author>李四</author>

          <publishDate>2002-9-16</publishDate>

          <price>92.0</price>

          </book>

          </bookList>

          //testJDOM.java

          import org.jdom.*;

          import org.jdom.output.*;

          import org.jdom.input.*;

          import java.io.*;

          public class TestJDOM{

          public static void main(String args[])throws Exception{

          SAXBuilder sb = new SAXBuilder();

          //從文件構造一個Document,因為XML文件中已經指定了編碼,所以這里不必了

          Document doc = sb.build(new FileInputStream("exampleA.xml"));

          ProcessingInstruction pi = new ProcessingInstruction//加入一條處理指令

          ("xml-stylesheet","href=\"bookList.html.xsl\" type=\"text/xsl\"");

          doc.addContent(pi);

          Element root = doc.getRootElement(); //得到根元素

          java.util.List books = root.getChildren(); //得到根元素所有子元素的集合

          Element book = (Element)books.get(0); //得到第一個book元素

          //為第一本書添加一條屬性

          Attribute a = new Attribute("hot","true");

          book.setAttribute(a);

          Element author = book.getChild("author"); //得到指定的字元素

          author.setText("王五"); //將作者改為王五

          //或 Text t = new Text("王五");book.addContent(t);

          Element price = book.getChild("price"); //得到指定的字元素

          //修改價格,比較郁悶的是我們必須自己轉換數據類型,而這正是JAXB的優勢

          author.setText(Float.toString(50.0f));

          String indent = " ";

          boolean newLines = true;

          XMLOutputter outp = new XMLOutputter(indent,newLines,"GBK");

          outp.output(doc, new FileOutputStream("exampleB.xml"));

          }

          };

          執行結果exampleB.xml:

          <?xml version="1.0" encoding="GBK"?>

          <bookList>

          <book hot=”true”>

          <name>Java編程入門</name>

          <author>50.0</author>

          <publishDate>2002-6-6</publishDate>

          <price>35.0</price>

          </book>

          <book>

          <name>XML在Java中的應用</name>

          <author>李四</author>

          <publishDate>2002-9-16</publishDate>

          <price>92.0</price>

          </book>

          </bookList>

          <?xml-stylesheet href="bookList.html.xsl" type="text/xsl"?>

          在默認情況下,JDOM的Element類的getText()這類的方法不會過濾空白字符,如果你需要過濾,用setTextTrim() 。


          1. /*
          2. ?*?QuickExcel.java
          3. ?*?作者:楊慶成
          4. ?*?Created?on?2004年11月22日,?下午4:05
          5. ?*?在實際應用中經常要將數據庫中的表導入Excel
          6. ?*?本人在Apache的POI基礎上寫了一個簡單的類
          7. ?*?有不當指出請指正,謝謝!
          8. ?*?
          9. ?*/
          10. package ?yqc.poi;
          11. import ?java.sql.*;
          12. import ?java.util.*;
          13. import ?java.io.*;
          14. import ?java.io.ByteArrayInputStream;
          15. import ?java.io.FileInputStream;
          16. import ?java.io.FileOutputStream;
          17. import ?java.io.IOException;
          18. import ?org.apache.poi.hssf.usermodel.*;
          19. import ?org.apache.poi.poifs.filesystem.POIFSFileSystem;
          20. import ?org.apache.poi.hssf.record.*;
          21. import ?org.apache.poi.hssf.model.*;
          22. import ?org.apache.poi.hssf.usermodel.*;
          23. import ?org.apache.poi.hssf.util.*;import?yqc.sql.*;
          24. /**
          25. ?*
          26. ?*?@author??Administrator
          27. ?*/
          28. public ?class?QuickExcel?{
          29. ????
          30. ????/**?Creates?a?new?instance?of?QuickExcel?*/
          31. ????private?QuickExcel(String?file){
          32. ????????_file=file;
          33. ????}
          34. ????
          35. ????private?void?open()throws?IOException{
          36. ????????InputStream?stream?=?null;
          37. ????????Record[]?records?=?null;
          38. ????????POIFSFileSystem?fs?=
          39. ????????????new?POIFSFileSystem(new?FileInputStream(_file));
          40. ????????_wb?=?new?HSSFWorkbook(fs);
          41. ????}
          42. ????
          43. ????private?void?create(){
          44. ????????_wb=new?HSSFWorkbook();
          45. ????}
          46. ????
          47. ????public?static?QuickExcel?newInstance?(String?file){
          48. ????????QuickExcel?qe=new?QuickExcel(file);
          49. ????????qe.create();
          50. ????????return?qe;
          51. ????}
          52. ????
          53. ????public?static?QuickExcel?openInstance(String?file)?throws?IOException?{
          54. ????????QuickExcel?qe=new?QuickExcel(file);
          55. ????????qe.open();
          56. ????????return?qe;
          57. ????}
          58. ????
          59. ????public?void?close(){
          60. ????????try{
          61. ????????????FileOutputStream?fileOut?=?new?FileOutputStream(_file);
          62. ????????????_wb.write(fileOut);//把Workbook對象輸出到文件workbook.xls中
          63. ????????????fileOut.close();
          64. ????????}
          65. ????????catch?(Exception?ex){
          66. ????????????System.out.println(ex.getMessage());
          67. ????????}
          68. ????}
          69. ????
          70. ????private?void?removeSheet(String?sheetName){
          71. ????????int?i=_wb.getSheetIndex("sheetName");
          72. ????????if?(i>=0)?_wb.removeSheetAt(i);
          73. ????}
          74. ????
          75. ????public?int?fillSheet?(ResultSet?rs,String?sheetName)throws?SQLException?{
          76. ????????HSSFSheet?st=?_wb.createSheet(sheetName);
          77. ????????ResultSetMetaData?rsmd=?rs.getMetaData();
          78. ????????int?index=0;
          79. ????????int?result=0;
          80. ????????HSSFRow?row=st.createRow(index++);
          81. ????????for(int?i=1;i<=rsmd.getColumnCount();++i){
          82. ????????????HSSFCell?cell=row.createCell((short)(i-1));
          83. ????????????cell.setCellValue(rsmd.getColumnName(i));
          84. ????????}
          85. ????????while(rs.next())?{
          86. ????????????result++;
          87. ????????????row=st.createRow(index++);
          88. ????????????for(int?i=1;i<=rsmd.getColumnCount();++i){
          89. ????????????????HSSFCell?cell=row.createCell((short)(i-1));
          90. ????????????????cell.setEncoding(cell.ENCODING_UTF_16);
          91. ????????????????cell.setCellValue(rs.getString(i));
          92. ????????????}
          93. ????????}
          94. ????????return?result;
          95. }
          96. ????
          97. ????public?static?void?main(String[]?args){
          98. ????????try{
          99. ????????????QuickConnection?qc=new?MssqlConnection("jdbc:microsoft:sqlserver://192.168.0.100:1433;DatabaseName=ls");
          100. ????????????QuickExcel?qe=QuickExcel.newInstance("a.xls");
          101. ????????????qc.connect();
          102. ????????????String?sql="select?*?from?ls.dbo.radio1_emcee";
          103. ????????????ResultSet?rs=qc.getStatement().executeQuery(sql);
          104. ????????????qe.fillSheet(rs,"MT");
          105. ????????????qe.close();
          106. ????????????qe=QuickExcel.openInstance("a.xls");
          107. ????????????qe.fillSheet(rs,"MO");
          108. ????????????qe.close();
          109. ????????????qc.close();
          110. ????????}
          111. ????????catch?(SQLException?ex){
          112. ????????????System.out.println(ex.getMessage());
          113. ????????}
          114. ????????catch?(IOException?ex){
          115. ????????????System.out.println(ex.getMessage());
          116. ????????}
          117. ????}
          118. ????
          119. ????HSSFWorkbook?_wb;
          120. ????String?_file="new.xls";
          121. }
          posted @ 2006-07-26 15:30 brock 閱讀(459) | 評論 (0)編輯 收藏

          摘要:

          Apache的Jakata項目的POI子項目,目標是處理ole2對象。目前比較成熟的是HSSF接口,處理MS Excel(97-2002)對象
          微軟在桌面系統上的成功,令我們不得不大量使用它的辦公產品,如:Word,Excel。時至今日,它的源代碼仍然不公開已封鎖了我們的進一步應用和開發。然而在要求更高的服務器領域,微軟本身的產品移植性不好,??
          性能不佳。在我們實際的開發中,表現層的解決方案雖然有多樣,但是Ie瀏覽器已成為最多人使用的瀏覽器,因為大家都用Windows。在企業辦公系統中,常常有客戶這樣子要求:你要把我們的報表直接用Excel打開。或者是:我們已經習慣用Excel打印。這樣子如果用.net開發是沒有問題的,但是有j2ee這個比.net更有前途的開放式的開發環境,難道我為了解決打印的要求去另寫客戶端的控件?或者在服務器端使用本地代碼?第一種方案的問題是關鍵數據的處理有時候不能在客戶端做,第2種方案的問題是犧牲了代碼的可移植性和穩定性。如果讓客戶端只負責處理生成好的報表,那將是一種誘人的選擇。

          Apache的Jakata項目的POI子項目,目標是處理ole2對象。目前比較成熟的是HSSF接口,處理MS Excel(97-2002)對象。它不象我們僅僅是用csv生成的沒有格式的可以由Excel轉換的東西,而是真正的Excel對象,你可以控制一些屬性如sheet,cell等等。這是一個年輕的項目,所以象HDF這樣直接支持Word對象的好東西仍然在設計中。其它支持word格式的純java方案還有itext,不過也是仍在奮斗中。但是HSSF已經成熟到能夠和足夠我們使用了。另外,無錫永中Office的實現方案也是純java的解決方案,不過那也是完全商業的產品,并不是公開代碼項目。其實,從開發歷史的角度講,在80年代中期starOffice的原作者在德國成立了StarOffice suite公司,然后到1999年夏天starOffice被sun收購,再到2000年6月starOffice5.2的發布;并且從starOffice6.0開始,starOffice建立在OpenOffice的api的基礎上,這個公開代碼的office項目已經進行了很長的時間。雖然那是由C++寫的,但是POI的代碼部分也是由openOffice改過來的。所以,應該對POI充滿足夠的信心。國內已經有部分公司在他們的辦公自動化等Web項目中使用poi了,如日恒的ioffice,海泰的HTOffice等。

          java當初把核心處理設成Unicode,帶來的好處是另代碼適應了多語言環境。然而由于老外的英語只有26個字母,有些情況下,一些程序員用8位的byte處理,一不小心就去掉了CJK的高位?;蛘呤怯捎诹晳T在程序中采用硬編碼,還有多種原因,使得許多java應用在CJK的處理上很煩惱。還好在POI HSSF中考慮到這個問題,可以設置encoding為雙字節。

          POI可以到www.apache.org下載到。編譯好的jar主要有這樣4個:poi包,poi Browser包,poi hdf包,poi hssf例程包。實際運行時,需要有poi包就可以了。如果用Jakarta ant編譯和運行,下載apache Jakarta POI的release中的src包,它里面已經為你生成好了build文件了。只要運行ant就可以了(ant 的安裝和使用在此不說了)。如果是用Jbuilder 運行,請在新建的項目中加入poi包。以Jbuilder6為例,選擇Tools菜單項的config libraries...選項,新建一個lib。在彈出的菜單中選擇poi包,如這個jakarta-poi-1.5.1-final-20020820.jar,把poi添加到jbuilder中。然后,右鍵點擊你的項目,在project的properties菜單中path的required Libraries中,點add,添加剛才加入到jbuilder中的poi到你現在的項目中。如果你僅僅是為了熟悉POI hssf的使用,可以直接看POI的samples包中的源代碼,并且運行它。hssf的各種對象都有例程的介紹。hssf提供的例程在org.apache.poi.hssf.usermodel.examples包中,共有14個,生成的目標xls都是workbook.xls。如果你想看更多的例程,可以參考hssf的Junit test cases,在poi的包的源代碼中有。hssf都有測試代碼。

          這里只對部分例程的實現做介紹。

          HSSF提供給用戶使用的對象在org.apache.poi.hssf.usermodel包中,主要部分包括Excell對象,樣式和格式,還有輔助操作。有以下幾種對象:

          HSSFWorkbook excell的文檔對象

          HSSFSheet excell的表單

          HSSFRow excell的行

          HSSFCell excell的格子單元

          HSSFFont excell字體

          HSSFName 名稱

          HSSFDataFormat 日期格式

          在poi1.7中才有以下2項:

          HSSFHeader sheet頭

          HSSFFooter sheet尾

          和這個樣式

          HSSFCellStyle cell樣式

          輔助操作包括

          HSSFDateUtil 日期

          HSSFPrintSetup 打印

          HSSFErrorConstants 錯誤信息表

          仔細看org.apache.poi.hssf包的結構,不難發現HSSF的內部實現遵循的是MVC模型。

          這里我用Rose把org.apache.poi.hssf.usermodel包中的對象反向導入并根據相互關系作了整理,詳見下面兩圖:

          ??IMG ../upload/article/a2005512101549.jpg[/IMG]

          圖1 基本對象

          從中不難可以發現每一個基本對象都關聯了一個Record對象。Record對象是一個參考Office格式的相關記錄。

          ?? IMG ../upload/article/2005512101631.jpg[/IMG]


          圖2 HSSFWorkbook

          HSSFWorkbook即是一個Excell對象。這幅類圖體現的是HSSFWorkbook和基本對象的相互關系??梢?,許多對象中也建立了Workbook的引用。還需要注意的是在HSSFWorkbook和HSSFSheet中建立了log機制POILogger,而且POILogger也是使用apache Log4J實現的。

          先看poi的examples包中提供的最簡單的例子,建立一個空xls文件。

          import org.apache.poi.hssf.usermodel.HSSFWorkbook;

          import java.io.FileOutputStream;

          import java.io.IOException;

          public class NewWorkbook

          {

          public static void main(String[] args)

          throws IOException

          {

          HSSFWorkbook wb = new HSSFWorkbook();//建立新HSSFWorkbook對象

          FileOutputStream fileOut = new FileOutputStream("workbook.xls");

          wb.write(fileOut);//把Workbook對象輸出到文件workbook.xls中

          fileOut.close();

          }

          }

          通過這個例子,我們建立的是一個空白的xls文件(不是空文件)。在此基礎上,我們可以進一步看其它的例子。


          import org.apache.poi.hssf.usermodel.*;

          import java.io.FileOutputStream;

          import java.io.IOException;

          public class CreateCells

          {

          public static void main(String[] args)

          throws IOException

          {

          HSSFWorkbook wb = new HSSFWorkbook();//建立新HSSFWorkbook對象

          HSSFSheet sheet = wb.createSheet("new sheet");//建立新的sheet對象


          // Create a row and put some cells in it. Rows are 0 based.

          HSSFRow row = sheet.createRow((short)0);//建立新行

          // Create a cell and put a value in it.

          HSSFCell cell = row.createCell((short)0);//建立新cell

          cell.setCellValue(1);//設置cell的整數類型的值


          // Or do it on one line.

          row.createCell((short)1).setCellValue(1.2);//設置cell浮點類型的值

          row.createCell((short)2).setCellValue("test");//設置cell字符類型的值

          row.createCell((short)3).setCellValue(true);//設置cell布爾類型的值

          HSSFCellStyle cellStyle = wb.createCellStyle();//建立新的cell樣式

          cellStyle.setDataFormat(HSSFDataFormat.getFormat("m/d/yy h:mm"));//設置cell樣式為定制的日期格式

          HSSFCell dCell =row.createCell((short)4);

          dCell.setCellValue(new Date());//設置cell為日期類型的值

          dCell.setCellStyle(cellStyle); //設置該cell日期的顯示格式

          HSSFCell csCell =row.createCell((short)5);

          csCell.setEncoding(HSSFCell.ENCODING_UTF_16);//設置cell編碼解決中文高位字節截斷

          csCell.setCellValue("中文測試_Chinese Words Test");//設置中西文結合字符串

          row.createCell((short)6).setCellType(HSSFCell.CELL_TYPE_ERROR);//建立錯誤cell


          // Write the output to a file

          FileOutputStream fileOut = new FileOutputStream("workbook.xls");

          wb.write(fileOut);

          fileOut.close();

          }

          }

          我稍微修改了原來的examples包中的CreateCells類寫了上面的功能測試類。通過這個例子,我們可以清楚的看到xls文件從大到小包括了HSSFWorkbook HSSFSheet HSSFRow HSSFCell這樣幾個對象。我們可以在cell中設置各種類型的值。尤其要注意的是如果你想正確的顯示非歐美的字符時,尤其象中日韓這樣的語言,必須設置編碼為16位的即是HSSFCell.ENCODING_UTF_16,才能保證字符的高8位不被截斷而引起編碼失真形成亂碼。

          其他測試可以通過參考examples包中的測試例子掌握poi的詳細用法,包括字體的設置,cell大小和低紋的設置等。需要注意的是POI是一個仍然在完善中的公開代碼的項目,所以有些功能正在不斷的擴充。如HSSFSheet的getFooter() getHeader()和setFooter(HSSFFooter hsf) setHeader(HSSFHeader hsh)是在POI1.7中才有的,而POI1.5中就沒有。運行測試熟悉代碼或者使用它做項目時請注意POI的版本。

          另外需要注意的是HSSF也有它的對xls基于事件的解析??梢詤⒖祭讨械腅ventExample.java。它通過實現HSSFListener完成從普通流認知Xls中包含的內容,在apache Cocoon中的org.apache.cocoon.serialization.HSSFSerializer中用到了這個解析。因為Cocoon2是基于事件的,所以POI為了提供快速的解析也提供了相應的事件。當然我們自己也可以實現這個事件接口。

          因為POI還不是一個足夠成熟的項目,所以有必要做進一步的開發和測試。但是它已經為我們用純java操作ole2對象提供了可能,而且克服了ole對象調用的缺陷,提供了服務器端的Excel解決方案。

          ?

          posted @ 2006-07-26 15:29 brock 閱讀(320) | 評論 (0)編輯 收藏

          where 1=1有什么用?在SQL語言中,寫這么一句話就跟沒寫一樣。

          select * from table1 where 1=1與select * from table1完全沒有區別,甚至還有其他許多寫法,1<>2,'a'='a','a'<>'b',其目的就只有一個,where的條件為永真,得到的結果就是未加約束條件的。

          在SQL注入時會用到這個,例如select * from table1 where name='lala'給強行加上select * from table1 where name='lala' or 1=1這就又變成了無約束的查詢了。

          最近發現的妙用在于,在不定數量查詢條件情況下,1=1可以很方便的規范語句。例如一個查詢可能有name,age,height,weight約束,也可能沒有,那該如何處理呢?

          String sql=select * from table1 where 1=1

          為什么要寫多余的1=1?馬上就知道了。

          if(!name.equals("")){
          ?sql=sql+"name='"+name+"'";
          }
          if(!age.equals("")){
          ?sql=sql+"age'"+age+"'";
          }
          if(!height.equals("")){
          ?sql=sql+"height='"+height+"'";
          }
          if(!weight.equals("")){
          ?sql=sql+"weight='"+weight+"'";
          }

          如果不寫1=1呢,那么在每一個不為空的查詢條件面前,都必須判斷有沒有where字句,否則要在第一個出現的地方加where

          posted @ 2006-07-26 14:24 brock 閱讀(414) | 評論 (0)編輯 收藏

          泛型是J2SE 5.0最重要的特性。他們讓你寫一個type(類或接口)和創建一個實例通過傳遞一個或多個引用類型。本文將教你如何操作泛型。它的第一部分是“沒有泛型的日子”,先讓我們回憶老版本JDK的不便。然后,舉一些泛型的例子。在討論完語法以及有界泛型的使用之后,文章最后一章將解釋如何寫泛型。
          J2SE 5.0中的泛型

          作者:Budi Kurniawan

          翻譯:RR00

          email:di_feng_ro@hotmail.com


          版權聲明:可以任意轉載,轉載時請務必以超鏈接形式標明文章原始出處和作者信息及本聲明
          英文原文地址:
          http://www.onjava.com/pub/a/onjava/2005/07/06/generics.html
          中文地址:
          http://www.matrix.org.cn/resource/article/43/43634_java_generics.html
          關鍵詞: java generics java5

          摘要
          ?????? 泛型是J2SE 5.0最重要的特性。他們讓你寫一個type(類或接口)和創建一個實例通過傳遞一個或多個引用類型。這個實例受限于只能作用于這些類型。比如,在java 5,java.util.List 已經被泛化。當建立一個list對象時,你通過傳遞一個java類型建立一個List實例,此list實例只能作用于所傳遞的類型。這意味著如果你傳遞一個String ,此List實例只能擁有String對象;如果你傳遞一個Integer,此實例只能存貯Integer對象。除了創建參數化的類型,你還能創建參數化的函數。
          ???? 泛型的第一個好處是編譯時的嚴格類型檢查。這是集合框架最重要的特點。此外,泛型消除了絕大多數的類型轉換。在JDK 5.0之前,當你使用集合框架時,你不得不進行類型轉換。
          ???? 本文將教你如何操作泛型。它的第一部分是“沒有泛型的日子”,先讓我們回憶老版本JDK的不便。然后,舉一些泛型的例子。在討論完語法以及有界泛型的使用之后,文章最后一章將解釋如何寫泛型。
          ??

          沒有泛型的日子
          ???? 所有的java類都源自java.lang.Object,這意味著所有的JAVA對象能轉換成Object。因此,在之前的JDK的版本中,很多集合框架的函數接受一個Object參數。所以,collections是一個能持有任何對象的多用途工具,但帶來了不良的后果。

          ???? 舉個簡單的例子,在JDK 5.0的之前版本中,類List的函數add接受一個Object參數:

          public boolean add(java.lang.Object element)


          ????????所以你能傳遞任何類型給add。這是故意這么設計的。否則,它只能傳遞某種特定的對象,這樣就會出現各種List類型,如,StringList, EmployeeList, AddressList等。
          ???? add通過Object傳遞能帶來好處,現在我們考慮get函數(返回List中的一個元素).如下是JDK 5之前版本的定義:

          public java.lang.Object get(int index) throws IndexOutOfBoundsException


          get返回一個Object.不幸的事情從此開始了.假如你儲存了兩個String對象在一個List中:

          List stringList1 = new ArrayList();
          stringList1.add("Java 5");
          stringList1.add("with generics");


          當你想從stringList1取得一個元素時,你得到了一個Object.為了操作原來的類型元素,你不得不把它轉換為String。

          String s1 = (String) stringList1.get(0);


          但是,假如你曾經把一個非String對象加入stringList1中,上面的代碼會拋出一個ClassCastException. 有了泛型,你能創建一個單一用途的List實例.比如,你能創建一個只接受String對象的List實例,另外一個實例只能接受Employee對象.這同樣適用于集合框架中的其他類型.


          泛型入門

          ?? 像一個函數能接受參數一樣,一個泛型也能接受參數.這就是一個泛型經常被稱為一個參數化類型的原因.但是不像函數用()傳遞參數,泛型是用<>傳遞參數的.聲明一個泛型和聲明一個普通類沒有什么區別,只不過你把泛型的變量放在<>中.
          ???? 比如,在JDK 5中,你可以這樣聲明一個java.util.List :??List<E> myList;
          E 稱為類型變量.意味著一個變量將被一個類型替代.替代類型變量的值將被當作參數或返回類型.對于List接口來說,當一個實例被創建以后,E 將被當作一個add或別的函數的參數.E 也會使get或別的參數的返回值.下面是add和get的定義:

          boolean add<E o>
          E get(int index)


          NOTE:一個泛型在聲明或例示時允許你傳遞特定的類型變量: E.除此之外,如果E是個類,你可以傳遞子類;如果E是個接口,你可以傳遞實現接口的類;

          -----------------------------譯者添加--------------------
          List<Number> numberList= new ArrayList<Number>();
          ?? numberList.add(2.0);
          ?? numberList.add(2);
          -----------------------------譯者添加--------------------


          如果你傳遞一個String給一個List,比如:

          List<String> myList;


          那么mylist的add函數將接受一個String作為他的參數,而get函數將返回一個String.因為返回了一個特定的類型,所以不用類型轉化了。

          NOTE:根據慣例,我們使用一個唯一的大寫字目表示一個類型變量。為了創建一個泛型,你需在聲明時傳遞同樣的參數列表。比如,你要想創建一個ArrayList來操作String ,你必須把String放在<>中。如:

          List<String> myList = new ArrayList<String>();


          再比如,java.util.Map 是這么定義的:

          public interface Map<K,V>


          K用來聲明map鍵(KEY)的類型而V用來表示值(VALUE)的類型。put和values是這么定義的:

          V put(K key, V value)
          Collection<V> values()


          NOTE:一個泛型不準直接的或間接的是java.lang.Throwable的子類。因為異常是在運行時拋出的,所以它不可能預言什么類型的異常將在編譯時拋出.

          列表1的例子將比較List在JDK 1.4 和JDK1.5的不同

          package com.brainysoftware.jdk5.app16;
          import java.util.List;
          import java.util.ArrayList;

          public class GenericListTest {
          ??public static void main(String[] args) {
          ????// in JDK 1.4
          ????List stringList1 = new ArrayList();
          ????stringList1.add("Java 1.0 - 5.0");
          ????stringList1.add("without generics");
          ????// cast to java.lang.String
          ????String s1 = (String) stringList1.get(0);
          ????System.out.println(s1.toUpperCase());

          ????// now with generics in JDK 5
          ????List<String> stringList2 = new ArrayList<String>();
          ????stringList2.add("Java 5.0");
          ????stringList2.add("with generics");
          ????// no need for type casting
          ????String s2 = stringList2.get(0);
          ????System.out.println(s2.toUpperCase());
          ??}
          }


          在列表1中,stringList2是個泛型。聲明List<String>告訴編譯器List的實例能接受一個String對象。當然,在另外的情況中,你能新建能接受各種對象的List實例。注意,當從List實例中返回成員元素時,不需要對象轉化,因為他返回的了你想要的類型,也就是String.

          NOTE:泛型的類型檢查(type checking)是在編譯時完成的.

          ??????最讓人感興趣的事情是,一個泛型是個類型并且能被當作一個類型變量。比如,你想你的List儲存lists of Strings,你能通過把List<String>作為他的類型變量來聲明List。比如:

          List<List<String>> myListOfListsOfStrings;


          要從myList中的第一個List重新取得String,你可以這么用:

          String s = myListOfListsOfStrings.get(0).get(0);


          下一個列表中的ListOfListsTest類示范了一個List(命名為listOfLists)接受一個String List作為參數。

          package com.brainysoftware.jdk5.app16;
          import java.util.ArrayList;
          import java.util.List;
          public class ListOfListsTest {
          ??public static void main(String[] args) {
          ????List<String> listOfStrings = new ArrayList<String>();
          ????listOfStrings.add("Hello again");
          ????List<List<String>> listOfLists = new ArrayList<List<String>>();
          ????listOfLists.add(listOfStrings);
          ????String s = listOfLists.get(0).get(0);
          ????System.out.println(s); // prints "Hello again"
          ??}
          }


          另外,一個泛型接受一個或多個類型變量。比如,java.util.Map有兩個類型變量s。第一個定義了鍵(key)的類型,第二個定義了值(value)的類型。下面的例子講教我們如何使用個一個泛型Map.

          package com.brainysoftware.jdk5.app16;
          import java.util.HashMap;
          import java.util.Map;
          public class MapTest {
          ??public static void main(String[] args) {
          ????Map<String, String> map = new HashMap<String, String>();
          ????map.put("key1", "value1");
          ????map.put("key2", "value2");
          ????String value1 = map.get("key1");
          ??}
          }


          在這個例子中,重新得到一個key1代表的String值,我們不需要任何類型轉換。

          沒有參數的情況下使用泛型

          ????既然在J2SE 5.0中收集類型已經泛型化,那么,原來的使用這些類型的代碼將如何呢?很幸運,他們在JAVA 5中將繼續工作,因為你能使用沒有參數的泛型。比如,你能繼續像原來一樣使用List接口,正如下面的例子一樣。

          List stringList1 = new ArrayList();
          stringList1.add("Java 1.0 - 5.0");
          stringList1.add("without generics");
          String s1 = (String) stringList1.get(0);


          一個沒有任何參數的泛型被稱為原型(raw type)。它意味著這些為JDK1.4或更早的版本而寫的代碼將繼續在java 5中工作。

          盡管如此,一個需要注意的事情是,JDK5編譯器希望你使用帶參數的泛型。否則,編譯器將提示警告,因為他認為你可能忘了定義類型變量s。比如,編譯上面的代碼的時候你會看到下面這些警告,因為第一個List被認為是原型。

          Note: com/brainysoftware/jdk5/app16/GenericListTest.java
          ????????uses unchecked or unsafe operations.
          Note: Recompile with -Xlint:unchecked for details.

          當你使用原型時,如果你不想看到這些警告,你有幾個選擇來達到目的:
          1.編譯時帶上參數-source 1.4
          2.使用@SupressWarnings("unchecked")注釋
          3.更新你的代碼,使用List<Object>. List<Object>的實例能接受任何類型的對象,就像是一個原型List。然而,編譯器不會報錯。

          使用 ? 通配符
          ?? 前面提過,如果你聲明了一個List<aType>, 那么這個List對aType起作用,所以你能儲存下面這些類型的對象:
          1.一個aType的實例
          2.它的子類的實例(如果aType是個類)
          3.實現aType接口的類實例(如果aType是個接口)
          但是,請注意,一個泛型本身是個JAVA類型,就像java.lang.String或java.io.File一樣。傳遞不同的類型變量給泛型可以創建不同的JAVA類型。比如,下面例子中list1和list2引用了不同的類型對象。

          List<Object> list1 = new ArrayList<Object>();
          List<String> list2 = new ArrayList<String>();


          list1指向了一個類型變量s為java.lang.Objects 的List而list2指向了一個類型變量s為String 的List。所以傳遞一個List<String>給一個參數為List<Object>的函數將導致compile time錯誤。下面列表可以說明:
          package com.brainysoftware.jdk5.app16;
          import java.util.ArrayList;
          import java.util.List;

          public class AllowedTypeTest {
          ??public static void doIt(List<Object> l) {
          ??}
          ??public static void main(String[] args) {
          ????List<String> myList = new ArrayList<String>();
          ????// 這里將產生一個錯誤
          ????doIt(myList);
          ??}
          }

          上面的代碼無法編譯,因為你試圖傳遞一個錯誤的類型給函數doIt。doIt的參數是List<Object>二你傳遞的參數是List<String>。
          可以使用 ? 通配符解決這個難題。List<?> 意味著一個對任何對象起作用的List。所以,doIt可以改為:

          public static void doIt(List<?> l) {}


          ????在某些情況下你會考慮使用 ? 通配符。比如,你有一個printList函數,這個函數打印一個List的所有成員,你想讓這個函數對任何類型的List起作用時。否則,你只能累死累活的寫很多printList的重載函數。下面的列表引用了使用 ? 通配符的printList函數。
          package com.brainysoftware.jdk5.app16;
          import java.util.ArrayList;
          import java.util.List;

          public class WildCardTest {

          ??public static void printList(List<?> list) {
          ????for (Object element : list) {
          ??????System.out.println(element);
          ????}
          ??}
          ??public static void main(String[] args) {
          ????List<String> list1 = new ArrayList<String>();
          ????list1.add("Hello");
          ????list1.add("World");
          ????printList(list1);

          ????List<Integer> list2 = new ArrayList<Integer>();
          ????list2.add(100);
          ????list2.add(200);
          ????printList(list2);
          ??}
          }


          這些代碼說明了在printList函數中,List<?>表示各種類型的List對象。然而,請注意,在聲明的時候使用 ? 通配符是不合法的,像這樣:

          List<?> myList = new ArrayList<?>(); // 不合法


          如果你想創建一個接收任何類型對象的List,你可以使用Object作為類型變量,就像這樣:

          List<Object> myList = new ArrayList<Object>();


          在函數中使用界限通配符
          在之前的章節中,你學會了通過傳遞不同的類型變量s來創建不同JAVA類型的泛型,但并不考慮類型變量s之間的繼承關系。在很多情況下,你想一個函數有不同的List參數。比如,你有一個函數getAverage,他返回了一個List中成員的平均值。然而,如果你把List<Number>作為getAverage的參數,你就沒法傳遞List<Integer> 或List<Double>參數,因為List<Number>和List<Integer> 和List<Double>不是同樣的類型。

          你能使用原型或使用通配符,但這樣無法在編譯時進行安全類型檢查,因為你能傳遞任何類型的List,比如List<String>的實例。你可以使用List<Number>作為參數,但是你就只能傳遞List<Number>給函數。但這樣就使你的函數功能減少,因為你可能更多的時候要操作List<Integer>或List<Long>,而不是List<Number>。

          J2SE5.0增加了一個規則來解決了這種約束,這個規則就是允許你定義一個上界(upper bound) 類型變量.在這種方式中,你能傳遞一個類型或它的子類。在上面getAverage函數的例子中,你能傳遞一個List<Number>或它的子類的實例,比如List<Integer> or List<Float>。

          使用上界規則的語法這么定義的:GenericType<? extends upperBoundType>. 比如,對getAverage函數的參數,你可以這么寫List<? extends Number>. 下面例子說明了如何使用這種規則。
          package com.brainysoftware.jdk5.app16;
          import java.util.ArrayList;
          import java.util.List;
          public class BoundedWildcardTest {
          ??public static double getAverage(List<? extends Number> numberList)
          ??{
          ????double total = 0.0;
          ????for (Number number : numberList)
          ??????total += number.doubleValue();
          ????return total/numberList.size();
          ??}

          ??public static void main(String[] args) {
          ????List<Integer> integerList = new ArrayList<Integer>();
          ????integerList.add(3);
          ????integerList.add(30);
          ????integerList.add(300);
          ????System.out.println(getAverage(integerList)); // 111.0
          ????List<Double> doubleList = new ArrayList<Double>();
          ????doubleList.add(3.0);
          ????doubleList.add(33.0);
          ????System.out.println(getAverage(doubleList)); // 18.0
          ??}
          }

          由于有了上界規則,上面例子中的getAverage函數允許你傳遞一個List<Number> 或一個類型變量是任何java.lang.Number子類的List。

          下界規則
          關鍵字extends定義了一個類型變量的上界。通過使用super關鍵字,我們可以定義一個類型變量的下界,盡管使用的情況不多。比如,如果一個函數的參數是List<? super Integer>,那么意味著你可以傳遞一個List<Integer>的實例或者任何java.lang.Integer的超類(superclass)。

          創建泛型

          前面的章節主要說明了如何使使用泛型,特別是集合框架中的類。現在我們開始學習如何寫自己的泛型。

          基本上,除了聲明一些你想要使用的類型變量s外,一個泛型和別的類沒有什么區別。這些類型變量s位于類型后面的<>中。比如,下面的Point就是個泛型。一個Point對象代表了一個系統中的點,它有橫坐標和縱坐標。通過使Point泛型化,你能定義一個點實例的精確程度。比如,如果一個Point對象需要非常精確,你就把Double作為類型變量。否則,Integer 就夠了。
          package com.brainysoftware.jdk5.app16;
          public class Point<T> {
          ??T x;
          ??T y;
          ??public Point(T x, T y) {
          ????this.x = x;
          ????this.y = y;
          ??}
          ??public T getX() {
          ????return x;
          ??}
          ??public T getY() {
          ????return y;
          ??}
          ??public void setX(T x) {
          ????this.x = x;
          ??}
          ??public void setY(T y) {
          ????this.y = y;
          ??}
          }


          在這個例子中,T是Point的類型變量 。T是getX和getY的返回值類型,也是setX和setY的參數類型。此外,構造函數結合兩個T參數。
          使用point類就像使用別的類一樣。比如,下面的例子創建了兩個Point對象:ponint1和point2。前者把Integer作為類型變量,而后者把Double作為類型變量。

          Point<Integer> point1 = new Point<Integer>(4, 2);
          point1.setX(7);
          Point<Double> point2 = new Point<Double>(1.3, 2.6);
          point2.setX(109.91);


          總結
          泛型使代碼在編譯時有了更嚴格的類型檢查。特別是在集合框架中,泛型有兩個作用。第一,他們增加了對集合類型在編譯時的類型檢查,所以集合類所能持有的類型對傳遞給它的參數類型起了限制作用。比如你創建了一個持有strings的java.util.List實例,那么他就將不能接受Integers或別的類型。其次,當你從一個集合中取得一個元素時,泛型消除了類型轉換的必要。
          泛型能夠在沒有類型變量的情況下使用,比如,作為原型。這些措施讓Java 5之前的代碼能夠運行在JRE 5中。但是,對新的應用程序,你最好不要使用原型,因為以后Java可能不支持他們。

          你已經知道通過傳遞不同類型的類型變量給泛型可以產生不同的JAVA類型。就是說List<String>和List<Object>的類型是不同的。盡管String是java.lang.Object。但是傳遞一個List<String>給一個參數是List<Object>的函數會參數會產生編譯錯誤(compile error)。函數能用 ? 通配符使其接受任何類型的參數。List<?> 意味著任何類型的對象。
          最后,你已經看到了寫一個泛型和別的一般JAVA類沒有什么區別。你只需要在類型名稱后面的<>中聲明一系列的類型變量s就行了。這些類型變量s就是返回值類型或者參數類型。根據慣例,一個類型變量用一個大寫字母表示。
          posted @ 2006-07-26 13:30 brock 閱讀(110) | 評論 (0)編輯 收藏

               摘要: 利用 Java 的 Properties 類讀取配置文件信息 ...  閱讀全文
          posted @ 2006-07-26 12:50 brock 閱讀(1455) | 評論 (0)編輯 收藏

          Eclipse快捷鍵指南


          Eclipse 快捷鍵指南
          本文檔從Eclipse軟件上整理,是列出了標準的快捷鍵,未列出Emacs快捷鍵。
          轉貼請注明作者和出處。
          ?
          編輯
          作用域
          功能
          快捷鍵
          全局
          查找并替換
          Ctrl+F
          文本編輯器
          查找上一個
          Ctrl+Shift+K
          文本編輯器
          查找下一個
          Ctrl+K
          全局
          撤銷
          Ctrl+Z
          全局
          復制
          Ctrl+C
          全局
          恢復上一個選擇
          Alt+Shift+↓
          全局
          剪切
          Ctrl+X
          全局
          快速修正
          Ctrl1+1
          全局
          內容輔助
          Alt+/
          全局
          全部選中
          Ctrl+A
          全局
          刪除
          Delete
          全局
          上下文信息
          Alt+?
          Alt+Shift+?
          Ctrl+Shift+Space
          Java編輯器
          顯示工具提示描述
          F2
          Java編輯器
          選擇封裝元素
          Alt+Shift+↑
          Java編輯器
          選擇上一個元素
          Alt+Shift+←
          Java編輯器
          選擇下一個元素
          Alt+Shift+→
          文本編輯器
          增量查找
          Ctrl+J
          文本編輯器
          增量逆向查找
          Ctrl+Shift+J
          全局
          粘貼
          Ctrl+V
          全局
          重做
          Ctrl+Y
          ?
          查看
          作用域
          功能
          快捷鍵
          全局
          放大
          Ctrl+=
          全局
          縮小
          Ctrl+-
          ?
          窗口
          作用域
          功能
          快捷鍵
          全局
          激活編輯器
          F12
          全局
          切換編輯器
          Ctrl+Shift+W
          全局
          上一個編輯器
          Ctrl+Shift+F6
          全局
          上一個視圖
          Ctrl+Shift+F7
          全局
          上一個透視圖
          Ctrl+Shift+F8
          全局
          下一個編輯器
          Ctrl+F6
          全局
          下一個視圖
          Ctrl+F7
          全局
          下一個透視圖
          Ctrl+F8
          文本編輯器
          顯示標尺上下文菜單
          Ctrl+W
          全局
          顯示視圖菜單
          Ctrl+F10
          全局
          顯示系統菜單
          Alt+-
          ?
          導航
          作用域
          功能
          快捷鍵
          Java編輯器
          打開結構
          Ctrl+F3
          全局
          打開類型
          Ctrl+Shift+T
          全局
          打開類型層次結構
          F4
          全局
          打開聲明
          F3
          全局
          打開外部javadoc
          Shift+F2
          全局
          打開資源
          Ctrl+Shift+R
          全局
          后退歷史記錄
          Alt+←
          全局
          前進歷史記錄
          Alt+→
          全局
          上一個
          Ctrl+,
          全局
          下一個
          Ctrl+.
          Java編輯器
          顯示大綱
          Ctrl+O
          全局
          在層次結構中打開類型
          Ctrl+Shift+H
          全局
          轉至匹配的括號
          Ctrl+Shift+P
          全局
          轉至上一個編輯位置
          Ctrl+Q
          Java編輯器
          轉至上一個成員
          Ctrl+Shift+↑
          Java編輯器
          轉至下一個成員
          Ctrl+Shift+↓
          文本編輯器
          轉至行
          Ctrl+L
          ?
          搜索
          作用域
          功能
          快捷鍵
          全局
          出現在文件中
          Ctrl+Shift+U
          全局
          打開搜索對話框
          Ctrl+H
          全局
          工作區中的聲明
          Ctrl+G
          全局
          工作區中的引用
          Ctrl+Shift+G
          ?
          文本編輯
          作用域
          功能
          快捷鍵
          文本編輯器
          改寫切換
          Insert
          文本編輯器
          上滾行
          Ctrl+↑
          文本編輯器
          下滾行
          Ctrl+↓
          ?
          文件
          作用域
          功能
          快捷鍵
          全局
          保存
          Ctrl+X
          Ctrl+S
          全局
          打印
          Ctrl+P
          全局
          關閉
          Ctrl+F4
          全局
          全部保存
          Ctrl+Shift+S
          全局
          全部關閉
          Ctrl+Shift+F4
          全局
          屬性
          Alt+Enter
          全局
          新建
          Ctrl+N
          ?
          項目
          作用域
          功能
          快捷鍵
          全局
          全部構建
          Ctrl+B
          ?
          源代碼
          作用域
          功能
          快捷鍵
          Java編輯器
          格式化
          Ctrl+Shift+F
          Java編輯器
          取消注釋
          Ctrl+\
          Java編輯器
          注釋
          Ctrl+/
          Java編輯器
          添加導入
          Ctrl+Shift+M
          Java編輯器
          組織導入
          Ctrl+Shift+O
          Java編輯器
          使用try/catch塊來包圍
          未設置,太常用了,所以在這里列出,建議自己設置。
          也可以使用Ctrl+1自動修正。
          ?
          運行
          作用域
          功能
          快捷鍵
          全局
          單步返回
          F7
          全局
          單步跳過
          F6
          全局
          單步跳入
          F5
          全局
          單步跳入選擇
          Ctrl+F5
          全局
          調試上次啟動
          F11
          全局
          繼續
          F8
          全局
          使用過濾器單步執行
          Shift+F5
          全局
          添加/去除斷點
          Ctrl+Shift+B
          全局
          顯示
          Ctrl+D
          全局
          運行上次啟動
          Ctrl+F11
          全局
          運行至行
          Ctrl+R
          全局
          執行
          Ctrl+U
          ?
          重構
          作用域
          功能
          快捷鍵
          全局
          撤銷重構
          Alt+Shift+Z
          全局
          抽取方法
          Alt+Shift+M
          全局
          抽取局部變量
          Alt+Shift+L
          全局
          內聯
          Alt+Shift+I
          全局
          移動
          Alt+Shift+V
          全局
          重命名
          Alt+Shift+R
          全局
          重做
          Alt+Shift+Y
          ?
          posted @ 2006-07-26 10:18 brock 閱讀(117) | 評論 (0)編輯 收藏

          僅列出標題
          共15頁: First 上一頁 7 8 9 10 11 12 13 14 15 下一頁 
          主站蜘蛛池模板: 巴塘县| 林芝县| 扎兰屯市| 沁水县| 北票市| 新兴县| 双牌县| 浑源县| 绩溪县| 会宁县| 郯城县| 昭通市| 新宾| 昌邑市| 汉川市| 象州县| 大宁县| 青田县| 盖州市| 屯门区| 会泽县| 开平市| 通城县| 霞浦县| 手机| 瓮安县| 舞阳县| 通榆县| 旬阳县| 大渡口区| 焦作市| 台中市| 涟源市| 延吉市| 武胜县| 大宁县| 南安市| 甘泉县| 甘南县| 龙海市| 扶风县|