跨系统调用接口方案--WebService

第一部分: 概述

webservice是一个  SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过 Internet 进行基于 HTTP协议的网络应用间的交互。

WebService的几种概念:

        实际上SOA只是一种架构设计模式,而SOAP、REST、RPC就是根据这种设计模式构建出来的规范,其中

  • SOAP:通俗理解就是http+xml的形式,
  • REST:就是http+json的形式,
  • RPC:是基于socket的形式。

  • CXF就是典型的SOAP/REST框架,
  • dubbo就是典型的RPC框架,
  • 而SpringCloud就是遵守REST规范的生态系统。

  web service大体上分为5个层次

  1. Http传输信道
  2. XML的数据格式
  3. SOAP封装格式(传递信息的格式)
  4. WSDL的描述方式(如何访问具体的接口)
  5. UDDI是一种目录服务,企业可以使用它对webservice进行注册和搜索(管理、分发、查询webservice)  

RESTful跟WebService的区别:

        REST是一种架构风格,其核心是面向资源,遵循CRUD原则,这个原则告诉我们对于资源只需要4种行为,分别是:创建,获取,更新和删除,并且这些资源执行的操作时通过HTTP协议规定的,而WebService底层是SOAP协议,核心是面向活动,有严格的规范和标准,包括安全,事务等方面。

那么我们是使用RESTful还是WebService就需要考虑资源本身的 ,看资源本身是那种简单的类似增删改查的业务操作,还是那种比较复杂,如转账,事务处理等。其次是看是否有严格的规范和标准的,而且有多个业务系统集成和开发的时候,我们使用SOAP协议就比较优势,如果是简单的数据操作,无事务处理,开发和调用比较简单的话使用REST架构风格比较有优势,较为复杂的面向活动的服务,我们使用REST意义不大。

RESTful风格的webservice 越来越流行了,

场景:

天气预报:可以通过实现 webservice客户端调用远程天气服务实现的。

单点登录:一个服务是所有系统的登录,不同的系统都可以通过webservice调用这个单点登录服务

1、异构系统(不同语言)的整合

2、不同客户端的整合 浏览器、手机端(android,ios.塞班)、微信端、PC端等终端来访问 

设计:比如现我有一个数据库,一个JavaWeb(或者PHP等)的网站客户端,一个安卓app客户端,一个IOS客户端。现在我要给用户提供一个注册账号的功能。

不用SOA的设计思想的实现:JavaWeb里面写一个注册账号的功能,安卓app里面写一个注册账号的功能,IOS同样如此。那么这样的实现有没有什么问题呢?比如有一天,我的注册方法需要改动,那是不是三个地方都要改,而且要改的一模一样。当然问题不止这一个。

SOA的设计思想实现:用Java(或者是其他语言皆可)单独创建一个工程部署在一台服务器上,并且写一个方法(或称函数)执行上述注册操作,然后提供一个接口,其他人可以通过某种途径(可以是http链接,或者是基于socket的RPC调用)访问这个方法来注册。就是说把这个操作封装到一个工程中去,然后暴露访问的方式,形成“服务”。要修改关于注册用户的业务方法只要改这个服务就好了,很好的解耦。

以HTTP协议为基础,通过XML进行客户端和服务器端通信的框架/组件

两个关键点:

1. 服务端提供的功能, 通过xml描述

2. 第一步中的描述的功能, 嵌入到HTTP协议中, 使得能通过HTTP协议进行通信【所谓的SOAP】.

采用这两个技术的目的主要是:

1. 跨平台, 支持HTTP协议的主机和服务器, 都能够建立通信联系, 并且大部分的主机和服务器(99.99%以上)将支持HTTP协议。一般而言,不同目标主机之间的通信,需要通过防火墙,打开某个端口, HTTP协议的优势在于,防火墙一般不会封掉80端口, 这样就可以方便,安全的通信。

2. 跨语言, 任何语言, 都支持XML文本解析, 这个的目的是为了实现不同语言之间的通信, 通信的内容,是被xml限制的,因此这样进行通信,能跨越语言障碍,即, Java开发的服务端,客户端可以用C访问, 可以用java,VB等访问, 反之亦然。

第二部分: 基本原理和架构

