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. 浅谈HTTP协议

    1 HTTP概念 把握三个点: 1 HTTP协议(超文本传输协议) HTTP是一个基于TCP/IP通信协议来传递数据,默认端口80 2 HTTP是无连接(限制每次连接只处理一个请求),无状态的(对于事 ...

  2. go语言调度器源代码情景分析之五:汇编指令

    本文是<go调度器源代码情景分析>系列 第一章 预备知识的第4小节. 汇编语言是每位后端程序员都应该掌握的一门语言,因为学会了汇编语言,不管是对我们调试程序还是研究与理解计算机底层的一些运 ...

  3. java实现开根号算法

    public static void main(String[] args) { long start = System.currentTimeMillis(); double target=9876 ...

  4. Android版数据结构与算法(八):二叉排序树

    本文目录 前两篇文章我们学习了一些树的基本概念以及常用操作,本篇我们了解一下二叉树的一种特殊形式:二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree) ...

  5. Unity的UI究竟为什么可以合批

    1.UI/Default代码研究首先,我想到的是,既然是对图集纹理进行采样,而且又不能统一更改材质的纹理UV值,我们通常写的shader都是直接根据模型UV值对主纹理进行采样,那会不会是shader中 ...

  6. Hibernate学习——持久化类的学习

    A.概念 持久化:将内存中的对象持久化(存储)到数据库的过程.Hibernate就是持久化的框架. 持久化类:一个普通java对象与数据库的表建立了映射关系,那么这个类在Hiberna中被称为持久化类 ...

  7. iftop命令使用范例

    iftop 介绍 iftop是一款实时流量监控工具,监控TCP/IP连接等,缺点就是无报表功能.必须以root身份才能运行. 实例 默认是监控第一块网卡的流量 iftop 监控eth1 iftop - ...

  8. vue实现商品购物车全选与全不选项目实战

    项目需求: 实现一个购物车 全选框实现对商家和商品的全选 商家全选框实现对当前商家所有商品的全选 取消其中一个商品则取消对应商家全选和全选框 选中一个商家下的所有商品则勾选对应商家的全选框,不勾选全选 ...

  9. 使用拷贝的方式(adb push) 绕过Android系统和adb install直接安装APK

    某些情况下定制的Android系统为了限制用户安装应用,例如电视盒子,车载中控等,通过修改代码屏蔽了正常安装应用的方式 本文探讨如何在 adb shell 具有读写data分区目录的权限前提下,通过a ...

  10. PyCharm 如何远程连接服务器编写程序

    写在前面 我之前一直通过mstsc远程服务器桌面修改代码,或者本地修改后上传到远程服务器等,各种不爽,现在改用xshell,但有时候还是感觉不方便.于是乎,自己动手配置PyCharm远程连接服务器,这 ...