如何查找当前点(118.818747°E,32.074497°N)附近500米的人?

这一类功能很常见(如微信附近的人、共享单车附近的车辆、美团附近的商家),那在java中是如何实

现的呢?

1 实现方式

目前普遍的实现方式有三种,下面将依次展开讨论:

  1. Mysql+外接正方形
  2. Mysql+geohash
  3. Redis+geohash

2 Mysql+外接正方形

2.1 实现思路

查找附近500米的人,就是以当前坐标点为圆心,以500米为半径画圆,找出圆内的人。

理论上可以直接计算数据库所有点与圆心的距离,与500米比较。但计算地球上两点距离公式复

杂,一旦数据库数据过多,计算起来就更麻烦了。

我们可以通过 外接正方形 的方式来解决这个问题。这样一来,计算量骤减。 [注:设定下图圆心在北

半球,东半球]

于是:实现附近的人功能实现分为:

① 计算外切正方形最大最小经纬度

② 查询在正方形范围内的数据

③ 过滤得到圆周内的点,即用正方形范围内的点-黄色区域的点(距离超过给定范围500米)

2.2 数据库准备

2.3 代码实现

获取外切正方形最大最小经纬度有两种方法,可以自己实现,也可用开源库实现。

①自己实现 getGpsRange 方法

此方法用到了半矢量公式,以下计算推导过程可参考https://www.jianshu.com/p/ed6ea376911e

  1. /**
  2. * 获取附近x米的人
  3. * *
  4. @param distance 距离范围 单位km
  5. * @param userLng 当前经度
  6. * @param userLat 当前纬度
  7. * @return
  8. */
  9. public List<User> nearBySearch1(double distance, double userLng, double userLat)
  10. {
  11. //1 获取外切正方形最大最小经纬度
  12. double[] point = getGpsRange(userLng, userLat, distance);
  13. //2 获取位置在正方形内的所有用户
  14. // 查询数据库操作,这里用mybatis plus实现
  15. List<User> users = list(Wrappers.
  16. <User>lambdaQuery().ge(User::getUserLongitude,
  17. point[0]).lt(User::getUserLongitude, point[1]).ge(User::getUserLatitude,
  18. point[2]).lt(User::getUserLatitude, point[3]));
  19. //3 过滤掉超过指定距离的用户
  20. users = users.stream().filter(a -> getDistance(a.getUserLongitude(),
  21. a.getUserLatitude(), userLng, userLat) <= distance)
  22. .collect(Collectors.toList());
  23. return users;
  24. }
  25. /**
  26. * 查询出某个范围内的最大经纬度和最小经纬度
  27. * 自己计算
  28. * *
  29. @param longitude 当前位置经度
  30. * @param latitude 当前位置纬度
  31. * @param rangeDis 距离范围,单位km
  32. * @return
  33. */
  34. public static double[] getGpsRange(double longitude, double latitude, double
  35. rangeDis) {
  36. //半矢量公式,与圆心在同纬度上,且在圆周上的点到圆点的经度差
  37. double dlng = 2 * Math.asin(Math.sin(rangeDis / (2 * EARTH_RADIUS)) /
  38. Math.cos(latitude * Math.PI / 180));
  39. //弧度转为角度
  40. dlng = dlng * 180 / Math.PI;
  41. //半矢量公式,与圆心在同经度上,且在圆周上的点到圆点的纬度差
  42. //弧度转为角度
  43. double dlat = rangeDis / EARTH_RADIUS;
  44. dlat = dlat * 180 / Math.PI;
  45. ②也可用开运库计算外接正方形坐标范围
  46. double minlng = longitude - dlng;
  47. double maxlng = longitude + dlng;
  48. double minlat = latitude - dlat;
  49. double maxlat = latitude + dlat;
  50. return new double[]{minlng, maxlng, minlat, maxlat};
  51. }
  52. /**
  53. * 根据地球上任意两点的经纬度计算两点间的距离(半矢量公式),返回距离单位:km
  54. * *
  55. @param longitude1 坐标1 经度
  56. * @param latitude1 坐标1 纬度
  57. * @param longitude2 坐标2 经度
  58. * @param latitude2 坐标2 纬度
  59. * @return 返回km
  60. */
  61. public static double getDistance(double longitude1, double latitude1, double
  62. longitude2, double latitude2) {
  63. double radLat1 = Math.toDegrees(latitude1);
  64. double radLat2 = Math.toDegrees(latitude2);
  65. double a = radLat1 - radLat2;
  66. double b = Math.toDegrees(longitude1) - Math.toDegrees(longitude2);
  67. double distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
  68. Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b /
  69. 2), 2)));
  70. distance = distance * EARTH_RADIUS;
  71. distance = Math.round(distance * 10000) / 10000.0;
  72. return distance;
  73. }

