我发现在 Java 7 上处理 Jaxb 与在 Java 8 上处理 Jaxb 之间存在另一个区别。我已将问题简化为一个简化的示例,并且代码应作为单个类运行。 (更改了类别,因此它与工作无关等)当 Unmarshaller 调用列表的 setter 时:
我的问题实际上是一个变体
- 编码列表访问器时建议省略
在编写 JaxB 时完全使用 Setter 吗? (因为它似乎确实处理
通过 Getter 列出)
- 有推荐的替代方法吗?
在 Java 7 中运行时,将使用列表中的数据调用 setter。
当在 Java 8 中运行时,只会使用一个空的 List 对象来调用 setter,该对象显然会在稍后的解组过程中填充。
我体验到的不同之处在于,我不能让 setter 对 List 进行任何处理,而是有一个仅在整个对象解组后才调用的进程。或者总结一下,“不要在 setter 中进行任何处理”。
示例如下:(三个类)- 在 Java 7 下,返回的结果是在 setter 中找到的列表中的第一个“专辑”标题。在 Java 8 下,返回 null。
该代码应作为没有依赖项的单个类运行。
如果在 Java 7 中运行,“第一张专辑”显示的标题是“Abbey Road”。
如果在 Java 8 中运行“第一张专辑”标题为 null
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
public class MainJaxbCase {
public static void main( String[] args ) {
new MainJaxbCase().testIt();
}
private void testIt() {
try {
AlbumLib myLib = (AlbumLib) loadJaxbDocFromString( inXmlStr, AlbumLib.class );
System.out.println("category:"+ myLib.getCateg());
List<AlbumItm> albumList = myLib.getAlbumList();
System.out.println("AlbumList size is " + albumList.size());
System.out.println("The first album is titled:"
+ myLib.getFirstAlbumTitle()
+ "- shows \"null\" if using Java 8, \"Abbey Road\" if using Java 7"
);
} catch ( Exception e ) {
System.out.println( e.getClass().getSimpleName() + ", msg:" + e.getMessage() );
e.printStackTrace();
}
}
private final String inXmlStr =
"<my_lib categ='albums'>"
+ " <album title='Abbey Road'/> "
+ " <album title='Revolver'/>"
+ " <album title='Sgt.Pepper'/>"
+ "</my_lib>";
private Object loadJaxbDocFromString ( String inStr, Class<?> clazz ) throws Exception {
Object result = null;
try {
InputStream is = new ByteArrayInputStream( inStr.getBytes() );
result = unmarshal( is, clazz );
} catch ( Exception e ) {
String msg = this.getClass().getSimpleName() + ".loadJaxbDocFromResource() caught " + e.getClass().getSimpleName() + " msg:" + e.getMessage();
throw new Exception(msg);
}
return result;
}
private Object unmarshal( InputStream prmIs, Class<?> clazz ) throws Exception{
Object obj = null;
try {
JAXBContext jaxbContext = JAXBContext.newInstance( clazz );
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
obj = jaxbUnmarshaller.unmarshal( prmIs );
} catch ( Exception e ) {
String msg = this.getClass().getSimpleName() + " caught " +
e.getClass().getSimpleName() + ", msg:" + e.getMessage();
msg += " Trying to Unmarshall class " + clazz.getName();
System.err.println(msg);
e.printStackTrace();
throw new Exception(msg);
}
return obj;
}
}
@XmlRootElement ( name= "my_lib")
class AlbumLib {
private String categ;
private List<AlbumItm> albumList;
private String firstAlbumTitle;
@XmlAttribute ( name="categ")
public String getCateg() {
return this.categ;
}
public void setCateg( String val ) {
this.categ=val;
}
@XmlElement ( name="album")
public List<AlbumItm> getAlbumList() {
return this.albumList;
}
public void setAlbumList( List<AlbumItm> newList ) {
if ( newList != null && newList.size() > 0 ) {
firstAlbumTitle = newList.get(0).getTitle();
}
this.albumList = newList;
}
public String getFirstAlbumTitle() {
return this.firstAlbumTitle;
}
}
@XmlType(name = "album")
class AlbumItm {
private String title;
@XmlAttribute ( name="title" )
public String getTitle() {
return this.title;
}
public void setTitle(String val ) {
this.title = val;
}
}
出现这个问题是因为我们的代码在切换到 Java 8 时开始表现出微妙(但重要)的差异,但没有任何明显的异常。
我们遇到了与您同样的问题,因为这篇博文 http://tonyz93.blogspot.com/2017/02/jaxb-diff-results-in-java7-and-java8.html#further stated.
- 在编码 JaxB 时,编码 List 访问器的建议做法是否完全省略 Setter? (因为它似乎确实通过 Getter 处理 List )
- 有推荐的替代方法吗?
重点不是“省略 Setter”,而是不要向 setter 添加更多功能。二传手只是二传手,仅此而已。添加更多逻辑违反了 setter 的“单一责任规则”,并且该函数的名称与其实际执行的操作不同,可能会出现更多错误。
当谈到推荐的方法时,没有涵盖所有情况的标准答案。考虑到不存在构造函数 init (这对于 JAXB 来说有点困难)并且我们在 setter 之后需要更多逻辑,我们有两个方向可供您选择:
- Use
XmlAdapter
自定义构造以添加逻辑:适配器示例 http://tonyz93.blogspot.com/2017/01/jaxb-problem-list-2.html;
- 不在此类中添加任何逻辑,创建另一个类来处理 xml 中的数据 --(这是首选,因为此类只是一些不应该有逻辑的 DTO)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)