@XmlSeeAlso xml转java对象 只能转换一种对象

soyestrellafortuna 2018-08-06 05:08:06
现有一个xml报文的功能需要转换为对应的对象。xml中有公共的属性。因此使用泛型方式进行了对象的设计
报文体对象

@XmlRootElement(name = "RSP")
@XmlSeeAlso({ QueryOut.class, SubmissionOut.class })
public class Response<T> {

private ResponseHead respHead;

@XmlAnyElement(lax = true)
private T t;

@XmlElement(name = "PUB")
public ResponseHead getRespHead() {
return respHead;
}

public void setRespHead(ResponseHead respHead) {
this.respHead = respHead;
}

@XmlTransient
public T getT() {
return t;
}

public void setT(T t) {
this.t = t;
}


查询报文对象QueryOut

package platform.interfaces.entity
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "OUT")
public class QueryOut {

/** 指令批次号 */
private String reqSeqID;
/** 批次处理状态 */
private String reqSeqState;

private List<QueryRd> rd;

@XmlElement(name = "ReqSeqID")
public String getReqSeqID() {
return reqSeqID;
}

public void setReqSeqID(String reqSeqID) {
this.reqSeqID = reqSeqID;
}

@XmlElement(name = "ReqSeqState")
public String getReqSeqState() {
return reqSeqState;
}

public void setReqSeqState(String reqSeqState) {
this.reqSeqState = reqSeqState;
}

@XmlElement(name = "RD")
public List<QueryRd> getRd() {
return rd;
}

public void setRd(List<QueryRd> rd) {
this.rd = rd;
}

}

提交类型报文对象SubmissionOut

package platform.interfaces.entity
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
* 数据提交<br>
* 批量代付代扣指令提交应答 <br/>
* <h1>指令特定元素</h1>
*
* @author admin
*
*/
@XmlRootElement(name = "OUT")
public class SubmissionOut {
/** 指令批次号 */
private String reqSeqID;
/** 保留字段 */
private String reqReserved1;
/** 保留字段 */
private String reqReserved2;

@XmlElement(name = "ReqSeqID")
public String getReqSeqID() {
return reqSeqID;
}

public void setReqSeqID(String reqSeqID) {
this.reqSeqID = reqSeqID;
}

@XmlElement(name = "ReqReserved1")
public String getReqReserved1() {
return reqReserved1;
}

public void setReqReserved1(String reqReserved1) {
this.reqReserved1 = reqReserved1;
}

@XmlElement(name = "ReqReserved2")
public String getReqReserved2() {
return reqReserved2;
}

public void setReqReserved2(String reqReserved2) {
this.reqReserved2 = reqReserved2;
}

}


现有一个返回样例报文
  public static void main(String[] args) throws JAXBException {

System.out.println("==========================");

String result = "<?xml version=\"1.0\" encoding=\"utf-8\"?><RSP><PUB><TransSource>LIS</TransSource><TransCode>1998</TransCode><TransDate>20130730</TransDate><TransTime>125955</TransTime><TransSeq>201307301259550117</TransSeq></PUB><OUT><RD><ReqSeqID>20130115030000AP002178</ReqSeqID><RdSeq>20130115030000AP002178-1</RdSeq><RtnCode>success</RtnCode><RtnMsg>通知成功</RtnMsg></RD></OUT></RSP>";

JAXBContext jaxbContext = JAXBContext.newInstance(Response.class);

Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Response<QueryOut> req = (Response<QueryOut>) unmarshaller.unmarshal(new StringReader(result));

System.out.println(req);

}

现在如果我的返回报文总是自动的转换成Response<SubmissionOut >对象。实际上应该转换成Response<QueryOut>。
当我将@XmlSeeAlso({ QueryOut.class, SubmissionOut.class }) 两个调换位置后,上面的测试代码又变成只能返回QueryOut对象。也就是说@XmlSeeAlso 这个列表里,只能识别最后的一个。

请问各位,这个问题有没有见到过,应该如何解决呢。谢谢了!!
...全文
3109 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
吃饺大仙 2020-01-06
  • 打赏
  • 举报
回复
其实这个泛型也不是说不能解决,如果你在使用泛型的时候,尝试过 Object<T> -> Xml 的话,会发现是能根据泛型转换成功的; 那么既然 Object<T> -> Xml 能进行转换,那么 Xml -> Object<T> 也应该可以转换的,尝试后,发现真的能转换成功,那么这个 xml 跟我们自己的 xml 有什么不同? 对比后我们发现 Object<T> -> Xml 的 Xml 中泛型转换后的标签上可以看到有一些属性,如下,这是我的项目中转换后的标签
<Transaction>
  <Transaction_Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="testReqBody">
  ....
  </Transaction_Body>
</Transaction>
这个 xsi:type 属性里面的内容是不是很熟悉,没错就是我们转换时的泛型首字母小写,该类在@XmlSeeAlso注解中也有定义
@XmlSeeAlso({TestReqBody.class, TestRespBody.class})
public class Transaction<T> {
    @XmlElement(name = "Transaction_Body")
    private T transactionBody;
...
}
这样就能解释为什么我们自己的 xml 转换总是以注解@XmlSeeAlso最后一个类为准,因为转换时根据 xml 找不到具体类型,就以最后一个为准,那么我们自己的 xml 在向泛型类转换时,可以加上以上属性即可转换成功,这个时候问题来了,以上属性会变化吗?属性值的来源是哪里? 通过测试,发现与以下注解有关(具体有什么样的关联,各位自己测试,这里就不举例了)
@XmlType(name = "xxx", namespace = "xxx")
这样我们就可以在转换的时候,根据自己 @XmlType 上定义的属性,通过正则表达式将泛型标签对应的属性和名称空间添加上即可。
soyestrellafortuna 2019-12-11
  • 打赏
  • 举报
回复 2
代码是内网开发的。记得当时处理的逻辑,就是将Response作为一个抽象类处理。其他的类继承Response进行处理。可以避免泛型擦除的情况发生。
城市之光丶 2019-12-10
  • 打赏
  • 举报
回复
同问作者具体调整方法,求代码
Rain_storms 2018-10-08
  • 打赏
  • 举报
回复
请问作者 具体调整方法
soyestrellafortuna 2018-08-07
  • 打赏
  • 举报
回复
以解决。被擦除了泛型,因此导致无法找到对应的类型 调整方法。response调整为抽象的父类,不同的对象继承该父类。
soyestrellafortuna 2018-08-06
  • 打赏
  • 举报
回复
环境清单:JDK1.8
	<!-- apache cxf -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
			<version>3.2.5</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http</artifactId>
			<version>3.2.5</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http-jetty</artifactId>
			<version>3.2.5</version>
		</dependency>
		<!-- apache cxf end -->

67,547

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