设为首页 收藏本站
查看: 936|回复: 0

[经验分享] Apache Commons Digester 一 (基础内容、核心API)

[复制链接]

尚未签到

发表于 2017-12-24 20:59:42 | 显示全部楼层 |阅读模式
前言
  在许多需要处理XML格式数据的应用环境中, 如果能够以“事件驱动”的方式来处理XML文档,比如,当识别出特定的XML元素时,触发“创建对象”操作事件(或者触发调用对象的方法事件),这对于应用程序开发来说,是非常有用的;
  熟悉以SAX(Simple API for XML Parsing)方式来处理XML文档的开发人员会认识到,Digester为SAX事件提供了更高层次,对开发者更加友好的接口,它隐藏了大部分导航XML元素层次结构的细节,以便于开发者更加专注于要执行的处理操作;

使用Digester的基本步骤


  • 创建一个 org.apache.commons.digester3.Digester 类的实例对象。这里补充说明下,只要我们已经完成XML解析操作,并且不在多个线程中使用同一个Digester对象,那么就可以安全的重复使用我们预先创建的这个Digester实例;不过重用Digester实例并不是非常推荐,最好每个XML解析对应一个单独的Digester实例;
  • 为Digester实例配置属性值,通过配置属性值,我们可以改变Digester 的解析行为,具体有哪些属性值可以配置,待会会介绍;
  • 可选的, 可以将我们的一些初始对象push到Digester栈里;.
  • 在输入的XML文档中,给所有需要触发规则(rule)处理的元素匹配模式(pattern)注册规则;针对任何一个模式,你可以注册任意数量的规则;补充说明下,如果一个模式对应多个规则,则begin和body事件方法会按照它们注册的顺序依次执行,而end事件方法是倒序执行的;
  • 最后,调用digester.parse()方法,该方法需要传入XML文件的引用作为参数,该参数支持多种格式的文件流;另外需要注意的是,该方法会抛出IOException or SAXException异常,以及各种可能的在规则解析处理时遇到的异常,如NoSuchMethodException、IllegalAccessException…
  了解基本步骤后,来看一个简单的示例,如下所示,是我们即将要解析的xml文件:
  

<foo name="The Parent">
  
<bar>
  
<bar>  
<bar>  
</foo>
  

  首先,创建两个java bean对应xml中的元素信息:
  Foo类

DSC0000.gif DSC0001.gif
  

package apache.commons.digester3.example.pojo;  

  

import java.util.ArrayList;  

import java.util.Iterator;  

import java.util.List;  

  

/**  
*
@author http://www.cnblogs.com/chenpi/  
*
@version 2017年6月3日  

*/
  