1. 服务器端(Provider) 提供统一的标准化服务。就像开办一个公司(即Server Provider), 工商行政管理局,注册一下公司地址和性质。目的是, 别人要用公司的服务,从工商管理局就知道你的地址。这样统一的做法,是方便所有的公司以及所有需要公司提供服务的客户。并且这些信息是最大限度的公开。

2. 客户端(Requester) 到注册中心(Registry)拿到公司的基本信息之后, 去找到这个公司, 然后使用该公司提供的服务。

 

图二: 基本的WebService架构流程图

 

图三: 细节步骤流程图

上图这些东西, 完完整整的呈现了WebService的整个原理流程:

1.       Client有需要,想调用一个服务,但不知道哪里去调用. 但知道UDDI Registry上可以查到。

2.       果然UDDI记录了某个一个叫做Web Server A的服务器能提供这样的服务。

3.       于是Client去Web Server A, 询问确切的调用方法。

4.       Web Server A看到Client提出的“确切方法查询”之后,立即返回给它一个WSDL描述的xml文档这里记录他能提供的各类方法接口. 

(WSDL(网络服务描述语言,Web Services Description Language)是一门基于 XML 的语言,用于描述 Web Services 以及如何对它们进行访问)

5.       Client了解到这些之后,将这些xml的接口方法,封装成为HTTP请求, 发给Web Server A. 这些封装方式采用的是标准的SOAP方式, 实质是满足HTTP协议的一些SOAP的报文消息。

(SOAP(Simple Object AccessProtocol)简单对象访问协议。基于 XML 的协议,它被设计成在 WEB 上交换结构化的和固化的信息。SOAP=RPC+HTTP+XML)

6.       Web Server A回应的也是HTTP协议的SOAP包. 这样双方的请求-响应完全畅通。

上面我们看到的是应用原理图, 进一步深入, 可以发现如下的协议架构图:

 

图四: 协议结构

第三部分实践WebService

看到上面的图那么复杂, 实质上SOAP+HTTP协议已经足够成熟,犯不着让我们通过xml生成带有SOAP变迁的HTML脚本, 有很多工具可以帮住我们实现。事实上,开发起来还是相当简便的。

图五:实际应用中的调用

参考资料:WebService的简介, 原理, 使用,流程图 - 锟斤拷锟斤拷 - 博客园 

1、发布第一个WebService服务 

package com.itcast;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
/**
* 第一个WebService服务应用
*/
//通过注解,标明此类发布为一个WebService
@WebService
public class HelloWorld {
public String sayHello(){
   return"Hello World";
}
//在main方法中,使用javax.xml.ws.Endpoint端点发布一个应用
public static void main(String[] args) {
Endpoint.publish("http://127.0.0.1:9999/helloworld",new HelloWorld());
}
}

http://127.0.0.1:9999/helloworld?wsdl 

调用  RunMain.java的源代码如下

/**
* 通过调用生成的类,来调用远程代码
*/
publicclass  RunMain {
publicstatic  void  main(String[] args) {
  //String url= http://127.0.0.1:9999/helloworld;
  //HelloWorld helloWorld = new HelloWorld( url ) ;
  //从HelloWorldSerice的getHelloWorldPort方法中返回调用接口
  HelloWorld helloWorld = new HelloWorldService().getHelloWorldPort();
  String str = helloWorld.sayHello(); //执行调用
  System.err.println(str); //返回HelloWorld字符串
}
}

2、WebService的部分注解

