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. Java 线程池(ThreadPoolExecutor)原理分析与使用

    在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...

  2. 【最小生成树】UVA1494Qin Shi Huang's National Road System秦始皇修路

    Description During the Warring States Period of ancient China(476 BC to 221 BC), there were seven ki ...

  3. BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP

    BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀 ...

  4. java  JDK配置环境变量

    1)将下载的jdk放置到一定文件夹中,注意文件夹名不能有中文! 2)设置环境变量 a.可以在系统变量中找到path这个变量,然后将jdk下的bin的根目录添加进去 注意:一定要放在path变量值的最前 ...

  5. Jenkins使用教程

    1 软件安装  1.1 运行环境   1.1.1 Maven的安装   1.1.2 Git的安装   1.1.3 Tomcat的安装  1.2 安装Jenkins  1.2.1 msi和war包安装2 ...

  6. 阿里云Centos7.x MySql安装教程示例

    创建用户 useradd mysql; passwd mysql; 下载(比如:5.5.61) 地址 https://dev.mysql.com/downloads/mysql/5.6.html#do ...

  7. Qt之表格控件蚂蚁线

    一.蚂蚁线 摘自互动百科:在图像影像软件中表示选区的动态虚线,因为虚线闪烁的样子像是一群蚂蚁在跑,所以俗称蚂蚁线.在Poshop,After Effect等软件中比较常见. 背景:用过excel的同学 ...

  8. Python调用ansible API系列(五)综合使用

    如何把动态生成资产信息.执行playbook以及自定义结果结合起来用呢? #!/usr/bin/env python # -*- coding: utf-8 -*- """ ...

  9. 目标检测 anchor 理解笔记

    anchor在计算机视觉中有锚点或锚框,目标检测中常出现的anchor box是锚框,表示固定的参考框. 目标检测的任务: 在哪里有东西 难点: 目标的类别不确定.数量不确定.位置不确定.尺度不确定 ...

  10. MySQL · 引擎特性 · InnoDB崩溃恢复

    前言 数据库系统与文件系统最大的区别在于数据库能保证操作的原子性,一个操作要么不做要么都做,即使在数据库宕机的情况下,也不会出现操作一半的情况,这个就需要数据库的日志和一套完善的崩溃恢复机制来保证.本 ...