如何通过传入点范围JSON筛选返回指定范围内的Location列表
改造Controller接口接收坐标点参数实现范围查询
一、修正目标JSON格式
你给出的目标JSON存在语法错误,正确格式需将p1和p2定义为包含经纬度的数组,示例如下:
{ "p1": [46.6, 15.4], "p2": [48.8, 17.5], "type": "premium", "limit": 3 }
二、方案一:使用POST请求+DTO接收参数(推荐)
这种方式更适配JSON参数传递场景,步骤如下:
1. 定义请求DTO类
创建封装请求参数的DTO,同时加入参数合法性校验:
import jakarta.validation.constraints.Size; import lombok.Data; @Data public class LocationSearchRequest { @Size(min = 2, max = 2, message = "p1需包含纬度和经度两个数值") private Double[] p1; @Size(min = 2, max = 2, message = "p2需包含纬度和经度两个数值") private Double[] p2; private Location.LocationType type; private Integer limit = 10; // 默认分页条数 }
注:未使用Lombok时,需手动编写getter、setter方法。
2. 修改Controller方法
将原GET接口改为POST,通过@RequestBody接收DTO并处理查询逻辑:
import jakarta.validation.Valid; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class LocationController { private final LocationRepository locationRepository; // 构造注入Repository public LocationController(LocationRepository locationRepository) { this.locationRepository = locationRepository; } @PostMapping("/locations/search") public ResponseEntity<List<Location>> searchLocations( @Valid @RequestBody LocationSearchRequest request) { // 解析坐标点的经纬度 Double lat1 = request.getP1()[0]; Double lng1 = request.getP1()[1]; Double lat2 = request.getP2()[0]; Double lng2 = request.getP2()[1]; // 计算经纬度范围边界(兼容坐标传入顺序) Double minLat = Math.min(lat1, lat2); Double maxLat = Math.max(lat1, lat2); Double minLng = Math.min(lng1, lng2); Double maxLng = Math.max(lng1, lng2); Pageable pageable = PageRequest.of(0, request.getLimit()); List<Location> locations = locationRepository.findByLatBetweenAndLngBetweenAndTypeOrderByTypeDesc( minLat, maxLat, minLng, maxLng, request.getType(), pageable); return ResponseEntity.ok(locations); } }
三、方案二:使用GET请求+字符串参数(兼容URL传参场景)
如果必须保留GET请求,可以将p1、p2作为逗号分隔的字符串参数传递,改造后的Controller方法如下:
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class LocationController { private final LocationRepository locationRepository; public LocationController(LocationRepository locationRepository) { this.locationRepository = locationRepository; } @GetMapping("/locations/search") public ResponseEntity<List<Location>> searchLocations( @RequestParam String p1, @RequestParam String p2, @RequestParam(required = false) Location.LocationType type, @RequestParam(required = false, defaultValue = "10") Integer limit) { // 拆分字符串解析经纬度 String[] p1Parts = p1.split(","); Double lat1 = Double.parseDouble(p1Parts[0]); Double lng1 = Double.parseDouble(p1Parts[1]); String[] p2Parts = p2.split(","); Double lat2 = Double.parseDouble(p2Parts[0]); Double lng2 = Double.parseDouble(p2Parts[1]); // 计算范围边界 Double minLat = Math.min(lat1, lat2); Double maxLat = Math.max(lat1, lat2); Double minLng = Math.min(lng1, lng2); Double maxLng = Math.max(lng1, lng2); Pageable pageable = PageRequest.of(0, limit); List<Location> locations = locationRepository.findByLatBetweenAndLngBetweenAndTypeOrderByTypeDesc( minLat, maxLat, minLng, maxLng, type, pageable); return ResponseEntity.ok(locations); } }
此时请求URL示例:
GET /locations/search?p1=46.6,15.4&p2=48.8,17.5&type=premium&limit=3
关键说明
- 参数校验:方案一通过
@Valid和@Size避免非法参数;方案二建议增加字符串拆分后的合法性校验(如判断数组长度、数值转换有效性)。 - 范围计算:两种方案都通过
Math.min/Math.max处理坐标顺序,确保查询范围正确。
内容的提问来源于stack exchange,提问作者Brendan Ahern
相关产品推荐
相关产品推荐

