HttpURLConnection,OKHttp以及xml解析
来源:互联网 发布:知乎周刊pdf 编辑:程序博客网 时间:2024/06/05 23:41
本篇文章主要介绍以几下个知识点:
- 使用 HTTP 协议访问网络:
使用 HttpURLConnection 和 OKHttp; - 解析 XML 格式数据:
Pull 和 SAX 解析;
使用 HttpURLConnection 和 OKHttp;
Pull 和 SAX 解析;
9.1 使用 HTTP 协议访问网络
HTTP 协议,其工作原理很简单:客户端向服务器发出一条 HTTP 请求,服务器收到请求后会返回一些数据给客户端,然后客户端再对这些数据进行解析和处理。
9.1.1 使用 HttpURLConnection
下面学习 HttpURLConnection 的用法,其请求步骤代码如下:
/** * HttpURLConnection 发送请求 */ private void sendRequestWithHttpURLConnection() { // 开启线程来发送网络请求 new Thread(new Runnable() { @Override public void run() { HttpURLConnection connection = null; BufferedReader reader = null; try{ URL url = new URL("http://www.baidu.com"); // 1. 获取 HttpURLConnection 实例 connection = (HttpURLConnection) url.openConnection(); // 2. 设置请求方法 connection.setRequestMethod("GET"); // 3. 自由定制,如设置连接超时、读取超时等 connection.setConnectTimeout(8000); connection.setReadTimeout(8000); // 4. 获取服务器返回的输入流 InputStream in = connection.getInputStream(); // 下面对获取到的输入流进行读取 reader = new BufferedReader(new InputStreamReader(in)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine())!= null){ response.append(line); } showResponse(response.toString());// 显示请求结果 }catch (Exception e){ e.printStackTrace(); }finally { if (reader != null){ try{ reader.close(); }catch (IOException e){ e.printStackTrace(); } } if (connection != null){ // 5.把 HTTP 连接关掉 connection.disconnect(); } } } }).start(); }
若是想要提交数据给服务器只需把请求方法改为 POST,并在获取输入流之前把要提交的数据写出即可。注意每条数据要以键值对的形式存在,数据与数据之间用 “&” 隔开,比如向服务器提交用户名和密码可写成:
connection.setRequestMethod("POST");DataOutputStream out = new DataOutputStream(connection.getOutputStream());out.writeBytes("username=admin&password=123456");
1.1.2 使用 OKHttp
接下来学习下网络请求开源项目 OKHttp,其项目主页地址是:https://github.com/square/okhttp
在使用 OKHttp 前,需要在项目中添加 OKHttp 库的依赖,如下:
compile 'com.squareup.okhttp3:okhttp:3.5.0'
下面学习 OKHttp 请求步骤,如下:
/** * OKHttp 发送请求 */ private void sendRequestWithOKHttp() { new Thread(new Runnable() { @Override public void run() { try{ // 1. 创建 OkHttpClient 实例 OkHttpClient client = new OkHttpClient(); // 2. 创建 Request 对象 Request request = new Request.Builder().url("http://www.baidu.com").build(); // 3. 调用 OkHttpClient 的 newCall() 方法来创建 Call 对象 Response response = client.newCall(request).execute(); // 4. 获取返回的内容 String responseData = response.body().string(); showResponse(responseData);// 显示请求结果 }catch (Exception e){ e.printStackTrace(); } } }).start(); }
相比 HttpURLConnection,OKHttp 简单易用,若是发起一条 POST 请求,会比 GET 请求稍微复杂点,需要构建一个 RequestBody 对象来存放待提交的参数:
RequestBody requestBody = new FormBody.Builder() .add("username","admin") .add("password","123456") .build();
然后在 Request.Builder 中调用一下 post() 方法,并将 RequestBody 对象传入:
Request request = new Request.Builder() .url("http://www.baidu.com") .post(RequestBody) .build();
1.1.3 网络编程的最佳实践
在实际开发中,我们通常将这些通用的网络操作提取到一个公共类里,接下来就简单封装下网络操作。
首先针对 HttpURLConnection 定义一个回调接口:
public interface HttpCallbackListener { void onFinish(String response);// 请求成功时调用 void onError(Exception e);// 请求失败时调用}
接着编写工具类 HttpUtil:
public class HttpUtil { /** * 用 HttpURLConnection 发送请求 * @param address * @param listener */ public static void sendHttpRequest(final String address,final HttpCallbackListener listener){ new Thread(new Runnable() { @Override public void run() { HttpURLConnection connection = null; try{ URL url = new URL(address); // 1. 获取 HttpURLConnection 实例 connection = (HttpURLConnection) url.openConnection(); // 2. 设置请求方法 connection.setRequestMethod("GET"); // 3. 自由定制,如设置连接超时、读取超时等 connection.setConnectTimeout(8000); connection.setReadTimeout(8000); connection.setDoInput(true); connection.setDoOutput(true); // 4. 获取服务器返回的输入流 InputStream in = connection.getInputStream(); // 下面对获取到的输入流进行读取 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine())!= null){ response.append(line); } if (listener != null){ // 回调 onFinish() 方法 listener.onFinish(response.toString()); } }catch (Exception e){ if (listener != null){ // 回调 onError() 方法 listener.onError(e); } }finally { if (connection != null){ // 5.把 HTTP 连接关掉 connection.disconnect(); } } } }).start(); } /** * 用 OKHttp 发送请求 * @param address * @param callback */ public static void sendOKHttpRequest(String address, Callback callback){ OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(address).build(); client.newCall(request).enqueue(callback); }}
这时候用 HttpURLConnection 发送请求就可以写成:
HttpUtil.sendHttpRequest(address, new HttpCallbackListener() { @Override public void onFinish(String response) { // 在这里根据返回内容执行具体的逻辑 } @Override public void onError(Exception e) { // 在这里对异常情况进行处理 } });
用 OKHttp 发送请求就可以写成:
HttpUtil.sendOKHttpRequest("http://www.baidu.com", new Callback() { @Override public void onFailure(Call call, IOException e) { // 在这里对异常情况进行处理 } @Override public void onResponse(Call call, Response response) throws IOException { // 得到服务器返回的具体内容 String responseData = response.body().string(); } });
下面举个例子巩固下,主要代码如下:
public class HttpActivity extends AppCompatActivity implements View.OnClickListener { private TextView response_text; /** * OKHttp 发送请求 */ private void sendRequestWithOKHttp() { HttpUtil.sendOKHttpRequest("http://www.baidu.com", new Callback() { @Override public void onFailure(Call call, IOException e) { // 异常情况处理 } @Override public void onResponse(Call call, Response response) throws IOException { // 得到服务器返回内容 String responseData = response.body().string(); showResponse(responseData); } }); } /** * HttpURLConnection 发送请求 */ private void sendRequestWithHttpURLConnection() { HttpUtil.sendHttpRequest("http://www.baidu.com", new HttpCallbackListener() { @Override public void onFinish(String response) { // 在根据返回内容执行具体的逻辑 showResponse(response); } @Override public void onError(Exception e) { // 异常情况处理 } }); } /** * 显示请求结果 * @param response */ private void showResponse(final String response) { runOnUiThread(new Runnable() { @Override public void run() { System.out.println(response); } }); }}
在网络上传输数据时最常用的格式有两种:XML 和 JSON。本节来学习下如何解析 XML 格式的数据。
解析 XML 格式的数据有多种方式,这里主要介绍 Pull 解析和 SAX 解析。解析前先来看看等下要解析的 XML 文本:
1.2.1 Pull 解析方式
Pull 解析整个过程比较简单,具体看代码注释:
/** * pull 解析 * @param xmlData 要解析的xml数据 */ private void parseXMLWithPull(String xmlData) { try { // 1. 获取 XmlPullParserFactory 实例 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); // 2. 借助 XmlPullParserFactory 实例得到 XmlPullParser 对象 XmlPullParser xmlPullParser = factory.newPullParser(); // 3. 调用 setInput() 方法设置xml数据 xmlPullParser.setInput(new StringReader(xmlData)); // 4. 获取当前的解析事件 int eventType = xmlPullParser.getEventType(); String id = ""; String name = ""; String sex = ""; // 5. 通过 while 循环不断地进行解析 while (eventType != XmlPullParser.END_DOCUMENT){ String nodeName = xmlPullParser.getName(); switch (eventType){ // 开始解析某个节点 case XmlPullParser.START_TAG: if ("id".equals(nodeName)){ id = xmlPullParser.nextText(); }else if ("name".equals(nodeName)){ name = xmlPullParser.nextText(); }else if ("sex".equals(nodeName)){ sex = xmlPullParser.nextText(); } break; // 完成解析某个节点 case XmlPullParser.END_TAG: if ("student".equals(nodeName)){ Log.d("pull解析:", "id is" + id); Log.d("pull解析:", "name is" + name); Log.d("pull解析:", "sex is" + sex); } break; default: break; } // 获取下一个解析事件 eventType = xmlPullParser.next(); } }catch (Exception e){ e.printStackTrace(); } }
1.2.2 SAX 解析方式
SAX 解析的用法比 Pull 解析要复杂些,但在语义方面会更加清楚。
用 SAX 解析需要建一个类继承 DefaultHandler,并重写父类的5个方法。为实现上面同样的功能,新建一个 ContentHandler 类,如下所示:
public class ContentHandler extends DefaultHandler { private String nodeName; private StringBuilder id; private StringBuilder name; private StringBuilder sex; /** * 开始 XML 解析时调用 * @throws SAXException */ @Override public void startDocument() throws SAXException { id = new StringBuilder(); name = new StringBuilder(); sex = new StringBuilder(); } /** * 开始解析某个节点时调用 * @param uri * @param localName * @param qName * @param attributes * @throws SAXException */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // 记录当前节点名 nodeName = localName; } /** * 获取节点中的内容时调用 * @param ch * @param start * @param length * @throws SAXException */ @Override public void characters(char[] ch, int start, int length) throws SAXException { // 根据当前节点名判断将内容添加到哪一个 StringBuilder 对象中 if ("id".equals(nodeName)){ id.append(ch,start,length); }else if ("name".equals(nodeName)){ name.append(ch,start,length); }else if ("sex".equals(nodeName)){ sex.append(ch,start,length); } } /** * 完成解析某个节点时调用 * @param uri * @param localName * @param qName * @throws SAXException */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { if ("student".equals(localName)){ Log.d("sax解析:", "id is" + id.toString().trim()); Log.d("sax解析:", "name is" + name.toString().trim()); Log.d("sax解析:", "sex is" + sex.toString().trim()); // 最后要将 StringBuilder 清空掉 id.setLength(0); name.setLength(0); sex.setLength(0); } } /** * 完成整个 XML 解析时调用 * @throws SAXException */ @Override public void endDocument() throws SAXException { super.endDocument(); }}
接下来就非常简单了,代码如下:
/** * sax 解析 * @param xmlData */ private void parseXMLWithSAX(String xmlData){ try { // 创建 SAXParserFactory 对象 SAXParserFactory factory = SAXParserFactory.newInstance(); // 获取 XMLReader 对象 XMLReader xmlReader = factory.newSAXParser().getXMLReader(); ContentHandler handler = new ContentHandler(); // 将 ContentHandler 的实例设置到 XMLReader 中 xmlReader.setContentHandler(handler); // 开始执行解析 xmlReader.parse(new InputSource(new StringReader(xmlData))); }catch (Exception e){ e.printStackTrace(); } }
1.2.3 举个例子实在点
下面在布局中放置两个按钮,分别进行pull解析和sax解析:
public class ParseXMLActivity extends AppCompatActivity implements View.OnClickListener { private Button btn_pull,btn_sax; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_parse_xml); btn_pull = (Button) findViewById(R.id.btn_pull); btn_sax = (Button) findViewById(R.id.btn_sax); btn_pull.setOnClickListener(this); btn_sax.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn_pull: HttpUtil.sendOKHttpRequest("http://10.0.2.2/get_data.xml", new Callback() { @Override public void onFailure(Call call, IOException e) { //ToastUtils.showShort("请求失败"); } @Override public void onResponse(Call call, Response response) throws IOException { String responseData = response.body().string(); parseXMLWithPull(responseData); // pull 解析 } }); break; case R.id.btn_sax: HttpUtil.sendOKHttpRequest("http://10.0.2.2/get_data.xml", new Callback() { @Override public void onFailure(Call call, IOException e) { //ToastUtils.showShort("请求失败"); } @Override public void onResponse(Call call, Response response) throws IOException { String responseData = response.body().string(); parseXMLWithSAX(responseData); // sax 解析 } }); break; } } /** * pull 解析 * @param xmlData 要解析的xml数据 */ private void parseXMLWithPull(String xmlData) { . . . } /** * sax 解析 * @param xmlData */ private void parseXMLWithSAX(String xmlData){ . . . }}
运行程序,打印的日志分别如下:
可以看到,已经将 XML 数据成功解析出来了。
- HttpURLConnection,OKHttp以及xml解析
- HttpURLConnection + SAXReader解析XML
- HttpUrlConnection解析Xml
- (HttpURLConnection )AsyncTask解析xml
- android利用HttpURLConnection+XmlPullParser解析Xml文件
- HttpURLCOnnection和OKhttp学习
- Android XML解析学习—Pull方式(HttpURLConnection xml)
- HttpURLConnection 解析
- HttpURLConnection解析
- HttpUrlConnection 和 okhttp 请求数据
- OkHttp和HttpUrlConnection的示例
- AsyncTask+HttpUrlConnection网络请求解析XML且定位
- OKhttp解析
- OKhttp解析
- OKHTTP解析
- OkHttp解析
- okhttp解析
- OkHttp解析
- 数据报警系统
- LightOJ
- 《珠珠图案》教程五:文字创作要领二
- flock和fcntl的区别
- HDU 4386(计算几何+婆罗摩笈多公式一般形式)
- HttpURLConnection,OKHttp以及xml解析
- 超级快印自助复印点位链接
- DevOps落地实践:BAT系列:ALI:企业研发效能解决方案
- 十道海量数据处理面试题与十个方法大总结
- android-----------实现微信登录和分享功能。
- Python的pickle模块
- android 打印线程信息
- linux系统安装redis教程
- C语言程序设计习题1-16 打印任意长度的输入行的长度,并尽可能多地打印文本