🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
***** **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; } } ~~~ `