当前位置: 首页 > news >正文

commons-digester3(XML解析框架)

概述

基于规则的XML解析框架,通过事件驱动机制将XML结构自动映射为Java对象,特别适用于配置管理和复杂对象关系处理。

        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-digester3 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-digester3</artifactId><version>3.2</version></dependency>

示例

XML和实体类

  • 需要解析的XML文件(user.xml)
<user userId="1"><userName>张三</userName><dept id="2" name="研发部"/><roles><role id="3" name="管理员"/><role id="4" name="普通用户"/></roles>
</user>
  • 实体类定义
public class User {private long userId;private String userName;private Dept dept;private List<Role> roles = new ArrayList<>();public void addRole(Role role) {this.roles.add(role);}public void setDept(Dept dept) {this.dept = dept;}//TODO 省略其他get/set方法
public class Dept {private long deptId;private String deptName;//TODO 省略其他get/set方法
}
public class Role {private long roleId;private String roleName;//TODO 省略其他get/set方法
}
  • XML规则文件(digester-rules.xml)
<?xml version="1.0"?>
<!DOCTYPE digester-rules SYSTEM "http://commons.apache.org/digester/dtds/digester-rules.dtd">
<digester-rules><!-- 对象创建规则 --><pattern value="user"><object-create-rule classname="com.example.demo2.pojo.User"/><set-properties-rule/><bean-property-setter-rule pattern="userName" propertyname="userName"></bean-property-setter-rule></pattern><!-- 嵌套对象规则 --><pattern value="user/dept"><object-create-rule classname="com.example.demo2.pojo.Dept"/><set-properties-rule/><set-next-rule methodname="setDept"/></pattern><!-- 嵌套对象规则 --><pattern value="user/roles/role"><object-create-rule classname="com.example.demo2.pojo.Role"/><set-properties-rule/><set-next-rule methodname="addRole"/></pattern>
</digester-rules>

解析示例

