使用XStream解析XML(使用淘宝开放API服务)

         本文意在简单说明XStream解析XML,配合淘宝的开放API,那么我们在电子商务模式的系统中就可以使用一些淘宝API来为系统增加一个与众不同的模块。

         首先来看淘宝API,这是本应用的重要部分,淘宝API的手册可以在线查看:下面就来说说简单的流程。我们通过URL发出请求,并收到返回的结果(XML或JSON)。请求中包含了一些必须的参数,这个就是文档中说明的。这里我们使用淘宝的商品API,获取一些商品的信息。在这之前需要在开放平台注册,获取你自己的APP_KEY和APP_SECRET,很简单。

         获取到必要信息后,我们来看一下URL请求,这个需要符合TAOBAO的要求,才能请求到数据,其中有一段信息是加密的,就是签名字段,这个字段的计算比较复杂,网站提供的方法好像已经不能用了,那么我根据TAOBAO提供的SDK源码自行提取有用部分来编写了一个简单的算法。首先我们来看一下测试应用的结构:

 

         使用Maven对应用进行管理,因为只是简单的应用程序,所以配置很简单,引入的第三方依赖也不多,我们来看看都需要些什么:

         加入了这些依赖之后,我们就可以进行开发了。看了之前的代码结构,我们先从请求TAOBAO的数据开始说。就是生成请求签名的类SinguratureGenerator.java来看:

 

1 package taobao.util;
2
3  import java.security.MessageDigest;
4
5  import java.util.Set;
6
7  import java.util.TreeMap;
8
9  import java.util.Map.Entry;
10
11  import org.apache.commons.lang.StringUtils;
12
13
14
15  /**
16
17 * 生成淘宝API中的签名密码
18
19 *
20
21 * @author Nanlei
22
23 *
24
25 */
26
27  public class SignatureGenerator {
28
29 /**
30
31 * 获取MD5加密结果
32
33 *
34
35 * @param params
36
37 * 参数集合
38
39 * @param secret
40
41 * 申请得到的APP_SECRET
42
43 * @return
44
45 */
46
47 public static String getMD5Signature(TreeMap<String, String> params,
48
49 String secret) {
50
51 // 存储签名的StringBuffer
52  
53 StringBuilder sign = new StringBuilder();
54
55 // 获取参数的项集合
56  
57 Set<Entry<String, String>> paramSet = params.entrySet();
58
59 // 组合要编码的串
60  
61 StringBuilder query = new StringBuilder(secret);
62
63 // 遍历参数集合,获取参数值,形式key+value
64  
65 for (Entry<String, String> param : paramSet) {
66
67 if (StringUtils.isNotEmpty(param.getKey())
68
69 && StringUtils.isNotEmpty(param.getValue())) {
70
71 query.append(param.getKey()).append(param.getValue());
72
73 }
74
75 }
76
77 try {
78
79 // 使用MD5加密
80  
81 MessageDigest md5 = MessageDigest.getInstance("MD5");
82
83 byte[] bytes = md5.digest(query.toString().getBytes("UTF-8"));
84
85 // 把二进制转化为大写的十六进制
86  
87 for (int i = 0; i < bytes.length; i++) {
88
89 String hex = Integer.toHexString(bytes[i] & 0xFF);
90
91 if (hex.length() == 1) {
92
93 sign.append("0");
94
95 }
96
97 sign.append(hex.toUpperCase());
98
99 }
100
101 } catch (Exception e) {
102
103 throw new java.lang.RuntimeException("Signature Generate Error!");
104
105 }
106
107 return sign.toString();
108
109 }
110
111 }
112
113  

 

 

         我们使用的是MD5的加密算法,需要传入一个TreeMap类型的参数集合对象,还有就是申请到的APP_SECRET字符串。使用TreeMap主要是利用其按照参数名的字典顺序排序特性,这也是TAOBAO的API要求的,那么算法注释很清楚了,这也是对它的SDK的简化,只保留必要内容。下面就是请求TAOBAO-API的类了,里面拼凑了请求参数并获得返回的结果:

 

