digester java_java digester

digester里面的所有add相关的方法都是调用了addRule这个方法,当然这个方法也可以直接调用,该方法就是把一个pattern和一个rule的实现类对象进行绑定,用户可以自己实现一个rule的实现类,也可以用jdk提供的一些rule实现类,例如CallMethodRule,他被addCallMethod()这个方法使用,所以当我们调用addCallMethod(),就等于使用了CallMethodRule。

public void addCallMethod(String pattern, String methodName) {

addRule(

pattern,

new CallMethodRule(methodName));

}

我们实现Rule主要是实现begin body end这几个方法,这几个方法分别会在startElement和endElement方法中被调用,这两个方法分别对应xml元素头(例如 )和元素位(例如 )

public void addRule(String pattern, Rule rule) {

rule.setDigester(this);

getRules().add(pattern, rule);

}

RulesBase的add方法

public void add(String pattern, Rule rule) {

// to help users who accidently add '/' to the end of their patterns

int patternLength = pattern.length();

if (patternLength>1 && pattern.endsWith("/")) {

pattern = pattern.substring(0, patternLength-1);

}

List list = cache.get(pattern);

if (list == null) {

list = new ArrayList();

cache.put(pattern, list);

}

list.add(rule);//将pattern和Rule放到cache(hashmap)中,也就是一个pattern对应一组Rule

rules.add(rule);

if (this.digester != null) {

rule.setDigester(this.digester);

}

if (this.namespaceURI != null) {

rule.setNamespaceURI(this.namespaceURI);

}

}

public void startElement(String namespaceURI, String localName,

String qName, Attributes list)

throws SAXException {

boolean debug = log.isDebugEnabled();

if (saxLog.isDebugEnabled()) {

saxLog.debug("startElement(" + namespaceURI + "," + localName + "," +

qName + ")");

}

// Parse system properties

list = updateAttributes(list);//解析元素的属性,放到list中

// Save the body text accumulated for our surrounding element

bodyTexts.push(bodyText);//把bodyText存起来,例如abc这个abc就是bodyText

bodyText = new StringBuilder();

// the actual element name is either in localName or qName, depending

// on whether the parser is namespace aware

String name = localName;//获取元素名

if ((name == null) || (name.length() < 1)) {

name = qName;  //获取元素名

}

// Compute the current matching rule

StringBuilder sb = new StringBuilder(match);

if (match.length() > 0) {

sb.append('/');

}

sb.append(name);  //多级元素组成目录格式,类似/a/b/c

match = sb.toString();

if (debug) {

log.debug("  New match='" + match + "'");

}

// Fire "begin" events for all relevant rules

List rules = getRules().match(namespaceURI, match);//利用match与之前记录在cache里的pattern做匹配,得到一组rule

matches.push(rules);//存起来到endelement会用

if ((rules != null) && (rules.size() > 0)) {

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

try {

Rule rule = rules.get(i);

if (debug) {

log.debug("  Fire begin() for " + rule);

}

rule.begin(namespaceURI, name, list);//依次执行这组rule

} catch (Exception e) {

log.error("Begin event threw exception", e);

throw createSAXException(e);

} catch (Error e) {

log.error("Begin event threw error", e);

throw e;

}

}

} else {

if (debug) {

log.debug("  No rules found matching '" + match + "'.");

}

}

}

public void endElement(String namespaceURI, String localName,

String qName) throws SAXException {

boolean debug = log.isDebugEnabled();

if (debug) {

if (saxLog.isDebugEnabled()) {

saxLog.debug("endElement(" + namespaceURI + "," + localName +

"," + qName + ")");

}

log.debug("  match='" + match + "'");

log.debug("  bodyText='" + bodyText + "'");

}

// Parse system properties

bodyText = updateBodyText(bodyText);//把bodyText中的变量进行替换

// the actual element name is either in localName or qName, depending

// on whether the parser is namespace aware

String name = localName;

if ((name == null) || (name.length() < 1)) {

name = qName;

}

// Fire "body" events for all relevant rules

List rules = matches.pop(); //把之前startelement中的记录弹出,先入后出,等于就是先处理最内层的元素的内容

if ((rules != null) && (rules.size() > 0)) {

String bodyText = this.bodyText.toString();

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

try {

Rule rule = rules.get(i);

if (debug) {

log.debug("  Fire body() for " + rule);

}

rule.body(namespaceURI, name, bodyText);

} catch (Exception e) {

log.error("Body event threw exception", e);

throw createSAXException(e);

} catch (Error e) {

log.error("Body event threw error", e);

throw e;

}

}

} else {

if (debug) {

log.debug("  No rules found matching '" + match + "'.");

}

if (rulesValidation) {

log.warn("  No rules found matching '" + match + "'.");

}

}

// Recover the body text from the surrounding element

bodyText = bodyTexts.pop();

// Fire "end" events for all relevant rules in reverse order

if (rules != null) {

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

int j = (rules.size() - i) - 1;

try {

Rule rule = rules.get(j);

if (debug) {

log.debug("  Fire end() for " + rule);

}

rule.end(namespaceURI, name);//依次执行rule,但执行顺序和start时相反

} catch (Exception e) {

log.error("End event threw exception", e);

throw createSAXException(e);

} catch (Error e) {

log.error("End event threw error", e);

throw e;

}

}

}

// Recover the previous match expression

int slash = match.lastIndexOf('/');

if (slash >= 0) {

match = match.substring(0, slash);

} else {

match = "";

}

}

especially,addObjectCreate这个方法

public void addObjectCreate(String pattern, String className,

String attributeName) {

addRule(pattern,

new ObjectCreateRule(className, attributeName));

}

ObjectCreateRule.begin()

public void begin(String namespace, String name, Attributes attributes)

throws Exception {

// Identify the name of the class to instantiate

String realClassName = className;

if (attributeName != null) {

String value = attributes.getValue(attributeName);

if (value != null) {

realClassName = value;

}

}

if (digester.log.isDebugEnabled()) {

digester.log.debug("[ObjectCreateRule]{" + digester.match +

"}New " + realClassName);

}

if (realClassName == null) {

throw new NullPointerException("No class name specified for " +

namespace + " " + name);

}

// Instantiate the new object and push it on the context stack

Class> clazz = digester.getClassLoader().loadClass(realClassName);

Object instance = clazz.newInstance(); //创建类实例

digester.push(instance);//将实例压入栈,目的是后续比如CallMethodRule里的方法会用这个里面的对象,调用这个对象的方法,所以相关的addObjectCreate和addCallMethod要写一起,别隔着其他的addObjectCreate,否则对象会找错

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值