Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JAXB:Isn';不使用@XmlJavaTypeAdapter就不能使用XmlAdapter吗?_Java_Jaxb_Adapter - Fatal编程技术网

JAXB:Isn';不使用@XmlJavaTypeAdapter就不能使用XmlAdapter吗?

JAXB:Isn';不使用@XmlJavaTypeAdapter就不能使用XmlAdapter吗?,java,jaxb,adapter,Java,Jaxb,Adapter,我能否将一堆XmlAdapter注册到Marshaller|解组器,这样我就不需要在每个字段上指定@XmlJavaTypeAdapter,因为它的类型本机不支持JAXB 我觉得有点像 顺便说一句,someMarshaller.setAdapter(…)似乎什么都不做。这是一个很好的问题 简而言之,在封送器/解封器上使用setAdapter并不意味着不必使用@XmlJavaTypeAdapter @XmlRootElement(name="event") @XmlType(name="") pub

我能否将一堆
XmlAdapter
注册到
Marshaller
|
解组器
,这样我就不需要在每个字段上指定
@XmlJavaTypeAdapter
,因为它的类型本机不支持JAXB

我觉得有点像


顺便说一句,
someMarshaller.setAdapter(…)
似乎什么都不做。

这是一个很好的问题

简而言之,在封送器/解封器上使用
setAdapter
并不意味着不必使用
@XmlJavaTypeAdapter

@XmlRootElement(name="event")
@XmlType(name="")
public class Event {

    @XmlElement(required=true)
    // @XmlJavaTypeAdapter(UserAdapter.class) 
    protected User performedBy;
}
让我用一个假设(但有效!)的场景来解释这一点

考虑在web应用程序中,以具有以下模式的xml形式获取事件:

<xs:element name="event" >
    <xs:complexType>
        <xs:sequence>
           <!-- Avoiding other elements for concentrating on our adapter -->
            <xs:element name="performedBy" type="xs:string" />   
        </xs:sequence> 
    </xs:complexType>  
</xs:element>
现在应用程序已经有了一个名为
User
的bean,它维护详细的 有关用户的信息

public class User {

    private String id;
    private String firstName;
    private String lastName;

    ..
}
请注意,您的JAXB上下文不知道这个
用户。
为了简单起见,我们将User作为POJO,但它可以是任何有效的Java类

应用程序架构师想要的是
Event
performedBy
应该表示为
User
获取全部细节

这里是@XmlJavaTypeAdapter出现的地方

JAXBContext知道
performedBy
xs:string
,但它必须表示为
用户
在Java内存中

修改后的模型如下所示:

@XmlRootElement(name="event")
@XmlType(name="")
public class Event {

     @XmlElement(required=true)
     @XmlJavaTypeAdapter(UserAdapter.class) 
     protected User performedBy;
}
UserAdapter.java:

public class UserAdapter extends XmlAdapter<String, User> {

     public String marshal(User boundType) throws   Exception {
             ..   
     } 

     public User unmarshal(String valueType) throws Exception {
             ..
     } 
}
setAdapter
方法在
Marshaller
Unmarshaller

注:

  • marshaller/unmarshaller上的
    setAdapter
    并不意味着您不必使用
    @XmlJavaTypeAdapter

    @XmlRootElement(name="event")
    @XmlType(name="")
    public class Event {
    
        @XmlElement(required=true)
        // @XmlJavaTypeAdapter(UserAdapter.class) 
        protected User performedBy;
    }
    
    如果省略这个JAXB运行时,就不知道用户是绑定类型&值类型是其他类型。它将尝试按原样封送
    用户
    &u将以错误的xml结束 (如果启用,则验证失败)

  • 虽然我们采用了一种场景,其中适配器必须带有参数,因此 使用
    setAdapter
    方法

    还有一些先进的用法,在中,即使您没有默认的arg构造函数,但仍然提供了适配器的实例

    可能此适配器配置了数据,封送/解封操作正在使用该数据


  • 您可以使用package-info.java

    这就是所谓的“包级别”

    例如: 将package-info.java放在要封送/解封的类所在的包中

    假设您有一个类mypackage.model.a和一个适配器CalendarAdapter在mypackage.adapter中。 在mypackage.model中声明一个package-info.java文件,其中包含:

    @XmlJavaTypeAdapters({
        @XmlJavaTypeAdapter(value = CalendarAdapter.class, type = Calendar.class)
    })
    package mypackage.model;
    
    import java.util.Calendar;
    import mypackage.adapter.CalendarAdapter;
    
    类A中Calendar类型的所有字段都将使用CalendarAdapter封送或取消封送

    您可以在那里找到有用的信息:

    所以简短的回答是否定的。如果不使用@xmlJavaTypeAdapter注释,就不能使用XmlAdapter
    public class Test {
    
    public static void main(String... args) { 
        JAXBContext context = JAXBContext.getInstance(Event.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();
    
          UserContext userContext = null; // fetch it from some where
          unmarshaller.setAdapter(UserAdapter.class, new UserAdapter(userContext));
    
          Event event = (Event) unmarshaller.unmarshal(..);
       }
    }
    
    @XmlRootElement(name="event")
    @XmlType(name="")
    public class Event {
    
        @XmlElement(required=true)
        // @XmlJavaTypeAdapter(UserAdapter.class) 
        protected User performedBy;
    }
    
    @XmlJavaTypeAdapters({
        @XmlJavaTypeAdapter(value = CalendarAdapter.class, type = Calendar.class)
    })
    package mypackage.model;
    
    import java.util.Calendar;
    import mypackage.adapter.CalendarAdapter;