public>  
{
  
private String name;
  
private List<Bar> barList = new ArrayList<Bar>();
  

  
public void addBar(Bar bar)
  
{
  
barList.add(bar);
  
}
  


  
public Bar findBar(int>  
{
  
for (Bar bar : barList)
  
{
  
if (bar.getId() ==>  
{
  
return bar;
  
}
  
}
  
return null;
  
}
  

  
public Iterator<Bar> getBars()
  
{
  
return barList.iterator();
  
}
  

  
/**
  
* @return the name
  
*/
  
public String getName()
  
{
  
return name;
  
}
  

  
/**
  
* @param name the name to set
  
*/
  
public void setName(String name)
  
{
  
this.name = name;
  
}
  

  
/**
  
* @return the barList
  
*/
  
public List<Bar> getBarList()
  
{
  
return barList;
  
}
  

  
/**
  
* @param barList the barList to set
  
*/
  
public void setBarList(List<Bar> barList)
  
{
  
this.barList = barList;
  
}
  

  
}
  


View Code  Bar类


  

package apache.commons.digester3.example.pojo;  

  

/**  
*
@author    http://www.cnblogs.com/chenpi/  
*
@version   2017年6月3日  

*/
  
public>  
{
  


  
private int>
  
private String>  

  
/**

  
* @return the>  
*/
  
public int getId()
  
{

  
return>  
}
  

  
/**

  
* @param>  
*/

  
public void setId(int>  
{

  
this.id =>  
}
  

  
/**

  
* @return the>  
*/
  
public String getTitle()
  
{

  
return>  
}
  

  
/**

  
* @param>  
*/

  
public void setTitle(String>  
{

  
this.title =>  
}
  

  
}
  


View Code  使用Digester解析xml:
  

package apache.commons.digester3.example.simpletest;  

  

import java.io.IOException;  

  

import org.apache.commons.digester3.Digester;  

import org.xml.sax.SAXException;  

  

import apache.commons.digester3.example.pojo.Bar;  

import apache.commons.digester3.example.pojo.Foo;  

  

/**  
*
  
*
@author http://www.cnblogs.com/chenpi/  
*
@version 2017年6月3日  

*/  


  
public>  
{
  

  
public static void main(String[] args)
  
{
  

  
try
  
{
  
//1、创建Digester对象实例
  
Digester digester = new Digester();
  

  
//2、配置属性值
  
digester.setValidating(false);
  

  
//3、push对象到对象栈
  
//digester.push(new Foo());
  

  
//4、设置匹配模式、规则
  
digester.addObjectCreate("foo", "apache.commons.digester3.example.pojo.Foo");
  
digester.addSetProperties("foo");
  
digester.addObjectCreate("foo/bar", "apache.commons.digester3.example.pojo.Bar");
  
digester.addSetProperties("foo/bar");
  
digester.addSetNext("foo/bar", "addBar", "apache.commons.digester3.example.pojo.Bar");
  

  
//5、开始解析
  
Foo foo = digester.parse(Main.class.getClassLoader().getResourceAsStream("example.xml"));
  

  
//6、打印解析结果
  
            System.out.println(foo.getName());
  
for (Bar bar : foo.getBarList())
  
{
  
System.out.println(bar.getId() + "," + bar.getTitle());
  
}
  

  
}
  
catch (IOException e)
  
{
  

  
e.printStackTrace();
  
}
  
catch (SAXException e)
  
{
  

  
e.printStackTrace();
  
}
  
}
  
}
  

  结果打印:

The Parent
  123,The First Child
  456,The Second Child
  789,The Second Child

  注意以上代码涉及类型的自动转换,如id属性,由字符串类型转为整型,这里所有的类型转换都是由commons-beanutils包的ConvertUtils来完成的。

Digester属性配置
  org.apache.commons.digester3.Digester实例对象包含若干成员属性,这些属性值是可以设置的,以便我们自定义解析操作;
  为了让这些配置在XML解析前生效,这些属性值的更改一定要在parse方法调用之前设置;
  如下是一些可以配置的属性

Property DescriptionclassLoader  通过配置这个属性值,我们可以指定ObjectCreateRule和FactoryCreateRule规则使用的类加载器;另外,在没指定该值的时候,如果useContextClassLoader属性值设为true,则会使用当前线程上下文类加载器,否则直接使用加载Digester类的同一个类加载器;

errorHandler
通过配置这个属性值,我们可以指定一个SAX ErrorHandler,当解析错误出现的时候,该Handler会收到通知;
namespaceAware
通过设置该boolean值,可以让Digester在解析的时候,识别出XML命名空间;
xincludeAware
通过设置该boolean值,可以让Digester在解析的时候,识别出语法 ,注意该设置只有在namespaceAware设为true的前提下才有效.
ruleNamespaceURI
该值一般配合namespaceAware使用,在namespaceAware设为true的情况下,设置ruleNamespaceURI,那么接下来的规则只会匹配ruleNamespaceURI命名空间下的元素;
rules
通过该属性,我们可以额外添加一些自定义解析匹配规则;
useContextClassLoader  如果useContextClassLoader属性值设为true,则会使用当前线程上下文类加载器,否则直接使用加载Digester类的同一个类加载器
  注意 - 如果设置了classLoader属性值,改属性配置将被忽略;

validating
通过设置该boolean值, 可以配置Digester是否做DTD检查;  另外,我们可以通过Digester的register方法,让Digester在遇到DOCTYPE声明时,使用本地dtd,而不是从网上获取,如下所示:
  

        URL url = new URL("/org/apache/struts/resources/struts-config_1_0.dtd");  
digester.register(
"-//Apache Software Foundation//DTD Struts Configuration 1.0//EN", url.toString());  


Digester对象栈
  Digester使用的一个核心技术就是动态构建一颗java对象树,在构建的过程中,一个重要的辅助数据结构即对象栈;
  以如下xml为例:
  

<foo name="The Parent">
  
<bar>
  
<bar>
  
<bar>  
</foo>
  

  在解析的时候:
  首先会创建一个foo对象,并压入对象栈,然后设置foo属性值name,紧接着,创建bar对象并压入栈,然后设置bar的属性值,然后将该bar对象添加的到foo对象的barlist属性集合中,然后bar对象弹出对象栈;
  以此类推,遇到起始标记的元素创建对象入栈,遇到结尾标记的元素做出栈操作,出栈前,需要将出栈对象并关联到上一个栈顶对象;
  最终,解析完xml后,留在栈顶的就关联了所有在xml解析中创建的动态对象了;
  Digester暴露出的与对象栈操作API如下所示:


  • clear() - 清除对象栈.
  • peek() - 返回栈顶对象引用,但是不弹出.
  • pop() - 返回栈顶对象,并弹出.
  • push() - 入栈操作.
Digester元素匹配模式
  Digester的一个关键特性是可以自动识别xml的层次结构,程序员只需要关心遇到匹配到某个元素后需要做哪些操作即可;
  如下是一个示例,其中a, a/b, a/b/c为匹配模式,对应xml中特定位置的元素:
  

  <a>         -- Matches pattern "a"  

<b>       -- Matches pattern "a/b"  

<c/>    -- Matches pattern "a/b/c"  

<c/>    -- Matches pattern "a/b/c"  

</b>  
<b>       -- Matches pattern "a/b"
  
<c/>    -- Matches pattern "a/b/c"
  
<c/>    -- Matches pattern "a/b/c"
  
<c/>    -- Matches pattern "a/b/c"
  
</b>
  
</a>
  


Digester规则处理
  当匹配到模式时,会触发规则处理,具体的规则处理机制是由这个org.apache.commons.digester3.Rule接口封装的,该接口定义了以下几个方法:


  • begin() - 匹配到xml元素开始标记时,调用该方法;
  • body() - 匹配到xml元素body时,调用该方法;
  • end() - 匹配到xml元素结束标记时,调用该方法;
  • finish() - 当所有解析方法解析完毕后,调用该方法,用于清楚临时数据等;
  默认情况下,Digester提供了以下Rule接口的实现类,我们在编码的时候可以直接使用,详见API文档:


  • ObjectCreateRule
  • FactoryCreateRule
  • SetPropertiesRule
  • SetPropertyRule
  • SetNextRule
  • SetTopRule
  • CallMethodRule
  • CallParamRule
  • NodeCreateRule
  如下是一个SetNextRule规则实现类的示例(两种写法):
  

            Rule rule = new SetNextRule("addBar",Bar.class);  
digester.addRule(
"foo/bar", rule );  

  

//digester.addSetNext("foo/bar", "addBar", Bar.class.getName());  


Digester日志
  日志是调试、排查错误非常关键的一个环节,Digester记录了非常详细的日志,我们可以按如下方式来开启日志打印功能;
  这里的日志实现选择log4j,
  首先,在pom.xml加上如下依赖:
  

        <!-- https://mvnrepository.com/artifact/log4j/log4j -->  
<dependency>
  
<groupId>log4j</groupId>
  
<artifactId>log4j</artifactId>
  
<version>1.2.17</version>
  
</dependency>
  

  然后,编写一个配置文件log4j.properties放到resources路径下:
  

### set log levels ###  
log4j.rootLogger = debug, stdout
  

  
### \u8F93\u51FA\u5230\u63A7\u5236\u53F0 ###
  
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
  
log4j.appender.stdout.Target = System.out
  
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
  
log4j.appender.stdout.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
  

  运行程序,发现已经可以看到DEBUG调试日志了日志:

2017-06-04 18:26:33  [ main:51 ] - [ DEBUG ]    Fire body() for SetPropertiesRule[aliases={}, ignoreMissingProperty=true]
  2017-06-04 18:26:33  [ main:51 ] - [ DEBUG ]    Popping body text ''
  2017-06-04 18:26:33  [ main:51 ] - [ DEBUG ]    Fire end() for SetPropertiesRule[aliases={}, ignoreMissingProperty=true]
  2017-06-04 18:26:33  [ main:52 ] - [ DEBUG ]    Fire end() for ObjectCreateRule[className=apache.commons.digester3.example.pojo.Foo, attributeName=null]
  2017-06-04 18:26:33  [ main:52 ] - [ DEBUG ]  [ObjectCreateRule]{foo} Pop 'apache.commons.digester3.example.pojo.Foo'
  2017-06-04 18:26:33  [ main:52 ] - [ DEBUG ]  endDocument()
  The Parent
  123,The First Child
  456,The Second Child
  789,The Second Child

Digester例子
  前面我们已经举了一个Digester的简单使用例子,这里将继续展示几个示例;

解析xml元素body值
  如下XML文档就是我们要解析内容:
  

<web-app>  
<servlet>
  
<servlet-name>action</servlet-name>
  
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
  
<init-param>
  
<param-name>application</param-name>
  
<param-value>org.apache.struts.example.ApplicationResources</param-value>
  
</init-param>
  
<init-param>
  
<param-name>config</param-name>
  
<param-value>/WEB-INF/struts-config.xml</param-value>
  
</init-param>
  
</servlet>
  
</web-app>
  

  首先,定义一个ServletBean,存储以上xml信息,如下所示:
  

/*  
* File Name: ServletBean.java
  
* Description:
  
* Author: http://www.cnblogs.com/chenpi/
  
* Create Date: 2017年6月4日
  
*/
  
package apache.commons.digester3.example.pojo;
  

  
import java.util.HashMap;
  
import java.util.Map;
  

  
/**
  
*
  
* @author    http://www.cnblogs.com/chenpi/
  
* @version   2017年6月4日
  
*/
  


  
public>  
{
  

  
private String servletName;
  
private String servletClass;
  
private Map
<String, String> initParams = new HashMap<String, String>();  

  

  
public void addInitParam(String paramName, String paramValue){
  
initParams.put(paramName, paramValue);
  
}
  
/**
  
* @return the servletName
  
*/
  
public String getServletName()
  
{
  
return servletName;
  
}
  
/**
  
* @param servletName the servletName to set
  
*/
  
public void setServletName(String servletName)
  
{
  
this.servletName = servletName;
  
}
  
/**
  
* @return the servletClass
  
*/
  
public String getServletClass()
  
{
  
return servletClass;
  
}
  
/**
  
* @param servletClass the servletClass to set
  
*/
  
public void setServletClass(String servletClass)
  
{
  
this.servletClass = servletClass;
  
}
  
/**
  
* @return the initParams
  
*/
  
public Map
<String, String> getInitParams()  
{
  
return initParams;
  
}
  
/**
  
* @param initParams the initParams to set
  
*/
  
public void setInitParams(Map
<String, String> initParams)  
{
  
this.initParams = initParams;
  
}
  
}
  

  编写规则解析xml,如下所示:
  

/*  
* File Name: Main2.java
  
* Description:
  
* Author:
http://www.cnblogs.com/chenpi/  
* Create Date: 2017年6月4日
  

*/  
package apache.commons.digester3.example.simpletest;
  

  
import java.io.IOException;
  

  
import org.apache.commons.digester3.Digester;
  
import org.apache.commons.digester3.Rule;
  
import org.apache.commons.digester3.SetNextRule;
  
import org.xml.sax.SAXException;
  

  
import apache.commons.digester3.example.pojo.Bar;
  
import apache.commons.digester3.example.pojo.Foo;
  
import apache.commons.digester3.example.pojo.ServletBean;
  

  
/**
  
*
  
* @author http://www.cnblogs.com/chenpi/
  
* @version 2017年6月4日
  
*/
  


  
public>  
{
  

  
public static void main(String[] args)
  
{
  
try
  
{
  
// 1、创建Digester对象实例
  
Digester digester = new Digester();
  

  
// 2、配置属性值
  
digester.setValidating(false);
  

  
// 3、push对象到对象栈
  

  
// 4、设置匹配模式、规则
  
digester.addObjectCreate("web-app/servlet", "apache.commons.digester3.example.pojo.ServletBean");
  
digester.addCallMethod("web-app/servlet/servlet-name", "setServletName", 0);
  
digester.addCallMethod("web-app/servlet/servlet-class", "setServletClass", 0);
  
digester.addCallMethod("web-app/servlet/init-param", "addInitParam", 2);
  
digester.addCallParam("web-app/servlet/init-param/param-name", 0);
  
digester.addCallParam("web-app/servlet/init-param/param-value", 1);
  

  
// 5、开始解析
  
ServletBean servletBean = digester
  
.parse(ExampleMain.class.getClassLoader().getResourceAsStream("web.xml"));
  

  
// 6、打印解析结果
  
            System.out.println(servletBean.getServletName());
  
System.out.println(servletBean.getServletClass());
  
for(String key : servletBean.getInitParams().keySet()){
  
System.out.println(key + ": " + servletBean.getInitParams().get(key));
  
}
  

  
}
  
catch (IOException e)
  
{
  

  
e.printStackTrace();
  
}
  
catch (SAXException e)
  
{
  

  
e.printStackTrace();
  
}
  

  
}
  
}
  

  结果打印:

action
  org.apache.struts.action.ActionServlet
  application: org.apache.struts.example.ApplicationResources
  config: /WEB-INF/struts-config.xml

解析XML命名空间
  对于没有使用命名空间的xml来说,Digester默认的处理机制已经足够满足我们的需求了。但是当XML文档使用命名空间的时候,对于不同命名空间的元素来说,有时候我们希望使用不同的规则去解析它。
  Digester 没有提供对命名空间的完全支持, 但已经足够完成大多数任务了. 开启Digester的命名空间支持只需要以下几个步骤即可:
  1、通过配置以下属性值,告诉 Digester,需要开启命名空间解析:
  

digester.setNamespaceAware( true );  

  2、声明接下来的规则关联的命名空间,注意我们这里没有指明任何前缀,XML文档的作者是可以使用任何他们喜欢的前缀的
  

digester.setRuleNamespaceURI( "http://www.mycompany.com/MyNamespace" );  

  3、添加该命名空间下的规则, 通常会调用 addObjectCreate() 或者 addSetProperties()这类方法. 注意,这里匹配的模式是不需要加上前缀的:
  

    digester.addObjectCreate( "foo/bar", "com.mycompany.MyFoo" );  
digester.addSetProperties(
"foo/bar");      

  4.    重复2、3步骤,解析其它命名空间的元素.
  如下,是一个示例,使用以上步骤即可完成解析:
  

<m:foo  
xmlns:m
="http://www.mycompany.com/MyNamespace"  
xmlns:y
="http://www.yourcompany.com/YourNamespace">  
<m:bar name="My Name" value="My Value"/>
  
<y:bar product="Product Description"/>
  
</m:foo>
  

  由于我们给Digester指定的命名空间为http://www.mycompany.com/MyNamespace,所以以上xml只有第一个bar会被解析出来。
  如下是一个完整示例(XML及对应解析代码):
  

<m:foo xmlns:m="http://www.mycompany.com/MyNamespace"  
xmlns:y
="http://www.yourcompany.com/YourNamespace" name="The Parent">
  
<m:bar>
  
<y:bar>
  
<m:bar>  
</m:foo>
  

  

/*  
* File Name: Main.java
  
* Description:
  
* Author:
http://www.cnblogs.com/chenpi/  
* Create Date: 2017年6月3日
  

*/  
package apache.commons.digester3.example.simpletest;
  

  
import java.io.IOException;
  

  
import org.apache.commons.digester3.Digester;
  
import org.xml.sax.SAXException;
  

  
import apache.commons.digester3.example.pojo.Bar;
  
import apache.commons.digester3.example.pojo.Foo;
  

  
/**
  
*
  
* @author http://www.cnblogs.com/chenpi/
  
* @version 2017年6月3日
  
*/
  


  
public>  
{
  

  
public static void main(String[] args)
  
{
  

  
try
  
{
  
Digester digester = new Digester();
  

  
digester.setValidating(false);
  
digester.setNamespaceAware(true);
  
digester.setRuleNamespaceURI("http://www.mycompany.com/MyNamespace");
  

  
digester.addObjectCreate("foo", Foo.class);
  
digester.addSetProperties("foo");
  
digester.addObjectCreate("foo/bar", Bar.class);
  
digester.addSetProperties("foo/bar");
  

  
digester.addSetNext("foo/bar", "addBar", Bar.class.getName());
  

  
Foo foo = digester
  
.parse(ExampleNSMain.class.getClassLoader().getResourceAsStream("example_ns.xml"));
  

  
System.out.println(foo.getName());
  
for (Bar bar : foo.getBarList())
  
{
  
System.out.println(bar.getId() + "," + bar.getTitle());
  
}
  

  
}
  
catch (IOException e)
  
{
  

  
e.printStackTrace();
  
}
  
catch (SAXException e)
  
{
  

  
e.printStackTrace();
  
}
  

  
}
  
}
  


使用命名空间前缀用于模式匹配
  当一个命名空间下的规则集合与另一个命名空间的规则集合相互独立的话,使用带命名空间的规则非常有用,但是当我们的规则逻辑需要使用到不同命名空间下的元素时,那么使用带命名空间前缀的模式将会是一个更好的策略;
  很简单,我们只需要,设置NamespaceAware 属性为false,然后在模式前面带上命名空间前缀即可。
  比如, (将 NamespaceAware 设为false), 那么模式 m:bar' 只会匹配命名空间前缀为m的bar元素.
  如下是一个完整demo:
  

/*  
* File Name: Main.java
  
* Description:
  
* Author:
http://www.cnblogs.com/chenpi/  
* Create Date: 2017年6月3日
  

*/  
package apache.commons.digester3.example.simpletest;
  

  
import java.io.IOException;
  

  
import org.apache.commons.digester3.Digester;
  
import org.xml.sax.SAXException;
  

  
import apache.commons.digester3.example.pojo.Bar;
  
import apache.commons.digester3.example.pojo.Foo;
  

  
/**
  
*
  
* @author http://www.cnblogs.com/chenpi/
  
* @version 2017年6月3日
  
*/
  


  
public>  
{
  

  
public static void main(String[] args)
  
{
  

  
try
  
{
  
Digester digester = new Digester();
  

  
digester.setValidating(false);
  
digester.setNamespaceAware(false);
  
//digester.setRuleNamespaceURI("http://www.mycompany.com/MyNamespace");
  

  
digester.addObjectCreate("m:foo", Foo.class);
  
digester.addSetProperties("m:foo");
  
digester.addObjectCreate("m:foo/m:bar", Bar.class);
  
digester.addSetProperties("m:foo/m:bar");
  
digester.addSetNext("m:foo/m:bar", "addBar", Bar.class.getName());
  

  
digester.addObjectCreate("m:foo/y:bar", Bar.class);
  
digester.addSetProperties("m:foo/y:bar");
  
digester.addSetNext("m:foo/y:bar", "addBar", Bar.class.getName());
  

  
Foo foo = digester
  
.parse(ExampleNS2Main.class.getClassLoader().getResourceAsStream("example_ns.xml"));
  

  
System.out.println(foo.getName());
  
for (Bar bar : foo.getBarList())
  
{
  
System.out.println(bar.getId() + "," + bar.getTitle());
  
}
  

  
}
  
catch (IOException e)
  
{
  

  
e.printStackTrace();
  
}
  
catch (SAXException e)
  
{
  

  
e.printStackTrace();
  
}
  

  
}
  
}
  


错误排查
  Digester 是基于 SAX 开发的. Digestion 会抛出两种类型的 Exception:


  • java.io.IOException
  • org.xml.sax.SAXException
  第一个异常很少会抛出,且该异常众所周知。 通常我们遇到最多的是第二个异常,当SAX解析无法完成的时候会抛出该异常,所以熟悉SAX的错误处理方式对诊断SAXException很有帮助。
  当一个SAX 解析器 遇到xml问题时 (哈哈,有时候,会在遇到xml问题之后),会抛出SAXParseException异常. 该异常是SAXException 的子类,并且包含了一些额外信息(哪里出错,出了什么错误),如果我们捕获了这类异常,那么就可以明确知道问题是XML引起的,而不是Digester或者我们的解析规则。通常来说,捕获该异常并记录详细信息到日志对诊断错误非常有帮助。
  一般情况下 SAXException 异常内部会组合另一个异常,换句话说,就是当Digester遇到异常的时候,会首先将该异常封装成一个SAXException异常,然后将该SAXException重新抛出 。所以,捕获SAXException异常,并仔细检查被封装的内部异常,有助于排查错误;
  错误示例:
  

org.xml.sax.SAXParseException; lineNumber: 4; columnNumber: 44; 元素类型 "y:bar" 必须后跟属性规范 ">" 或 "/>"。  
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1239)
  
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:648)
  
at org.apache.commons.digester3.Digester.parse(Digester.java:1642)
  
at org.apache.commons.digester3.Digester.parse(Digester.java:1701)
  
at apache.commons.digester3.example.simpletest.ExampleNS2Main.main(ExampleNS2Main.java:48)
  


参考资料
  http://commons.apache.org/proper/commons-digester/guide/core.html

示例代码
  https://github.com/peterchenhdu/apache-commons-digester-example

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-427638-1-1.html 上篇帖子: WAMP下Apache配置Vhost (2 下篇帖子: org.springframework.beans.MethodInvocationException: Property 'cacheManager' thr
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表