Redis实现简单附近人功能
1、用户进入附近人页面传经纬度地址存入表中。
2、根据经纬度地址计算出该用户距离范围内用户。
3、使用 Redis 根据行政编码分类存放 用户。
4、具体逻辑根据业务需求完善 ...... 博主结合了各种筛选条件在线离线状况这里不一一列举。
数据库表
Redis 存放结构(使用hash存储方便用户更新坐标操作)
controller接口
附近人入参DTO类
@Data
public class NearbyDTO extends BaseDto {
@ApiModelProperty ( value = "城市编码" , name = "cityCode" )
@NotNull ( message = "城市编码不能为空" )
private Integer cityCode;
@ApiModelProperty ( value = "省份编码" , name = "adCode" )
@NotNull ( message = "省份编码不能为空" )
private Integer adCode;
@NotNull ( message = "经度不能为空" )
private Double lng;
@NotNull ( message = "纬度不能为空" )
private Double lat;
@NotNull ( message = "标签不能为空" )
private String label;
@ApiModelProperty ( value = "距离:KM" , name = "scope" )
private int scope;
}
@Override
public List< NearbyVO> nearbyList ( NearbyDTO dto) {
SysUser user = sysUserService. selectById ( userToken. getUserId ( ) ) ;
String cacheKey = String. format ( NEARBY_CACHE_KEY, dto. getCityCode ( ) , dto. getAdCode ( ) ) ;
NearbyVO vo = new NearbyVO ( ) ;
vo. setUid ( user. getId ( ) ) ;
vo. setLng ( dto. getLng ( ) ) ;
vo. setLat ( dto. getLat ( ) ) ;
vo. setLabel ( dto. getLabel ( ) ) ;
BeanUtils. copyProperties ( user, vo) ;
redisDao. hset ( cacheKey, user. getId ( ) + "" , JSONObject. toJSONString ( vo) ) ;
Map< String, String> cacheAll = redisDao. hGetAll ( cacheKey) ;
if ( cacheAll. isEmpty ( ) || cacheAll. size ( ) == 0 ) return null;
if ( dto. getScope ( ) > MAX_DISTANCE) {
dto. setScope ( MAX_DISTANCE) ;
}
List< NearbyVO> result = new ArrayList < NearbyVO> ( ) ;
for ( String item : cacheAll. keySet ( ) ) {
NearbyVO bo = JSONObject. parseObject ( cacheAll. get ( item) , NearbyVO. class ) ;
double distance = MapUtils. getDistance ( dto. getLat ( ) , dto. getLng ( ) , bo. getLat ( ) , bo. getLng ( ) ) ;
if ( distance > dto. getScope ( ) ) {
continue ;
}
bo. setScope ( distance) ;
result. add ( bo) ;
}
if ( ! result. isEmpty ( ) ) {
Collections. sort ( result, new Comparator < NearbyVO> ( ) {
@Override
public int compare ( NearbyVO o1, NearbyVO o2) {
if ( o1. getScope ( ) > o2. getScope ( ) ) {
return 1 ;
}
if ( o1. getScope ( ) == o2. getScope ( ) ) {
return 0 ;
}
return - 1 ;
}
} ) ;
}
threadPoolTaskExecutor. execute ( new Runnable ( ) {
@Override
@Transactional ( rollbackFor = Exception. class )
public void run ( ) {
NearbyUser nearbyUser = new NearbyUser ( ) ;
nearbyUser. setUid ( user. getId ( ) ) ;
nearbyUser. setLable ( dto. getLabel ( ) ) ;
nearbyUser. setLat ( dto. getLat ( ) ) ;
nearbyUser. setLng ( dto. getLng ( ) ) ;
nearbyUser. setCreateTime ( new Date ( ) ) ;
Wrapper< NearbyUser> wrapper = new EntityWrapper < NearbyUser> ( ) . eq ( "uid" , user. getId ( ) ) ;
Integer flag = 0 ;
if ( nearbyUserMapper. selectCount ( wrapper) > 0 ) {
flag = nearbyUserMapper. update ( nearbyUser, wrapper) ;
} else {
flag = nearbyUserMapper. insert ( nearbyUser) ;
}
log. info ( "------> 用户【{}】同步数据到附近用户表状态为【{}】、注.0 失败 >1 成功" , user. getId ( ) , flag) ;
}
} ) ;
return result;
}
效果图