Đây là một câu hỏi khá hay!
Câu trả lời ngắn gọn là không, sử dụng setAdapter
trên marshaller/unmarshaller không có nghĩa là bạn không cần phải sử dụng @XmlJavaTypeAdapter
.
Hãy để tôi giải thích điều này với một kịch bản giả định (nhưng hợp lệ!).
xem xét trong một ứng dụng web, người ta lấy về một sự kiện trong dạng xml có sau schema:
<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>
Tương đương này, mô hình của bạn sẽ trông giống như:
@XmlRootElement(name="event")
@XmlType(name="")
public class Event {
@XmlElement(required=true)
protected String performedBy;
}
Bây giờ ứng dụng đã có một bean được gọi là User
, trong đó duy trì thông tin chi tiết về người dùng.
public class User {
private String id;
private String firstName;
private String lastName;
..
}
Lưu ý rằng điều này User
không được biết đến trong ngữ cảnh JAXB của bạn. Để đơn giản, chúng tôi có User là POJO, nhưng nó có thể là bất kỳ Lớp Java hợp lệ nào.
Kiến trúc sư ứng dụng muốn là performedBy
của phải được đại diện là User
để có được chi tiết đầy đủ.
Đây là nơi @XmlJavaTypeAdapter đi vào hình ảnh
JAXBContext là nhận thức về performedBy
như xs:string
, nhưng nó phải được thể hiện dưới dạng User
trong bộ nhớ trong Java.
mô hình Modified trông giống như:
@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 {
..
}
}
nét
Các Adapter nói rằng -
- BoundType là User (Trong đại diện Memeory)
- ValueType là String (Bối cảnh kiểu dữ liệu JAXB được nhận thức)
Quay lại câu hỏi của bạn -
Tôi thấy nó hơi dư thừa.
BTW, someMarshaller.setAdapter (...) dường như không làm gì cả.
Hãy xem xét Bộ điều hợp của chúng tôi yêu cầu một lớp được gọi là UserContext để sắp xếp/unmarshal thành công.
public class UserAdapter extends XmlAdapter<String, User> {
private UserContext userContext;
public String marshal(User boundType) throws Exception {
return boundType.getId();
}
public User unmarshal(String valueType) throws Exception {
return userContext.findUserById(valueType);
}
}
Bây giờ, câu hỏi là UserAdapter sẽ tìm nạp một instace của UserContext như thế nào ?? Là một thiết kế tốt ta nên luôn luôn cung cấp cho nó trong khi nó đã bị khởi ..
public class UserAdapter extends XmlAdapter<String, User> {
private UserContext userContext;
public UserAdapter(UserContext userContext) {
this.userContext = userContext;
}
public String marshal(User boundType) throws Exception {
return boundType.getId();
}
public User unmarshal(String valueType) throws Exception {
return userContext.findUserById(valueType);
}
}
Nhưng JAXB Runtime chỉ có thể chấp nhận Adapter với No-args constructor .. (Rõ ràng JAXBContext không biết về mô hình ứng dụng cụ thể)
vì vậy, may mắn có một tùy chọn: D
bạn có thể nói với bạn unmarshaller
sử dụng Ví dụ nhất định UserAdapter
hơn instating nó bằng cách riêng của mình.
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(..);
}
}
setAdapter
phương pháp có sẵn trên cả Marshaller
& Unmarshaller
Lưu ý:
setAdapter
trên marshaller/unmarshaller không có nghĩa là bạn không cần phải sử dụng @XmlJavaTypeAdapter
.
@XmlRootElement(name="event")
@XmlType(name="")
public class Event {
@XmlElement(required=true)
// @XmlJavaTypeAdapter(UserAdapter.class)
protected User performedBy;
}
Nếu bạn bỏ qua thời gian chạy JAXB này không có đầu mối nào Người dùng là Loại ràng buộc & Loại giá trị của bạn là thứ khác. Nó sẽ cố gắng sắp xếp User
như là & u sẽ kết thúc có sai xml (hoặc xác nhận thất bại nếu được kích hoạt)
Trong khi chúng tôi đã thực hiện một kịch bản mà Adaptor bắt buộc phải có đối số, do đó sử dụng setAdapter
phương pháp.
Một số tập quán adavanced cũng có ở đó, nơi mà trong ngay cả khi bạn có mặc định không-arg constructor, nhưng bạn cung cấp một thể hiện của Adapter
Có bộ chuyển đổi này được cấu hình với dữ liệu, mà soái/hoạt động unmarshal đang sử dụng !
** câu trả lời quá ngắn là KHÔNG ** Bạn không thể sử dụng XmlAdapter mà không sử dụng @xmlJavaTypeAdapter chú thích. – user1128134