轉自:https://blog.csdn.net/lydong_/article/details/79812626
`1.
1、不認識到犯錯,然后得到永久的教訓。
也不是所謂的教訓吧,真正的教訓來自於對錯誤的剖析理解很深刻。然后有種“吃一塹,長一智”的感覺才叫教訓。近日和團隊工頭們用CXF3.0和Spring4.0開發一個平台,模仿着第三方支付,用xml進行數據交互。
因此,搜了下。果斷用了dom4j,用自己鍵盤papa打了個叫做XmlOjbUtil的工具類。后來百度下,雖然不是萬能的百度。但也要表揚下,發現人家搭着REST的CXF卻集成了Jaxb。
果斷拋棄了!(有時候決定就需要這么果斷。)
先做個鋪墊,我們先說下一些知識點:
CXF實現webService項目,有兩種模式可以開發。Jax-ws實現經典的Web Service和Jax-rs實現REST標准。在Java EE 5/6中,Jaxb可以方便地集成,負責xml與JavaBean的映射。其實Jaxb也可以作為xml解析的一種技術。
2、認識JAXB
JAXB(Java Architecture for XML Binding)是根據XML Schema映射到JavaBean的技術。過程中,JAXB將XML實例文檔反向生成Java對象樹的方法,並能將Java對象樹的內容重新寫到 XML實例文檔。
在JDK1.6時,JAXB 2.0是JDK 1.6的組成部分。JAXB 2.2.3是JDK 1.7的組成部分。
提前修一下文檔知識吧:
JDK中JAXB相關的重要Class和Interface:
1、JAXBContext類,是應用的入口,用於管理XML/Java綁定信息。
2、Marshaller接口,將Java對象序列化為XML數據。
3、Unmarshaller接口,將XML數據反序列化為Java對象。
JDK中JAXB相關的重要Annotation:
1、@XmlType,將Java類或枚舉類型映射到XML模式類型
2、@XmlAccessorType(XmlAccessType.FIELD) ,控制字段或屬性的序列化。FIELD表示JAXB將自動綁定Java類中的每個非靜態的(static)、非瞬態的(由@XmlTransient標 注)字段到XML。其他值還有XmlAccessType.PROPERTY和XmlAccessType.NONE。
3、@XmlAccessorOrder,控制JAXB 綁定類中屬性和字段的排序。
4、@XmlJavaTypeAdapter,使用定制的適配器(即擴展抽象類XmlAdapter並覆蓋marshal()和unmarshal()方法),以序列化Java類為XML。
5、@XmlElementWrapper ,對於數組或集合(即包含多個元素的成員變量),生成一個包裝該數組或集合的XML元素(稱為包裝器)。
6、@XmlRootElement,將Java類或枚舉類型映射到XML元素。
7、@XmlElement,將Java類的一個屬性映射到與屬性同名的一個XML元素。
8、@XmlAttribute,將Java類的一個屬性映射到與屬性同名的一個XML屬性。
3、代碼實戰
我們既然要設計報文,所以我這邊拿出來一個注冊的Bean的設計。首先我們設計注冊的Bean,代碼如下:
DataBean.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
package com.xidian.wq.imaopay.model.mesdata.base;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author BYSocket
* 報文頭-[報文基礎信息]
*/
@XmlRootElement(name="data_bean")
public class DataBean
{
// 版本信息(data_version)
String version;
////消息類型(data_type)
// 000001 - 注冊[個人信息Post|Respose]
// 000002 - 綁定銀行卡[首次綁定,保存個人信息]
// 000003 - 綁定銀行卡[二次,校驗個人信息]
// 100001 - 支付[錢包支付]
// 100002 - 查詢
// 200001
String data_type;
////訂單編號(order_id)
// 總長20位, 有字母要用大寫
String batch_no;
// 平台賬號(platform_account)
String user_name;
////請求狀態
// 000
String trans_state;
// 簽名信息(msg_sign)
String msg_sign;
// 時間戳(randomTime)
private String rd_time;
// 隨機數(randomNum)
private String rd_num;
// 密鑰(keySign)
private String k_sign;
// 保留域
String reserve;
public String getVersion()
{
return version;
}
public void setVersion(String version)
{
this.version = version;
}
public String getData_type()
{
return data_type;
}
public void setData_type(String data_type)
{
this.data_type = data_type;
}
public String getBatch_no()
{
return batch_no;
}
public void setBatch_no(String batch_no)
{
this.batch_no = batch_no;
}
public String getUser_name()
{
return user_name;
}
public void setUser_name(String user_name)
{
this.user_name = user_name;
}
public String getTrans_state()
{
return trans_state;
}
public void setTrans_state(String trans_state)
{
this.trans_state = trans_state;
}
public String getMsg_sign()
{
return msg_sign;
}
public void setMsg_sign(String msg_sign)
{
this.msg_sign = msg_sign;
}
public String getRd_time()
{
return rd_time;
}
public void setRd_time(String rd_time)
{
this.rd_time = rd_time;
}
public String getRd_num()
{
return rd_num;
}
public void setRd_num(String rd_num)
{
this.rd_num = rd_num;
}
public String getK_sign()
{
return k_sign;
}
public void setK_sign(String k_sign)
{
this.k_sign = k_sign;
}
public String getReserve()
{
return reserve;
}
public void setReserve(String reserve)
{
this.reserve = reserve;
}
}
|
RegBean.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
<
font
size
=
"4"
face
=
"宋體"
>package com.xidian.wq.imaopay.model.mesdata.base;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author BYSocket
* 報文體-[用戶注冊報文體信息]
*/
@XmlRootElement(name="reg_bean")
public class RegBean
{
// 注冊報文體流水號(reg_data_sn)
private String reg_sn;
////用戶編號(user_info_id)
// 業務系統的用戶編號只做記錄不在支付系統中邏輯處理
private Integer user_id;
// 注冊賬號(reg_account)
private String reg_no;
// 注冊途徑(reg_way)
private String reg_way;
// 保留域
private String reserve;
////提交日期(set_time)
// 業務系統上傳
private String set_time;
// 后台信息返回路徑(return_url)
private String ret_url;
// 備注
String remarks;
public String getReg_sn()
{
return reg_sn;
}
public void setReg_sn(String reg_sn)
{
this.reg_sn = reg_sn;
}
public Integer getUser_id()
{
return user_id;
}
public void setUser_id(Integer user_id)
{
this.user_id = user_id;
}
public String getReg_no()
{
return reg_no;
}
public void setReg_no(String reg_no)
{
this.reg_no = reg_no;
}
public String getReg_way()
{
return reg_way;
}
public void setReg_way(String reg_way)
{
this.reg_way = reg_way;
}
public String getReserve()
{
return reserve;
}
public void setReserve(String reserve)
{
this.reserve = reserve;
}
public String getSet_time()
{
return set_time;
}
public void setSet_time(String set_time)
{
this.set_time = set_time;
}
public String getRet_url()
{
return ret_url;
}
public void setRet_url(String ret_url)
{
this.ret_url = ret_url;
}
public String getRemarks()
{
return remarks;
}
public void setRemarks(String remarks)
{
this.remarks = remarks;
}
}
</
font
>
|
注冊報文體MsgRegBean.java,支持內容的列表。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
package com.xidian.wq.imaopay.model.mesdata;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import com.xidian.wq.imaopay.model.mesdata.base.DataBean;
import com.xidian.wq.imaopay.model.mesdata.base.RegBean;
@XmlRootElement( name = "msg_bean" )
public class MsgRegBean
{
private DataBean dataBean;
private List<
RegBean
> regBeans;
public DataBean getDataBean()
{
return dataBean;
}
@XmlElement(name = "data_bean")
public void setDataBean(DataBean dataBean)
{
this.dataBean = dataBean;
}
@XmlElementWrapper(name = "reg_beans")
@XmlElement(name = "reg_bean")
public List<
RegBean
> getRegBeans()
{
return regBeans;
}
public void setRegBeans(List<
RegBean
> regBeans)
{
this.regBeans = regBeans;
}
}
|
然后針對的我們用Jaxb實現一個轉換的Util類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
<
font
size
=
"4"
face
=
"宋體"
>package com.xidian.wq.imaopay.util;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import com.alibaba.fastjson.JSON;
import com.xidian.wq.imaopay.model.mesdata.MsgRegBean;
import com.xidian.wq.imaopay.model.mesdata.base.DataBean;
import com.xidian.wq.imaopay.model.mesdata.base.RegBean;
/**
*
* @author BYSocket
* Jaxb2.0 處理Xml與Object轉換
*
*/
public class JaxbObjectAndXmlUtil
{
/**
* @param xmlStr 字符串
* @param c 對象Class類型
* @return 對象實例
*/
@SuppressWarnings("unchecked")
public static <
T
> T xml2Object(String xmlStr,Class<
T
> c)
{
try
{
JAXBContext context = JAXBContext.newInstance(c);
Unmarshaller unmarshaller = context.createUnmarshaller();
T t = (T) unmarshaller.unmarshal(new StringReader(xmlStr));
return t;
} catch (JAXBException e) { e.printStackTrace(); return null; }
}
/**
* @param object 對象
* @return 返回xmlStr
*/
public static String object2Xml(Object object)
{
try
{
StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance(object.getClass());
Marshaller marshal = context.createMarshaller();
marshal.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 格式化輸出
marshal.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");// 編碼格式,默認為utf-8
marshal.setProperty(Marshaller.JAXB_FRAGMENT, false);// 是否省略xml頭信息
marshal.setProperty("jaxb.encoding", "utf-8");
marshal.marshal(object,writer);
return new String(writer.getBuffer());
} catch (Exception e) { e.printStackTrace(); return null;}
}
public static void main(String[] args)
{
/** 構造測試報文頭對象 */
DataBean dataBean = new DataBean();
dataBean.setBatch_no("N20150204");
dataBean.setData_type("000001");
dataBean.setVersion("v1.0");
dataBean.setUser_name("xx");
dataBean.setMsg_sign("未知");
dataBean.setRd_num("6631383");
dataBean.setRd_time("20150204");
dataBean.setK_sign("75CC479AAC09F00BA28F0E968B1BC9D1B90ADCC2");
/** 構造測試報文體對象 */
RegBean regBean = new RegBean();
regBean.setReg_sn("REG20150204");
regBean.setUser_id(12);
regBean.setReg_no("33");
regBean.setReg_way("pc");
regBean.setSet_time("20150204 16:18");
regBean.setRet_url("未知");
regBean.setRemarks("無備注");
MsgRegBean msgBean = new MsgRegBean();
List<
RegBean
> regBeans = new ArrayList<
RegBean
>();
regBeans.add(regBean);
regBeans.add(regBean);
msgBean.setRegBeans(regBeans);
msgBean.setDataBean(dataBean);
String xmlStr = JaxbObjectAndXmlUtil.object2Xml(msgBean);//構造報文 XML 格式的字符串
System.out.println("對象轉xml報文: \n"+xmlStr);
MsgRegBean msgBean2 = JaxbObjectAndXmlUtil.xml2Object(xmlStr, MsgRegBean.class);
System.out.println("報文轉xml轉: \n"+JSON.toJSONString(msgBean2));
}
} </
font
>
|
運行下測試main函數,可以得到如下的輸出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
對象轉xml報文:
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
standalone
=
"yes"
?>
<
msg_bean
>
<
data_bean
>
<
batch_no
>N20150204</
batch_no
>
<
data_type
>000001</
data_type
>
<
k_sign
>75CC479AAC09F00BA28F0E968B1BC9D1B90ADCC2</
k_sign
>
<
msg_sign
>未知</
msg_sign
>
<
rd_num
>6631383</
rd_num
>
<
rd_time
>20150204</
rd_time
>
<
user_name
>xx</
user_name
>
<
version
>v1.0</
version
>
</
data_bean
>
<
reg_beans
>
<
reg_bean
>
<
reg_no
>33</
reg_no
>
<
reg_sn
>REG20150204</
reg_sn
>
<
reg_way
>pc</
reg_way
>
<
remarks
>無備注</
remarks
>
<
ret_url
>未知</
ret_url
>
<
set_time
>20150204 16:18</
set_time
>
<
user_id
>12</
user_id
>
</
reg_bean
>
<
reg_bean
>
<
reg_no
>33</
reg_no
>
<
reg_sn
>REG20150204</
reg_sn
>
<
reg_way
>pc</
reg_way
>
<
remarks
>無備注</
remarks
>
<
ret_url
>未知</
ret_url
>
<
set_time
>20150204 16:18</
set_time
>
<
user_id
>12</
user_id
>
</
reg_bean
>
</
reg_beans
>
</
msg_bean
>
報文轉xml轉:
{"dataBean":{"batch_no":"N20150204","data_type":"000001","k_sign":"75CC479AAC09F00BA28F0E968B1BC9D1B90ADCC2","msg_sign":"未知","rd_num":"6631383","rd_time":"20150204","user_name":"xx","version":"v1.0"},"regBeans":[{"reg_no":"33","reg_sn":"REG20150204","reg_way":"pc","remarks":"無備注","ret_url":"未知","set_time":"20150204 16:18","user_id":12},{"reg_no":"33","reg_sn":"REG20150204","reg_way":"pc","remarks":"無備注","ret_url":"未知","set_time":"20150204 16:18","user_id":12}]}
|
代碼中間注意點:
Marshaller.JAXB_FORMATTED_OUTPUT :決定是否在轉換成xml時同時進行格式化(即按標簽自動換行,否則即是一行的xml) 。
Marshaller.JAXB_ENCODING :xml的編碼方式。
Marshaller.JAXB_FRAGMENT :是否省略xml頭信息
marshal.setProperty(“jaxb.encoding”, “utf-8″); : 設置編碼格式 utf-8