请求:
GET /api/geocoding/reverse?lat={latitude}&lng={longitude}
参数:
lat (必填): 纬度,如 35.6762lng (必填): 经度,如 139.6503响应 (成功):
{
"success": true,
"data": {
"address": "渋谷区",
"city": "東京都",
"district": "渋谷区",
"country": "日本",
"latitude": 35.6762,
"longitude": 139.6503
}
}
响应 (失败):
{
"success": false,
"message": "Geocoding failed"
}
@RestController
@RequestMapping("/api/geocoding")
public class GeocodingController {
@Autowired
private GeocodingService geocodingService;
@GetMapping("/reverse")
public ResponseEntity<ApiResponse<GeocodingResult>> reverseGeocode(
@RequestParam Double lat,
@RequestParam Double lng
) {
try {
GeocodingResult result = geocodingService.reverseGeocode(lat, lng);
return ResponseEntity.ok(ApiResponse.success(result));
} catch (Exception e) {
return ResponseEntity.ok(ApiResponse.error("Geocoding failed"));
}
}
}
@Service
public class GeocodingService {
@Autowired
private RestTemplate restTemplate;
@Value("${google.maps.api.key}")
private String googleApiKey;
@Cacheable(value = "geocoding", key = "#lat + '_' + #lng")
public GeocodingResult reverseGeocode(Double lat, Double lng) {
String url = String.format(
"https://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&key=%s&language=ja",
lat, lng, googleApiKey
);
GoogleGeocodingResponse response = restTemplate.getForObject(
url,
GoogleGeocodingResponse.class
);
if (response != null && "OK".equals(response.getStatus())) {
return parseGoogleResponse(response);
}
throw new RuntimeException("Geocoding failed");
}
private GeocodingResult parseGoogleResponse(GoogleGeocodingResponse response) {
// 解析 Google Maps API 响应
// ...
return result;
}
}
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(30)); // 缓存30天
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
}
google:
maps:
api:
key: ${GOOGLE_MAPS_API_KEY}
spring:
redis:
host: localhost
port: 6379
前端只需发送坐标到后端:
const result = await reverseGeocode(35.6762, 139.6503);
// 后端会返回: "渋谷区"
如果后端接口不可用,会自动降级到 Nominatim(免费服务)。