Loopback4 REST Service: Integrate with a geo-coding service

1. 痛点

由于Loopback4的 geo-coding service学习样例使用的是美国政府提供的Web API 地图服务,由于伟大的墙,多次测试失败,故决定使用百度地图提供的API进行测试

2. 百度地图API使用须知

使用百度地图的Web API服务,需要带 ak 参数,这个需要注册成为百度开发者,并创建应用,下面是相关的链接与请求样例

ak申请流程
百度开发者控制平台
百度地图API使用说明

所用到的API的使用样例:

https://api.map.baidu.com/geocoding/v3/?address=北京市海淀区上地十街10号&output=json&ak=您的ak&callback=showLocation //GET请求

3. 生成datasource

命令行输入:

$ lb4 datasource
? Datasource name: geocoder
? Select the connector for geocoder: REST services (supported by StrongLoop)
? Base URL for the REST service:
? Default options for the request:
? An array of operation templates:
? Use default CRUD mapping: No
   create src/datasources/geocoder.datasource.ts
 # npm will install dependencies now
    update src/datasources/index.ts

Datasource Geocoder was created in src/datasources/

/src/datasources/geocoder.datasource.ts

// 修改config为如下所示
const config = {
  name: 'geocoder',
  connector: 'rest',
  options: {
    headers: {
      accept: 'application/json',
      'content-type': 'application/json'
    }
  },
  // 百度地图
  operations: [
    {
      template: {
        method: 'GET',
        url: 'https://api.map.baidu.com/geocoding/v3',
        query: {
          output: 'json', // 默认为xml格式,此处修改输出为json格式
          address: '{address}',
          ak: "你的ak"
        },
        // responsePath: '$.result.addressMatches[*].coordinates',
      },
      functions: {
        geocode: ['address'],
      }
    }
  ],
};

4. Implement a service provider

命令行输入:

lb4 service
? Service type: Remote service proxy backed by a data source
? Please select the datasource GeocoderDatasource
? Service name: geocoder
   create src/services/geocoder.service.ts
   update src/services/index.ts

Service Geocoder was created in src/services/

/src/datasources/geocoder.datasource.ts

import {inject, Provider} from '@loopback/core';
import {getService} from '@loopback/service-proxy';
import {GeocoderDataSource} from '../datasources';

interface GeoResult {
  comprehension: number,
  confidence: number,
  level: string,
  location: {
    lng: number, // 经度
    lat: number //  维度
  },
  precise: number
}

export interface GeoPoint {
  /**
   * latitude
   */
  status: number;

  /**
   * longitude
   */
  result: GeoResult;
}

export interface Geocoder {
  // this is where you define the Node.js methods that will be
  // mapped to REST/SOAP/gRPC operations as stated in the datasource
  // json file.
  geocode(address: string): Promise<GeoPoint>
}

export class GeocoderProvider implements Provider<Geocoder> {
  constructor(
    // geocoder must match the name property in the datasource json file
    @inject('datasources.geocoder')
    protected dataSource: GeocoderDataSource = new GeocoderDataSource(),
  ) { }

  value(): Promise<Geocoder> {
    return getService(this.dataSource);
  }
}

5. Add two new properties to our Todo model: remindAtAddress and remindAtGeo.

src/models/todo.model.ts

 @property({
    type: 'string',
  })
  remindAtAddress?: string; // e.g. 北京市海淀区中关村南大街27号

  @property({
    type: 'string'
  })
  remindAtGeo?: string; // latitude(纬度), longitude(经度)  e.g."39.95531276573692, 116.33060053251218"

6. 将GeoCoder服务注入到TodoController的构造函数中,并修改create()方法

import {inject} from '@loopback/core';
import {TodoRepository} from '../repositories';

export class TodoController {
  constructor(
    @repository(TodoRepository)
    public todoRepository: TodoRepository,
    @inject('services.Geocoder') protected geoService: Geocoder,
  ) { }

 @post('/todos')
  @response(200, {
    description: 'Todo model instance',
    content: {'application/json': {schema: getModelSchemaRef(Todo)}},
  })
  async create(
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(Todo, {
            title: 'NewTodo',
            exclude: ['id'],
          }),
        },
      },
    })
    todo: Omit<Todo, 'id'>,
  ): Promise<Todo> {
    if (todo.remindAtAddress) {
      const geo = await this.geoService.geocode(todo.remindAtAddress);

      if (!geo) {
        // address not found
        throw new HttpErrors.BadRequest(
          `Address not found: ${todo.remindAtAddress}`
        );
      }

      todo.remindAtGeo = `${geo.result.location.lat}, ${geo.result.location.lng}`;

    }
    return this.todoRepository.create(todo);
  }
}

7. API测试

  1. 命令行输入npm start 启动server
  2. 打开 http://[::1]:3000/explorer/
  3. 测试POST /todos方法
    点击Try it out
    Request body 输入:
{
  "title": "GET MORE MILE",
  "desc": "SQUEEZE MORE MILK",
  "remindAtAddress": "北京市海淀区中关村南大街27号"
}

点击Execute, 返回结果如下:
测试结果图

github代码地址:https://github.com/RokeyJoe/Loopback4-todo-list
注意: geocoder.datasource.ts 配置中的 ak 参数需要自行申请填入,否则测试会失败(见 3. 生成datasource)

本文参考链接: https://loopback.io/doc/en/lb4/todo-tutorial-geocoding-service.html

百度地图ak申请参考链接: https://blog.csdn.net/c1052981766/article/details/113340317

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值