使用XStream解析XML(使用HttpClient 4发送请求)

本文意在简单说明XStream解析XML,配合HttpClient 4发送请求,请求淘宝的开放API,那么我们在电子商务模式的系统中就可以使用一些淘宝API来为系统增加一个与众不同的模块。
首先来看淘宝API,这是本应用的重要部分,淘宝API的手册可以在线查看:下面就来说说简单的流程。我们通过URL发出请求,并收到返回的结果(XML或JSON)。请求中包含了一些必须的参数,这个就是文档中说明的。这里我们使用淘宝的商品API,获取一些商品的信息。在这之前需要在开放平台注册,获取你自己的APP_KEY和APP_SECRET,很简单。
获取到必要信息后,我们来看一下URL请求,这个需要符合TAOBAO的要求,才能请求到数据,其中有一段信息是加密的,就是签名字段,这个字段的计算比较复杂,网站提供的方法好像已经不能用了,那么我根据TAOBAO提供的SDK源码自行提取有用部分来编写了一个简单的算法。首先我们来看一下测试应用的结构:
[img]http://dl.iteye.com/upload/attachment/344392/51480749-ffc3-37ce-9466-2bfc4a0972da.png[/img]
使用Maven对应用进行管理,因为只是简单的应用程序,所以配置很简单,引入的第三方依赖也不多,我们来看看都需要些什么:
[img]http://dl.iteye.com/upload/attachment/344394/a3a79195-f84c-3d2b-9ca8-9c69a0b9ae1b.png[/img]
加入了这些依赖之后,我们就可以进行开发了。看了之前的代码结构,我们先从请求TAOBAO的数据开始说。就是生成请求签名的类SinguratureGenerator.java来看:
package taobao.util;
import java.security.MessageDigest;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;
import org.apache.commons.lang.StringUtils;

/**
* 生成淘宝API中的签名密码
*
* @author Sarin
*
*/
public class SignatureGenerator {
/**
* 获取MD5加密结果
*
* @param params
* 参数集合
* @param secret
* 申请得到的APP_SECRET
* @return
*/
public static String getMD5Signature(TreeMap<String, String> params,
String secret) {
// 存储签名的StringBuffer
StringBuilder sign = new StringBuilder();
// 获取参数的项集合
Set<Entry<String, String>> paramSet = params.entrySet();
// 组合要编码的串
StringBuilder query = new StringBuilder(secret);
// 遍历参数集合,获取参数值,形式key+value
for (Entry<String, String> param : paramSet) {
if (StringUtils.isNotEmpty(param.getKey())
&& StringUtils.isNotEmpty(param.getValue())) {
query.append(param.getKey()).append(param.getValue());
}
}
try {
// 使用MD5加密
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] bytes = md5.digest(query.toString().getBytes("UTF-8"));
// 把二进制转化为大写的十六进制
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
sign.append("0");
}
sign.append(hex.toUpperCase());
}
} catch (Exception e) {
throw new java.lang.RuntimeException("Signature Generate Error!");
}
return sign.toString();
}
}

