• eclipse使用CXF3.1.*创建webservice服务端客户端以及客户端手机APP(二)


    eclipse使用CXF3.1.*创建webservice服务端客户端以及客户端手机APP(二)

    接上篇博客,本篇博客主要包含两个内容:

    4.使用Android studio创建webservice客户端APP访问服务端。

    5.开发过程中可能出现的一些错误。

    闲话少叙,直奔主题。

    4.使用Android studio创建webservice 客户端APP访问服务端

    先介绍操作,再介绍原理。

    手机端运行时,必须和电脑端在同一局域网下。

    使用Android studio创建一个项目,使用这个下载链接 https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/ksoap2-android/ksoap2-android-assembly-2.4-jar-with-dependencies.jar 下载soap的jar包。

    在AndroidManifest.xml中加入网络访问权限代码:

    1. <!-- 访问网络的权限 -->
    2. <uses-permission android:name="android.permission.INTERNET" />

    左边列表使用project,项目名称-----app----libs,然后把上面地址下载的jar包复制进去,在jar包上右击,选择下面的add as library即可导入包。

    这是我的项目目录结构图,

    下面依然粘贴代码:

    界面代码Activity_main.xml,只有一个输入框,一个显示textView,一个按钮,

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <LinearLayout
    3.     xmlns:android="http://schemas.android.com/apk/res/android"
    4.     xmlns:app="http://schemas.android.com/apk/res-auto"
    5.     xmlns:tools="http://schemas.android.com/tools"
    6.     android:layout_width="match_parent"
    7.     android:layout_height="match_parent"
    8.     tools:context="com.dyf.sharedpsclient.MainActivity">
    9.  
    10.     <EditText
    11.         android:id="@+id/id_et_input"
    12.         android:layout_width="148dp"
    13.         android:layout_height="wrap_content"
    14.         android:ems="10"
    15.         android:inputType="textPersonName"
    16.         />
    17.  
    18.     <TextView
    19.         android:id="@+id/id_tv_show"
    20.         android:layout_width="wrap_content"
    21.         android:layout_height="wrap_content"
    22.         android:text="Hello World!"
    23.         app:layout_constraintBottom_toBottomOf="parent"
    24.         app:layout_constraintLeft_toLeftOf="parent"
    25.         app:layout_constraintRight_toRightOf="parent"
    26.         app:layout_constraintTop_toTopOf="parent"/>
    27.  
    28.     <Button
    29.         android:id="@+id/id_btn_get"
    30.         android:layout_width="wrap_content"
    31.         android:layout_height="wrap_content"
    32.         android:text="获取信息"
    33.         tools:layout_editor_absoluteX="147dp"
    34.         tools:layout_editor_absoluteY="321dp"/>
    35.  
    36. </LinearLayout>

    操作代码MainActivity.java,主要包括初始化控件,按钮的点击操作,开启新线程发送webservice请求,接收返回结果,使用Handler修改界面信息。

    1. package com.dyf.sharedpsclient;
    2.  
    3. import android.app.Activity;
    4. import android.os.Bundle;
    5. import android.os.Handler;
    6. import android.os.Message;
    7. import android.util.Log;
    8. import android.view.View;
    9. import android.widget.Button;
    10. import android.widget.EditText;
    11. import android.widget.TextView;
    12.  
    13. import org.ksoap2.SoapEnvelope;
    14. import org.ksoap2.serialization.SoapObject;
    15. import org.ksoap2.serialization.SoapSerializationEnvelope;
    16. import org.ksoap2.transport.HttpTransportSE;
    17.  
    18. public class MainActivity extends Activity implements View.OnClickListener
    19. {
    20.     private TextView tv = null;
    21.     private Button btn_Get = null;
    22.     private EditText et_Input = null;
    23.  
    24.     @Override
    25.     protected void onCreate(Bundle savedInstanceState)
    26.     {
    27.         super.onCreate(savedInstanceState);
    28.         setContentView(R.layout.activity_main);
    29.         tv = (TextView) findViewById(R.id.id_tv_show);
    30.         btn_Get = (Button) findViewById(R.id.id_btn_get);
    31.         et_Input = (EditText) findViewById(R.id.id_et_input);
    32.         //直接调用webservice中的getParklotName方法
    33.         btn_Get.setOnClickListener(this);
    34.     }
    35.  
    36.     private String callService()
    37.     {
    38.         //命名空间
    39.         String nameSpace = "http://dao.diy.com";
    40.         //serviceURL
    41.         String serviceURL = "http://10.201.23.77:8080/webservice";
    42.         //调用的方法名称
    43.         String methodName = "sayHello";
    44.         //创建HttpTransportSE传输对象
    45.         HttpTransportSE transport = new HttpTransportSE(serviceURL);
    46.         //transport.debug = true;
    47.  
    48.         //使用Soap1.1创建SoapSerializationEnvelope对象
    49.         SoapSerializationEnvelope envelop = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    50.         //实例化SoapObject对象
    51.         SoapObject request = new SoapObject(nameSpace, methodName);
    52.         String soapAction = nameSpace +"/"+ methodName;
    53.         String inputText = et_Input.getText().toString();
    54.         Log.i("inputText:",inputText);
    55.         request.addProperty("arg0", inputText);
    56.         envelop.dotNet = true;
    57.         envelop.bodyOut = request;
    58.         envelop.setOutputSoapObject(request);
    59.         envelop.encodingStyle = "UTF-8";
    60.         //调用webservice
    61.         try
    62.         {
    63.             transport.call(soapAction, envelop);
    64.             Log.i("envelop.getresponse:", envelop.getResponse().toString());
    65.             if (envelop.getResponse().toString() != null)
    66.             {
    67.                 SoapObject result = (SoapObject) envelop.bodyIn;
    68.                 String word = result.getProperty(0).toString();
    69.                 return word;
    70.                 //tv.setText(word);
    71.             }
    72.         } catch (Exception e)
    73.         {
    74.             Log.i("调用webservice出错:",e.toString());
    75.             e.printStackTrace();
    76.             return "no";
    77.         }
    78.         return null;
    79.     }
    80.  
    81.     //定义Handler对象
    82.     private Handler handler = new Handler(){
    83.  
    84.         @Override
    85.         public void handleMessage(Message msg)
    86.         {
    87.             String str= null;
    88.             switch (msg.what)
    89.             {
    90.                 case 1:
    91.                     str = msg.obj.toString();
    92.                     tv.setText(str);
    93.             }
    94.         }
    95.     };
    96.  
    97.     /**
    98.      * Called when a view has been clicked.
    99.      *
    100.      * @param v The view that was clicked.
    101.      */
    102.     @Override
    103.     public void onClick(View v)
    104.     {
    105.         switch (v.getId())
    106.         {
    107.             case R.id.id_btn_get:
    108.                 new Thread() {
    109.                     @Override
    110.                     public void run() {
    111.                         // 你要执行的方法
    112.                         Log.i("tag","new thread");
    113.                         Message message = new Message();
    114.                         message.what = 1;
    115.                         message.obj = callService();
    116.                         Log.i("message.what", String.valueOf(message.what));
    117.                         Log.i("message.obj",message.obj.toString());
    118.                         // 执行完毕后给handler发送消息
    119.                         handler.sendMessage(message);
    120.                     }
    121.                 }.start();
    122.                 break;
    123.         }
    124.     }
    125. }

    运行之后的结果:左边是软件一进入的界面,右边是输入框输入之后,点击获取信息按钮,然后显示服务端返回的内容。

    下面介绍一下这个程序中的代码。

    按照程序流程一步步进行,首先是103行的点击按钮的click事件,定义一个Message对象,接收返回结果使用,115行的message.obj = callService();使用callService方法,得到服务端返回结果,然后由handler发送消息,82行判断之后,修改主界面信息。其中callService方法是一个主要过程,下面重点说明一下。

    首先39行声明命名空间nameSpace,值就是服务器端提供服务接口所在包倒写,最后不加 "/" ,否则下面运行时eclipse服务端会报 下面这个错误,(主要看第二行,楼主就在这个地方坑了两天)

    1. 警告: Interceptor for {http://dao.diy.com}SayHelloService#{http://dao.diy.com}sayHello has thrown exception, unwinding now
    2. org.apache.cxf.interceptor.Fault: Unexpected wrapper element {http://dao.diy.com/}sayHello found. Expected {http://dao.diy.com}sayHello.
    3.    at org.apache.cxf.wsdl.interceptors.DocLiteralInInterceptor.handleMessage(DocLiteralInInterceptor.java:107)
    4.    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
    5.    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
    6.    at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267)
    7.    at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:234)
    8.    at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:76)
    9.    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1129)
    10.    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1065)
    11.    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    12.    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
    13.    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    14.    at org.eclipse.jetty.server.Server.handle(Server.java:499)
    15.    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311)
    16.    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:258)
    17.    at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544)
    18.    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
    19.    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
    20.    at java.lang.Thread.run(Thread.java:745)

    然后41行定义服务访问的serviceURL,值就是服务端发布时的发布地址,结尾不要加 "/" ,不加 "?wsdl"。

    43行定义调用的方法名称,注意名称和大小写别写错。

    52行的soapAction ,注意是nameSpace+"/"+methodName,别忘了这个 "/" ,如果没有,服务端控制台那里报错,会打出这个soapaction,自己一看就明白了。

    55行的request.addProperty(key ,value),这句是添加参数的,因为上面的sayHello方法只有一个参数,所以这里写了一次,如果有多个参数,则这里写对应个数的参数即可。

    63行发起请求。

    65行判断返回值不为空的情况,在67行可能会出现一个问题,使用SoapObject类时,Android studio控制台可能会报

    java.lang.ClassCastException: org.ksoap2.serialization.SoapPrimitive cannot be cast to org.ksoap2.serialization.SoapObject , 类转换错误,出现这个错误的话,把SoapObject改为Object就可以了,网上有人说是版本的问题,楼主也不是很清楚,但是如果出现这个错误,改为Object就可以了。

    另外67行还有一个坑,有的使用envelop.getResponse() 的时候,也可能会报错,改为使用 envelop.bodyIn即可。

    上面就是Android studio主要代码中的一些说明了。

    下面是项目中,可能会遇到的一些错误。

    5.开发过程中可能会出现的一些错误

    (1)java.lang.ClassCastException: org.ksoap2.serialization.SoapPrimitive,类转换错误。

    参考: https://www.cnblogs.com/gushandujian/p/3495191.html

    http://blog.csdn.net/whybiang/article/details/6533051 ,解释很详细,感谢作者。

    在服务器端返回值是String类型的数值的时候使用SoapObject soapObject = (SoapObject) envelope.getResponse();和 SoapObject result = (SoapObject)envelope.bodyIn;这两种方法来接受值都会报出 java.lang.ClassCastException: org.ksoap2.serialization.SoapPrimitive这样的错误。 我们可以使用 Object object = (Object)envelope.getResponse();就可以解决这种错误。

    (2)org.apache.cxf.interceptor.Fault: The given SOAPAction http://wsservice.abc.com/icService does not match an operation. 或者是 org.apache.cxf.interceptor.Fault: Unexpected wrapper element {http://wsservice.abc.com}icService found. Expected {http://wsservice.abc.com/}icService.

    参考: http://www.yyjjssnn.cn/articles/706.html ,解释很详细,感谢作者。

    这两种错误都是因为服务端编写时,没有在服务和方法上加入或者编写注解不对导致的,请详细查看注解是否正确,以及网页中的wsdl 描述的soapaction是否正确,详细可以查看我的上一篇博客,查看webservice服务端代码如何编写。

    新增demo源码下载地址:链接:https://pan.baidu.com/s/1sm1w3ud  密码:0n40,链接失效的话,请评论区留言个人百度账号,给你分享一下。

    由于编者水平有限,文章中如有不妥之处或者有什么疑问,可直接在下面评论指出,不胜感激。

  • 相关阅读:
    1114 Family Property (25 分)(并查集)
    【专题复习4:Dijkstra】1003、1018、1030、1072、1087、1111
    1133 Splitting A Linked List (25 分)(链表)
    【专题复习5:并查集】1107、1114、1118
    Java Window 下安装 java
    OpenShift4 节点TimeZone修改
    PHP魔术方法
    .NET中的HashSet
    格式化字符串
    Jetpack Compose
  • 原文地址:https://www.cnblogs.com/diyunfei/p/8184418.html
Copyright © 2020-2023  润新知