第一部分: 概述
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个层次:
- Http传输信道
- XML的数据格式
- SOAP封装格式(传递信息的格式)
- WSDL的描述方式(如何访问具体的接口)
- 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一多,地址不好规范 ,但测试很方便 随便设地址