1 package taobao;
2
3  import java.io.IOException;
4
5  import java.text.DateFormat;
6
7  import java.text.SimpleDateFormat;
8
9  import java.util.ArrayList;
10
11 import java.util.List;
12
13 import java.util.TreeMap;
14
15 import org.apache.http.HttpResponse;
16
17 import org.apache.http.HttpStatus;
18
19 import org.apache.http.NameValuePair;
20
21 import org.apache.http.client.HttpClient;
22
23 import org.apache.http.client.entity.UrlEncodedFormEntity;
24
25 import org.apache.http.client.methods.HttpPost;
26
27 import org.apache.http.impl.client.DefaultHttpClient;
28
29 import org.apache.http.message.BasicNameValuePair;
30
31 import org.apache.http.util.EntityUtils;
32
33 import taobao.util.SignatureGenerator;
34
35 /**
36
37 * 获取淘宝API返回的结果
38
39 *
40
41 * @author Nanlei
42
43 *
44
45 */
46
47 public class GetResult {
48
49 // 需要的常量参数
50
51 private static final String URL = "http://gw.api.taobao.com/router/rest";
52
53 private static final String APP_KEY = "请填写你申请的";
54
55 private static final String APP_SECRET = "请填写你申请的";
56
57 private static final String FORMAT = "xml";
58
59 private static final String METHOD = "taobao.item.get";
60
61 private static final String VERSION = "2.0";
62
63 private static DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
64
65 /**
66
67 * 获取结果的方法
68
69 *
70
71 * @param fields
72
73 * 需要请求的商品字段
74
75 * @param num_iid
76
77 * 商品ID,淘宝网URL中获得
78
79 * @return
80
81 */
82
83 public static String getResult(String fields, String num_iid) {
84
85 String content = null;
86
87 HttpClient client = new DefaultHttpClient();
88
89 HttpPost post = new HttpPost(URL);
90
91 String timestamp = getFullTime();
92
93 List<NameValuePair> params = new ArrayList<NameValuePair>();
94
95 params.add(new BasicNameValuePair("app_key", APP_KEY));
96
97 params.add(new BasicNameValuePair("format", FORMAT));
98
99 params.add(new BasicNameValuePair("method", METHOD));
100
101 params.add(new BasicNameValuePair("num_iid", num_iid));
102
103 params.add(new BasicNameValuePair("fields", fields));
104
105 params.add(new BasicNameValuePair("timestamp", timestamp));
106
107 params.add(new BasicNameValuePair("partner_id", "911"));
108
109 params.add(new BasicNameValuePair("v", VERSION));
110
111 params.add(new BasicNameValuePair("sign", SignatureGenerator
112
113 .getMD5Signature(getParams(timestamp, fields, num_iid),
114
115 APP_SECRET)));
116
117 try {
118
119 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
120
121 HttpResponse response = client.execute(post);
122
123 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_IMPLEMENTED) {
124
125 System.err
126
127 .println("The Post Method is not implemented by this URI");
128
129 } else {
130
131 content = EntityUtils.toString(response.getEntity());
132
133 }
134
135 } catch (IOException e) {
136
137 System.err.println(e);
138
139 } finally {
140
141 client.getConnectionManager().shutdown();
142
143 }
144
145 return content;
146
147 }
148
149 /**
150
151 * 拼装参数
152
153 *
154
155 * @param timestamp
156
157 * 当前时间戳
158
159 * @param fields
160
161 * 需要请求的商品字段
162
163 * @param num_iid
164
165 * 商品ID,淘宝网URL中获得
166
167 * @return
168
169 */
170
171 public static TreeMap<String, String> getParams(String timestamp,
172
173 String fields, String num_iid) {
174
175 TreeMap<String, String> treeMap = new TreeMap<String, String>();
176
177 treeMap.put("timestamp", timestamp);
178
179 treeMap.put("v", VERSION);
180
181 treeMap.put("app_key", APP_KEY);
182
183 treeMap.put("method", METHOD);
184
185 treeMap.put("partner_id", "911");
186
187 treeMap.put("format", FORMAT);
188
189 treeMap.put("fields", fields);
190
191 treeMap.put("num_iid", num_iid);
192
193 return treeMap;
194
195 }
196
197 /**
198
199 * 获取格式化好的时间
200
201 *
202
203 * @return
204
205 */
206
207 public static String getFullTime() {
208
209 return df.format(new java.util.Date());
210
211 }
212
213 }
214
215

 

 

         至此我们已经可以获得返回的XML数据,其中封装了商品信息,剩下的就是解析商品信息了,TAOBAO对商品信息定义了数据结构,我们按照这个结构封装对象,之后结合XStream来解析XML就获得了我们想要的数据了,那么先看商品数据结构,这里仅获取几个简单的供示例演示使用:

 