我们使用的是MD5的加密算法,需要传入一个TreeMap类型的参数集合对象,还有就是申请到的APP_SECRET字符串。使用TreeMap主要是利用其按照参数名的字典顺序排序特性,这也是TAOBAO的API要求的,那么算法注释很清楚了,这也是对它的SDK的简化,只保留必要内容。下面就是请求TAOBAO-API的类了,里面拼凑了请求参数并获得返回的结果:
package taobao;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import taobao.util.SignatureGenerator;
/**
* 获取淘宝API返回的结果
*
* @author Sarin
*
*/
public class GetResult {
// 需要的常量参数
private static final String URL = "http://gw.api.taobao.com/router/rest";
private static final String APP_KEY = "请填写你申请的";
private static final String APP_SECRET = "请填写你申请的";
private static final String FORMAT = "xml";
private static final String METHOD = "taobao.item.get";
private static final String VERSION = "2.0";
private static DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* 获取结果的方法
*
* @param fields
* 需要请求的商品字段
* @param num_iid
* 商品ID,淘宝网URL中获得
* @return
*/
public static String getResult(String fields, String num_iid) {
String content = null;
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(URL);
String timestamp = getFullTime();
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("app_key", APP_KEY));
params.add(new BasicNameValuePair("format", FORMAT));
params.add(new BasicNameValuePair("method", METHOD));
params.add(new BasicNameValuePair("num_iid", num_iid));
params.add(new BasicNameValuePair("fields", fields));
params.add(new BasicNameValuePair("timestamp", timestamp));
params.add(new BasicNameValuePair("partner_id", "911"));
params.add(new BasicNameValuePair("v", VERSION));
params.add(new BasicNameValuePair("sign", SignatureGenerator
.getMD5Signature(getParams(timestamp, fields, num_iid),
APP_SECRET)));
try {
post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpResponse response = client.execute(post);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_IMPLEMENTED) {
System.err
.println("The Post Method is not implemented by this URI");
} else {
content = EntityUtils.toString(response.getEntity());
}
} catch (IOException e) {
System.err.println(e);
} finally {
client.getConnectionManager().shutdown();
}
return content;
}
/**
* 拼装参数
*
* @param timestamp
* 当前时间戳
* @param fields
* 需要请求的商品字段
* @param num_iid
* 商品ID,淘宝网URL中获得
* @return
*/
public static TreeMap<String, String> getParams(String timestamp,
String fields, String num_iid) {
TreeMap<String, String> treeMap = new TreeMap<String, String>();
treeMap.put("timestamp", timestamp);
treeMap.put("v", VERSION);
treeMap.put("app_key", APP_KEY);
treeMap.put("method", METHOD);
treeMap.put("partner_id", "911");
treeMap.put("format", FORMAT);
treeMap.put("fields", fields);
treeMap.put("num_iid", num_iid);
return treeMap;
}
/**
* 获取格式化好的时间
*
* @return
*/
public static String getFullTime() {
return df.format(new java.util.Date());
}
}

至此我们已经可以获得返回的XML数据,其中封装了商品信息,剩下的就是解析商品信息了,TAOBAO对商品信息定义了数据结构,我们按照这个结构封装对象,之后结合XStream来解析XML就获得了我们想要的数据了,那么先看商品数据结构,这里仅获取几个简单的供示例演示使用:
package taobao.bean;
public class Response {
private Item item;
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
}

这里封装了整体的响应结果,item是商品的数据结构,如下:
package taobao.bean;
public class Item {
private String nick;
private String price;
private Location location;
public String getNick() {
return nick;
}
public void setNick(String nick) {
this.nick = nick;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
}

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

package taobao.bean;
public class Location {
private String state;
private String city;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}

获取省份和城市,这些数据结构的完整信息就要参考API文档了,这里仅仅是示例。下面就可以运行测试类了:
package taobao;
import taobao.bean.Item;
import taobao.bean.Location;
import taobao.bean.Response;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
/**
* 获取商品信息测试类
*
* @author Sarin
*
*/
public class TaobaoXMLResult {
public static void main(String[] args) throws Exception {
// 获取的商品ID和需要的字段
String resultXML = GetResult.getResult("price,location,nick",
"74222099XX");
// XStream解析XML
XStream xstream = new XStream(new DomDriver());
xstream.alias("item_get_response", Response.class);
xstream.alias("item", Item.class);
xstream.alias("location", Location.class);
System.out.println(resultXML);
// XML转对象
Response response = (Response) xstream.fromXML(resultXML);
Item item = response.getItem();
// 打印结果
System.out.println("省份: " + item.getLocation().getState());
System.out.println("价格: " + item.getPrice());
System.out.println("店铺名称: " + item.getNick());
}
}

XStream的使用很简单,将XML中的标签和对象进行别名绑定,之后读取XML并根据标签的层级进行数据填充,之后我们就可以按照预先定于的对象进行数据获取了,这里为了保护测试的卖家信息,将ID中最后两位隐藏,运行测试类,就得到如下的信息了:
[img]http://dl.iteye.com/upload/attachment/344411/7a27bcb4-54bc-3a8d-add1-9e7299748495.png[/img]
本文系作者的实践探索,文中做法也许并非最佳实践,仅提供简单示例供参考,后续还有使用JACKON解析JSON的示例,同时结合另外一种API来展示应用。欢迎交流,希望对使用者有用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值