也可以使用开源库计算外接正方形坐标范围

  1. <dependency>
  2. <groupId>com.spatial4j</groupId>
  3. <artifactId>spatial4j</artifactId>
  4. <version>0.5</version>
  5. </dependency>
  1. private SpatialContext spatialContext = SpatialContext.GEO;
  2. /**
  3. * 获取附近x米的人
  4. * *
  5. @param distance 距离范围 单位km
  6. * @param userLng 当前经度
  7. * @param userLat 当前纬度
  8. * @return
  9. */
  10. public List<User> nearBySearch(double distance, double userLng, double userLat)
  11. {
  12. //1 获取外切正方形最大最小经纬度
  13. Rectangle rectangle = getRectangle(distance, userLng, userLat);
  14. //2.获取位置在正方形内的所有用户
  15. // 查询数据库操作,这里用mybatis plus实现3 Mysql+geohash
  16. 第二种实现方式引入了 geohash
  17. GeoHash是一种地址编码方法。他能够把二维的空间经纬度数据编码成一个字符串。
  18. 3.1 geohash算法
  19. 3.1.1 geohash算法思想
  20. List<User> users = list(Wrappers.
  21. <User>lambdaQuery().ge(User::getUserLongitude,
  22. rectangle.getMinX()).lt(User::getUserLongitude,
  23. rectangle.getMaxX()).ge(User::getUserLatitude,
  24. rectangle.getMinY()).lt(User::getUserLatitude, rectangle.getMaxY()));
  25. //3.剔除半径超过指定距离的多余用户
  26. users = users.stream().filter(a -> getDistance(a.getUserLongitude(),
  27. a.getUserLatitude(), userLng, userLat) <= distance)
  28. .collect(Collectors.toList());
  29. return users;
  30. } /
  31. **
  32. * 利用开源库计算外接正方形坐标
  33. * *
  34. @param distance
  35. * @param userLng 当前经度
  36. * @param userLat 当前纬度
  37. * @return
  38. */
  39. private Rectangle getRectangle(double distance, double userLng, double
  40. userLat) {
  41. return spatialContext.getDistCalc()
  42. .calcBoxByDistFromPt(spatialContext.makePoint(userLng, userLat),
  43. distance * DistanceUtils.KM_TO_DEG, spatialContext,
  44. null);
  45. }
  46. /***
  47. * 球面中,两点间的距离(第三方库方法)
  48. * *
  49. @param longitude 经度1
  50. * @param latitude 纬度1
  51. * @param userLng 经度2
  52. * @param userLat 纬度2
  53. * @return 返回距离,单位km
  54. */
  55. public double getDistance(Double longitude, Double latitude, double userLng,
  56. double userLat) {
  57. return spatialContext.calcDistance(spatialContext.makePoint(userLng,
  58. userLat),
  59. spatialContext.makePoint(longitude, latitude)) *
  60. DistanceUtils.DEG_TO_KM;
  61. }

3 Mysql+geohash

第二种实现方式引入了 geohash 。

GeoHash是一种地址编码方法。他能够把二维的空间经纬度数据编码成一个字符串。

3.1 geohash算法

3.1.1 geohash算法思想

将地球球面沿着180°经线分开,平铺到平面上。

0°经线和0°纬线将此平面划分为四部分。设定西经为负,南纬为负,地球上的经度范围就是

[-180°,180°],纬度范围就是[-90°,90°]。

如果纬度范围[-90°, 0°)用二进制0代表,(0°, 90°]用二进制1代表,经度范围[-180°, 0°)用二进制0

代表,(0°, 180°]用二进制1代表,那么划分出的四部分用二进制表示为:

如果再对此递归对半划分呢?

geohash算法就是基于这种思想,划分的次数越多,区域越多,区域面积越小。

3.1.2 geohash算法编码经纬度

