The NoteBook of EricKong

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks
          工作中,使用JAVA的JAXP讀取解析XML文件中,就碰到了一件奇件的事。在Web工程中,調試發現JAXP實際使用的是Xerces解析器, 
          可是,當將工程中的一個小Swing工具,與Web使用一樣的jar包,打成一個可執行的jar包時,調試卻發現JAXP實際使用的是Crimson 
          解析器,還會發現解析XML文件時出現錯誤,經過分析,發現Crimson解析器是Sun公司開發的(實際使用發現Crimson沒有Xerces解析器穩定), 
          打包在JAVA_HOME/lib/dt.jar包中,這個dt.jar被設置在環境變量CLASSPATH中了,當運行可執行的jar包是,JAXP會使用CLASSPATH的解析器, 
          在Web工程中的War包則不會。 
          通過閱讀JDK源碼javax.xml.parsers.FactoryFinder,javax.xml.parsers.SAXParserFactory以及DocumentBuilderFactory發現JDK按照如下順序:

          1 系統屬性javax.xml.parsers.DocumentBuilderFactory或javax.xml.parsers.SAXParserFactory

          2 在jdk-dir/lib/jaxp.properties中設定的javax.xml.parsers.DocumentBuilderFactory或javax.xml.parsers.SAXParserFactory屬性

          3 運行時jar包中META-INF/services/javax.xml.parsers.DocumentBuilderFactory或javax.xml.parsers.SAXParserFactory文件中設定的值

          4. 如果上面的解析器都沒有找到,則使用Crimson。如果還沒有。。。。。。那報ClassNotFound異常了。

          通過JAXP查找解析器的順序,我們可以使用下面方式來決定,我們使用的實際解析器,
          1 在程序中寫死實際的解析器

          javax.xml.parsers.DocumentBuilderFactory factory= new org.apache.crimson.jaxp.DocumentBuilderFactoryImpl();
          2 使用JAXP的 DocumentBuilderFactory 工廠類,如
          javax.xml.parsers.DocumentBuilderFactory factory= javax.xml.parsers.DocumentBuilderFactory.newInstance();
          再通過下面的方式來指定實際的解析器類
          方法一:在運行java時,通過設置java -D javax.xml.parsers.DocumentBuilderFactory=new org.apache.crimson.jaxp.DocumentBuilderFactoryImpl
          方法二:在程序中調用System.setProperty(“javax.xml.parsers.DocumentBuilderFactory”,” org.apache.crimson.jaxp.DocumentBuilderFactoryImpl”)
          來設定實際的XML解析器.
          方法三:編寫一個jaxp.properties文件,在其中加入如下內容
          javax.xml.parsers.DocumentBuilderFactory=org.apache.crimson.jaxp.DocumentBuilderFactoryImpl
          再將此文件放入JAVA_HOME/lib/下
          方法四:在打jar包下,在目錄META-INF/下新建一個services目錄,在此目錄新建一個文件名為javax.xml.parsers.DocumentBuilderFactory的文件,
          文件內容寫上實際使用的解析器類,如寫org.apache.crimson.jaxp.DocumentBuilderFactoryImpl
          通過,上面,我們就可以對JAXP有一個比較深的了解。其實,JAVA中有許多這種思想的做法,這種思想,指的是什么的,就是平臺無關性,發展到不依賴于具體的實現。
          如我們熟悉的JNDI,JDBC,JAXP等。JNDI是抽像各種目錄服務操作的類庫,因為目錄服務器廠商太多了,如SUN公司的ldapsdk,還有novell公司等等。JDBC是抽像各種數據庫
          操作的類庫,因為數據庫廠商也太多了,如ORACLE,SQLSERVER,MYSQL,INFORMIX等等,JAXP就是抽像各種XML解析器和轉換器產品的類庫,因為XML解析器和轉換器產品夠多
          的了。

          訪問AIX系統中部署在OC4J中的web 模塊的頁面時遇到這個錯誤:
          javax.xml.parsers.FactoryConfigurationError: Provider null could not be instantiated: 
          java.lang.NullPointerException
          at javax.xml.parsers.SAXParserFactory.newInstance(Unknown Source)
          at org.apache.commons.digester.Digester.getFactory(Digester.java:478)
          at org.apache.commons.digester.Digester.getParser(Digester.java:683)
          at org.apache.commons.digester.Digester.getXMLReader(Digester.java:891)
          at org.apache.commons.digester.Digester.parse(Digester.java:1591)
          at org.apache.struts.action.ActionServlet.initServlet(ActionServlet.java:1433)
          at org.apache.struts.action.ActionServlet.init(ActionServlet.java:466)
          at javax.servlet.GenericServlet.init(GenericServlet.java:256)
          at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) ].server.http.HttpApplication.loadServlet(HttpApplication.java:2231)
          at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) ].server.http.HttpApplication.findServlet(HttpApplication.java:4617)
          ……
          或者這樣的異常:
          javax.servlet.jsp.JspException: Can't get definitions factory from context.
          at org.apache.struts.taglib.tiles.InsertTag.processDefinitionName(InsertTag.java:583)
          at org.apache.struts.taglib.tiles.InsertTag.createTagHandler(InsertTag.java:487)
          at org.apache.struts.taglib.tiles.InsertTag.doStartTag(InsertTag.java:451)
          at _welcome._jspService(_welcome.java:54)
          [SRC:/welcome.jsp:4]

          …… 
          而當在Windows環境下部署時就沒有問題。

          這里是因為IBMAIX系統使用的是IBMJDK。而出現這個問題正是因為IBMSUNJDK的差異。 具體是因為$JAVA_HOME/jre/lib/jaxp.properties 這個文件。

          這個文件以key=value的形式配置和指定實際使用的XML解析器實現類(譬如:javax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl)。在XML解析器初始化之前,JDK首先會搜索Systemproperties尋找解析器的配置項,如果沒有則會搜索 $JAVA_HOME/jre/lib 路徑下的 jaxp.properties 文件,如果還沒有,接下來會在classpath上的.jar包中尋找,仍然沒有的話就會使用默認的解析器。

          實際上這個文件在SUNJDK中是不存在的。在找不到文件的情況下,最終將使用默認解析器。在IBMJDK中存在 jaxp.properties這個文件。但是這個文件中默認所有的配置項是注釋掉的,所以在搜索到此處時,不再繼續向下搜索,但是由于讀取不到配置項,所以會返回null ,于是出現了上文的第一個錯誤。第二個異常大概是因為訪問使用tiles框架的頁面時,由于XML解析器初始化出錯,所以tiles框架的配置文件也就讀取不了了。

          posted on 2015-01-15 12:42 Eric_jiang 閱讀(827) 評論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 罗源县| 庄浪县| 湘潭市| 桦南县| 浦江县| 邯郸县| 齐河县| 额尔古纳市| 香格里拉县| 巢湖市| 小金县| 荥经县| 紫阳县| 青铜峡市| 正安县| 高雄市| 黑龙江省| 太和县| 启东市| 阳朔县| 白水县| 庆阳市| 镇平县| 连江县| 黔西| 同心县| 资阳市| 长丰县| 牙克石市| 肇州县| 屯昌县| 政和县| 拉萨市| 运城市| 灌阳县| 福泉市| 盐山县| 霞浦县| 芜湖市| 封丘县| 神农架林区|