`
sarin
  • 浏览: 1756923 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
E3b14d1f-4cc5-37dd-b820-b6af951740bc
Spring数据库访问系列...
浏览量:173658
C2083dc5-6474-39e2-993e-263652d27795
Android学习笔记
浏览量:368126
5f40a095-b33c-3e8e-8891-606fcf3b8d27
iBatis开发详解
浏览量:189263
B272a31d-e7bd-3eff-8cc4-c0624ee75fee
Objective-C学习...
浏览量:99838
社区版块
存档分类
最新评论

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

阅读更多
    本文意在简单说明XStream解析XML,配合HttpClient 4发送请求,请求淘宝的开放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 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中最后两位隐藏,运行测试类,就得到如下的信息了:

    本文系作者的实践探索,文中做法也许并非最佳实践,仅提供简单示例供参考,后续还有使用JACKON解析JSON的示例,同时结合另外一种API来展示应用。欢迎交流,希望对使用者有用。
  • 大小: 9.3 KB
  • 大小: 56 KB
  • 大小: 53.3 KB
分享到:
评论
4 楼 sarin 2011-04-18  
sckalman 写道
我用您的代码测试出现这个问题

Exception in thread "main" com.thoughtworks.xstream.mapper.CannotResolveClassException: error_response : error_response
at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:68)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38)at com.thoughtworks.xstream.XStream.fromXML(XStream.java:853)
at com.thoughtworks.xstream.XStream.fromXML(XStream.java:845)
at taobao.TaobaoXMLResult.main(TaobaoXMLResult.java:25) 请指教 suncansoftware@gmail.com

这个代码的允许需要TAOBAO的key,看看是不是返回的XML本身出现问题导致后面无法解析的。设置断点跟踪一下即可。
3 楼 sckalman 2011-04-18  
我用您的代码测试出现这个问题

Exception in thread "main" com.thoughtworks.xstream.mapper.CannotResolveClassException: error_response : error_response
at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:68)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:38)at com.thoughtworks.xstream.XStream.fromXML(XStream.java:853)
at com.thoughtworks.xstream.XStream.fromXML(XStream.java:845)
at taobao.TaobaoXMLResult.main(TaobaoXMLResult.java:25) 请指教 suncansoftware@gmail.com
2 楼 sarin 2010-11-25  
sniperking 写道
问一下你那个类图是用什么工具生成的啊

maven的eclipse插件m2e
1 楼 sniperking 2010-11-25  
问一下你那个类图是用什么工具生成的啊

相关推荐

    http over xml的实例

    - 客户端接收到响应后,使用XStream解析XML,还原成Java对象。 - 客户端根据反序列化后的对象执行相应的业务逻辑。 这个实例展示了如何结合HTTP协议的易用性和XML的结构化数据能力,构建一个简单的服务端-客户端...

    Java号码归属地查询,xml转化实体类

    在Java中,可以使用HTTP客户端库(如Apache HttpClient或Java内置的HttpURLConnection)发送请求,并处理返回的响应。 接着,我们来谈谈XML处理。XML是一种用于存储和传输结构化数据的标记语言。在Java中,我们可以...

    微信支付最新jar包

    综合这些库,我们可以推断出这个微信支付最新jar包的实现方式:通过HttpClient发起HTTP请求,使用XStream处理XML数据交换,依赖Commons Codec进行编码解码,利用SLF4J进行日志记录,同时在开发过程中使用JUnit进行...

    微信支付所jar包及源码

    10. **xpp3_min-1.1.4c.jar**: 这是一个轻量级的XML Pull解析器,用于解析XML文档。在处理微信支付的XML响应时,XPP3可能会被用到,尤其是当需要快速解析大量数据时。 通过这些jar包,开发者可以构建一个完整的微信...

    android中调用webservice总结

    Android内置的HttpURLConnection或Apache HttpClient库可以用来发送GET、POST等HTTP请求,然后使用Gson或Jackson库解析响应数据。 - **XML-RPC**:虽然不如SOAP和REST流行,但也有相应的Android库支持,如XMLRPC-...

    xfire所需jar包(共20个)

    在xfire中,JDOM可能用于构建和解析XML消息。 8. **xfire-aegis-1.2.6.jar**:Aegis是xfire的一个绑定模块,负责将Java对象与XML Schema映射,实现对象到XML的自动转换。 9. **XmlSchema-1.1.jar**:这个库提供了...

    tomcat 异常

    - `xercesImpl-2.9.1.jar`:XML解析器,处理XML文档的读取和验证。 - `commons-collections-3.2.1.jar`:Apache Commons Collections库,提供了丰富的集合操作工具。 - `mail-1.4.4.jar`:JavaMail API,用于发送...

    java各种工具类-非常齐全

    此外,`org.dom4j`或`com.thoughtworks.xstream`等库提供了更便捷的XML操作。 5. **JSON工具类**: JSON作为一种轻量级的数据交换格式,广泛用于前后端交互。Java有多种JSON库,如`org.json`、`com.google.gson`和...

    Restful WebService

    可能使用了HttpURLConnection、HttpClient或者Spring的RestTemplate来发送HTTP请求并解析响应。 - **SpringRestTest**:这可能是Spring的测试类,利用JUnit和Mockito等工具对Restful服务进行单元测试或集成测试。...

    整合SSM框架所需要用到的所有JAR

    - **DOM4J库**:XML解析库,用于读取、写入、修改XML文档。 - **HttpClient库**:如httpclient,提供HTTP协议的客户端编程接口,用于网络请求。 - **XStream库**:XML和对象之间的转换工具,方便对象序列化为XML和反...

    Android典型技术模块开发详解

    11.4 HttpClient 11.4.1 HttpGet请求 11.4.2 HttpPost请求 11.5 本章小结 第12章 数据解析 12.1 XML 12.1.1 DOM 12.1.2 SAX 12.1.3 PULL 12.2 JSON格式 12.2.1 基本类型 12.2.2 数组和集合 12.2.3 类对象 12.3 JSON...

Global site tag (gtag.js) - Google Analytics