geohash算法将经纬度编码分为三步:

①将经纬度变成二进制

以点 (118.818747,32.074497) 为例。

纬度的范围是(-90,90),以其中间值0将此范围划分为两个区间(-90,0)和(0,90),若给定的纬

度在左区间(-90,0),则为0;若给定的纬度在右区间(0,90),则为1;纬度32.074497在右区间,因此

为1。

再将(0,90)这个区间以中间值划分为左右区间,按照以上方法判定为1还是0。

依此方法,可得到纬度的二进制表示,如下表:

纬度范围 划分的左区间 划分的右区间 纬度32.074497的二进制表示
(-90,90) (-90,0) (0,90) 1
(0,90) (0,45) (45,90) 0
(0,45) (0,22.5) (22.5,45) 1
(22.5,45) (22.5,33.75) (33.75,45) 0
| (22.5,33.75)| (22.5,28.125) | | …… | …… | …… | …… | (28.125,33.75) |1|

划分10次后,得到的纬度二进制表示为 10101 10110

同样的方法,可得到划分9次后经度二进制表示为 110101

②将经纬度合并

合并方法: 经度占偶数位,纬度占奇数位

经纬度合并结果为 11100 11001 11000 10110

③按照Base32进行编码

将②的结果用Base32编码得到字符串 wtsq 。也就是说点(118.818747,32.074497)可用wtsq

表示。

  1. GeoHash字符串越长,表示的位置越精确,字符串长度越长代表在距离上的误差越小。具体

    的不同精度的距离误差可参考下表:

  1. GeoHash值表示的并不是一个点,而是一个矩形区域。
  2. Geohash比直接用经纬度的高效很多,而且使用者可以发布地址编码,既能表明自己所在区域,又不至于暴露自己的精确坐标,有助于隐私保护。
  3. 距离越近的坐标,转换后的geohash字符串越相似,例如:

3.2 实现思路

以上详细介绍了geohash算法,那么如何利用Mysql+geohash实现附近的人功能呢?

  • 添加新用户时计算该用户的geohash字符串,并存储到用户表中。
  • 当要查询某个点附近指定距离的用户信息时,通过比对geohash误差表确定需要的geohash字符串

    精度。
  • 当要查询某个点附近指定距离的用户信息时,通过比对geohash误差表确定需要的geohash字符串 精度。
  • 计算获得当前坐标的geohash字符串,并查询与当前字符串前缀相同的数据。
  • 如果geohash字符串的精度远大于给定的距离范围时,查询出的结果集中必然存在在范围之外的数

    据。
  • 计算两点之间距离,对于超出距离的数据进行剔除。

3.3 数据库准备

3.4 代码实现

  1. <dependency>
  2. <groupId>com.spatial4j</groupId>
  3. <artifactId>spatial4j</artifactId>
  4. <version>0.5</version>
  5. </dependency>
  1. private SpatialContext spatialContext = SpatialContext.GEO;
  2. /**
  3. * 获取附近指定范围的人
  4. * *
  5. @param distance 距离范围 单位km
  6. * @param len geoHash的精度
  7. * @param userLng 当前用户的经度
  8. * @param userLat 当前用户的纬度
  9. * @return
  10. */
  11. public List<User> nearBySearch2(double distance, int len, double userLng,
  12. double userLat) {
  13. //1.根据要求的范围,确定geoHash码的精度,获取到当前用户坐标的geoHash码
  14. String geoHashCode = GeohashUtils.encodeLatLon(userLat, userLng, len);
  15. //2.匹配指定精度的geoHash码
  16. //查询数据库操作 mybatis plus实现
  17. List<User> users = list(Wrappers.
  18. <User>lambdaQuery().likeRight(User::getGeohash, geoHashCode));
  19. //3.过滤超出距离的
  20. users = users.stream()
  21. .filter(a -> getDistance1(a.getUserLongitude(),
  22. a.getUserLatitude(), userLng, userLat) <= distance)
  23. .collect(Collectors.toList());
  24. return users;
  25. }
  26. /***
  27. * 球面中,两点间的距离(第三方库方法)
  28. * *
  29. @param longitude 经度1
  30. * @param latitude 纬度1
  31. * @param userLng 经度2
  32. * @param userLat 纬度2
  33. * @return 返回距离,单位km
  34. */
  35. public double getDistance(Double longitude, Double latitude, double userLng,
  36. double userLat) {
  37. return spatialContext.calcDistance(spatialContext.makePoint(userLng,
  38. userLat),
  39. spatialContext.makePoint(longitude, latitude)) *
  40. DistanceUtils.DEG_TO_KM;
  41. }
  42. /**
  43. * 向数据库添加数据
  44. *
  45. @param user 用户对象
  46. * @return
  47. */
  48. public boolean save(User user) {
  49. //默认精度12位
  50. String geoHashCode = GeohashUtils.encodeLatLon(user.getUserLatitude(),
  51. user.getUserLongitude());
  52. //插入数据库操作 mybatis plus实现
  53. super.save(user.setGeohash(geoHashCode));
  54. }

3.5 边界问题优化

geohash算法提高了效率,但在实际应用场景中存在一些问题。首先就是 边界问题 。

如图,如果当前在红点位置,区域内还有一个黄点。相邻区域内的绿点明显离红点更近。但因为黄

点的编码和红点一样,最终找到的将是黄点。这就有问题了。

要解决这个问题,除了要找到当前区域内的点,还要要再查找周边8个区域内的点,看哪个离自己

更近。

这里提供了求解当前区域周围8个区域的思路:Geohash求当前区域周围8个区域编码的一种思路

由此优化代码为:

  1. <dependency>
  2. <groupId>com.spatial4j</groupId>
  3. <artifactId>spatial4j</artifactId>
  4. <version>0.5</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>ch.hsr</groupId>
  8. <artifactId>geohash</artifactId>
  9. <version>1.0.10</version>
  10. </dependency>
  1. private SpatialContext spatialContext = SpatialContext.GEO;
  2. /**
  3. * 获取附近x米的人,geohash区域+8个周围区域
  4. * *
  5. @param distance 距离范围 单位km
  6. * @param len geoHash的精度
  7. * @param userLng 当前经度
  8. * @param userLat 当前纬度
  9. * @return json
  10. */
  11. public List<User> nearBySearch4(double distance, int len, double userLng,
  12. double userLat) {
  13. //1 根据要求的范围,确定geoHash码的精度,获取到当前用户坐标的geoHash码
  14. GeoHash geoHash = GeoHash.withCharacterPrecision(userLat, userLng, len);
  15. //2 获取到用户周边8个方位的geoHash码
  16. GeoHash[] adjacent = geoHash.getAdjacent();
  17. //查询数据库操作 mybatis plus实现
  18. QueryWrapper<User> queryWrapper = new QueryWrapper<User>
  19. ().likeRight("user_geohash", geoHash.toBase32());
  20. Stream.of(adjacent).forEach(a ->
  21. queryWrapper.or().likeRight("user_geohash", a.toBase32()));
  22. //匹配指定精度的geoHash码
  23. List<User> users = list(queryWrapper);
  24. //3 过滤超出距离的
  25. users = users.stream()
  26. .filter(a -> getDistance(a.getUserLongitude(),
  27. a.getUserLatitude(), userLng, userLat) <= distance)
  28. .collect(Collectors.toList());
  29. return users;
  30. }
  31. /***
  32. * 球面中,两点间的距离(第三方库方法)
  33. * *
  34. @param longitude 经度1
  35. * @param latitude 纬度1
  36. * @param userLng 经度2
  37. * @param userLat 纬度2
  38. * @return 返回距离,单位km
  39. */
  40. public double getDistance(Double longitude, Double latitude, double userLng,
  41. double userLat) {
  42. return spatialContext.calcDistance(spatialContext.makePoint(userLng,
  43. userLat),
  44. spatialContext.makePoint(longitude, latitude)) *
  45. DistanceUtils.DEG_TO_KM;
  46. }

4 Redis+geohash

基于前两种方案,我们可以发现此功能属于 读多写少 的情况,如果使用redis来实现附近的人,想

必效率会大大提高。

自Redis 3.2开始,Redis基于geohash和有序集合Zset提供了地理位置相关功能。

关于Redis提供的geohash操作命令介绍可移步:Redis 到底是怎么实现“附近的人”这个功能的呢?

4.1 实现思路

  • 用 GEOADD 方法添加用户坐标信息到redis,redis会将经纬度参数值转换为52位的geohash码,
  • Redis以geohash码为score,将其他信息以Zset有序集合存入key中
  • 通过调用 GEORADIUS 命令,获取指定坐标点某一范围内的数据
  • 因geohash存在精度误差,剔除超过指定距离的数据

4.2 代码实现

  1. @Autowired
  2. private RedisTemplate redisTemplate;
  3. //GEO相关命令用到的KEY
  4. private final static String KEY = "user_info";
  5. /**
  6. * 根据当前位置获取附近指定范围内的用户
  7. * *
  8. @param distance 指定范围 单位km ,可根据{@link Metrics} 进行设置
  9. * @param userLng 用户经度
  10. * @param userLat 用户纬度
  11. * @return
  12. */
  13. public List<User> nearBySearch3(double distance, double userLng, double
  14. userLat) {
  15. List<User> users = new ArrayList<>();
  16. //GEORADIUS获取附近范围内的信息
  17. GeoResults<RedisGeoCommands.GeoLocation<Object>> reslut =
  18. redisTemplate.opsForGeo().radius(KEY,
  19. new Circle(new Point(userLng, userLat), new
  20. Distance(distance, Metrics.KILOMETERS)),
  21. RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
  22. .includeDistance()
  23. .includeCoordinates().sortAscending());
  24. //存入list
  25. List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> content =
  26. reslut.getContent();
  27. //过滤掉超过距离的数据
  28. content.forEach(a -> users.add(
  29. new User().setDistance(a.getDistance().getValue())
  30. .setUserLatitude(a.getContent().getPoint().getX())
  31. .setUserLongitude(a.getContent().getPoint().getY())));
  32. return users;
  33. }
  34. /**
  35. * 用户信息存入Redis
  36. * *
  37. @param user 用户对象
  38. * @return
  39. */
  40. public boolean save(User user) {
  41. Long flag = redisTemplate.opsForGeo().add(KEY, new
  42. RedisGeoCommands.GeoLocation<>(
  43. user.getUserAccount(),
  44. new Point(user.getUserLatitude(), user.getUserLatitude()))
  45. );
  46. return flag != null && flag > 0;
  47. }

5 总结

GeoHash实现附近的人功能(如微信附近的人、共享单车附近的车辆、美团附近的商家)的更多相关文章

  1. 微信"附近的人"新增商家公众号入驻功能

    微信近日升级了“附近的人”,新增商家公众号(认证的服务号和有卡券功能的公众号)可自入驻,这是微信在推出卡券和微信wifi功能后,又一加强连接线下商户能力的功能. 微信在“附近的人”中 增加搜索商户功能 ...

  2. Android端IM应用中的@人功能实现:仿微博、QQ、微信,零入侵、高可扩展

    本文由“猫爸iYao”原创分享,感谢作者. 1.引言 最近有个需求:评论@人(没错,就是IM聊天或者微博APP里的@人功能),就像下图这样:   ▲ 微信群聊界面里的@人功能    ▲ QQ群聊界面里 ...

  3. IM里“附近的人”功能实现原理是什么?如何高效率地实现它?

    1.引言 基本上以陌生人社交为主的IM产品里,都会增加“附近的人”.“附近的xxx”这种以LBS(地理位置)为导向的产品特色(微信这个熟人社交产品里为啥也有“附近的人”?这当然是历史原因了,微信当初还 ...

  4. 微信附近的人,用redis也能实现?(GEO)

    相信微信附近的人的功能大家都应该用过 我可以很随意的通过我自己的定位能看到我附近的人,并且能看到那个人距离我的距离,大家有没有思考过这个是怎么实现的? 作为一个程序猿任何问题应该都有一个思考的过程,而 ...

  5. 在XMPP的JAVA开源实现Openfire中,增加LBS 附近的人功能

    1. XMPP协议 与 Openfire XMPP协议是IM领域的标准协议了,具体可参考  http://xmpp.org   及RFC6120,RFC6121,RFC6122等相关文档. http: ...

  6. 【LBS】基于地理位置的搜索之微信 附近的人 简单实现

    缘由 本周技术群有一个同学说我们该怎么实现 由近到远的基于地理位置的搜索,我创业做电商的系统做过类似这样的服务,我把我们以前的操作给大家分享下 什么是LBS LBS 全称是 Location  Bas ...

  7. 在存放源程序的文件夹中建立一个子文件夹 myPackage。例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage)。在 myPackage 包中创建一个YMD类,该类具有计算今年的年份、可以输出一个带有年月日的字符串的功能。设计程序SY31.java,给定某人姓名和出生日期,计算该人年龄,并输出该人姓名、年龄、出生日期。程序使用YM

    题目补充: 在存放源程序的文件夹中建立一个子文件夹 myPackage.例如,在“D:\java”文件夹之中创建一个与包同名的子文件夹 myPackage(D:\java\myPackage).在 m ...

  8. 使用ElasticSearch完成百万级数据查询附近的人功能

    上一篇文章介绍了ElasticSearch使用Repository和ElasticSearchTemplate完成构建复杂查询条件,简单介绍了ElasticSearch使用地理位置的功能. 这一篇我们 ...

  9. 怎样把QQ群降级(1000人降到200或500人,500人降到200)

    怎样把QQ群降级(1000人降到200或500人,500人降到200)QQ群只有升级的选项,没有降级选项,一旦升级为1000人,就无法直接降级为200人或500人,建群时选择了500人也无法降到200 ...

  10. 给ofo共享单车撸一个微信小程序

    想学一下微信小程序,发现文档这东西,干看真没啥意思.所以打算自己先动手撸一个.摩拜单车有自己的小程序,基本功能都有,方便又小巧,甚是喜爱.于是我就萌生了一个给ofo共享单车撸一个小程序(不知道为啥of ...

随机推荐

  1. 记录--vue+three,制作iview大波浪特效

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.效果图 具体效果可参考iview官方界面iView - 一套高质量的UI组件库 大波浪效果,使用的是three.js的官方例子,需要先 ...

  2. 任何样式,javascript都可以操作,让你所向披靡

    前言 习惯了在 css 文件里面编写样式,其实JavaScript 的 CSS对象模型也提供了强大的样式操作能力, 那就随文章一起看看,有多少能力是你不知道的吧. 样式来源 客从八方来, 样式呢, 样 ...

  3. hacker守则

    hacker守则 永远不要相信用户的输入,任何输入数据在证明其无害之前,都是有害的 不在任何场景下谈论hacker 学习时,养成做笔记的好习惯 不谈论所有与hack相关的文章/ 电脑 / 电脑不要说 ...

  4. Oracle 索引原理

    B-Tree索引 一个B树索引只有一个根节点,它实际就是位于树的最顶端的分支节点. 可以用下图一来描述B树索引的结构.其中,B表示分支节点,而L表示叶子节点. 对于分支节点块(包括根节点块)来说,其所 ...

  5. 基于SCCB协议的FPGA实现

    SCCB协议 1.协议内容 SCCB协议常用于vo系列的摄像头的寄存器配置中,是有IIC协议演变而来.本来,本人接触这个协议也是想配置摄像头用于摄像模块.但是,由于配置寄存器实在是太多,而且需要找的资 ...

  6. Debug模式调试技巧

    Debug模式调试技巧 断点管理窗口  菜单栏方式 Run -> view breakpoints  Actions方式 双击shift调出Actions窗口,输入view breakpoint ...

  7. #贪心#洛谷 3173 [HAOI2009]巧克力

    题目 分析 既然每一刀都要切,那肯定代价越大的要越早切, 考虑按代价降序排序,如果切了一行,求切列的时候贡献的行数就多了1. 代码 #include <cstdio> #include & ...

  8. 批量拉取/git pull 指定文件夹下面所有 Git 项目的最新代码

    背景 因为工作需要,当前所负责的项目较多:但是人力紧缺,其中绝大部分项目平时也不会去跟进迭代.所以经常需要批量拉取最新的代码查看最新的改动. 解决方案 一键批量拉取指定文件夹下所有 Git 项目的最新 ...

  9. 轻松上手Jackjson(珍藏版)

    写在前面 虽然现在市面上有很多优秀的json解析库,但 Spring默认采用Jackson解析Json. 本文将通过一系列通俗易懂的代码示例,带你逐步掌握 Jackson 的基础用法.进阶技巧以及在实 ...

  10. Linux程序崩溃自启动方法

    linux进程挂掉后,可以通过配置 systemd 来自动启动服务 1.创建 systemd 服务文件,例如:huyang.service,需要放置在系统文件夹 /etc/systemd/system ...