*****
**WebService简介及实战**
[TOC=6]
# 1. WebService简介
简单来说Web Service就是某个站点开放出来的数据服务。
Web service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的互操作的应用程序。
(1)SOAP协议:
SOAP协议的概念:简单的对象访问协议,是一种轻量型,简单,基于XML协议,它被设计成在WEB上交换结构化的和固化的信息;
SOAP协议组成部分:
* SOAP封装:定义了一个框架(描述信息的多少,谁发送,谁接受,谁处理,怎么处理等信息);
* SOAP编码规则:定义了可选数据编码规则;
* SOAP RPC表示:定义一个远程调用风格信息交换的模式;
* SOAP绑定:定义了SOAP和HTTP之间绑定和使用的底层协议的交换;
(2)WSDL:
Web Service描述语言WSDL 就是用机器能阅读的方式提供的一个正式描述文档而基于XML(标准通用标记语言下的一个子集)的语言,用于描述Web Service及其函数、参数和返回值。因为是基于XML的,所以WSDL既是机器可阅读的,又是人可阅读的。
# 2. Webservice 实战 天气预报
![](https://box.kancloud.cn/e32a5b41e982c7416aaaacf0d7fa976e_1080x1920.png)
## 2.1 需求:
* 选择省份--城市联动
* 选择城市--天气联动
* 显示5天天气
## 2.2 代码实现
WebService使用注意点:
1.创建HttpTransportSE传输对象:
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
SERVICE_URL是webservice提供服务的url
2.使用SOAP1.1协议创建Envelop对象:
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
设置SOAP协议的版本号,根据服务端WebService的版本号设置。
3.实例化SoapObject对象:
SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE, methodName);
第一个参数表示WebService的命名空间,可以从WSDL文档中找到WebService的命名空间。第二个参数表示要调用的WebService方法名。
4.设置调用方法的参数值,如果没有参数,可以省略:例如
soapObject.addProperty("theCityCode", cityName);
5.记得设置bodyout属性 envelope.bodyOut = soapObject;
6.调用webservice:ht.call(SERVICE_NAMESPACE+methodName, envelope);
7.获取服务器响应返回的SOAP消息:
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName+"Result");
### 2.2.1 WebServiceUtil代码
`
~~~
package cn.zhaoliang5156.demo;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* WebService 工具类
* @author zhaoliang
* @version 1.0
*/
public class WebServiceUtil {
// 定义webservice的命名空间
public static final String SERVICE_NAMESPACE = "http://WebXml.com.cn/";
// 定义webservice提供服务的url
public static final String SERVICE_URL = "http://ws.webxml.com.cn/WebServices/WeatherWS.asmx";
// 调用远程webservice获取省份列表
public static List<String> getProvinceList() {
// 调用 的方法
String methodName = "getRegionProvince";
// 创建HttpTransportSE传输对象
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
try {
ht.debug = true;
// 使用SOAP1.1协议创建Envelop对象
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
// 实例化SoapObject对象
SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE,
methodName);
envelope.bodyOut = soapObject;
// 设置与.NET提供的webservice保持较好的兼容性
envelope.dotNet = true;
// 调用webservice
ht.call(SERVICE_NAMESPACE + methodName, envelope);
if (envelope.getResponse() != null) {
// 获取服务器响应返回的SOAP消息
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName
+ "Result");
// 解析服务器响应的SOAP消息
return parseProvinceOrCity(detail);
}
} catch (SoapFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// 根据省份获取城市列表
public static List<String> getCityListsByProvince(String province) {
// 调用的方法
String methodName = "getSupportCityString";
// 创建httptransportSE传输对象
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
ht.debug = true;
// 实例化SoapObject对象
SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE, methodName);
// 添加一个请求参数
soapObject.addProperty("theRegionCode", province);
// 使用soap1.1协议创建envelop对象
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.bodyOut = soapObject;
// 设置与.NET提供的webservice保持较好的兼容性
envelope.dotNet = true;
// 调用webservice
try {
ht.call(SERVICE_NAMESPACE + methodName, envelope);
if (envelope.getResponse() != null) {
// 获取服务器响应返回的SOAP消息
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName
+ "Result");
// 解析服务器响应的SOAP消息
return parseProvinceOrCity(detail);
}
} catch (SoapFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// 解析省份或城市
public static List<String> parseProvinceOrCity(SoapObject detail) {
ArrayList<String> result = new ArrayList<>();
for (int i = 0; i < detail.getPropertyCount(); i++) {
// 解析出每个省份
result.add(detail.getProperty(i).toString().split(",")[0]);
}
return result;
}
// 根据城市字符串获取相应天气情况
public static SoapObject getWeatherByCity(String cityName) {
String methodName = "getWeather";
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
ht.debug = true;
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE, methodName);
soapObject.addProperty("theCityCode", cityName);
soapObject.addProperty("theUserID", "d54a91e159fd40a8b10a0ff9a92944eb");
envelope.bodyOut = soapObject;
envelope.dotNet = true;
try {
ht.call(SERVICE_NAMESPACE + methodName, envelope);
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName
+ "Result");
return detail;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
~~~
`
### 2.2.2 主界面布局
`
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="省份:" />
<Spinner
android:id="@+id/sp_province"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="城市:" />
<Spinner
android:id="@+id/sp_city"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:id="@+id/tv_current_weather"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ListView
android:id="@+id/weather_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
~~~
`
### 2.2.3 列表布局
`
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/icon_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/weather"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0" />
</LinearLayout>
~~~
`
### 2.2.4 Activity代码
`
~~~
package cn.zhaoliang5156.demo;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import org.ksoap2.serialization.SoapObject;
import java.util.ArrayList;
import java.util.List;
/**
* 天气预报主界面
* @author zhaoliang
* @version 1.0
*/
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final int UPDATE_PROVICE = 0x01;
private static final int UPDATE_CITY = 0x02;
private static final int UPDATE_WEATHER = 0x03;
// 声明对象
private Spinner spProvince, spCity;
private TextView tvCurrentWeather;
private ListView lvWeather;
// 声明数据集合
private List<String> provinces = new ArrayList<>();
private List<String> citys = new ArrayList<>();
// 页面数据适配器
private ArrayAdapter<String> provinceAdapter;
private ArrayAdapter<String> cityAdapter;
private SoapObject watherDetail = null;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_PROVICE:
provinceAdapter.notifyDataSetChanged();
break;
case UPDATE_CITY:
cityAdapter.notifyDataSetChanged();
break;
case UPDATE_WEATHER:
lvWeather.setAdapter(new WeatherAdapter(MainActivity.this, watherDetail));
// tvCurrentWeather.setText(watherDetail.getProperty(7).toString());
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindView();
initData();
}
/**
* 初始化 省份和城市
*/
private void initData() {
provinceAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, provinces);
spProvince.setAdapter(provinceAdapter);
cityAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, citys);
spCity.setAdapter(cityAdapter);
getProvince();
getCity("黑龙江");
}
/**
* 绑定视图
*/
private void bindView() {
spProvince = findViewById(R.id.sp_province);
spCity = findViewById(R.id.sp_city);
tvCurrentWeather = findViewById(R.id.tv_current_weather);
lvWeather = findViewById(R.id.weather_list);
spProvince.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
getCity(provinces.get(position));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spCity.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
getWeather(citys.get(position));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
/**
* 获取省份
*/
private void getProvince() {
new Thread() {
@Override
public void run() {
provinces.clear();
provinces.addAll(WebServiceUtil.getProvinceList());
mHandler.sendEmptyMessage(UPDATE_PROVICE);
}
}.start();
}
/**
* 获取城市
*
* @param province
*/
private void getCity(final String province) {
new Thread() {
@Override
public void run() {
citys.clear();
citys.addAll(WebServiceUtil.getCityListsByProvince(province));
mHandler.sendEmptyMessage(UPDATE_CITY);
}
}.start();
}
/**
* 获取天气
*
* @param city
*/
private void getWeather(final String city) {
new Thread() {
@Override
public void run() {
watherDetail = null;
watherDetail = WebServiceUtil.getWeatherByCity(city);
mHandler.sendEmptyMessage(UPDATE_WEATHER);
}
}.start();
}
}
~~~
`
### 2.2.5 ListAdapter代码
`
~~~
package cn.zhaoliang5156.demo;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import org.ksoap2.serialization.SoapObject;
/**
* 天气列表适配器
*
* @author zhaoliang
* @version 1.0
*/
public class WeatherAdapter extends BaseAdapter {
private Context context;
private SoapObject data;
private int iconOne = 10;
private int iconTwo = 11;
private int weatherOne = 7;
private int weatherTwo = 8;
private int weatherThree = 9;
public WeatherAdapter(Context context, SoapObject data) {
this.context = context;
this.data = data;
}
@Override
public int getCount() {
return data == null ? 0 : 5;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHodler hodler = null;
if (convertView == null) {
hodler = new ViewHodler();
convertView = LayoutInflater.from(context).inflate(R.layout.list_item, null);
hodler.ivIconOne = convertView.findViewById(R.id.icon_one);
hodler.ivIconTwo = convertView.findViewById(R.id.icon_two);
hodler.tvWeather = convertView.findViewById(R.id.weather);
convertView.setTag(hodler);
} else {
hodler = (ViewHodler) convertView.getTag();
}
hodler.ivIconOne.setImageResource(parseIcon(data.getProperty(iconOne).toString()));
hodler.ivIconTwo.setImageResource(parseIcon(data.getProperty(iconTwo).toString()));
hodler.tvWeather.setText(data.getProperty(weatherOne) + "\n" + data.getProperty(weatherTwo) + "\n" + data.getProperty(weatherThree));
iconOne += 5;
iconTwo += 5;
weatherOne += 5;
weatherTwo += 5;
weatherThree += 5;
return convertView;
}
class ViewHodler {
ImageView ivIconOne;
ImageView ivIconTwo;
TextView tvWeather;
}
// 工具方法,该方法负责把返回的天气图标字符串,转换为程序的图片资源ID。
private int parseIcon(String strIcon) {
if (strIcon == null)
return -1;
if ("0.gif".equals(strIcon))
return R.drawable.a_0;
if ("1.gif".equals(strIcon))
return R.drawable.a_1;
if ("2.gif".equals(strIcon))
return R.drawable.a_2;
if ("3.gif".equals(strIcon))
return R.drawable.a_3;
if ("4.gif".equals(strIcon))
return R.drawable.a_4;
if ("5.gif".equals(strIcon))
return R.drawable.a_5;
if ("6.gif".equals(strIcon))
return R.drawable.a_6;
if ("7.gif".equals(strIcon))
return R.drawable.a_7;
if ("8.gif".equals(strIcon))
return R.drawable.a_8;
if ("9.gif".equals(strIcon))
return R.drawable.a_9;
if ("10.gif".equals(strIcon))
return R.drawable.a_10;
if ("11.gif".equals(strIcon))
return R.drawable.a_11;
if ("12.gif".equals(strIcon))
return R.drawable.a_12;
if ("13.gif".equals(strIcon))
return R.drawable.a_13;
if ("14.gif".equals(strIcon))
return R.drawable.a_14;
if ("15.gif".equals(strIcon))
return R.drawable.a_15;
if ("16.gif".equals(strIcon))
return R.drawable.a_16;
if ("17.gif".equals(strIcon))
return R.drawable.a_17;
if ("18.gif".equals(strIcon))
return R.drawable.a_18;
if ("19.gif".equals(strIcon))
return R.drawable.a_19;
if ("20.gif".equals(strIcon))
return R.drawable.a_20;
if ("21.gif".equals(strIcon))
return R.drawable.a_21;
if ("22.gif".equals(strIcon))
return R.drawable.a_22;
if ("23.gif".equals(strIcon))
return R.drawable.a_23;
if ("24.gif".equals(strIcon))
return R.drawable.a_24;
if ("25.gif".equals(strIcon))
return R.drawable.a_25;
if ("26.gif".equals(strIcon))
return R.drawable.a_26;
if ("27.gif".equals(strIcon))
return R.drawable.a_27;
if ("28.gif".equals(strIcon))
return R.drawable.a_28;
if ("29.gif".equals(strIcon))
return R.drawable.a_29;
if ("30.gif".equals(strIcon))
return R.drawable.a_30;
if ("31.gif".equals(strIcon))
return R.drawable.a_31;
return 0;
}
}
~~~
`
- 咨询项目实战
- 第一单元 HTTP协议
- 1.1 OSI七层模型
- 1.2 HTTP协议(重点)
- 1.3 HTTPS协议(了解)
- 1.4 TCP/IP协议扩展
- 1.5 WebService简介及实战(无接口)
- 1.6 课后练习
- 第二单元 HTTPURLConnection
- 2.1 ANR
- 2.2 网络判断
- 2.3 HTTPURLConnection
- 2.4 课后练习
- 第三单元 AsyncTask
- 3.1 AsyncTask概述
- 3.2 AsyncTask基本使用
- 3.3 课后练习
- 第四单元 图片异步加载
- 4.1 图片异步加载概述
- 4.2 LruCache
- 4.3 DiskLRUCache
- 4.4 图片三级缓存概述
- 4.5 封装图片加载缓存框架
- 第五单元 ListView多条目
- 5.1 ListView多条目概述
- 5.2 ListView多条目的使用
- 第六单元 ListView实现下拉刷新上拉加载
- 6.1 下拉刷新和上拉加载更多
- 6.2 XListView概述
- 6.3 XListView的使用
- 第七单元 封装网络框
- 7.1 封装网络框架概述
- 7.2 网络框架的封装
- 第八单元 项目介绍
- 8.1 公司项目团队架构简介
- 8.2 项目文档及项目流程介绍
- 8.3 项目管理
- 8.4 项目开发
- 第九单元 项目框架搭建
- 9.1 基类封装概述
- 9.2 Application中初始化配置
- 9.3 项目中的工具类
- 9.4 封装网络请求框架
- 9.5 封装图片异步缓存框架
- 第十单元 搭建UI框架1
- 10.1 侧滑菜单概述
- 10.2 主界面框架搭建
- 第十一单元 搭建UI框架2
- 11.1 TabLayout的概述
- 11.2 TabLayout的使用
- 第十二单元 图片上传
- 12.1 图片上传概述
- 12.2 图片上传的实现
- 第十三单元 PullToRefresh
- 13.1 PullToRefresh概述
- 13.2 PullToRefresh的使用
- 13.3 缓存业务实现思路
- 第十四单元 事件分发及滑动冲突
- 14.1 事件分发概述
- 14.2 事件分发流程
- 14.3 事件分发的使用
- 第十五单元 传感器的基本使用
- 15.1 传感器概述
- 15.2 传感器的使用
- 第十六单元 HTML与CSS复习
- 16.1 HTML
- 16.2 CSS
- 第十七单元 js复习
- 17.1 js基础语法
- 17.2 js数组和内置对象
- 17.3 js常用事件
- 17.4 js对象模型
- 17.5 js 正则表达式
- 第十八单元 WebView
- 18.1 WebView 概述
- 18.2 WebView的使用
- 18.3 WebView与js交互
- 第十九单元 项目案例
- 项目概述
- 第二十单元 项目答辩
- 周考
- 第一周周考
- 第二周周考
- 第三种周考
- 月考
- 接口文档