1. 文章目的

随着WebApiClient的不断完善,越来越多开发者选择WebApiClient替换原生的HttpClient,然而在应用到实际项目中多多少少会遇到一些项目结合上的疑问和困难,本文将以WebApiClient使用者的身份,在Asp.net core mvc项目中使用WebApiClient来请求百度地图服务接口,以展示WebApiClient的使用技巧。

2. 百度地图服务接口

  1. 静态图接口

    http://api.map.baidu.com/staticimage/v2?ak=你的密钥&mcode=666666&center=116.403874,39.914888&width=300&height=200&zoom=11

  2. 坐标转换接口

    http://api.map.baidu.com/geoconv/v1/?coords=114.21892734521,29.575429778924&from=1&to=5&ak=你的密钥

3. 接口分析

通过分析百度地图的接口,我们发现:

  • 所有接口都在api.map.baidu.com这个域名上;
  • ak参数是一个客户端身份标识的参数,所有请求接口都需要附加这个ak值;
  • 接口中需要的116.403874,39.914888这种参数值,实际是(经度,纬度),为两个值组成;
  • from和to是枚举数值类型;

在我们进行Coding的时候,应该重点考虑这些共性,以减少重复的工作内容。

4. 接口声明

4.1 公共域名

[HttpHost("http://api.map.baidu.com/")]
public interface IBdMapApi : IHttpApi
{
}

4.2 公共的AK参数

我们要实现一个接口级或方法级的ApiAction特性,用于给请求路径增加公共的ak参数:

/// <summary>
/// 表示百度AK信息
/// </summary>
public class AkAttribute : ApiActionAttribute
{
private readonly string ak; /// <summary>
/// 百度AK信息
/// 执行时追加到请求query
/// </summary>
/// <param name="ak"></param>
public AkAttribute(string ak)
{
this.ak = ak;
} /// <summary>
/// 请求前
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override async Task BeforeRequestAsync(ApiActionContext context)
{
context.RequestMessage.AddUrlQuery("ak", this.ak);
await Task.CompletedTask;
}

然后把Ak特性追加到接口上:

[HttpHost("http://api.map.baidu.com/")]
[Ak("qde9uxuEhwMlngvTbWGo3BIQOKfqvjdc")]
public interface IBdMapApi : IHttpApi
{
}

4.3 静态图staticimage接口

参照接口文档,声明最初的StaticImage接口:

[HttpGet("staticimage/v2")]
ITask<Stream> StaticImageAsync(
string center,
int width = 300,
int height = 200,
int zoom = 11,
int mcode = 666666);

目前center参数是string类型,约束性非常弱,与接口要求的(经度,纬度)这种格式数据差异比较大。所以我们应该定一个继承自IApiParameterable的BdLocation类型,将传入的经度和纬度转换为这种文本格式:

/// <summary>
/// 表示位置信息
/// </summary>
public class BdLocation : IApiParameterable
{
/// <summary>
/// 获取位置值
/// </summary>
public string Value { get; private set; } /// <summary>
/// 位置信息
/// 执行时追加到请求query
/// </summary>
/// <param name="lng">经</param>
/// <param name="lat">纬</param>
public BdLocation(decimal lng, decimal lat)
{
this.Value = $"{lng},{lat}";
} public override string ToString()
{
return this.Value;
} /// <summary>
/// 自解释模式
/// </summary>
/// <param name="context"></param>
/// <param name="parameter"></param>
/// <returns></returns>
Task IApiParameterable.BeforeRequestAsync(ApiActionContext context, ApiParameterDescriptor parameter)
{
context.RequestMessage.AddUrlQuery(parameter.Name, this.Value);
return Task.CompletedTask;
}
}

修改后StaticImage接口修改为:

[HttpGet("staticimage/v2")]
ITask<Stream> StaticImageAsync(
BdLocation center,
int width = 300,
int height = 200,
int zoom = 11,
int mcode = 666666);

4.4 坐标转换Geoconv接口

依照文档,编写出最初的接口

[HttpGet("geoconv/v1/")]
ITask<string> GeoconvAsync(
string coords,
int from = 1,
int to = 5);

和StaticImage接口一样,我们还需要合理修改这个接口的参数约束,coords实际为BdLocation类型, from和to可以修改为枚举类型,返回值string修改为强类型的模型,修改后的接口为:

[HttpGet("geoconv/v1/")]
ITask<BdResult<BdPoint[]>> GeoconvAsync(
BdLocation coords,
BdFrom from = BdFrom.wgs84,
BdTo to = BdTo.bd09ll);

4.5 完整的接口声明

/// <summary>
/// 定义百度地图接口
/// </summary>
[Ak("qde9uxuEhwMlngvTbWGo3BIQOKfqvjdc")]
[HttpHost("http://api.map.baidu.com/")]
public interface IBdMapApi : IHttpApi
{
/// <summary>
/// 静态图
/// </summary>
/// <param name="center"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="zoom"></param>
/// <param name="mcode"></param>
/// <returns></returns>
// http://api.map.baidu.com/staticimage/v2?ak=你的密钥&mcode=666666&center=116.403874,39.914888&width=300&height=200&zoom=11
[HttpGet("staticimage/v2")]
ITask<Stream> StaticImageAsync(
BdLocation center,
int width = 300,
int height = 200,
int zoom = 11,
int mcode = 666666); /// <summary>
/// 坐标转换
/// </summary>
/// <param name="coords"></param>
/// <param name="from"></param>
/// <param name="to"></param>
/// <returns></returns>
// http://api.map.baidu.com/geoconv/v1/?coords=114.21892734521,29.575429778924&from=1&to=5&ak=你的密钥 //GET请求
[HttpGet("geoconv/v1/")]
ITask<BdResult<BdPoint[]>> GeoconvAsync(
BdLocation coords,
BdFrom from = BdFrom.wgs84,
BdTo to = BdTo.bd09ll);
}

5. 接口的依赖注入

WebApiClient的HttpApiClient创建的代理实例,适合使用单例模式,在支持依赖注入的项目开发中,应尽量使用依赖注入来完成HttpApiClient的创建和生命周期管理。

5.1 Asp.net core的依赖注入

在ConfigureServices方法里添加IBdMapApi的注入配置

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(HttpApiClient.Create<IBdMapApi>());
......
}

