大家好,又见面了,我是你们的朋友全栈君。
http接口是什么,我一直没找到比较明确的定义(如果有哪位可以提点一下,我将非常感谢),今天就自己来总结一下吧。个人认为,http接口就是一种基于http服务的api,是系统之间交互的一种约定,所谓的web service其实也就是一种http接口,只不过它是比较规范的、通用的。
http接口有什么用,个人体会是,http接口最主要的作用是能够较好地解决不同系统(可能是功能不同、开发语言不同、服务商不同,等等,但都是基于http服务的)之间的交互的需求,比如像微信公众号的各种接口,不管是使用Java开发还是PHP进行开发,不管是A公司在开发还是B公司在开发,也不管是要做商城系统还是做企业宣传网站,都一样可以很好地调用。
接下来就展现一套自己写的简易的http接口,作为自己这段时间学习与实践的一个小总结。这套接口的基本框架,在本人的具体开发实践中是有用到的,目前来看,运行效率和可扩展性还算能满足需要。
下图就是整个框架项目的目录结构
整个接口服务端的处理流程如下:
1、接收并解析请求;
包括检查数据格式、验证签名等。
2、根据请求实例化对应的处理器;
简单工厂模式,映射规则为:接口名称为test,则实例化apis\TestApi类。
3、处理器具体处理请求;
调用处理器的handle()方法,比如userinfo接口,handle()可能就是去数据库中查找响应的user信息。
4、处理器输出响应
调用response()方法。
前面也说了,接口是一种约定,因此发送数据和输出响应都是要遵循这个约定的,一般情况下,约定分为总体约定和具体接口约定两个部分,总体约定如下:
1、以http的post方式提交数据,数据在$_POST中的键名为data;
2、数据提交时需要先后经过json和base64编码,中文需保持原样,输出的响应同样如此;
3、提交数据的格式:
$data = [
‘api’ => ‘userinfo’, // 具体接口名称,必须
‘noncestr’ => ‘123’,// 随机字符串,必须
‘serial’ => ‘123’, // 调用流水号,必须
‘signature’ => ‘xxx’, // 签名,必须
‘body’ => [
… // 请求详细数据,由具体接口约定,可选
]
];
4、响应数据的格式:
$data = [
‘code’ => 0, // 状态码,0为调用成功,非0为失败,必须
‘serial’ => ‘123’, // 调用流水号,必须
‘signature’ => ‘xxx’, // 签名,非必须
‘body’ => [
… // 响应详细数据,由具体接口约定,可选
]
];
以下是各文件的代码:
aHttpApiHandler.php
<?php
namespace apis;
use libraries\HttpApiUtil;
/**
* api处理器抽象类
*/
abstract class aHttpApiHandler {
/**
* 请求数据
* @var array
*/
protected $data = [];
/**
* 处理结果
* @var array
*/
protected $result = [];
/**
* 处理请求
*/
abstract function handle();
/**
* 构造方法
* @access public
* @param array $data
* @return void
*/
public function __construct($data) {
$this->data = $data;
}
/**
* 输出响应
* @access public
* @return mixed
*/
public function response() {
$result = HttpApiUtil::makeReturn(0, '', $this->data['serial'], $this->result);
echo base64_encode(json_encode($result, JSON_UNESCAPED_UNICODE));
}
}
TestApi.php
<?php
namespace apis;
/**
* test接口
*/
class TestApi extends aHttpApiHandler {
/**
* 处理请求
* @access public
* @return mixed
*/
public function handle() {
echo '调用' . __CLASS__ . '处理请求', PHP_EOL;
}
/**
* 输出响应
* @access public
* @return mixed
*/
public function response() {
echo '调用' . __CLASS__ . '处理请求完毕,输出响应', PHP_EOL;
}
}
UserinfoApi.php
<?php
namespace apis;
/**
* userinfo接口
*/
class UserinfoApi extends aHttpApiHandler {
/**
* 处理请求
* @access public
* @return mixed
*/
public function handle() {
// 模拟从数据库取得用户信息
$id = $this->data['body']['id'];
$this->result = [
'id' => $id,
'name' => 'webmaster',
'nickname' => 'web管理员'
];
}
}
common.php
<?php
/**
* 类自动加载函数
*/
function api_autoload($class) {
@include $class . '.php';
}
// 设置自动加载路径
$includePath = ['apis', 'libraries'];
$includePath = implode(';', array_map(function($v){
return ROOT_PATH . '/' . $v;
}, $includePath));
set_include_path($includePath);
// 注册自动加载函数
spl_autoload_register('api_autoload');
CurlUtil.php
<?php
namespace libraries;
/**
* curl工具类
*/
class CurlUtil {
/**
* 以post方式获取结果
* @access public
* @param string $url url地址
* @param string $data 数据
* @throws \Exception
* @return string
*/
public static function doPost($url, $data = null) {
// 初始化
if (!$ch = curl_init()) throw new \Exception('curl初始化失败');
// 设置选项
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if ($data) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$result = curl_exec($ch);
if (curl_errno($ch)) throw new \Exception(curl_error($ch));
curl_close($ch);
return $result;
}
}
HttpApiConfig.php
<?php
namespace libraries;
/**
* api配置类
*/
class HttpAPiConfig {
/**
* 签名key
* @var string
*/
const KEY = 'key for signature';
}
HttpApiError.php
<?php
namespace libraries;
/**
* api错误定义
*/
class HttpApiError {
/**
* 数据格式错误
* @var integer
*/
const INVALID_DATA = 10001;
/**
* 数据解析错误
* @var integer
*/
const DATA_PARSE_ERROR = 10002;
/**
* 签名错误
* @var integer
*/
const INVALID_SIGNATURE = 10003;
/**
* 接口不存在
* @var integer
*/
const INVALID_API = 10004;
/**
* 无法创建处理器
* @var integer
*/
const CANT_CREATE_HANDLER = 10005;
/**
* 未知错误
* @var integer
*/
const UNKNOWN_ERROR = 90001;
/**
* 错误码与错误信息映射
* @var array
*/
private static $errors = [
10001 => '数据格式错误',
10002 => '数据解析错误',
10003 => '签名错误',
10004 => '接口不存在',
10005 => '无法创建处理器',
90001 => '未知错误',
];
/**
* 获取错误信息
* @access public
* @param integer $code 错误码
* @return mixed
*/
public static function getError($code) {
return isset(self::$errors[$code]) ? self::$errors[$code] : false;
}
}
HttpApiHandlerFactory.php
<?phpnamespace libraries;/** * api处理器工厂 */class HttpApiHandlerFactory { /** * 生成api处理器实例 * @access public * @param string $data * @throws \Exception * @return \libraries\aHttpApiHandler */ public static function create($data) { $info = HttpApiParser::parse($data); if ($info['code']) { throw new \Exception($info['msg'], $info['code']); } $request = $info['body']; $class = '\\apis\\' . ucfirst(strtolower($request['api'])) . 'Api'; try { $rfc = new \ReflectionClass($class); return $rfc->newInstance($request); } catch (\Exception $e) { throw new \Exception(HttpApiError::getError(HttpApiError::CANT_CREATE_HANDLER), HttpApiError::CANT_CREATE_HANDLER); } }}
HttpApiParser.php
<?phpnamespace libraries;/** * api请求解析器 */class HttpApiParser { /** * 解析请求 * @access public * @param string $data * @return array */ public static function parse($data) { if (!is_array($data) || !array_key_exists('data', $data)) { return HttpApiUtil::makeReturn(HttpApiError::INVALID_DATA, HttpApiError::getError(HttpApiError::INVALID_DATA)); } $request = json_decode(base64_decode($data['data']), true); if (json_last_error()) { return HttpApiUtil::makeReturn(HttpApiError::UNKNOWN_ERROR, HttpApiError::getError(HttpApiError::UNKNOWN_ERROR)); } // 检查数据格式 if (empty($request['api']) || empty($request['noncestr']) || empty($request['serial']) || empty($request['signature'])) { return HttpApiUtil::makeReturn(HttpApiError::INVALID_DATA, HttpApiError::getError(HttpApiError::INVALID_DATA)); } // 检查签名 if ($request['signature'] != HttpApiUtil::makeSign($request)) { return HttpApiUtil::makeReturn(HttpApiError::INVALID_SIGNATURE, HttpApiError::getError(HttpApiError::INVALID_SIGNATURE), $request['serial']); } return HttpApiUtil::makeReturn(0, '', $request['serial'], $request); }}
index.php
<?php// 接收请求use libraries\HttpApiHandlerFactory;use libraries\HttpApiUtil;define('ROOT_PATH', __DIR__);include ROOT_PATH . '/common/common.php';// **************************************// 创建处理器try { $api = HttpApiHandlerFactory::create($_POST);} catch (\Exception $e) { print_r(HttpApiUtil::makeReturn($e->getCode(), $e->getMessage())); exit();}// 执行操作$api->handle();$api->response();
test.php
<?php
// 发起调用
use libraries\HttpApiUtil;
use libraries\CurlUtil;
define('ROOT_PATH', __DIR__);
include ROOT_PATH . '/common/common.php';
// **************************************
$url = 'http://api.local.com/index.php';
$data = [
'api' => 'test',
'noncestr' => HttpApiUtil::makeNoncestr(),
'serial' => HttpApiUtil::makeSerial(),
'body' => [
]
];
$data['signature'] = HttpApiUtil::makeSign($data);
$json = 'data=' . base64_encode(json_encode($data));
try {
$response = CurlUtil::doPost($url, $json);
echo $response;// 原始输出
print_r(json_decode(base64_decode($response), true));
} catch (Exception $e) {
echo $e->getMessage();
}
OK,简易的http接口就是这样了,如果要新增一个具体接口,比如查看用户列表,可以考虑新增一个apis\UserlistApi类,继承aHttpApiHandler类并实现相应的方法即可了。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/142475.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...