项目里存储车辆位置用到了mongdb的GeoJsonPoints,但是报错说反序列化找不到默认的构造器
(no args construtor like new GeoJsonpoints(){}…)
查找了相似的问题和帖子:
https://stackoverflow.com/questions/52915203/jackson-serialize-geojsonpoint-as-latitude-longitude
https://stackoverflow.com/questions/48088738/spring-requestbody-with-geojsonpoint
更奇怪的是,写了个简单的demo,并没问题…
1、POJO类
/**
* ClassName SiteExt
* Author Lin
* Date 2019/5/30 16:56
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "SiteExt")
@CompoundIndexes({
@CompoundIndex(name = "location_index", def = "{'location': '2dsphere'}"),
})
public class SiteExt {
@Id
private String plateNo;
private GeoJsonPoint location;
}
2、DAO类
package com.skywilling.cn.manager.car.service.impl;
import com.skywilling.cn.manager.car.model.AutonomousCarInfo;
import com.skywilling.cn.manager.car.model.SiteExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.BulkOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* ClassName SiteExtDao
* Author Lin
* Date 2019/5/30 16:57
**/
@Repository
public class SiteExtDao {
@Autowired
private MongoTemplate mongoTemplate;
public List<SiteExt> findPointInPolygon(GeoJsonPolygon geoJsonPolygon, String collectionName) {
Query query = new Query(Criteria.where("location").within(geoJsonPolygon));
List<SiteExt> list = mongoTemplate.find(query, SiteExt.class,collectionName);
return list;
}
public void insert(SiteExt siteExt, String collectionName) {
mongoTemplate.insert(siteExt,collectionName);
}
public void insertBatch(List<SiteExt> list, String collectionName) {
// BulkMode.UNORDERED:表示并行处理,遇到错误时能继续执行不影响其他操作;BulkMode.ORDERED:表示顺序执行,遇到错误时会停止所有执行
BulkOperations ops = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, collectionName);
ops.insert(list);
// 执行操作
ops.execute();
}
public List<SiteExt> findAll(String collectionName) {
Query query=new Query();
List<SiteExt> list = mongoTemplate.find(query, SiteExt.class,collectionName);
return list;
}
public List<SiteExt> findByDist(GeoJsonPoint geoJsonPoint, double dis) {
Criteria geoCriteria = Criteria.where("location").nearSphere(geoJsonPoint).maxDistance(dis);
Query query = Query.query(geoCriteria);
return mongoTemplate.find(query,SiteExt.class);
}
public SiteExt nearVehicle(GeoJsonPoint point) {
Criteria geoCriteria = Criteria.where("location").nearSphere(point);
Query query= Query.query(geoCriteria);
query.with(new PageRequest(0,1));
return mongoTemplate.find(query,SiteExt.class).get(0);
}
}
3、测试类
@Test
public void TestGeoJsonPoints(){
GeoJsonPoint geoJsonPoint1 = new GeoJsonPoint(new Point(113.330908,23.155678));
SiteExt siteExt1 = new SiteExt("A",geoJsonPoint1);
GeoJsonPoint geoJsonPoint2 = new GeoJsonPoint(new Point(113.33831,23.137335));
SiteExt siteExt2 = new SiteExt("B",geoJsonPoint2);
siteExtDao.insert(siteExt1,"SiteExt");
siteExtDao.insert(siteExt2,"SiteExt");
}
@Test
public void TestGeoPolgy(){
Point p1 = new Point(113.314882,23.163055);
Point p2 = new Point(113.355845,23.167042);
Point p3 = new Point(113.370289,23.149564);
Point p4 = new Point(113.356779,23.129758);
Point p5 = new Point(113.338238,23.13913);
Point p6 = new Point(113.330979,23.124706);
Point p7 = new Point(113.313588,23.140858);
Point p8 = new Point(113.323865,23.158204);
Point p9 = new Point(113.314882,23.163055);
List<Point> list = new ArrayList<>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
list.add(p5);
list.add(p6);
list.add(p7);
list.add(p8);
list.add(p9);
//用9个点围成一个区域,首尾两个点p1和p9要相同,才能构成一个区域
GeoJsonPolygon geoJsonPolygon = new GeoJsonPolygon(list);
//传入区域和数据库表名
List<SiteExt> pointInPolygon = siteExtDao.findPointInPolygon(geoJsonPolygon,"SiteExt");
pointInPolygon.forEach(
p -> {
System.out.println(p.getLocation());
}
);
SiteExt near = siteExtDao.nearVehicle(new GeoJsonPoint(new Point(113.330908,23.155678)));
System.out.println(near);
List<SiteExt> res = siteExtDao.findByDist(new GeoJsonPoint(new Point(113.33,23.14)),2000);
System.out.println(res);
}
4、测试结果
Point [x=113.330908, y=23.155678]
SiteExt(plateNo=A, location=Point [x=113.330908, y=23.155678])
[SiteExt(plateNo=B, location=Point [x=113.338310, y=23.137335]), SiteExt(plateNo=A, location=Point [x=113.330908, y=23.155678])]
demo测试结果完全没毛病
4、项目中也是当做自己类的一个字段,
@Data
@AllArgsConstructor
@NoArgsConstructor
@Repository
@Document(collection = "autonomousCarInfo")
//复合索引,加复合索引后通过复合索引字段查询将大大提高速度,如@CompoundIndex(name = "age_idx", def = "{'lastName': 1, 'age': -1}")
//lastName和age将作为复合索引age_idx,数字参数指定索引的方向,1为正序,-1为倒序。方向对单键索引和随机存不要紧,但如果你要执行分组和排序操作的时候,它就非常重要了
//空间索引(判断一个点POINT是否在一个区域POLYGON内)
@CompoundIndexes({
@CompoundIndex(name = "location_index", def = "{'position':'2dsphere'}"),
@CompoundIndex(name = "lane_station_idx", def = "{'lane':1, 'station':1}"),
})
public class AutonomousCarInfo implements Serializable {
private static final long serialVersionUID = 23412341209L;
@Id
private String vin;
@Field
private String tripId;
@Field
private int state;
@Field
private String taskId;
@Field
private double velocity;
@Field
private double wheelAngle;
@Field
private double gear;
@Field
private Pose pose;
@Field
private String station;
/** 当前的lane*/
@Field
private String fromLane;
/** 预瞄的lane*/
@Field
private String lane;
@Field
private long timestamp;
@Field
private List<ModuleInfo> RosNodes;
/**
* 便于直接使用geohash索引
* */
private GeoJsonPoint geoJsonPoint;
public AutonomousCarInfo(String vin) {
this.vin = vin;
this.tripId = null;
}
/* public AutonomousCarInfo(String vin, GeoJsonPoint jsonPoint){
this.vin = vin;
this.setGeoJsonPoint(jsonPoint);
}*/
}
6、总结
猜想是我们字段直接使用了GeoJsonPoints这个数据结构,但是这个库中类没有默认构造函数,序列化不受控,利用fastJson解析的时候找不到反序列化标准。
后来思考可能是demo用的带参构造函数来创建实例,而我项目中是用new AutonomoCarinfo();然后setXXX来传入的方式,尝试了加入了新的带参数构造函数,也没解决。
最后也没解决这个问题,直接不用了。-。-