一次清楚SOAP
目录
安装soap扩展
## 下载
wget -O php7.1.26.tar.gz http://cn2.php.net/get/php-7.1.26.tar.gz/from/this/mirror
## 解压
tar xvf php7.1.26.tar.gz
## 进入扩展目录
cd php-7.1.26/
## 配置
./configure --enable-soap=shared
## 编译so文件
make
## 复制so文件到PHP扩展目录中
sudo cp modules/soap.so /usr/lib/php/20160303/
如果configure过程中提示报错:
error: xml2-config not found. Please check your libxml2 installation
sudo apt-get install libxml2-dev
什么是SOAP
SOAP 是简单对象访问协议的首字母缩写。它是一种基于 XML 的消息传递协议,用于在计算机之间交换信息。SOAP 是 XML 规范的一个应用程序。SOAP 是一种旨在通过 Internet 进行通信的通信协议。
SOAP 可以扩展 HTTP 以进行 XML 消息传递。
SOAP 为 Web 服务提供数据传输。
SOAP 可以交换完整的文档或调用远程过程。
SOAP 可用于广播消息。
SOAP 与平台和语言无关。
SOAP 是定义发送信息的方式为 XML 方式。
SOAP 使客户端应用程序能够轻松连接到远程服务并调用远程方法。
SOAP 扩展主要用来处理 RPC 形式的 Web Services。不过,你也可以使用文本形式的 WSDL 文件配合 WSDL 模式的服务端和客户端。
关于更多介绍:SOAP Web 服务介绍 - SegmentFault 思否
php的SOAP扩展
SoapClient 类
这个类用来使用 Web Services。SoapClient 类可以作为给定 Web Services 的客户端。 它有两种操作形式:
- WSDL 模式
- Non-WSDL 模式
在 WSDL 模式中,构造器可以使用 WSDL 文件名作为参数,并自动从 WSDL 中提取使用服务时所需要的信息。
Non-WSDL 模式中使用参数来设置使用服务时所需要的信息。这个类有许多可以用来使用服务的有用的方法。其中 SoapClient::__soapCall() 是最重要的。这个方法可以用来调用服务中的某个操作。
SoapServer 类
这个类可以用来提供 Web Services。与 SoapClient 类似,SoapServer 也有两种操作模式:WSDL 模式和 non-WSDL模式。这两种模式的意义跟 SoapClient 的两种模式一样。在 WSDL 模式中,服务实现了 WSDL 提供的接口;在 non-WSDL 模式中,参数被用来管理服务的行为。
在 SoapServer 类的众多方法中,有三个方法比较重要。它们是 SoapServer::setClass()、SoapServer::addFunction() 和 SoapServer::handle()。
SoapServer::setClass()方法设定用来实现 Web Services 的类。SoapServer::setClass 所设定的类中的所有公共方法将成为 Web Services 的操作(operation)。
SoapServer::addFunction() 方法用来添加一个或多个作为 Web Services 操作(operation)的函数。
SoapServer:: handle() 方法指示 Web Services 脚本开始处理进入的请求。Web Services 脚本是用 PHP 脚本写的一个或多个 SoapServer 对象的实例。尽管你可以有不止一个的 SoapServer 对象,但通常的习惯是一个脚本只拥有一个 SoapServer 实例。在调用 SoapServer::handle() 方法之前,Web Services 脚本会使用设置在 SoapServer 对象实例上的任何信息来处理进入的请求和输出相应的内容。
SoapFault 类
这个类从 Exception 类继承而来,可以用来处理错误。SoapFault 实例可以抛出或获取 Soap 错误的相关信息并按程序员的要求处理。
SoapHeader 类
这个类可以用来描述 SOAP headers。它只是一个只包含构造器方法的数据容器。
SoapParam 类
SoapParam 也是一个只包含构造器方法的数据容器。这个方法可以用来描述传递给 Web Services 操作的参数。在 non-WSDL 模式中这是一个很有用的类,可以用来传递所期望格式的参数信息。
SoapVar 类
SoapVar 也是一个只包含构造器的低级类,与 SoapHeader 和 SoapParam 类相似。这个类可以用来给一个Web Services 操作传递编码参数。这个类对 non-WSDL 中传递类型信息是非常有用的。
注:SoapParam 和 SoapVar 主要用来封装用于放入 SOAP 请求中的数据,他们主要在 non-WSDL 模式下使用。事实上,在 WSDL 模式下,SOAP 请求的参数可以通过数组方式包装,SOAP 扩展会根据 WSDL 文件将这个数组转化成为 SOAP 请求中的数据部分,所以并不需要这两个类。而在 non-WSDL 模式下,由于没有提供 WSDL 文件,所以必须通过这两个类进行包装。
SoapHeader 类用来构造 SOAP 头,SOAP 头可以对 SOAP 的能力进行必要的扩展。SOAP 头的一个主要作用就是用于简单的身份认证。
WSDL VS. non-WSDL 模式
Web Services 有两种实现模式:契约先行(Contract first)模式和代码先行(Code first)模式。
契约先行模式使用了一个用 XML 定义的服务接口的WSDL文件。WSDL 文件定义了服务必须实现或客户端可以使用的接口。SoapServer 和 SoapClient 的 WSDL 模式就基于这个概念。
在代码先行模式中,首先要先写出实现服务的代码。然后在大多数情况下,代码会产生一个契约(可以借助一些工具生成),换种说法,一个 WSDL 文件。接着客户端在使用服务的时候就可以使用那个 WSDL 来获得服务的接口及其他信息。尽管如此,PHP5 的扩展并没有从代码输出一个 WSDL 的实现,考虑到这种情况,可以在 non-WSDL 模式下使用 SoapServer 和 SoapClient。
范例
SOAP服务端
SOAPHandler.php
class SOAPHandler
{
/**
* 检查$_SERVER中的PHP_AUTH_USER
*/
public function check(){
if ($_SERVER['PHP_AUTH_USER'] != 'jm' || $_SERVER['PHP_AUTH_PW'] != 'chinese') {
header('WWW-Authenticate: Basic realm="NMG Terry"');
header('HTTP/1.0 401 Unauthorized');
exit();
}
}
/**
* 检查header中的Authorization: Basic am06Y2hpbmVzZQ==
* @param type $auth
* @throws SOAPFault
*/
public function auth($auth)
{
if ($auth->string[0] != 'jm' || $auth->string[1] != 'chinese') {
throw new SOAPFault('Server', 'No Permission From Server');
}
}
// 域名链接字符串
public function domainLink($domain = '',$url="")
{
return "<a href=".$url.">".$domain."</a>";
}
public function getServerInfo(){
return $_SERVER;//array
}
}
soapServer.php
require 'SOAPHandler.php';
$handler = new SOAPHandler();
$handler->check();
// no wsdl mode
try {
$serverUri = "soap/soapServer";
$config = array(
'uri' => $serverUri
);
$server = new SOAPServer(null, $config);
$server->setObject($handler);//设置处理请求的对象,也可以使用setClass设置处理请求的类
$server->handle();//开始处理请求
} catch (SOAPFault $f) {
echo "Error:".$f->getMessage();
}
SOAP客户端
$serverLocation = "http://demo.130.com/FunctionsReference/soap/soapServer.php";
$serverUri = "soap/soapServer";
$config = [
'location' => $serverLocation,
'uri' => $serverUri,
'login' => 'jm',//[PHP_AUTH_USER] => jm | [PHP_AUTH_PW] => chinese | Authorization: Basic am06Y2hpbmVzZQ==
'password' => 'chinese',
'trace' => true
];
try{
$auth = ['jm', 'chinese'];
// no wsdl
$client = new SOAPClient(null, $config);
$header = new SOAPHeader("soap/header", 'auth', $auth, false,SOAP_ACTOR_NEXT);//SOAP_ACTOR_NEXT:soap服务端接收到请求并进入handle处理后,会调用对应的auth方法,并传递$auth参数
$client->__setSoapHeaders([$header]);
$link1 = $client->domainLink("9ong",'www.9ong.com');
$link2 = $client->__soapCall('domainLink', ['9ong', 'www.9ong.com']);
echo $link1.'<br />';
echo $link2.'<br />';
print_r($client->getServerInfo());
print_r($client->__getLastRequestHeaders());
}catch(SOAPFault $e){
echo "ERROR:".$e->getMessage();
}
输出
<a href=www.9ong.com>9ong</a>
<a href=www.9ong.com>9ong</a>
Array
(
[HTTP_AUTHORIZATION] => Basic am06Y2hpbmVzZQ==
[HTTP_CONTENT_LENGTH] => 587
[HTTP_SOAPACTION] => "soap/soapServer#getServerInfo"
[HTTP_CONTENT_TYPE] => text/xml; charset=utf-8
[HTTP_USER_AGENT] => PHP-SOAP/7.1.26
...
[DOCUMENT_ROOT] => /var/www/html/php-shiyanchang
[DOCUMENT_URI] => /FunctionsReference/soap/soapServer.php
[REQUEST_URI] => /FunctionsReference/soap/soapServer.php
[SCRIPT_NAME] => /FunctionsReference/soap/soapServer.php
[CONTENT_LENGTH] => 587
[CONTENT_TYPE] => text/xml; charset=utf-8
[REQUEST_METHOD] => POST
[QUERY_STRING] =>
[SCRIPT_FILENAME] => /var/www/html/php-shiyanchang/FunctionsReference/soap/soapServer.php
[PATH_INFO] =>
[FCGI_ROLE] => RESPONDER
[PHP_SELF] => /FunctionsReference/soap/soapServer.php
[PHP_AUTH_USER] => jm
[PHP_AUTH_PW] => chinese
)
POST /FunctionsReference/soap/soapServer.php HTTP/1.1
Host: demo.130.com
Connection: Keep-Alive
User-Agent: PHP-SOAP/7.1.26
Content-Type: text/xml; charset=utf-8
SOAPAction: "soap/soapServer#getServerInfo"
Content-Length: 587
Authorization: Basic am06Y2hpbmVzZQ==
关于soapHeader的用途
$header = new SOAPHeader("soap/header", 'auth', $auth, false,SOAP_ACTOR_NEXT);//SOAP_ACTOR_NEXT:soap服务端接收到请求并进入handle处理后,会调用对应的auth方法,并传递$auth参数
上面的范例中,我们看到handler中的auth方法在server端接收到请求后就会执行,这个是为什么呢?我们看鸟哥怎么说的:
还有人在用SOAP吗
zhuzhibin 2020-01-10 20:48:58 +08:00
我之前对接过。。自己封装了一层 W ebservice SOAP 来处理请求, 有点不太习惯了,因为都是基于 xml 描述,现在大多数都是 json 了,还是挺难受的
Tn5ohB1Yecdk3qCK 2020-01-10 18:39:39 +08:00
天气,电视节目 等等好像都是用的 webservice
CHENJIAJIE 2020-01-10 18:35:55 +08:00
电视端的节目媒资注入都是用 webservice
murmur 2020-01-10 17:03:18 +08:00
我们的一些老接口还是 webservice,新接口已经让外包商用 json 了
zhuzhibin 2020-01-10 20:48:58 +08:00
我之前对接过。。自己封装了一层 W ebservice SOAP 来处理请求, 有点不太习惯了,因为都是基于 xml 描述,现在大多数都是 json 了,还是挺难受的
Revenant 2020-01-10 23:45:34 +08:00
医保平台接口都还是走 WebService 的形式呢
yangsh 2020-01-10 23:15:44 +08:00
有,我们 现在的产品内部还在广泛的使用 webservice
jiashun 2020-01-11 10:36:27 +08:00
国家电网内的异构系统集成基本上都是走 ESB,各服务厂商提供 WebService 集成接口在 ESB 上进行注册。
至于“WebService 的连接超时,和读取超时问题”,调用 webservice 接口的时候可以使用 soap 工具类,设置连接超时和读取超时参数; webservice 接口调用也可以使用 http 的方式,根据 wsdl 描述来手工拼装 webservice 报文,用 http 工具类进行 http 请求。
cway 2020-01-11 12:43:37 +08:00
很多 SAP ERP 系统都还是用 WebService 呢
国企最多
hantsy 2020-01-11 12:20:25 +08:00 ❤️ 1
@fox0001 1. SOA 是企业开发为目标的产物。2 SOA 很大程度上想解决各应用服务器供应的技术上互操作问题,SUN,IBM,还 MS 都是在 SOAP,SOA 付出很出。结果很多东西还是各自为政(如 MS 有很多扩展没办法在 Java 平台用,SUN 有业务流程上有 JBI,与 BPEL 不兼容,IBM 搞了自己的 SCA ),没有达到预期的效果。
CHYK 2020-01-10 16:10:13 +08:00
有,仅在单位内网的项目上,对外则是微服务了。