1. 痛点
由于Loopback4的 geo-coding service学习样例使用的是美国政府提供的Web API 地图服务,由于伟大的墙,多次测试失败,故决定使用百度地图提供的API进行测试
2. 百度地图API使用须知
使用百度地图的Web API服务,需要带 ak 参数,这个需要注册成为百度开发者,并创建应用,下面是相关的链接与请求样例
所用到的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测试
- 命令行输入
npm start
启动server - 打开 http://[::1]:3000/explorer/
- 测试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