问题是:
我有一个叫做Schema的基类,它是抽象的,它是一个未生成的类。我有两个从Schema继承生成的JAXB类:FixedWidthSchema和DelimitedSchema。
我使用外部绑定(xjb)文件来指定XSD和Java类之间的映射。
在基类模式中,我定义了几个方法:
我希望抽象方法(2,4,5和6)在生成的jaxb类FixedWidthSchema和DelimitedSchema中实现。两者都扩展了基类架构。因此,当我调用schema.isFixedWidth()时,底层继承类将应答这个调用,并告诉调用方:true/false。只有派生的类知道他们是谁:fixedwidth或delimited。
下面是xsd:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="schema" type="SchemaType"/>
<xs:complexType name="SchemaType">
<xs:choice>
<xs:element minOccurs="1" maxOccurs="1" name="delimited" type="DelimitedSchemaType"/>
<xs:element minOccurs="1" maxOccurs="1" name="fixedwidth" type="FixedWidthSchemaType"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="DelimitedSchemaType">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="locale" type="LocaleType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="FixedWidthSchemaType">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="locale" type="LocaleType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="LocaleType">
<xs:attribute name="language" type="languageType" use="required"/>
<xs:attribute name="country" type="countryType" use="required"/>
<xs:attribute name="variant" type="variantType" use="optional"/>
</xs:complexType>
</xs:schema>
XML模式包含两个选择:fixedwidth或delimited,两者都有一个区域设置类型。为了清楚起见,省略了架构的其余部分。
绑定文件如下所示:
<?xml version="1.0" encoding="utf-8"?>
<jaxb:bindings jaxb:version="2.2" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://jaxb2-commons.dev.java.net/basic/inheritance"
schemaLocation="myschema.xsd" node="/xs:schema">
<jaxb:schemaBindings>
<jaxb:package name="org.mylib.schema"/>
</jaxb:schemaBindings>
<jaxb:bindings node="//xs:complexType[@name='DelimitedSchemaType']">
<jaxb:class name="DelimitedSchema"/>
<xjc:extends>org.mylib.schema.Schema</xjc:extends>
</jaxb:bindings>
<jaxb:bindings node="//xs:complexType[@name='FixedWidthSchemaType']">
<jaxb:class name="FixedWidthSchema"/>
<xjc:extends>org.mylib.schema.Schema</xjc:extends>
</jaxb:bindings>
<jaxb:bindings node="//xs:complexType[@name='LocaleType']">
<jaxb:class name="locale" />
</jaxb:bindings>
</jaxb:bindings>
我的maven pom.xml文件如下所示:
...
<build>
<resources>
<resource>
<directory>${pom.basedir}/src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.13.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<specVersion>2.2</specVersion>
<schemaDirectory>src/main/resources</schemaDirectory>
<schemaIncludes>
<schemaInclude>myschema.xsd</schemaInclude>
</schemaIncludes>
<bindingDirectory>src/main/resources</bindingDirectory>
<bindingIncludes>
<bindingInclude>dataschema.xjb</bindingInclude>
</bindingIncludes>
<generateDirectory>${project.build.directory}/generated-sources/jaxb2</generateDirectory>
<extension>true</extension>
<args>
<arg>-Xinheritance</arg>
</args>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>1.11.1</version>
</plugin>
</plugins>
<!-- Generate lots of output -->
<verbose>true</verbose>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
XJC输出以下生成的类:
SchemaType类如下所示:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SchemaType", propOrder = { "delimited", "fixedwidth"})
public class SchemaType {
protected DelimitedSchema delimited;
protected FixedWidthSchema fixedwidth;
public DelimitedSchema getDelimited() {
return delimited;
}
public void setDelimited(DelimitedSchema value) {
this.delimited = value;
}
public FixedWidthSchema getFixedwidth() {
return fixedwidth;
}
public void setFixedwidth(FixedWidthSchema value) {
this.fixedwidth = value;
}
}
现在不好的部分是,编译器(XJC)抱怨:
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] \mylib\target\generated-sources\jaxb2\org\mylib\schema\DelimitedSchema.java:[51,7] error: DelimitedSchema is not abstract and does not override abstract method isFixedWidth() in Schema
[ERROR] \mylib\target\generated-sources\jaxb2\org\mylib\schema\FixedWidthSchema.java:[51,7] error: FixedWidthSchema is not abstract and does not override abstract method isFixedWidth() in Schema
[INFO] 2 errors
[INFO] -------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] -------------------------------------------------------------
我要问的问题是:
到目前为止,我还没有找到解决这些问题的方法。有可能吗?还是我在寻找一个无法使用JAXB2.x创建的不可能的解决方案?
所需的解决方案:
我的解决方案--考虑的方向是执行封送和解封的Schema类,模式知道要封送/解封哪个模式。派生类实现了Schema类定义的需要实现的方法。
任何方向正确的帮助/建议都非常感谢。
更新:
抽象模式类(它是非生成的类)与生成的类FixedWidthSchema和DelimitedSchema有关系。DelimitedSchema是一个模式,FixedWidthSchema是一个模式。因此,模式接口--定义为抽象类--是用户需要拥有/使用的唯一接口。用户不需要知道模式的内部细节,它是FixedWidth还是Delimited模式对用户并不重要,只对我正在编写的代码重要。代码可以通过调用isFixedWidth()或isDelimited()方法来确定它是哪个模式。用户只需要引用接口架构,而不需要引用任何FixedWidthSchema或DelimitedSchema实例。在用户视点中隐藏的。我面临的问题是,我可以从手写的Schema类扩展生成的类FixedWidthSchema或DelimitedSchema,但现在手写的Schema不包含生成的SchemaType类,封送/解封送XML源中的
File f = new File("path/to/my/xmlfile.xml");
Reader r = new FileReader(f);
Schema sch = Schema.unmarshal(r);
// somewhere in other code parts:
if (sch.isDelimited()) {
DelimitedSchema delSch = (DelimitedSchema)sch;
}
// or...:
if (sch.isFixedWidth()) {
FixedWidthSchema fwSch = (FixedWidthSchema)sch;
}
现在,内部代码可以获得所转换模式的特定方法,从而寻址该特定模式的getters/setters。
通常,用户不需要知道模式的内部内容,因为代码本身将通过内部转换为“Right”类来处理fixedwidth或delimited之间的差异。
用户只对这些方法调用中的一个感兴趣:
// To get a Schema instance (either fixedwidth or delimited) by unmarshalling a XML file.
Schema sch = Schema.unmarshal(aReader);
// Marshal the current schema instance to a XML file, using a Writer.
Writer wtr = sch.marshal();
// Create a schema instance by providing a Model on which the schema is based. This can be a fixedwidth or delimited Model.
Schema sch = Schema.create(m);
// Validate the schema if there are no errors.
sch.validate();
注意:我不希望SchemaType类包含在has-a关系中的Schema类中。我希望它是基/超类模式和派生生成的FixedWidthSchema或DelimitedSchema之间的is-a关系。我认为这是可能的,至少在正常的Java代码中是可能的,但问题是:如何使用JAXB生成的类来完成这一点?这是我还没想好怎么做的部分。
我还很好奇如何编写一个JAXB插件,将类和方法修饰符的访问修饰符从public修改为package-private。
感谢所有的帮助,因为这对我来说是一个真正的JAXB难题。在正常的(非生成的)代码中,这对编程来说是小菜一碟。
额外:
分隔和固定宽度XML文件的内容。
分隔的XML:
<?xml version="1.0" encoding="utf-8"?>
<dataschema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<delimited> <-- should be handled in Schema.java and not in SchemaType.java
<locale language="en" country="en" />
</delimited>
</dataschema>
FixedWidth XML:
<?xml version="1.0" encoding="utf-8"?>
<dataschema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<fixedwidth> <-- should be handled in Schema.java and not in SchemaType.java
<locale language="en" country="en" />
</fixedwidth>
</dataschema>
fixedwidth和delimited架构不相同!我省略了所有其他元素,以使示例XML文件在StackOverflow中的问题达到最低限度。
解决方案
我设法解决了代码和思维中的一些怪癖。这些是吸取的宝贵经验教训:
>
不要创建JAXB生成的类必须从其扩展的非生成的抽象Java基/超类。所以,手写的Java类和生成的类之间没有遗传!
如果真的需要,可以使用建议的JAXB
插件由user lexicore进行代码注入,而不是继承!
代码注入使用以下设置与Maven一起工作(有关配置上下文,请参阅上面的
):
· ·
而不是继承或代码注入,在代码生成的类中尽可能地阻止使用这些机制。当看到/使用生成的类仅作为数据容器时,就不需要它们了。
对业务数据类和业务逻辑类进行区分。例如:模式类只保存要从模型类封送和解封的数据。模型类保存数据和应用程序操作数据的实际方法。模式类是JAXB生成的类。模型类是手写的类。
使生成的类尽可能简单,最好用外部绑定文件(*.jxb)修改生成的类。例如:重命名类名、指定用于转换的XmlAdapter类等。
为了克服不能将@XmlRootElement注释添加到生成的基/根类中的问题,请确保将基/根元素的complexType作为匿名complexType嵌入到XSD中。注意,@XmlRootElement将只为顶级元素的匿名类型生成,而不是顶级类型!
在特定领域(JAXB)中更有经验的开发人员提供给您的建议时,请听取good advise(好建议)。当解决方法很简单的时候,不要试图变得“聪明”。
结论:将业务逻辑从生成的代码中移开!
最终结果很简单(在DataModel类中):
所有生成的模式类现在只在DataModel的marshal()和unmarshal()方法内部使用。这使得DataModel API独立于生成的类,因此在开发过程中稍后修改XML模式或生成的类时不会出现接口问题。
那都是人。
对于1,您可以使用代码注入器插件。请参阅此问题
对于2,我没能理解您所说的“将生成的SchemaType类集成到Schema类中”是什么意思。
对于3-是的,使用您自己的XJC插件,但这可能有点难。:)
一个建议:只将模式派生的类用作DTO,不要试图在那里推进太多的业务逻辑。
更新
想要实现什么,还是有点难以理解。您用所有这些“is-a”和“has-a”来解释您想为用户做什么,但仍然不清楚“integrate”是什么意思。
从另一方面讲,整个故事归结为以下问题:
现在生成哪些代码,您希望生成哪些代码?
那是核心。如果你回答了这个问题,你就会得到一个可以回答的编程问题。现在,您只需描述您的用例,并期望有人为您设计一个解决方案。
根据我的理解,您只是希望您的模式派生的类delimitedschema
和fixedwidthschema
实际实现(或扩展)您的基类schema
。那你为什么不这么做呢?通过xjc:extends
(或JAXB继承插件),您可以轻松地使delimitedschema
和fixedwidthschema
扩展schema
。您的schema
类可能是一个抽象类,它定义了几个只能由特定实现来实现的抽象方法。
这可以通过使用代码注入器插件注入代码来完成。您只需将Schema
类中抽象方法的实现注入到DelimitedSchema
和FixedWidthSchema
类中。则这些类的实例可以作为schema
的实现返回给用户。
令我不解的是,你其实已经知道了所有这些元素。您了解xjc:extends
、代码注入等等。少了什么?
最后提出几点建议。
unmarshal
/marshal
方法移动到业务类。将序列化与业务模型分开。实现单独的SchemaReader
或类似的东西。是否有任何JAXB绑定可以告诉JAXB代码生成器将Java类生成为,而不必在XSD中将相应的XML类型标记为? 情况如下: > 我在xsd中定义架构: 我使用内联JAXB绑定(“inline”==“直接在模式中”)来指示应该生成JAXB类的包(): 我使用内联JAXB绑定为我的每个复杂类型(在本例中、和)指示实现类的名称: 我从模式生成JAXB类。这导致: 我自己编写类: 使用这两个类层次结构这样
我目前正在尝试使用JaxB,但对于一个相对简单的示例,我并不是很成功。我的示例如下: 我所有的尝试(甚至编组)都失败了。我浏览了BlaiseDoughan的博客,包括http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html但他们似乎对我的例子都没有帮助。我很可能误用了他的例子。在我看来,我的示例应该是JaxB中
继承一个可以实现的普通超类有什么不同吗? atm我有一个名为的抽象类,我有/扩展这个。 abstractcar中的一个字段设置为"私有int容量" 但是在子类“小型汽车”中,当我输入“容量”作为构造函数中使用的变量时,它说“容量在抽象汽车中有私有访问” 我想: > 子类继承超类的所有字段和方法? 我现在该怎么进行?
我有一个抽象类,这个类是在她的子类中扩展的: < li >我在这个抽象类上实现了一个方法,并抽象了另一个方法 < li >实现的方法是每个子类对象都必须访问的通用方法。所以我决定在抽象类上实现它,避免在每个子类上实现相同的方法。 小例子: 我想听听你对这种实施方式的看法, 问候。
问题内容: 我正在尝试使用JAXB解组一些XML,但出现“无法创建…的实例”异常。我知道为什么- 它试图建立一个抽象类的实例。我想要的是让它成为特定实现类的实例。我的目标是对setter方法进行特定于类的检查。对于BarImpl,也许“ qux”是有效的baz值,但BarImpl2想要做其他事情。 我没有通过注释Foo来实现这一目标,但是如果我不注释bar,事情就会变得很丑。 问题答案: 您可以执
本文向大家介绍php中的抽象方法和抽象类,包括了php中的抽象方法和抽象类的使用技巧和注意事项,需要的朋友参考一下 1、什么是抽象方法? 我们在类里面定义的没有方法提的方法就是抽象方法。所谓的没有方法体指的是,在声明的时候没有大括号以及其中的内容,而是直接在声明时在方法名后加上分号结束,另外在声明抽象方法时方法还要加一个关键字"abstract"来修饰。 例如: 2、什么是抽象类? 只要一个类里面