1 package taobao.bean;
2
3 public class Response {
4
5 private Item item;
6
7 public Item getItem() {
8
9 return item;
10
11 }
12
13 public void setItem(Item item) {
14
15 this.item = item;
16
17 }
18
19 }
20
21

 

 

         这里封装了整体的响应结果,item是商品的数据结构,如下:

 

1 package taobao.bean;
2
3 public class Item {
4
5 private String nick;
6
7 private String price;
8
9 private Location location;
10
11 public String getNick() {
12
13 return nick;
14
15 }
16
17 public void setNick(String nick) {
18
19 this.nick = nick;
20
21 }
22
23 public String getPrice() {
24
25 return price;
26
27 }
28
29 public void setPrice(String price) {
30
31 this.price = price;
32
33 }
34
35 public Location getLocation() {
36
37 return location;
38
39 }
40
41 public void setLocation(Location location) {
42
43 this.location = location;
44
45 }
46
47 }
48
49

 

 

         这里我们只要三个信息:卖家名称,商品价格,商品所在地,而所在地又是一个封装的数据结果对象,简单示例如下:

 

1 package taobao.bean;
2
3 public class Location {
4
5 private String state;
6
7 private String city;
8
9 public String getState() {
10
11 return state;
12
13 }
14
15 public void setState(String state) {
16
17 this.state = state;
18
19 }
20
21 public String getCity() {
22
23 return city;
24
25 }
26
27 public void setCity(String city) {
28
29 this.city = city;
30
31 }
32
33 }
34
35

 

 

         获取省份和城市,这些数据结构的完整信息就要参考API文档了,这里仅仅是示例。下面就可以运行测试类了:

 

1 package taobao;
2
3 import taobao.bean.Item;
4
5 import taobao.bean.Location;
6
7 import taobao.bean.Response;
8
9 import com.thoughtworks.xstream.XStream;
10
11 import com.thoughtworks.xstream.io.xml.DomDriver;
12
13 /**
14
15 * 获取商品信息测试类
16
17 *
18
19 * @author Nanlei
20
21 *
22
23 */
24
25 public class TaobaoXMLResult {
26
27 public static void main(String[] args) throws Exception {
28
29 // 获取的商品ID和需要的字段
30
31 String resultXML = GetResult.getResult("price,location,nick",
32
33 "74222099XX");
34
35 // XStream解析XML
36
37 XStream xstream = new XStream(new DomDriver());
38
39 xstream.alias("item_get_response", Response.class);
40
41 xstream.alias("item", Item.class);
42
43 xstream.alias("location", Location.class);
44
45 System.out.println(resultXML);
46
47 // XML转对象
48
49 Response response = (Response) xstream.fromXML(resultXML);
50
51 Item item = response.getItem();
52
53 // 打印结果
54
55 System.out.println("省份: " + item.getLocation().getState());
56
57 System.out.println("价格: " + item.getPrice());
58
59 System.out.println("店铺名称: " + item.getNick());
60
61 }
62
63 }
64
65

 

 

         XStream的使用很简单,将XML中的标签和对象进行别名绑定,之后读取XML并根据标签的层级进行数据填充,之后我们就可以按照预先定于的对象进行数据获取了,这里为了保护测试的卖家信息,将ID中最后两位隐藏,运行测试类,就得到如下的信息了:

posted @ 2010-11-07 21:48  nanlei  阅读(2481)  评论(0)    收藏  举报