- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个基于 XSD 的嵌套 XML 结构。我使用 JAXB 进行解码(只读)。
通常,我需要在大型结构中的某处查找一个或多个元素。为了避免每次需要搜索时都要遍历结构,我想添加一个带有内部缓存的优化搜索功能。
定义它的最佳方式是什么?不同方式的优点/缺点是什么?
我最初想到使用外观或适配器,其中适配器类访问生成的类并根据需要添加方法;不过我想征求建议。
<小时/>作为一个(稍微)简化的示例,需要在基于此 XSD 的 XML 中搜索具有特定“boq”元素的“step”类型的元素:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="test">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="group"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="group">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="step"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="step">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" ref="number"/>
<xs:element ref="name"/>
<xs:element ref="type"/>
<xs:element ref="target"/>
<xs:sequence minOccurs="0">
<xs:element ref="boq"/>
<xs:element ref="remote"/>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="number" type="xs:integer"/>
<xs:element name="name" type="xs:NCName"/>
<xs:element name="type" type="xs:NCName"/>
<xs:element name="target" type="xs:NCName"/>
<xs:element name="boq" type="xs:string"/>
<xs:element name="remote" type="xs:string"/>
</xs:schema>
该架构是使用 JAXB 编译的,因此我得到了几个类。使用解码功能,我可以在内存中获得可访问 XML 的数据结构。
现在考虑一下,我需要一个优化的搜索函数,它访问定义了 boq 元素的所有步骤,并返回 boq 和 remote 的值(如果也定义了)。
HashMap<String,Step> resultMap = new HashMap<>();
test.getGroup().forEach(group ->
group.getStep().forEach(step -> {
if ("searchpattern".equals(step.getBoq()))
resultMap.put("searchpattern", step);
}));
封装此类搜索的最佳方法是什么?我可以编写第二个类作为包含此方法的适配器,或者是否有更好的选择?遗产?使用 JAXB 本身的选项?使用第三方插件,例如 Maven 的 jaxb-delegate 插件?
最佳答案
有很多选项可以解决这个问题。
最简单的方法是在实用程序类中简单地实现访问路由。因此,基本上您将调用类似 SearchPatterns.of(foo)
的内容,并将模式派生类的实例传递给它。与 foo.getSearchPatterns()
(其中 getSearchPatterns()
以某种方式添加到架构派生类中)相比,区别并不大。好吧,好吧,不是那么 OOP 封装,无论如何,但是,坦率地说,谁在乎呢。
您可以使用 XJC 代码注入(inject)器插件在生成的类中注入(inject)任何代码。请参阅以下问题的示例:
Inserting code with XJC+xsd+jxb using the options " -Xinject-code -extension "
(如果您遇到问题,请提出另一个问题。我意识到我们在 jaxb 中没有首选的 XJC 代码注入(inject)器问题。)
这对您来说相对容易,并且允许您注入(inject)任何您想要的代码。
缺点是部分 Java 代码将驻留在奇怪的 XML 文件中。
另一种选择是准备一个抽象类,其中包含您需要的访问器方法(例如,getSearchpatterns()
)及其使用的方法(getGroup()
),如下所示抽象方法。然后让你的模式派生类扩展这个准备好的抽象类。生成的方法将实现在准备好的父类(super class)中定义的抽象方法。这本质上是一种“模板方法”模式。
有很多方法可以使架构派生类扩展现有类。这是其中之一:
JAXB Marshalling - extending an existing class
或者您可以使用JAXB2 Basics中的继承插件。 免责声明:我是作者。
您可以使用模板方法+访问器的默认方法定义一个接口(interface),并让您的架构派生类实现它,而不是扩展类。
我不喜欢这个选项,因为它滥用继承只是为了添加实用方法。
您想要添加的访问器背后可能有一些特定的逻辑。因此,也许您实际上可以根据“特定逻辑”生成访问器,而不是简单地注入(inject)代码(如使用代码注入(inject)器插件)。
然而,这是一种非常复杂的方法。请参阅this answer进行简短概述。只有当确实存在“特定逻辑”时我才会接受
我个人更喜欢将业务逻辑与模式派生类分开。我可能是那里最大的 JAXB/XJC 粉丝之一。我肯定会编写一个实用程序类来提供您想要的任何访问器。
我不喜欢“代码注入(inject)器”选项,因为这样您的部分代码就会出现在一些奇怪的 XML 文件中。因此,如果您要在 IDE 中重构任何内容,则不会触及该代码。
扩展一个准备好的抽象类或实现一个准备好的接口(interface)也不是我最喜欢的。我认为这只是滥用 OOP 结构来添加一些实用程序代码。
对于没有太多 XJC 插件经验的开发人员来说,编写自己的插件实在太复杂了。另外,我无法识别可以以某种方式概括的“特定逻辑”,因此这个选项可能甚至没有意义。
关于java - 将访问例程添加到 JAXB 生成的源自 XSD 的类集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51340580/
我最近购买了《C 编程语言》并尝试了 Ex 1-8这是代码 #include #include #include /* * */ int main() { int nl,nt,nb;
早上好!我有一个变量“var”,可能为 0。我检查该变量是否为空,如果不是,我将该变量保存在 php session 中,然后调用另一个页面。在这个新页面中,我检查我创建的 session 是否为空,
我正在努力完成 Learn Python the Hard Way ex.25,但我无法理解某些事情。这是脚本: def break_words(stuff): """this functio
我是一名优秀的程序员,十分优秀!