如果项目里声明了很多接口,比如IBaiduApi、ITengxunApi等等,可以循环批量注入:

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
var apis = this.GetType().Assembly.GetTypes().Where(item => typeof(IHttpApi).IsAssignableFrom(item));
foreach (var api in apis)
{
services.AddSingleton(api, HttpApiClient.Create(api, new HttpApiConfig()));
}
}

5.2 接收和使用IBdMapApi代理实例

public class HomeController : Controller
{
private readonly IBdMapApi bdMapApi; public HomeController(IBdMapApi bdMapApi)
{
this.bdMapApi = bdMapApi;
} public async Task<IActionResult> Index()
{
var image = await this.bdMapApi.StaticImageAsync(new BdLocation(116.403874m, 39.914888m));
var geoResult = await this.bdMapApi.GeoconvAsync(new BdLocation(116.403874m, 39.914888m)); return View();
}
}

6. 监视请求提交的内容

WebApiClient对Http请求进行的高度抽象,只有声明,没有实现,在没有熟悉WebApiClient的情况下,我们开发中可能需要在请求发送的内容进行监视,从而知道是否符合服务器的接口数据要求。在不使用第三方工具比如Fiddler等的情况下,我们可以为接口修饰一个自定义过滤器,在过滤器里实现访打印求消息内容的能力。

6.1 定义TraceFilter过滤器

/// <summary>
/// 请求内容追踪过滤器
/// </summary>
public class TraceFilter : ApiActionFilterAttribute
{
/// <summary>
/// 打印请求内容
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override async Task OnBeginRequestAsync(ApiActionContext context)
{
var request = await context.RequestMessage.ToStringAsync();
System.Diagnostics.Debug.Print(request);
}
}

6.2 接口关联TraceFilter

/// <summary>
/// 定义百度地图接口
/// </summary>
[TraceFilter]
[Ak("qde9uxuEhwMlngvTbWGo3BIQOKfqvjdc")]
[HttpHost("http://api.map.baidu.com/")]
public interface IBdMapApi : IHttpApi
{
}

6.3 查看请求内容

开启程序调试,输出窗口里打印

GET /staticimage/v2?ak=qde9uxuEhwMlngvTbWGo3BIQOKfqvjdc&center=116.403874%2c39.914888&width=300&height=200&zoom=11&mcode=666666 HTTP/2.0
Host: api.map.baidu.com GET /geoconv/v1/?ak=qde9uxuEhwMlngvTbWGo3BIQOKfqvjdc&coords=116.403874%2c39.914888&from=1&to=5 HTTP/2.0
Host: api.map.baidu.com

7. 结束语