@WebService注解

   1、serviceName: 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service。缺省值为 Java 类的简单名称 + Service。(字符串)

   2、endpointInterface: 服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口

   3、name:此属性的值包含XML Web Service的名称。在默认情况下,该值是实现XML Web Service的类的名称,wsdl:portType 的名称。缺省值为 Java 类或接口的非限定名称。(字符串

   4、portName:  wsdl:portName。缺省值为 WebService.name+Port。

   5、targetNamespace:指定你想要的名称空间,认是使用接口实现类的包名的反缀

   6、wsdlLocation:指定用于定义 Web Service 的 WSDL 文档的 Web 地址。Web 地址可以是相对路径或绝对路径。(字符串)

   注意:实现类上可以不添加Webservice注解  

3、WebService开源框架的选择

目前主流的Web Service框架主要有3种: Axis 2, CXF, 和 Spring WS。

Axis 2和CXF都是来自于Apache, 各个方面相差不多,但是目前市场上使用CXF比较多一点。

Spring + CXF框架 开发 RESTful的WebService

发布需要整合CXF+spring+mybatis,spring+mybatis负责查询,CXF+spring负责配置bean和发布接口,在xml配置文件中;

二、CXF整合Spring开发WebService

Spring和CXF整合发布WebService(服务端、客户端)_天黑黑~的博客-CSDN博客_cxf spring

CXF整合Spring开发WebService - 江南一点雨 - 博客园

1、发布服务

这里写图片描述

IMyServer.java

@WebService
public interface IMyServer {

    @WebResult(name="addResult")
    public int add(@WebParam(name="a")int a,@WebParam(name="b")int b);
}

MyServerImpl.java

@WebService(endpointInterface="cxf.lenve.test.IMyServer")
public class MyServerImpl implements IMyServer {

    @Override
    public int add(int a, int b) {
        System.out.println("服务端..."+a+"+"+b+"="+(a+b));
        return a+b;
    }
}

写一个接口一个实现类就可以了,至于发布则在配置文件中完成即可

webservice-beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
    xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
    <!-- 定义webservice服务,相当于发布 -->
    <jaxws:server id="MyServer" address="/MyServer" serviceClass="cxf.lenve.test.IMyServer">
        <!--发布服务类  -->
        <jaxws:serviceBean>
            <bean class="cxf.lenve.test.MyServerImpl"></bean>
        </jaxws:serviceBean>
    </jaxws:server>
</beans>

好了,文档已经发布,剩下的就是配置web.xml文件了,看:

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee  http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1" metadata-complete="true">
     
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/beans.xml</param-value>
</context-param>
<listener>
    <listener-class>
         org.springframework.web.context.ContextLoaderListener
      </listener-class>
</listener>
<!--cxfservlet的作用就是解析webservice请求  -->
<servlet>
    <servlet-name>cxf</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<!-- 所有前缀为ws的请求都被解析为webservice请求 -->
<servlet-mapping>
    <servlet-name>cxf</servlet-name>
    <url-pattern>/ws/*</url-pattern>
</servlet-mapping>

</web-app>

好了,至此一个cxf整合spring的webservice的应用编写成功了,运行该网站,在浏览器中查看wsdl文档:

服务端成功发布,客户端该怎样访问呢?从前我们使用wsimport将wsdl导出为java文件,现在使用cxf,可以直接使用cxf中自带的工具wsdl2java导出wsdl文件。
先创建一个客户端工程,在命令行进入该工程的src文件夹中,然后,使用如下命令导出java文件:

这里写图片描述

刷新客户端工程,就可以看到导出的java文件了。
这里写图片描述

2. 生成客户端调用方式 

第二种方式

在cmd命令中输入:wsdl2java -d 指定代码生成目录 -client webservice的访问地址url

示例:wsdl2java -d E:\\AllWorkSpace\\MyWork\\TheClient\\src -client http://localhost:8080/Dom4j_AxisDemo/service/hello?wsdl

第二种方式
JDK提供的生成客户端的命令。

在cmd命令中输入:wsimport -s 指定代码生成目录 -p 包名 -keep webservice访问地址url

示例:wsimport -s E:\\AllWorkSpace\\MyWork\\TheClient\\src -p com.eastcom.ws.client -keep http://localhost:8080/Dom4j_AxisDemo/service/hello?wsdl

另外一个项目就可以调用了

3、直接调用即可:

public class Client1 {

    public static void main(String[] args) {
        IMyServer iMyServer = new IMyServerService().getIMyServerPort();
        System.out.println(iMyServer.add(3, 4));
    }
}

这便是cxf整合spring的一个简单项目。

三:与WebService服务器进行交互的方式、java调用webservice接口的几种方式

 第二种:CXF,QName调用---推荐这种方式

public class Test2 {
    public static void main(String[] args) {
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        org.apache.cxf.endpoint.Client client = dcf.createClient("http://localhost:85/Exam/WS/userServiceWS?wsdl"); // url为调用webService的wsdl地址
        QName name = new QName("http://webservice.service.exam.xm.cn/", "getUserByUseridcard");// namespace是命名空间,methodName是方法名
        Object[] objects;
        try {
            objects = client.invoke(name, "140581197705070518");// 第一个参数是上面的QName,第二个开始为参数,可变数组
            System.out.println(objects);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public class MyTestQNameWebService {
    @Test
    public void test() throws MalformedURLException{
        //创建一个连接(地址对应的就是webservice服务器中的地址,wsdl地址 )
        URL url = new URL("http://localhost:9090/MyFirstWebService?wsdl");
        //这个参数,主要是根据我们设定的webService的接口来进行的
        //1.namespaceURI - 命名空间地址 (wsdl文档中的targetNamespace:是使用接口实现类的包名的反缀)
        //2.localPart - 服务视图名  (wsdl文档中服务名称,例如<wsdl:service name="MobileCodeWS">
        QName serviceName = new QName("http://webservice.scw.hnu.com/","MyFirstWebServiceService");
        Service ws = Service.create(url , serviceName );
        //获取到调用的对象内容
        MyFirstWebService port = ws.getPort(MyFirstWebService.class);
        //方法的调用
        String result = port.testWebService("my name is scw");
        System.out.println(result);
    }
}

注意:

(1)QName的第一个参数必须带斜杠,也就是必须写为http://webservice.service.exam.xm.cn/,否则会报下面异常:

org.apache.cxf.common.i18n.UncheckedException: No operation was found with the name {http://webservice.service.exam.xm.cn}getUserByUseridcard.
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:331)
    at Test2.main(Test2.java:15)

(2)发布的webservice的接口和实现类要在同一个包,或者在实现类用注解声明发布的webservice地址。

  CXF发布用的是业务类(xxxServiceImpl.java),那么默认的命名空间就会是业务类所在包(路径),而对外界暴露的则是接口类(XXXService.java),那么对于客户端(第三方)调用访问时,需要按照接口类所在包(路径)进行命名空间的定义。所以需要接口与实现在同一个包或者在实现类指定接口地址。

如下:(最好以/结尾---下面没有以斜杠结尾)

@Service
@WebService(targetNamespace = "http://webservice.service.exam.xm.cn")
public class UserWebServiceImpl implements UserWebService {
  。。。

(3)查看namespace相关信息:(两两相同是因为上面发布的时候没有以/结尾,最好以/结尾四个namespace就会相同)

public String getOnline(String url){
        int errCode=0;
        JSONObject resultJson=new JSONObject();
        String result="";
        Service service = new Service();
        Call call;
        try {
            call=(Call) service.createCall();
            QName opAddEntry = new QName("urn:demo", "GetOnlineInfo"); //设置命名空间和需要调用的方法名
            call.setTargetEndpointAddress(url); //设置请求路径
            call.setOperationName("GetNcgOnlineInfo");  //调用的方法名
            call.setTimeout(Integer.valueOf(2000));        //设置请求超时            
            call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//设置返回类型 
            result= (String) call.invoke(opAddEntry,new Object[]{});
           } catch (ServiceException e) {
            // TODO Auto-generated catch block
            System.out.println("查询在线状态1:"+e.getMessage());
            errCode=1;
        } catch (RemoteException e) { 
           System.out.println("查询在线状态2:"+e.getMessage());
            errCode=2;
        }
        resultJson.put("errCode", errCode);
        resultJson.put("data", result);
         return resultJson.toString();
    }

 第三种:利用HttpURLConnection拼接和解析报文进行调用。URLConnection方式

开发步骤: 
第一步:创建服务地址 
第二步:打开一个通向服务地址的连接 
第三步:设置参数 
设置POST,POST必须大写,如果不大写,报如下异常 
这里写图片描述 
如果不设置输入输出,会报如下异常 
这里写图片描述 
第四步:组织SOAP数据,发送请求 
第五步:接收服务端响应,打印

//创建url地址
URL url = new URL("http://localhost:9090/MyFirstWebService");
//打开连接
URLConnection conn = url.openConnection();
//转换成HttpURL
HttpURLConnection httpConn = (HttpURLConnection) conn;
//打开输入输出的开关
httpConn.setDoInput(true);
httpConn.setDoOutput(true);
//设置请求方式
httpConn.setRequestMethod("POST");
//设置请求的头信息
httpConn.setRequestProperty("Content-type", "text/xml;charset=UTF-8");
//拼接请求消息
String data = "<soapenv:Envelope xmlns:soapenv=" +     "\"http://schemas.xmlsoap.org/soap/envelope/\" " +     "xmlns:q0=\"http://server.rl.com/\" " +     "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +     "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"     + "<soapenv:Body>"     + "<q0:testWebService>"     + "<arg0>my name is scw</arg0> "    + "</q0:testWebService>"    + "</soapenv:Body>"    + "</soapenv:Envelope>";
//获得输出流
OutputStream out = httpConn.getOutputStream();
//发送数据
out.write(data.getBytes());
//判断请求成功
if (httpConn.getResponseCode() == 200) {   //获得输入流   //获取返回报文
      
    InputStream in = httpConn.getInputStream();   //使用输入流的缓冲区
      
    BufferedReader reader = new BufferedReader(new InputStreamReader( in ));  
    StringBuffer sb = new StringBuffer();  
    String line = null;   //读取输入流
      
    while ((line = reader.readLine()) != null) {    
        sb.append(line);  
    }   //创建sax的读取器
      
    SAXReader saxReader = new SAXReader();   //创建文档对象
      
    Document doc = saxReader.read(new StringReader(sb.toString()));   //获得请求响应return元素
      
    List < Element > eles = doc.selectNodes("//return");  
    for (Element ele: eles) {    
        System.out.println(ele.getText());  
    }
} 
/**
* @ClassName: HttpURLConectionMode 
* @Description: TODO(通过HttpURLConnection发送http请求) 
*   sope协议,比较麻烦的是需要拼接xml格式的请求数据
 */
public class HttpURLConectionMode {
    public static void main(String[] args) throws IOException {
        //第一步:创建服务地址,不是WSDL地址 
        URL url = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx");  
        //第二步:打开一个通向服务地址的连接  
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
        //第三步:设置参数  
        //3.1发送方式设置:POST必须大写  
        connection.setRequestMethod("POST");
        //3.2设置数据格式:content-type  
        connection.setRequestProperty("content-type", "text/xml;charset=utf-8");  
        //3.3设置输入输出,因为默认新创建的connection没有读写权限,  
        connection.setDoInput(true);  
        connection.setDoOutput(true);
 
        //第四步:组织SOAP数据,发送请求  
        String soapXML = getXML("15226466316");
        OutputStream os = connection.getOutputStream();  
        os.write(soapXML.getBytes()); 
 
        //第五步:接收服务端响应,打印(xml格式数据)
        int responseCode = connection.getResponseCode();  
        if(200 == responseCode){//表示服务端响应成功
            InputStream is = null;
            InputStreamReader isr = null;
            BufferedReader br = null;
            StringBuilder sb = null;
            try {
                is = connection.getInputStream();  
                isr = new InputStreamReader(is);  
                br = new BufferedReader(isr);  
 
                sb = new StringBuilder();  
                String temp = null;  
                while(null != (temp = br.readLine())){  
                    sb.append(temp);  
                }
                 System.out.println(sb.toString()); 
            } catch (Exception e) {
                e.printStackTrace();
                throw e;
            } finally {
                br.close();
                isr.close();
                is.close();
            }
        }  
         os.close();
    }
    
    public static String getXML(String phoneNum){  
        String soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"  
        +"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"  
            +"<soap:Body>"  
            +"<getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\">"  
                +"<mobileCode>"+phoneNum+"</mobileCode>"  
              +"<userID></userID>"  
            +"</getMobileCodeInfo>"  
          +"</soap:Body>"  
        +"</soap:Envelope>";  
        return soapXML;  
    }  
 }

第四种、利用Httpclient调用远程接口

1、HttpGet 

 使用方法:
1,创建HttpClient对象;
2,指定请求URL,并创建请求对象,如果是get请求则创建HttpGet对象,post则创建HttpPost对象;
3,如果请求带有参数,对于get请求可直接在URL中加上参数请求,或者使用setParam(HetpParams params)方法设置参数,对于HttpPost请求,可使用setParam(HetpParams params)方法或者调用setEntity(HttpEntity entity)方法设置参数;
4,调用httpClient的execute(HttpUriRequest request)执行请求,返回结果是一个response对象;
5,通过response的getHeaders(String name)或getAllHeaders()可获得请求头部信息,getEntity()方法获取HttpEntity对象,该对象包装了服务器的响应内容。
实例:
博主使用了property文件来保存不同API对应的链接,也可以除去properties文件的读取代码,直接将变量
API换成所需URL 

public class APIUtil { 
    /**
     * 返回API调用结果
     * @param APIName 接口在api.properties中的名称
     * @param params 访问api所需的参数及参数值
     * @return 此处返回的是JSON格式的数据
     */
    public static String API(String APIName, Map<String, Object> params) {
         String content = "";    //请求结果  
                CloseableHttpResponse response = null;   //实例化httpclient  
                CloseableHttpClient httpclient = HttpClients.createDefault();   
            try {
             //读取配置文件的URL
             Properties properties = new Properties();
             URL fileURL = APIUtil.class.getClassLoader().getResource("api.properties");
             properties.load( new FileInputStream (new File ( fileURL.getFile())));
            String API = properties.getProperty(APIName);
            //构造url请求
            StringBuilder url = new StringBuilder(API);
            if(params!=null && params.size()>0) {
                url.append("?");
                for(Map.Entry<String, Object> entry : params.entrySet()) {
                    url.append(entry.getKey()+"="+entry.getValue()+"&");
                }
                url.substring(0, url.length()-1);
            }
            //实例化get方法  
            HttpGet httpget = new HttpGet(url.toString()); 
            //执行get请求
        response = httpclient.execute(httpget);
        if(response.getStatusLine().getStatusCode()==200) {
            content = EntityUtils.toString(response.getEntity(),"utf-8");
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
        return content;
    }
} 

2、HttpPost 请求

使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。
1. 创建HttpClient对象。
2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HttpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。
5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
6. 释放连接。无论执行方法是否成功,都必须释放连接。 

public JSONObject doPost(String queryEngine, String querySql, String jobNo) {
        JSONObject jsonObject = null;
        //1.创建httpClient对象
        CloseableHttpClient client = HttpClients.createDefault();

        //2.创建请求方法的实例,并指定请求URL
        String url = "http://192.168.1.11:8080";
        HttpPost post = new HttpPost(url);
        post.setHeader("Content-Type", "application/json;charset=utf8");

        //3.参数
        AuroraPriviledge auroraPriviledge = new AuroraPriviledge();
        auroraPriviledge.setQueryEngine(queryEngine);
        auroraPriviledge.setQuerySql(querySql);
        auroraPriviledge.setJobNo(jobNo);
        String jsonString = JSON.toJSONString(auroraPriviledge);
        StringEntity entity = new StringEntity(jsonString, "UTF-8");

        post.setEntity(entity);
        //4.调用execute,返回response
        CloseableHttpResponse response = null;
        try {
            response = client.execute(post);
            HttpEntity responseEntity = response.getEntity();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return jsonObject;
    }

 项目开发中存在系统之间互调问题,又不想用dubbo,这里提供几种springboot方案:SpringBoot跨系统调用接口方案_仙道Bob的博客-CSDN博客_springboot跨服务调用

1、使用Feign进行消费(推荐)
2、使用原始httpClient请求
3、使用RestTemplate方法

第五种、RPC单编程方式(和第一种方式一样)

public class RPCApp {
    private void incomeService() {      
            String xmlStr = "xmlData"; //xml格式的参数数据拼成的字符串   
                  
            String url = "http://127.0.0.1:8080/webProject/services/systemDDLService";
            /wsdl地址
      String method="incomeJC"; 
      String webObject = null; 
      try { 
        RPCServiceClient serviceClient = new RPCServiceClient(); 
        Options options = serviceClient.getOptions(); 
        EndpointReference targetEPR = new EndpointReference(url); 
        options.setTo(targetEPR); 
        QName opAddEntry = new QName("http:/ / org.tempuri ",method);
        Object[] opAddEntryArgs = new Object[] {xmlStr}; 
        Class[] classes = new Class[] { String.class }; 
        webObject = (String)serviceClient.invokeBlocking(opAddEntry,opAddEntryArgs, classes)[0]; 
        System.out.println(webObject); 
      }catch (Exception e) { 
        e.printStackTrace(); 
        long end = System.currentTimeMillis(); 
      }
    }
}

三、webservice中jaxws:server 和jaxws:endpoint的区别

今天在学习使用spring+cxf发布webservice时遇到个问题,我原来是用

<jaxws:endpoint id="helloWorld" implementor="org.andy.cxf.HelloWorldImpl"
address="/HelloWorld">
</jaxws:endpoint>

来发布的,但是有个问题,是方法发布不上去,调用的时候会报错,原因是我的两个文件不在同一级目录下 
这里写图片描述 
将impl移到上面来就可以了 
这里写图片描述 
但是这样做的话不够规范,为什么要这样做我也不明白,所以我换了一种发布的方法 jaxws:server,换了之后按照图一的写法可以正确的发布webservice,现在把代码贴出来

<!-- 这是实现类 -->
<bean id="HelloWorldImpl" class="org.andy.cxf.impl.HelloWorldImpl" />
<!-- org.andy.cxf.HelloWorld 是接口的路径-->
<jaxws:server serviceClass="org.andy.cxf.HelloWorld" address="/HelloWorld">
	<jaxws:serviceBean>
		<ref bean="HelloWorldImpl" />
	</jaxws:serviceBean>
</jaxws:server>

至于两者的区别,我百度了下答案如下:

1、endpoint是java提供的方法,server是cxf提供的

2、访问wsdl地址设置不同 endpoint可以直接设,server这要根据你的项目及cxf.xml决定

3、endpoint不推荐用,具体的话估计是wsdl一多,地址不好规范 ,但测试很方便 随便设地址

ps:主要解决在webservice中,我们想从另外一个项目调用webservice项目的接口,也就是项目调用接口 这里主要用到了xfire wsdl 废话不说了 直接上东西 1. 首先新建一个项目 2. 在src下创建两个文件: a) 第一个是你想要访问的webservice接口,比如我想访问的接口是 ReleaseService 那就在当前项目创建一个ReleaseService接口(接口中的方法必须和你想要访问的webservice接口中的方法相同) b) 第二个是你的调用类 3. 导入相应的jar包,这些包不能引用,一定要复制到lib文件夹下面在引用 4. 具体的实现代码 TestWebService方法的代码: package com.isanta.webServiceTest; import java.io.InputStream; import java.net.MalformedURLException; import java.util.Properties; import java.util.Scanner; import org.codehaus.xfire.XFireFactory; import org.codehaus.xfire.client.XFireProxyFactory; import org.codehaus.xfire.service.Service; import org.codehaus.xfire.service.binding.ObjectServiceFactory; public class TestWebService { /** * @param args */ public static void testWebService() throws MalformedURLException, Exception{ // TODO Auto-generated method stub /** *这里是我的参数放在了properties文件中,我在读取里面的参数,这里我们也可以通过方法传参数 *如 : testWebService(String url,String xMlStr)() 那么在调用的时候就可以直接传进来了 *url 是你访问的webservice 的tomcat 的服务器地址 */ Properties pro = new Properties(); InputStream in = null; in = TestWebService.class.getResourceAsStream("/request.properties"); pro.load(in); String url = pro.getProperty("url"); String xMLstr = pro.getProperty("xMLstr"); Service s=new ObjectServiceFactory().create(ReleaseService.class); XFireProxyFactory xf=new XFireProxyFactory(XFireFactory.newInstance().getXFire()); System.out.println("url="+url); try { //这里就是获取webservice接口的实例对象 ReleaseService seleaseService=(ReleaseService) xf.create(s,url); System.out.println("进入接口----------------->请求报文:"+xMLstr); //这里就是调用你需要的接口的方法 String st=seleaseService.queryReceiptDatas(xMLstr); System.out.print(st); } catch(Exception e) { e.printStackTrace(); } } } 5. 将整个项目打包成jar 6. 将打好的jar包引入到你想要调用的项目中,然后就想 正常的代码一样来调用,如: import java.net.MalformedURLException; import com.isanta.webServiceTest.TestWebService; public class Test { public static void main(String[] args) throws MalformedURLException, Exception { TestWebService.testWebService(); } }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四月天03

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值