  • 简单示例
    Digester digester = new Digester();//对象规则digester.addObjectCreate("user", User.class);//映射对象digester.addSetProperties("user");//属性映射digester.addBeanPropertySetter("user/userName","userName");//子标签映射对象属性//一对一嵌套对象规则digester.addObjectCreate("user/dept", Dept.class);//映射对象digester.addSetProperties("user/dept");//属性映射digester.addSetNext("user/dept", "setDept");//设置对象属性set方法//一对多嵌套对象规则digester.addObjectCreate("user/roles/role", Role.class);//映射对象digester.addSetProperties("user/roles/role");//属性映射digester.addSetNext("user/roles/role", "addRole");//设置对象集合属性add方法//解析xmlUser user = digester.parse(new File("E:\\demo2\\src\\test\\resources\\user.xml"));System.out.println(JSON.toJSONString(user, SerializerFeature.PrettyFormat));
  • 简单示例(DigesterLoader方式)
    //创建 Digester 实例Digester digester = DigesterLoader.newLoader(new AbstractRulesModule() {@Overrideprotected void configure() {//对象规则forPattern("user").createObject().ofType(User.class);forPattern("user").setProperties();forPattern("user/userName").setBeanProperty().withName("userName");//一对一嵌套对象规则forPattern("user/dept").createObject().ofType(Dept.class);forPattern("user/dept").setProperties();forPattern("user/dept").setNext("setDept");//一对多嵌套对象规则forPattern("user/roles/role").createObject().ofType(Role.class);forPattern("user/roles/role").setProperties();forPattern("user/roles/role").setNext("addRole");}}).newDigester();//解析xmlUser user = digester.parse(new File("E:\\demo2\\src\\test\\resources\\user.xml"));System.out.println(JSON.toJSONString(user, SerializerFeature.PrettyFormat));
  • 简单示例(addRule方式)
    Digester digester = new Digester();//对象规则digester.addRule("user",new ObjectCreateRule(User.class));digester.addRule("user",new SetPropertiesRule());digester.addRule("user/userName",new BeanPropertySetterRule("userName"));//一对一嵌套对象规则digester.addRule("user/dept",new ObjectCreateRule(Dept.class));digester.addRule("user/dept",new SetPropertiesRule());digester.addRule("user/dept",new SetNextRule("setDept"));//一对多嵌套对象规则digester.addRule("user/roles/role",new ObjectCreateRule(Role.class));digester.addRule("user/roles/role",new SetPropertiesRule());digester.addRule("user/roles/role",new SetNextRule("addRole"));//解析xmlUser user = digester.parse(new File("E:\\demo2\\src\\test\\resources\\user.xml"));System.out.println(JSON.toJSONString(user, SerializerFeature.PrettyFormat));
  • 简单示例(addRuleSet方式)
    Digester digester = new Digester();digester.addRuleSet(new RuleSetBase() {@Overridepublic void addRuleInstances(Digester digester) {//对象规则digester.addObjectCreate("user", User.class);//映射对象digester.addSetProperties("user");//属性映射digester.addBeanPropertySetter("user/userName","userName");//子标签映射对象属性//一对一嵌套对象规则digester.addObjectCreate("user/dept", Dept.class);//映射对象digester.addSetProperties("user/dept");//属性映射digester.addSetNext("user/dept", "setDept");//设置对象属性set方法//一对多嵌套对象规则digester.addObjectCreate("user/roles/role", Role.class);//映射对象digester.addSetProperties("user/roles/role");//属性映射digester.addSetNext("user/roles/role", "addRole");//设置对象集合属性add方法}});//解析xmlUser user = digester.parse(new File("E:\\demo2\\src\\test\\resources\\user.xml"));System.out.println(JSON.toJSONString(user, SerializerFeature.PrettyFormat));
  • 加载xml规则示例
    Digester digester = DigesterLoader.newLoader(new FromXmlRulesModule() {@Overrideprotected void loadRules() {loadXMLRules(getClass().getResource("/digester-rules.xml"));}}).newDigester();digester.setValidating(false);//解析xmlUser user = digester.parse(new File("E:\\demo2\\src\\test\\resources\\user.xml"));System.out.println(JSON.toJSONString(user, SerializerFeature.PrettyFormat));
  • 注解配置规则示例
    Digester digester =  DigesterLoader.newLoader(new FromAnnotationsRuleModule() {@Overrideprotected void configureRules() {bindRulesFrom(User.class);}}).newDigester();User user = digester.parse(new File("E:\\demo2\\src\\test\\resources\\user.xml"));System.out.println(JSON.toJSONString(user, SerializerFeature.PrettyFormat));
@ObjectCreate(pattern = "user")
public class User {@SetProperty(pattern = "user")private long userId;@BeanPropertySetter(pattern = "user/userName")private String userName;private Dept dept;private List<Role> roles = new ArrayList<>();@SetNextpublic void addRole(Role role) {this.roles.add(role);}@SetNextpublic void setDept(Dept dept) {this.dept = dept;}//TODO 省略其他get/set方法
}
@ObjectCreate(pattern = "user/dept")
public class Dept {@SetProperty(pattern = "user/dept")private long deptId;@SetProperty(pattern = "user/dept")private String deptName;//TODO 省略其他get/set方法
}
@ObjectCreate(pattern = "user/roles/role")
public class Role {@SetProperty(pattern = "user/roles/role")private long roleId;@SetProperty(pattern = "user/roles/role")private String roleName;//TODO 省略其他get/set方法
}

常用API

Digester

方法说明
Digester()
Digester(SAXParser parser)
Digester(XMLReader reader)
构造方法
addRule(String pattern, Rule rule)用于将 XML 节点路径与自定义规则(Rule)绑定的核心方法,允许在解析到特定节点时执行用户定义的逻辑。
addRuleSet(RuleSet ruleSet)用于批量注册规则集合
addBeanPropertySetter(String pattern)
addBeanPropertySetter(String pattern, String propertyName)
用于将 XML 节点的文本内容或子节点内容自动映射到 Java Bean 属性的规则方法,适用于简化属性赋值操作。
addCallMethod(String pattern, String methodName)
addCallMethod(String pattern, String methodName, int paramCount)
addCallMethod(String pattern, String methodName, int paramCount, String[] paramTypes)
addCallMethod(String pattern, String methodName, int paramCount, Class<?>[] paramTypes)
用于调用 Java Bean 方法的规则,允许在解析到特定 XML 节点时触发指定方法,并支持参数传递。
addCallParam(String pattern, int paramIndex)
addCallParam(String pattern, int paramIndex, String attributeName)
addCallParam(String pattern, int paramIndex, boolean fromStack)
addCallParam(String pattern, int paramIndex, int stackIndex)
addCallParamPath(String pattern, int paramIndex)
用于指定 addCallMethod 调用方法时的参数来源的规则方法,支持从 XML 节点文本、属性或对象栈中动态获取参数值。
addObjectParam(String pattern, int paramIndex, Object paramObj)用于向 addCallMethod 绑定的方法传递固定对象参数的规则方法,适用于需要注入非动态值(如常量、配置对象)的场景。
addFactoryCreate(String pattern, String className)
addFactoryCreate(String pattern, Class<? extends ObjectCreationFactory<?>> clazz)
addFactoryCreate(String pattern, String className, String attributeName)
addFactoryCreate(String pattern, Class<? extends ObjectCreationFactory<?>> clazz, String attributeName)
addFactoryCreate(String pattern, ObjectCreationFactory<?> creationFactory)
addFactoryCreate(String pattern, String className, boolean ignoreCreateExceptions)
addFactoryCreate(String pattern, Class<? extends ObjectCreationFactory<?>> clazz, boolean ignoreCreateExceptions)
addFactoryCreate(String pattern, String className, String attributeName, boolean ignoreCreateExceptions)
addFactoryCreate(String pattern, Class<? extends ObjectCreationFactory<?>> clazz, String attributeName, boolean ignoreCreateExceptions)
addFactoryCreate(String pattern, ObjectCreationFactory<?> creationFactory, boolean ignoreCreateExceptions)
用于通过工厂模式动态创建对象的规则方法,适用于需要自定义对象实例化逻辑的场景。
addObjectCreate(String pattern, String className)
addObjectCreate(String pattern, Class<?> clazz)
addObjectCreate(String pattern, String className, String attributeName)
addObjectCreate(String pattern, String attributeName, Class<?> clazz)
用于在解析 XML 节点时创建 Java 对象,通过指定规则路径和对象类型,将 XML 节点映射为 Java 对象并压入对象栈。
addSetNestedProperties(String pattern)
addSetNestedProperties(String pattern, String elementName, String propertyName)
addSetNestedProperties(String pattern, String[] elementNames, String[] propertyNames)
用于将 XML 子节点的文本内容自动映射到 Java 对象属性的规则方法,特别适用于处理嵌套结构的 XML 配置。
addSetNext(String pattern, String methodName)
addSetNext(String pattern, String methodName, String paramType)
用于将栈顶对象作为参数传递给次栈顶对象指定方法的核心规则方法,常用于处理父子对象关系的构建。
addSetRoot(String pattern, String methodName)
addSetRoot(String pattern, String methodName, String paramType)
用于将当前栈顶对象作为参数传递给根对象(栈底对象)指定方法的规则方法,适用于处理全局对象关系的构建。
addSetProperties(String pattern)
addSetProperties(String pattern, String attributeName, String propertyName)
addSetProperties(String pattern, String[] attributeNames, String[] propertyNames)
用于将 XML 节点的属性自动映射到 Java 对象属性,通过匹配属性名与对象字段名(或指定映射关系)实现属性值的自动注入。
addSetProperty(String pattern, String name, String value)用于将 XML 节点的特定属性值设置为 Java 对象属性,适用于需要显式指定属性名和值的场景。
addSetTop(String pattern, String methodName)
addSetTop(String pattern, String methodName, String paramType)
用于将次栈顶对象作为参数传递给栈顶对象指定方法的规则方法,常用于处理兄弟对象或相邻层级对象之间的交互。
findNamespaceURI(String prefix)根据命名空间前缀查找对应 URI 的方法,通常在处理带命名空间的 XML 文档时使用
getClassLoader()
setClassLoader(ClassLoader classLoader)
用于获取或设置类加载器
getCount()获取规则匹配栈的深度
getCurrentElementName()返回当前 SAX 解析器正在处理的 XML 元素名称
getErrorHandler()
setErrorHandler(ErrorHandler errorHandler)
用于获取获取设置当前 SAX 解析错误处理器
getFactory()用于获取底层 SAX 解析器工厂
getFeature(String feature)
setFeature(String feature, boolean value)
用于检查或配置解析器的功能支持状态
getLogger()
setLogger(Log log)
用于获取或设置当前日志记录器
getSAXLogger()
setSAXLogger(Log saxLog)
用于获取或设置 SAX 解析器内部日志
getMatch()用于获取当前 XML 解析路径
getMatches()返回 Rules 接口实例,包含所有已注册的规则
getNamespaceAware()
setNamespaceAware(boolean namespaceAware)
用于获取或设置 XML 命名空间感知
getXIncludeAware()
setXIncludeAware(boolean xincludeAware)
用于获取或设置 XML XInclude 解析支持,它允许在 XML 文档中嵌入其他 XML 资源。
setPublicId(String publicId)
getPublicId()
用于获取或设置当前解析的 XML 文档公共标识符(Public ID),通常用于 DTD 或 Schema 验证场景
getRuleNamespaceURI()
setRuleNamespaceURI(String ruleNamespaceURI)
用于获取或设置当前规则匹配的命名空间 URI ,通常在自定义规则或调试时使用。
getParser()用于获取底层 SAX 解析器
getProperty(String property)
setProperty(String property, Object value)
用于获取或设置当前解析器的配置属性
getRules()
setRules(Rules rules)
用于获取或设置当前规则集合
getXMLSchema()
setXMLSchema(Schema schema)
获取或设置 Schema 验证
getUseContextClassLoader()
setUseContextClassLoader(boolean use)
用于检查或设置是否使用上下文类加载器(Context ClassLoader)来加载规则相关类
getValidating()
setValidating(boolean validating)
用于检查或设置当前解析器是否启用 XML 文档有效性验证
getXMLReader()用于获取底层 SAX XMLReader 实例
getSubstitutor()
setSubstitutor(Substitutor substitutor)
用于获取或设置当前配置的变量替换器,该替换器负责在解析 XML 时处理变量替换逻辑。
getCustomContentHandler()
setCustomContentHandler(ContentHandler handler)
用于获取用户自定义的 ContentHandler 的方法,该处理器会覆盖 Digester 默认的 XML 事件处理逻辑。
setStackAction(StackAction stackAction)
getStackAction()
用于设置或获取自定义栈操作逻辑的方法,允许在解析 XML 时对对象栈进行动态控制。
getCurrentNamespaces()用于获取当前解析过程中活动的命名空间集合
getExecutorService()
setExecutorService(ExecutorService executorService)
用于获取或设置当前配置的异步解析线程池,该线程池用于支持 asyncParse() 方法的异步 XML 解析。
characters(char[] buffer, int start, int length)用于处理 XML 标签体中的字符数据
startDocument()用于在 XML 文档解析开始时执行初始化操作。
startElement(String namespaceURI, String localName, String qName, Attributes list)用于处理 XML 标签开始时的逻辑
startPrefixMapping(String prefix, String namespaceURI)用于处理 XML 命名空间前缀映射的开始事件。
endDocument()用于在 XML 文档解析结束时执行收尾操作。
endElement(String namespaceURI, String localName, String qName)用于处理 XML 标签结束时的逻辑
endPrefixMapping(String prefix)用于处理 XML 命名空间前缀映射的结束事件。
ignorableWhitespace(char[] buffer, int start, int len)忽略空白字符
processingInstruction(String target, String data)用于处理 XML 文档中的处理指令
getDocumentLocator()
setDocumentLocator(Locator locator)
用于记录 XML 解析过程中的错误位置或调试信息。
skippedEntity(String name)遇到 XML 文档中被跳过的实体时触发的回调方法
notationDecl(String name, String publicId, String systemId)在解析 XML 文档时遇到的 NOTATION 声明时触发的回调方法
unparsedEntityDecl(String name, String publicId, String systemId, String notation)在解析 XML 文档时遇到的未解析实体声明时触发的回调方法
setEntityResolver(EntityResolver entityResolver)
getEntityResolver()
用于自定义 XML 实体解析逻辑,允许开发者覆盖默认的实体解析行为
resolveEntity(String publicId, String systemId)在加载 XML 外部实体(如 DTD 或外部 Schema)时调用的回调方法
error(SAXParseException exception)在遇到 XML 格式错误或解析问题时触发的回调方法
fatalError(SAXParseException exception)在遇到无法恢复的 XML 解析错误时触发的回调方法
warning(SAXParseException exception)遇到 XML 格式可恢复问题或非严重错误时触发的回调方法
parse(File file)
parse(InputSource input)
parse(InputStream input)
parse(Reader reader)
parse(String uri)
parse(URL url)
用于触发 XML 解析流程,将 XML 数据转换为 Java 对象或集合。
asyncParse(File file)
asyncParse(InputSource input)
asyncParse(InputStream input)
asyncParse(Reader reader)
asyncParse(String uri)
asyncParse(final URL url)
异步解析方法,允许在后台线程中解析 XML,避免阻塞主线程。
register(String publicId, URL entityURL)
register(String publicId, String entityURL)
用于将 DTD 或 Schema 文件注册到解析器,以便在解析 XML 时进行本地验证。
registerAll(Map<String, URL> entityValidator)用于批量注册 DTD/Schema 文件
createInputSourceFromURL(URL url)
createInputSourceFromURL(String url)
用于从 URL 创建 XML 输入源的方法,通常用于将远程 XML 资源转换为可解析的 InputSource 对象。
clear()用于清空栈中所有元素,通常在解析开始前或需要重置栈状态时调用。
peek()
peek(int n)
用于获取栈顶元素的引用而不移除它,常用于在解析过程中访问当前正在处理的对象。
pop()用于移除并返回栈顶元素,常用于在解析 XML 时完成当前节点的处理并返回父节点。
push(T object)
push(String stackName, T value)
用于将对象压入栈顶,作为后续解析操作的上下文或父对象。
pop(String stackName)用于移除并返回栈顶元素,常用于在解析 XML 时完成当前节点的处理并返回父节点。
peek(String stackName)
peek(String stackName, int n)
用于获取栈顶元素的引用而不移除它。
isEmpty(String stackName)用于检查 Digester 内部对象栈是否为空,但需注意其参数应为栈对象而非字符串形式的栈名。
getRoot()用于获取解析 XML 后生成的根对象(即栈中最后剩余的唯一对象)。
resetRoot()用于重置根对象或清空对象栈。
isConfigured()用于判断解析器是否已完成初始配置。
peekParams()
peekParams(int n)
用于查看参数栈顶对象但不移除它的方法,通常与 CallMethodRule 配合使用
popParams()用于移除并返回参数栈顶对象的方法,通常与 CallMethodRule 配合处理动态参数。
pushParams(Object… object)用于将对象压入参数栈的方法,通常与 CallMethodRule 配合使用以实现动态参数传递。
createSAXException(String message, Exception e)
createSAXException(Exception e)
createSAXException(String message)
用于创建并包装底层 SAX 解析异常的辅助方法,主要用于统一处理 XML 解析过程中的错误。

DigesterLoader

方法说明
newLoader(RulesModule… rulesModules)
newLoader(Iterable rulesModules)
静态方法,创建实例
setUseContextClassLoader(boolean useContextClassLoader)可链式调用,用于控制是否使用线程上下文类加载器
setClassLoader(ClassLoader classLoader)可链式调用,用于显式指定类加载器
setSubstitutor(Substitutor substitutor)可链式调用,用于配置 XML 解析时变量替换
setNamespaceAware(boolean namespaceAware)
isNamespaceAware()
可链式调用,用于启用 XML 命名空间感知的核心配置,确保解析器能正确处理带命名空间的 XML 标签和属性
setSchema(Schema schema)可链式调用
register(String publicId, URL entityURL)
register(String publicId, String entityURL)
可链式调用 ,用于批量注册 DTD/Schema 文件
setEntityResolver(EntityResolver entityResolver)可链式调用,用于自定义 XML 实体解析逻辑,允许开发者覆盖默认的实体解析行为
setStackAction(StackAction stackAction)可链式调用,用于设置或获取自定义栈操作逻辑的方法,允许在解析 XML 时对对象栈进行动态控制。
setExecutorService(ExecutorService executorService)
getExecutorService()
可链式调用,用于获取或设置当前配置的异步解析线程池,该线程池用于支持 asyncParse() 方法的异步 XML 解析。
setErrorHandler(ErrorHandler errorHandler)
getErrorHandler()
可链式调用, 用于获取获取设置当前 SAX 解析错误处理器
setDocumentLocator(Locator locator)
getDocumentLocator()
可链式调用,用于记录 XML 解析过程中的错误位置或调试信息。
setXIncludeAware(boolean xIncludeAware)
isXIncludeAware()
可链式调用 , 用于获取或设置 XML XInclude 解析支持,它允许在 XML 文档中嵌入其他 XML 资源。
setValidating(boolean validating)
isValidating()
可链式调用 ,用于检查或设置当前解析器是否启用 XML 文档有效性验证
newDigester()
newDigester(Rules rules)
newDigester(SAXParser parser)
newDigester(SAXParser parser, Rules rules)
newDigester(XMLReader reader)
newDigester(XMLReader reader, Rules rules)
创建Digester对象
addRules(Digester digester)用于向 Digester 实例批量注册规则
createRuleSet()用于组织和管理规则集合的核心方法,通过自定义 RuleSet 实现复杂 XML 结构的规则复用和模块化解析。
getRegistrations()用于获取当前已注册规则集合的方法,返回包含所有匹配模式和对应规则的映射表。

实用RulesModule抽象类

抽象类说明
AbstractRulesModule用于定义规则绑定的抽象基类,通过模板方法模式简化规则配置,支持模块化扩展和可读性优化。
AbstractNamespaceURIBasedRulesModule自动将规则与指定的命名空间URI关联,避免在每个规则中重复声明namespaceURI。通过继承该类并实现forPattern()方法,可快速创建模块化的规则绑定。子类可通过重写方法动态修改命名空间绑定行为。
FromAnnotationsRuleModule用于从注解类自动加载规则的模块,通过扫描类上的 Digester 注解动态生成解析规则,大幅简化 XML 到 Java 对象的映射配置。
FromXmlRulesModule用于从 XML 文件动态加载规则的模块,通过解析外部 XML 配置文件生成解析规则,实现规则与代码的解耦。

可用注解

注解说明
ObjectCreate指定 XML 元素匹配时创建的 Java 类
CreationRule等同 ObjectCreate,但需要和DigesterRule一起使用
FactoryCreate通过工厂模式创建复杂对象
SetProperty将 XML 元素属性映射到 Java 对象属性
BeanPropertySetter通过子元素文本设置属性
SetNext建立对象间的父子关系
CallMethod调用对象方法(可指定参数)
CallParam为 @CallMethod 提供参数(如按顺序或属性名绑定)
PathCallParam用于将 XML 解析路径作为参数传递给方法调用的注解,通常与 @CallMethod 配合使用,实现动态参数绑定。
SetRoot设置根对象
SetTop调整对象栈顺序
DigesterRule自定义规则注解
DigesterRuleList自定义规则注解,重复规则声明

可用规则实现类

实现类说明
ObjectCreateRule根据 XML 路径创建 Java 对象
FactoryCreateRule通过工厂模式创建Java对象
BeanPropertySetterRule将 XML 元素内容绑定到 Java Bean 属性。
SetPropertiesRule将XML属性映射到Java对象属性
SetPropertyRule设置单个指定属性
SetNextRule将当前对象绑定到父对象的指定方法。
CallMethodRule定义要调用的方法名
CallParamRule定义方法参数的来源和类型,必须与CallMethodRule配合使用
ObjectParamRule在方法调用时传递固定值或来自XML属性的值,必须与CallMethodRule配合使用
PathCallParamRule用于将当前解析路径作为参数传递给目标方法,必须与CallMethodRule配合使用
IncludeRule用于在解析过程中动态加载和合并外部XML片段。
NodeCreateRule用于将XML元素转换为DOM节点,支持创建Element或DocumentFragment类型的节点,适用于需要保留XML结构或进行DOM操作的场景。
PatternRule用于基于XPath模式匹配XML元素并触发自定义处理,通过组合Pattern匹配器和Rule处理器实现灵活的XML解析逻辑。
PluginCreateRule用于动态插件创建,允许在解析XML时根据配置动态实例化插件对象,支持用户指定或默认插件类,并可加载自定义规则。
PluginDeclarationRule用于预声明插件类,允许在XML中通过ID或类名引用插件,并在后续解析时动态创建插件实例。
SetNamespaceURIRule用于设置XML命名空间URI,它允许在解析过程中动态关联命名空间与规则集。
SetRootRule当匹配到指定XML元素时,将当前栈顶对象作为参数调用根对象
SetTopRule将次栈顶对象作为参数调用栈顶对象,常用于建立父子对象关系。
http://www.dtcms.com/a/474996.html

相关文章:

  • 静态网站开发学网站开发看什么书
  • OpenAI Agents 记忆管理示例
  • 网站 做 app开发工具wordpress页眉插件
  • 做网站用的什么服务器建筑模板怎么装
  • 网站后台文档深圳做h5网站设计
  • Git版本控制的讲解及详细的安装流程
  • 珠海市手机网站建设公司邗江区做网站
  • 深圳营销型网站建设服务商网站开发与部署
  • 北京建网站 优帮云建设企业网站地址
  • 邢台住房和城乡建设部网站西安网页设计工资
  • 网站加后台广州建设外贸网站
  • Ape.Volo项目启动前端项目时报错“digital envelope routines::unsupported”
  • 全球算力投资激增与人工智能产业演进:多维度分析与未来展望
  • 网站建设岗位廉政风险防控正规的网页制作
  • 东莞高埗网站建设简易网站建设维护
  • C#中堆和栈的概念
  • 安康网站制作青岛网站建站团队
  • 域名估价哪个网站准确江西恒通建设工程有限公司网站
  • 沈阳黑酷做网站建设优化公司怎么样jsp mysql 网站开发
  • 网站开发使用云数据库技术教程制作图片的软件加字体
  • 防火墙的类别和登录Web的方法
  • 江西教育网站建设成都短视频代运营
  • 鸿运通网站建设怎么样马鞍山网站建设费用
  • Agent S / Agent S2 的架构、亮点与局限
  • [数据结构] 哈希表
  • 网站域名后缀那个好中山做网站费用
  • Linux系统编程—Linux进程信号
  • 中小企业网站制作是什么网站php源码
  • MySQL笔记12
  • 改变网站的域名空间国家示范校建设网站