您的位置:首页 > 其它

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

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

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

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



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



加入了这些依赖之后,我们就可以进行开发了。看了之前的代码结构,我们先从请求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 Nanlei

*

*/

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 Nanlei

*

*/

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 Nanlei

*

*/

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中最后两位隐藏,运行测试类,就得到如下的信息了:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: