因为我把自己项目的名字换成了projectName 所以如果你要运行一下代码,必须注意!

最近有一个需求。我理解的意思是在已有的项目里面写一个webservice,然后供web端、安卓端调用(ios没条件,暂时不考虑)。最终历经八十一难,还是搞定了。
1、webservice(cxf3.0.1 + jdk1.6)项目环境是springmvc+sprng+spring data jpa

1.1、首先定义一个接口,@WebService注解的属性大多不知道是什么意思,不过targetNamespace属性在后面安卓调用时候确实有用到, 

 @WebParam(name="distance")参数的定义最好要写,因为wsdl文件的参数会根据name属性显示 

 @WebService(targetNamespace="http://com.study/ws") 

 public interface PsI { 

     @WebMethod 

     public String getPoints(@WebParam(name="distance")String distance); 

 } 

 1.2、然后写一些接口的实现,注意实现类的@WebService的endpointInterface属性,就是定义接口的路径 


 @WebService(endpointInterface="x.x.PsI",serviceName="peiSong", 

 name="peiSong", portName="peiSong", targetNamespace="http://com.ums.study/ws") 

 public class PsImp implements PsI{ 


     @Autowired 

     private PsService psService; 

      

     @Override 

     @WebMethod 

     public String getPoints(@WebParam(name="distance")String distance) { 

             system.out.println("server:  " + distance); 

             return "hello,client"; 

         } 

          

     } 


 } 

 @WebParam 可以让你的参数名字在wsdl文件显示出来 



 1.3、web.xml配置 这个没什么好说的 

 <servlet> 

         <servlet-name>cxf</servlet-name> 

         <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> 

         <load-on-startup>1</load-on-startup> 

     </servlet> 

     <servlet-mapping> 

         <servlet-name>cxf</servlet-name> 

         <url-pattern>/services/*</url-pattern> 

 </servlet-mapping> 


 1.4、spring相关配置 

 <import resource="classpath:META-INF/cxf/cxf.xml" /> 

 <jaxws:endpoint id="psProcess" 

         implementor="#psImpl" address="/ws/ps"/> 

 <bean id="psImpl" class="x.x.PsImp" /> 

 很多人不知道cxf.xml在哪里。cxf core包 META-INF目录下面,不是在package里面的 

 另外值得注意的两个地方 

 (1)、jaxws:endpoint 的implementor属性要加 "#" 

 (2)、jaxws:endpoint 的 adress属性的配置有两种:一种绝对路径,如"http://ip:port/ws/ps" 另外一种是相对路径,如"/ws/ps" 

 一开始我用的是绝对路径,自己写的javaproject 或者是 web project都可以用,但是用到项目里面就不行了。琢磨了好久,修改成相对路径才成功 


 1.5、如果你的项目里面有一些安全框架,例如 springsecurity、apacheshiro,或许你还要过滤调一些资源,毕竟,别人调用webservice的时候肯定 

 不希望去做登录的都工作。我的项目里面是用的springsecurity 

 <beans>节点下面加上 

 <http pattern="/services/ws/*" security="none" /> 


 1.6、测试 

 到这里,服务端的基本上已经写好了 

 因为我的webservice是交给spring来管理,就没有在main方法里,写一个启动服务的代码。直接启动web服务器 

 在浏览器输入  http://ip:port/prijectName/services/ws/ps?wsdl 出现wsdl文件,说明成功了 


 2、安卓调用webservice 


 2.1、安卓访问webservice 需要 ksoap2-android-assembly-2.6.0.jar 

 package com.ums.demo; 


 import org.ksoap2.SoapEnvelope; 

 import org.ksoap2.serialization.SoapObject; 

 import org.ksoap2.serialization.SoapSerializationEnvelope; 

 import org.ksoap2.transport.HttpTransportSE; 


 public class HttpWS { 

     // 声明WS的命名空间,命名空间在WSDL的头部显示 

     private static final String NAMESPACE = "http://com.ums.study/ws"; 

     // 设置WS的路径 

     private static String SERVICEURL = "http://10.0.2.2:8080/projectName/services/ws/ps?wsdl"; 


     public String GetWS(String methodName, String[] parames, String[] paramesKey) { 

         System.out.println("########################start"); 

         // SOAP Action 

         String soapAction = NAMESPACE +"/"+ methodName; 

         // 创建SoapObject对象,并指定WebService的命名空间和调用的方法名 

         SoapObject request = new SoapObject(NAMESPACE, methodName); 

          

          

         // 生成调用WebService方法的SOAP请求信息,并指定SOAP的版本 

         SoapSerializationEnvelope envelope = new SoapSerializationEnvelope( 

                 SoapEnvelope.VER11); 

          

          

         if (parames != null) { 

             for (int i = 0; i < parames.length; i++) { 

                 System.out.println("key: "+ paramesKey[i] + "   value: "+parames[i]); 

                 request.addProperty(paramesKey[i], parames[i]); 

             } 

         } 


         // 上边的一句等价于下边的这句 将SoapObject对象赋给envelope对象 

         envelope.bodyOut = request; 

      

         // 当前开发的是Java WSen  这里需要不调用.net WS 

         envelope.dotNet = false; 

         String res = ""; 

         HttpTransportSE ht = new HttpTransportSE(SERVICEURL); 

         try { 

             // 请求WSz 

             ht.call(null, envelope); 

             if (envelope.getResponse() != null) { 

                 // 获得WS函数返回值信息 

                 res = envelope.getResponse().toString(); 

             } 

         } catch (Exception e) { 

             e.printStackTrace(); 

         } 

         System.out.println("########################end"); 

         return res; 

     } 

 }


这是访问工具类的代码

private static final String NAMESPACE = "http://com.ums.study/ws"; 

 这个是 webservice接口的实现类的 targetNamespace属性的值 

 如果用这个代码 

 private static String SERVICEURL = "http://10.0.2.2:8080/projectName/services/ws/ps?wsdl"; 

 这个projectName 必须改成自己项目的路径,而且安卓localhost 为 10.0.2.2:8080




代码在这里,如果你正在写相关代码,并且在阅读这篇文章,祝你好运!