博主为WebApiClient库的作者,致力于站在使用者的角度去设计WebApiClient,欢迎大家给WebApiClient提建议。

WebApiClient百度地图服务接口实践的更多相关文章

  1. httpclient案例二(调用百度地图的接口)

    一,class T package com.http.test; import org.junit.Test; import com.http.BaiduMapProxyService; import ...

  2. 简单几行代码使用百度地图API接口分页获取信息

    首发于: 万能助手扩展开发:使用百度地图API接口分页获取信息_电脑计算机编程入门教程自学 http://jianma123.com/viewthread.aardio?threadid=426 使用 ...

  3. Angular 调用百度地图API接口

    Angular 调用百度地图API接口 参考原文:https://blog.csdn.net/yuyinghua0302/article/details/80624274 下面简单介绍一下如何在Ang ...

  4. tp5 封装百度地图api接口

    //服务器端api extend\Map <?php /** * 百度地图业务封装 */ class Map{ /** * 根据地址来获取经纬度 * @param $address */ pub ...

  5. 百度云服务接口错误:Parameter invalid, the key input with filter parameter is not searchfilter column key

    百度LBS云服务接口: 地址:http://lbsyun.baidu.com/index.php?title=lbscloud/api/geosearch 访问接口:http://api.map.ba ...

  6. 百度地图API应用实践(一) —— 栅格图(草稿)

    概述 运用百度地图JS API,实现了在百度地图上绘制栅格并按统计值渲染栅格颜色.实现的过程是不断补习的过程,其中用到一些技术,是个人首次尝试.包括:(1)简单的jQuery语法,并实现Ajax:(2 ...

  7. 百度地图HTML接口

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  8. 百度地图LV1.5实践项目开发工具类bmap.util.jsV1.3

    /** * 百度地图使用工具类-v1.5 * * @author boonya * @date 2013-7-7 * @address Chengdu,Sichuan,China * @email b ...

  9. 百度地图LV1.5实践项目开发工具类bmap.util.jsV1.2

    /** * 百度地图使用工具类-v1.5 * * @author boonya * @date 2013-7-7 * @address Chengdu,Sichuan,China * @email b ...

随机推荐

  1. Clean http handlers in Go

    Introduction For this blog post we are going to take a look at the http.HandlerFunc type and how we ...

  2. BZOJ_1179_[Apio2009]Atm_tarjan+spfa

    BZOJ_1179_[Apio2009]Atm_tarjan+spfa 题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1179 分析: 显然有环 ...

  3. BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树

    BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...

  4. ArcGIS API for JavaScript 入门教程[3] 你看得到:数据与视图分离

    这篇开始正式讲API. 数据和视图分离不是什么奇怪的事情了,这是一个著名的设计--数据与视图分开. 转载注明出处,博客园/CSDN/B站:秋意正寒. 目录:https://www.cnblogs.co ...

  5. 【爆料】-《澳大利亚联邦大学毕业证书》FedUni一模一样原件

    ☞澳大利亚联邦大学毕业证书[微/Q:2544033233◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士& ...

  6. Python-常用 Linux 命令的基本使用

    常用 Linux 命令的基本使用 操作系统 作用:管理好硬件设备,让软件可以和硬件发生交互类型 桌面操作系统 Windows macos linux 服务器操作系统 linux Windows ser ...

  7. 基于 HTML5 的 WebGL 3D 版俄罗斯方块

    前言 摘要:2D 的俄罗斯方块已经被人玩烂了,突发奇想就做了个 3D 的游戏机,用来玩俄罗斯方块...实现的基本想法是先在 2D 上实现俄罗斯方块小游戏,然后使用 3D 建模功能创建一个 3D 街机模 ...

  8. HTTP 视频怎么在 MIP 页面中使用?

    在 MIP 中,一些资源的使用需要支持 HTTPS,视频就是其中一种.但目前大部分站点的视频资源都还是 HTTP 的资源,无法在百度 MIP 搜索结果中直接使用, mip-video 视频组件针对 H ...

  9. 使用MediatR重构单体应用中的事件发布/订阅

    标题:使用MediatR重构单体应用中的事件发布/订阅 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/10640280.html 源代码:https ...

  10. Java日志正确使用姿势

    前言 关于日志,在大家的印象中都是比较简单的,只须引入了相关依赖包,剩下的事情就是在项目中“尽情”的打印我们需要的信息了.但是往往越简单的东西越容易让我们忽视,从而导致一些不该有的bug发生,作为一名 ...