package com.stylefeng.guns.modular.system.util;
|
|
import com.stylefeng.guns.core.util.ToolUtil;
|
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.data.geo.Circle;
|
import org.springframework.data.geo.GeoResult;
|
import org.springframework.data.geo.GeoResults;
|
import org.springframework.data.geo.Point;
|
import org.springframework.data.redis.connection.RedisGeoCommands;
|
import org.springframework.data.redis.core.HashOperations;
|
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.stereotype.Component;
|
|
import javax.annotation.PostConstruct;
|
import java.util.*;
|
import java.util.concurrent.Executors;
|
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.TimeUnit;
|
|
|
/**
|
* Redis工具类
|
*/
|
@Component
|
public class RedisUtil {
|
|
@Autowired
|
private RedisTemplate redisTemplate;
|
|
private final Map<String, ScheduledExecutorService> LOCK_TASK_MAP = new HashMap<>();
|
|
/**
|
* 向redis中存储字符串没有过期时间
|
* @param key
|
* @param value
|
*/
|
public void setStrValue(String key, String value){
|
if(ToolUtil.isNotEmpty(key) && ToolUtil.isNotEmpty(value)){
|
redisTemplate.opsForValue().set(key, value);
|
}
|
}
|
|
|
/**
|
* 以分钟为单位设置存储值(设置过期时间)
|
* @param key
|
* @param value
|
* @param time 秒
|
*/
|
public void setStrValue(String key, String value, int time){
|
if(ToolUtil.isNotEmpty(key) && ToolUtil.isNotEmpty(value)){
|
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
|
}
|
}
|
|
|
/**
|
* 从redis中获取值
|
* @param key
|
* @return
|
*/
|
public String getValue(String key){
|
if(ToolUtil.isNotEmpty(key)){
|
System.err.println("查询缓存:" + key);
|
Object o = redisTemplate.opsForValue().get(key);
|
System.err.println(o);
|
return (String) o;
|
}
|
return null;
|
}
|
|
|
|
|
/**
|
* 删除key
|
* @param key
|
*/
|
public void remove(String key){
|
if(ToolUtil.isNotEmpty(key)){
|
redisTemplate.delete(key);
|
}
|
}
|
|
|
/**
|
* 加锁
|
* @param key
|
* @param time
|
* @return
|
*/
|
public boolean lock(String key, long keepTime, long time){
|
ScheduledExecutorService scheduledExecutorService = LOCK_TASK_MAP.get(key);
|
if(null == scheduledExecutorService || scheduledExecutorService.isTerminated()){
|
unlock(key);
|
}
|
keepTime *= 1000;
|
Boolean ifAbsent = redisTemplate.opsForValue().setIfAbsent(key, UUIDUtil.getRandomCode());
|
if(ifAbsent){
|
return addLockMap(key, time);
|
}
|
long timeMillis = System.currentTimeMillis();
|
while (timeMillis + keepTime > System.currentTimeMillis()){
|
ifAbsent = redisTemplate.opsForValue().setIfAbsent(key, UUIDUtil.getRandomCode());
|
if(ifAbsent){
|
return addLockMap(key, time);
|
}
|
try {
|
Thread.sleep(100);
|
} catch (InterruptedException e) {
|
e.printStackTrace();
|
}
|
}
|
return false;
|
}
|
|
|
private boolean addLockMap(String key, long time){
|
ScheduledExecutorService scheduledExecutorService = LOCK_TASK_MAP.get(key);
|
if(null == scheduledExecutorService){
|
scheduledExecutorService = Executors.newScheduledThreadPool(1);
|
}
|
LOCK_TASK_MAP.put(key, scheduledExecutorService);
|
scheduledExecutorService.schedule(()->{
|
redisTemplate.delete(key);
|
LOCK_TASK_MAP.remove(key);
|
}, time, TimeUnit.SECONDS);
|
return true;
|
}
|
|
|
/**
|
* redis释放锁
|
* @return
|
*/
|
public boolean unlock(String key){
|
redisTemplate.delete(key);
|
ScheduledExecutorService scheduledExecutorService = LOCK_TASK_MAP.get(key);
|
if(null != scheduledExecutorService){
|
scheduledExecutorService.shutdownNow();
|
}
|
LOCK_TASK_MAP.remove(key);
|
return true;
|
}
|
|
|
/**
|
* 检索坐标为中心直径范围内的数据,单位米
|
* @param k
|
* @param lon
|
* @param lat
|
* @param radius
|
* @return
|
*/
|
public List<GeoResult<RedisGeoCommands.GeoLocation<String>>> getNearGeo(String k, Double lon, Double lat, Double radius){
|
Circle within = new Circle(lon, lat, radius);
|
GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = redisTemplate.opsForGeo().radius(k, within);
|
return geoResults.getContent();
|
}
|
|
|
/**
|
* 检索坐标为中心直径范围内的数据,单位米,由近到远排序
|
* @param k
|
* @param lon
|
* @param lat
|
* @param radius
|
* @return
|
*/
|
public List<GeoResult<RedisGeoCommands.GeoLocation<String>>> getNearGeoSortAscending(String k, Double lon, Double lat, Double radius){
|
Circle within = new Circle(lon, lat, radius);
|
RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
|
geoRadiusCommandArgs.sortAscending();
|
GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = redisTemplate.opsForGeo().radius(k, within, geoRadiusCommandArgs);
|
return geoResults.getContent();
|
}
|
|
|
/**
|
* 添加地理空间索引坐标
|
* @param k
|
* @param lon
|
* @param lat
|
* @param object
|
*/
|
public void addGeo(String k, Double lon, Double lat, String object){
|
Point point = new Point(lon, lat);
|
redisTemplate.opsForGeo().add(k, point, object);
|
}
|
}
|