SnowFlakeUtil
@Slf4j
public class SnowFlakeUtil {
public static final SnowFlakeUtil instance = new SnowFlakeUtil();
/**
* 起始的时间戳
*/
private final long START_TIMESTAMP = 1557489395327L;
/**
* 序列号占用位数
*/
private final long SEQUENCE_BIT = 12;
/**
* 机器标识占用位数
*/
private final long MACHINE_BIT = 10;
/**
* 时间戳位移位数
*/
private final long TIMESTAMP_LEFT = SEQUENCE_BIT + MACHINE_BIT;
/**
* 最大序列号 (4095)
*/
private final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT);
/**
* 最大机器编号 (1023)
*/
private final long MAX_MACHINE_ID = ~(-1L << MACHINE_BIT);
/**
* 生成id机器标识部分
*/
private long machineIdPart;
/**
* 序列号
*/
private long sequence = 0L;
/**
* 上一次时间戳
*/
private long lastStamp = -1L;
/**
* 构造函数初始化机器编码
*/
private SnowFlakeUtil() {
//模拟这里获得本机机器编码
// long localIp = 0;
// localIp = hostNameUtil.getMachineNo();
// 机器码随机生成
long randomNum = new Random().nextInt(1023);
log.info("当前机器编码:{}", randomNum);
//localIp & MAX_MACHINE_ID最大不会超过1023,在左位移12位
machineIdPart = (randomNum & MAX_MACHINE_ID) << SEQUENCE_BIT;
}
/**
* 获取雪花ID
*/
public synchronized long nextId() {
long currentStamp = timeGen();
//避免机器时钟回拨
while (currentStamp < lastStamp) {
// //服务器时钟被调整了,ID生成器停止服务.
throw new RuntimeException(String.format("时钟已经回拨. Refusing to generate id for %d milliseconds", lastStamp - currentStamp));
}
if (currentStamp == lastStamp) {
// 每次+1
sequence = (sequence + 1) & MAX_SEQUENCE;
// 毫秒内序列溢出
if (sequence == 0) {
// 阻塞到下一个毫秒,获得新的时间戳
currentStamp = getNextMill();
}
} else {
//不同毫秒内,序列号置0
sequence = 0L;
}
lastStamp = currentStamp;
//时间戳部分+机器标识部分+序列号部分
return (currentStamp - START_TIMESTAMP) << TIMESTAMP_LEFT | machineIdPart | sequence;
}
/**
* 阻塞到下一个毫秒,直到获得新的时间戳
*/
private long getNextMill() {
long mill = timeGen();
//
while (mill <= lastStamp) {
mill = timeGen();
}
return mill;
}
/**
* 返回以毫秒为单位的当前时间
*/
protected long timeGen() {
return System.currentTimeMillis();
}
/**
* 获取long类型雪花ID
*/
public long uniqueLong() {
return nextId();
}
/**
* 获取String类型雪花ID
*/
public String uniqueLongHex() {
return String.format("%016x", uniqueLong());
}
}
RedisUtils
@Component
public class RedisUtils {
protected static final Logger logger = LoggerFactory.getLogger(RedisUtils.class);
private static RedisTemplate redisTemplate;
@Autowired
public RedisUtils(RedisTemplate stringObjectRedisTemplate){
RedisUtils.redisTemplate = stringObjectRedisTemplate;
}
@SuppressWarnings("unchecked")
public static <T> T get(String key, Class<T> clazz) {
try {
ValueOperations<String, T> ops = getRedisTemplate().opsForValue();
T value = ops.get(key);
return value;
} catch (Exception e) {
logger.info("get from Cache error! key = {" + key + "}", e);
logger.warn("catch error!", e);
return null;
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Set getSet(String key) {
try {
SetOperations ops = getRedisTemplate().opsForSet();
return ops.members(key);
} catch (Exception e) {
logger.info("get from Cache error! key = {" + key + "}", e);
logger.warn("catch error!", e);
return null;
}
}
public static String getString(String key) {
return get(key, String.class);
}
public static Integer getInteger(String key) {
return get(key, Integer.class);
}
public static BigDecimal getDecimal(String key) {
return get(key, BigDecimal.class);
}
@SuppressWarnings("unchecked")
public static <T> boolean set(String key, T value, int expire) {
try {
if (value == null) {
return Boolean.FALSE;
}
ValueOperations<String, T> ops = getRedisTemplate().opsForValue();
ops.set(key, value);
return getRedisTemplate().expire(key, expire, TimeUnit.SECONDS);
} catch (Exception e) {
logger.info("set to Cache error! key = {" + key + "}", e);
logger.warn("set to Cache error!", e);
}
return Boolean.FALSE;
}
public static <T> void setAndexpire(String key, T value, int expire) {
try {
ValueOperations<String, T> ops = getRedisTemplate().opsForValue();
ops.set(key, value,expire,TimeUnit.SECONDS);
} catch (Exception e) {
logger.info("set to Cache error! key = {" + key + "}", e);
logger.warn("set to Cache error!", e);
}
}
/**
* 获取分页数据
*
* @param key Redis中的列表key
* @param pageNum 当前页码(从1开始)
* @param pageSize 每页大小
* @return 分页数据列表
*/
public static CommonPageResp getPagedData(String key, int pageNum, int pageSize) {
if (pageNum <= 0) {
throw new IllegalArgumentException("Page number must be greater than 0");
}
if (pageSize <= 0) {
throw new IllegalArgumentException("Page size must be greater than 0");
}
// 计算起始和结束索引
int start = (pageNum - 1) * pageSize;
int end = start + pageSize - 1;
CommonPageResp objectCommonPageResp = new CommonPageResp<>();
// 使用LRANGE命令获取指定范围的数据
List range = getRedisTemplate().opsForList().range(key, start, end);
objectCommonPageResp.setRows(range);
objectCommonPageResp.setPageNo(pageNum);
objectCommonPageResp.setPageSize(pageSize);
long listLength = getRedisTemplate().opsForList().size(key);
objectCommonPageResp.setTotal(listLength);
return objectCommonPageResp;
}
public static void hincrBy_StringSerialize(String key, String hashKey, Long value) {
try {
getRedisTemplate().opsForHash().increment(key, hashKey, value);
} catch (Exception e) {
logger.error("RedisUtils put error key[{}], hashKey[{}], value[{}], exception:{}", key, hashKey, value, e.getMessage());
}
}
public static Long putHashMap_StringSerialize(String cacheKey, Map map, long time) {
try {
getRedisTemplate().opsForHash().putAll(cacheKey, map);
if (time > 0) {
getRedisTemplate().expire(cacheKey, time, TimeUnit.SECONDS);
}
return getRedisTemplate().opsForHash().size(cacheKey);
} catch (Exception e) {
logger.error("putHashMap,cacheKey[" + cacheKey + "]", e);
}
return 0l;
}
public static void put_StringSerialize(String key, String hashKey, String value) {
try {
getRedisTemplate().opsForHash().put(key, hashKey, value);
} catch (Exception e) {
logger.error("RedisUtils put error key[{}], hashKey[{}], value[{}], exception:{}", key, hashKey, value, e.getMessage());
}
}
/**
* 获取总页数
*
* @param key Redis中的列表key
* @param pageSize 每页大小
* @return 总页数
*/
// public long getTotalPages(String key, int pageSize) {
// if (pageSize <= 0) {
// throw new IllegalArgumentException("Page size must be greater than 0");
// }
//
// // 获取列表长度
// long listLength = getRedisTemplate().opsForList().size(key);
//
// // 计算总页数(向上取整)
// return (listLength + pageSize - 1) / pageSize;
// }
/**
* @title: 根据前缀删除
* @author: luo heng
* @date: 2021/12/20 11:14
* @description: TODO
* @version:
* @param pattern
* @return:
*/
// public static Set<Object> scanDel(String pattern) {
// RedisTemplate redisTemplate = getRedisTemplate();
// redisTemplate.execute((RedisCallback<Set<Object>>) connection -> {
// JedisCommands commands = (JedisCommands) connection.getNativeConnection();
// MultiKeyCommands multiKeyCommands = (MultiKeyCommands) commands;
// int scanInvokeCount = 0;
// int totalCount = 0;
// logger.info("RedisHelper_clearScan_invoke_start scanInvokeCount:{}",scanInvokeCount);
// ScanParams scanParams = new ScanParams();
// scanParams.match(pattern + "*");
// scanParams.count(500);
// ScanResult<String> scan = multiKeyCommands.scan("0", scanParams);
// scanInvokeCount++;
// while (null != scan.getStringCursor()) {
// List<String> keys = scan.getResult();
// if (!CollectionUtils.isEmpty(keys)){
// int count = 0;
// for (String key : keys) {
// try {
// connection.del(key.getBytes());
// logger.info("RedisHelper_clearScan key:{}",key);
// count++;
// totalCount++;
// } catch (Exception e) {
// logger.info("RedisHelper_clearScan_fail key:{}",key);
// e.printStackTrace();
// }
// }
// logger.info("RedisHelper_clearScan_delete count:{}",count);
// }
// if (!StringUtils.equals("0", scan.getStringCursor())) {
// scan = multiKeyCommands.scan(scan.getStringCursor(), scanParams);
// scanInvokeCount++;
// logger.info("RedisHelper_clearScan_invoke scanInvokeCount:{}",scanInvokeCount);
// continue;
// } else {
// break;
// }
// }
// logger.info("RedisHelper_clearScan_invoke_end totalCount:{}",totalCount);
// logger.info("RedisHelper_clearScan_invoke_end scanInvokeCount:{}",scanInvokeCount);
// return null;
// });
// return null;
// }
public static <T> void set(String key, T value) {
try {
if (value == null) {
return;
}
ValueOperations<String, T> ops = getRedisTemplate().opsForValue();
ops.set(key, value);
} catch (Exception e) {
logger.info("set to Cache error! key = {" + key + "}", e);
logger.warn("set to Cache error!", e);
}
}
/**
* 查找匹配key
*
* @param pattern key
* @return /
*/
public static List<String> scan(String pattern) {
ScanOptions options = ScanOptions.scanOptions().match(pattern).build();
RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
RedisConnection rc = Objects.requireNonNull(factory).getConnection();
Cursor<byte[]> cursor = rc.scan(options);
List<String> result = new ArrayList<>();
while (cursor.hasNext()) {
result.add(new String(cursor.next()));
}
try {
RedisConnectionUtils.releaseConnection(rc, factory,false);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
CollectionUtil.removeEmpty(result);
return result;
}
public static List<String> scanHashKey(String hashKey,String pattern) {
Map<String,Object> allHashMap = getAllHashMap(hashKey);
if(CollectionUtil.isNotEmpty(allHashMap)){
Set<String> keys = allHashMap.keySet();
List<String> collect = keys.stream().filter(s -> s.startsWith(pattern)||s.endsWith(pattern)).collect(Collectors.toList());
CollectionUtil.removeEmpty(collect);
return collect;
}
return new ArrayList<>();
}
public static boolean setString(String key, String value, int expire) {
return set(key, value, expire);
}
public static boolean setDefExpire(String key, String value) {
return set(key, value, 5 * 60 * 1000);
}
public static <T> boolean setDefExpire(String key, T value) {
return set(key, value, 5 * 60 * 1000);
}
@SuppressWarnings("unchecked")
public static void del(String key) {
try {
getRedisTemplate().delete(key);
} catch (Exception e) {
logger.info("delete from Cache error! key = {" + key + "}", e);
logger.warn("delete from Cache error!", e);
}
}
/**
* key是否存在
*
* @param key
*/
@SuppressWarnings("unchecked")
public static boolean exists(final String key) {
return getRedisTemplate().hasKey(key);
}
/**
* 把lis放入redis缓存起来,当天
*
* @param cacheKey
* @param list
*/
// public static void putListByRedisCache2ToDay(String cacheKey, List<?> list) {
// putListByRedisCache(cacheKey, list, DateUtils.getMilliSecondsLeftToday());
// }
/**
* 把lis放入redis缓存起来,一个小时
*
* @param cacheKey
* @param list
*/
public static void putListByRedisCache2ToOneHours(String cacheKey, List<?> list) {
putListByRedisCache(cacheKey, list, 2 * 60 * 60 * 1000);
}
/**
* 把lis放入redis缓存起来,30分钟
*
* @param cacheKey
* @param list
*/
public static void putListByRedisCache2To30Min(String cacheKey, List<?> list) {
putListByRedisCache(cacheKey, list, 5 * 60 * 60 * 1000);
}
/**
* 把map放入redis缓存起来,当天
*
* @param cacheKey
* @param map
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Long putHashMap(String cacheKey, Map map, long time) {
try {
getRedisTemplate().opsForHash().putAll(cacheKey, map);
if (time > 0) {
getRedisTemplate().expire(cacheKey, time, TimeUnit.SECONDS);
}
return getRedisTemplate().opsForHash().size(cacheKey);
} catch (Exception e) {
logger.error("putHashMap,cacheKey[" + cacheKey + "]", e);
}
return 0l;
}
/**
* 向key对应的map中添加缓存对象
*
* @param cacheKey
* cache对象key
* @param field
* map对应的key
* @param value
* 值
*/
@SuppressWarnings("unchecked")
public static void addMap(String cacheKey, String field, Object value) {
getRedisTemplate().opsForHash().put(cacheKey, field, value);
}
/**
* 把map放入redis缓存起来,当天
*
* @param cacheKey
*/
@SuppressWarnings("rawtypes")
public static Map getAllHashMap(String cacheKey) {
@SuppressWarnings("unchecked")
BoundHashOperations boundHashOperations = getRedisTemplate().boundHashOps(cacheKey);
return boundHashOperations.entries();
}
/**
* 把map放入redis缓存起来,当天
*
* @param cacheKey
*/
@SuppressWarnings("unchecked")
public static Object getMapField(String cacheKey, String field) {
return getRedisTemplate().boundHashOps(cacheKey).get(field);
}
/**
public static Object getMapField(String cacheKey, String field) {
return getRedisTemplate().boundHashOps(cacheKey).get(field);
}
/**
* 删除map中的某个对象
*
* @param key
* map对应的key
* @param field
* map中该对象的key
* @author lh
* @date 2016年8月10日
*/
@SuppressWarnings("unchecked")
public static void delMapField(String key, Object... field) {
BoundHashOperations<String, String, ?> boundHashOperations = getRedisTemplate().boundHashOps(key);
boundHashOperations.delete(field);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void putListByRedisCache(String cacheKey, List list, long time) {
try {
Set set = getRedisTemplate().opsForSet().members(cacheKey);
if (!set.isEmpty()) {// 如果当天数据已经存在redis中则不进行更新
return;
}
SetOperations operations = getRedisTemplate().opsForSet();
int size = 0;
for (int i = 0; i < list.size(); i++) {
size += operations.add(cacheKey, list.get(i));
}
// 放入缓存的时间 毫秒
getRedisTemplate().expire(cacheKey, time, TimeUnit.MILLISECONDS);
if (size == list.size()) {
logger.info("[" + cacheKey + "]缓存成功,size:" + size);
} else {
logger.info("[" + cacheKey + "]缓存失败,size:" + size);
logger.error("[" + cacheKey + "]缓存失败,size:" + size + ",listsize:" + list.size());
}
} catch (Exception e) {
logger.error("[" + cacheKey + "]缓存失败,List:" + JSONObject.toJSONString(list));
}
}
@SuppressWarnings("unchecked")
public static boolean hasKey(String pubparadescmap, String key) {
try {
return getRedisTemplate().boundHashOps(pubparadescmap).hasKey(key);
} catch (Exception e) {
logger.error("hasKey[" + key + "]hasKey,List:", e);
}
return false;
}
/**
* pub 、sub 模式
*
* @param channel
* @param message
* @return
*/
public static boolean pubMessage(String channel, Object message) {
try {
getRedisTemplate().convertAndSend(channel, message);
} catch (Exception e) {
logger.error("pubMessage,channel=" + channel + ",message=" + JSONObject.toJSONString(message) + " ", e);
return false;
}
return true;
}
@SuppressWarnings("rawtypes")
public static RedisTemplate getRedisTemplate() {
return redisTemplate;
}
public static void putListByRedisWithExpired(String cacheKey, List<?> list) {
try {
getRedisTemplate().opsForList().leftPushAll(cacheKey, list);
getRedisTemplate().expire(cacheKey, 8 * 60 * 60 * 1000, TimeUnit.MILLISECONDS);
}catch (Exception e){
logger.error("缓存["+cacheKey+"]失败:", e);
}
}
public static void putSetByRedisWithExpired(String cacheKey, List<?> list) {
try {
SetOperations setOperations = getRedisTemplate().opsForSet();
if(exists(cacheKey)){
//set集已存在,无需再次存入
logger.info("缓存"+cacheKey+"已存在,无需重复插入!");
return;
}
for(int i = 0; i < list.size(); i++){
setOperations.add(cacheKey, list.get(i));
}
getRedisTemplate().expire(cacheKey, 8 * 60 * 60 * 1000, TimeUnit.MILLISECONDS);
}catch (Exception e){
logger.error("缓存["+cacheKey+"]失败:", e);
}
}
public static List getList(String cacheKey ) {
try {
return getRedisTemplate().opsForList().range(cacheKey, 0, -1);
}catch (Exception e){
logger.error("获取缓存["+cacheKey+"]失败:", e);
}
return new ArrayList();
}
public static List getList(String cacheKey ,int page,int pageSize) {
try {
return getRedisTemplate().opsForList().range(cacheKey, 0, -1);
}catch (Exception e){
logger.error("获取缓存["+cacheKey+"]失败:", e);
}
return new ArrayList();
}
ExcelUtil
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
@Slf4j
public class WriteExcelUtil {
/**
* 创建xlsx导出开始(适用于多个sheet)
* 使用案例:
* ExcelWriter writer = WriteExcelUtil.createExport(response, "name");
* WriteExcelUtil.writeSheet(writer, "s1", list, ContractPageDto.class);
* WriteExcelUtil.writeSheet(writer, "s2", listBills, BusinessBillsPageDto.class);
* WriteExcelUtil.finishWrite(writer);
*
* @param response
* @param fileName 导出的文件名,不需要加.xlsx
*/
public static <T> ExcelWriter createExport(HttpServletResponse response, String fileName) {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
try {
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("导出XLS时发送错误");
}
OutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
} catch (IOException e) {
throw new RuntimeException("导出XLS发送错误");
}
ExcelWriter excelWriter = EasyExcel.write(outputStream).registerWriteHandler(new ExcelWidthStyleStrategy()).build();
return excelWriter;
}
/**
* 写入一个sheet
*
* @param sheetName 工作表名
* @param list<T>
* @param entityClass
*/
public static <T> void writeSheet(ExcelWriter excelWriter, String sheetName, List<T> list, Class entityClass) {
WriteSheet sheet = EasyExcel.writerSheet(sheetName).head(entityClass).build();
excelWriter.write(list, sheet);
}
/**
* 结束写入sheet并导出
*/
public static <T> void finishWrite(ExcelWriter excelWriter) {
excelWriter.finish();
}
/**
*返回blob类型
* @param listData
* @param response httpRes
* @param fileName
* @throws IOException
*/
static public void writeExcelToBrowser(List<? extends Object> listData, HttpServletResponse response, String fileName) throws IOException {
if(listData.size()>10000){
throw new RuntimeException("数据量超过10000条,无法导出");
}
if(!CollectionUtils.isEmpty(listData)){
try {
String name = fileName + ".xlsx";
fileName = new String(name.getBytes(), StandardCharsets.UTF_8);
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
EasyExcel.write(response.getOutputStream(), listData.get(0).getClass())
.registerWriteHandler(new ExcelWidthStyleStrategy())
.sheet(fileName)
.doWrite(listData);
}catch (Exception e){
log.error("导出excel失败",e);
}
}
}
static public ResponseEntity exportExcel(List<? extends Object> listData, String fileName) {
try {
//数据写入到字节流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
boolean flag = writeExcel(bos, listData.get(0).getClass(), listData , fileName);
//下载文件
fileName = fileName + ".xlsx";
//excel导出
if (flag) {
return downloadExcel(fileName, bos);
}
} catch (Exception e) {
log.error("导出excel异常", e);
}
return null;
}
/**
* 表头进行自动扩展的导出
*
* @param os 文件输出流
* @param clazz Excel实体映射类
* @param data 导出数据
* @param sheetName sheet名称
* @return
*/
public static Boolean writeExcel(OutputStream os, Class clazz, List<?> data, String sheetName) {
try (BufferedOutputStream bos = new BufferedOutputStream(os)) {
EasyExcel.write(bos, clazz)
.sheet(sheetName)
//使用该方法对表头的宽度进行扩展
.doWrite(data);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* ResponseEntity下载文件
*
* @param fileName
* @param byteOutPutStream
*/
public static ResponseEntity<byte[]> downloadExcel(String fileName, ByteArrayOutputStream byteOutPutStream) {
//下载文件
try {
HttpHeaders headers = new HttpHeaders();
if (byteOutPutStream != null && byteOutPutStream.toByteArray().length > 0) {
headers.setContentDispositionFormData("attachment", fileName);
return new ResponseEntity<byte[]>(byteOutPutStream.toByteArray(), headers, HttpStatus.OK);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
WebContext
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class WebContext {
private static final ThreadLocal<WebContext> LOCAL_CONTEXT = new ThreadLocal();
private final HttpServletRequest request;
private final HttpServletResponse response;
public WebContext(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response;
}
public static void initWebContext(HttpServletRequest request, HttpServletResponse response) {
WebContext context = new WebContext(request, response);
initWebContext(context);
}
public static void initWebContext(WebContext webContext) {
LOCAL_CONTEXT.set(webContext);
}
public static WebContext getWebContext() {
return (WebContext)LOCAL_CONTEXT.get();
}
public static void clear() {
LOCAL_CONTEXT.remove();
}
public HttpServletRequest getRequest() {
return this.request;
}
public HttpServletResponse getResponse() {
return this.response;
}
public HttpSession getSession() {
return this.request.getSession();
}
public static String getHsSessionid() {
return getWebContext().getRequest().getHeader("hssessionid");
}
public static String getHeader(String name) {
return getHeader(name, "");
}
public static String getHeader(String name, String defaultValue) {
return getWebContext() != null && getWebContext().getRequest() != null ? getWebContext().getRequest().getHeader(name) : defaultValue;
}
}
TraceUtil
import org.apache.commons.lang.StringUtils;
import org.slf4j.MDC;
import org.springframework.util.CollectionUtils;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;
/**
* Trace 工具
**/
public class TraceUtil {
public final static String TRACE_ID = "trace_id";
public final static String TRACE_URI = "uri";
/**
* 初始化 TraceId
* @param uri 请求uri
*/
public static void initTrace(String uri) {
if(StringUtils.isBlank(MDC.get(TRACE_ID))) {
String traceId = generateTraceId();
setTraceId(traceId);
MDC.put(TRACE_URI, uri);
}
}
/**
* 将 Trace 相关信息,包括 TraceId 和 TraceUri 放入 RPC上下文中
* 给 Dubbo 消费端调用
* @param context Dubbo 的 RPC 上下文
*/
public static String getCurrThreadTraceId() {
String traceId = MDC.get(TRACE_ID);
return traceId;
}
/**
* 从 MDC 中清除当前线程的 Trace信息
*/
public static void clearTrace() {
MDC.clear();
}
/**
* 将traceId放入MDC
* @param traceId 链路ID
*/
public static void setTraceId(String traceId) {
traceId = StringUtils.left(traceId, 36);
MDC.put(TRACE_ID, traceId);
}
/**
* 生成traceId
* @return 链路ID
*/
private static String generateTraceId() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
public static <T> Callable<T> wrap(final Callable<T> callable, final Map<String, String> context) {
return () -> {
if (CollectionUtils.isEmpty(context)) {
MDC.clear();
} else {
MDC.setContextMap(context);
}
try {
return callable.call();
} finally {
// 清除子线程的,避免内存溢出,就和ThreadLocal.remove()一个原因
MDC.clear();
}
};
}
public static Runnable wrap(final Runnable runnable, final Map<String, String> context) {
return () -> {
if (CollectionUtils.isEmpty(context)) {
MDC.clear();
} else {
MDC.setContextMap(context);
}
try {
runnable.run();
} finally {
MDC.clear();
}
};
}
}
ThreadLocalUtils
import java.util.*;
public final class ThreadLocalUtil {
private static final ThreadLocal<Map<String, Object>> threadLocal = new ThreadLocal() {
protected Map<String, Object> initialValue() {
return new HashMap(4);
}
};
public static Map<String, Object> getThreadLocal(){
return threadLocal.get();
}
public static <T> T get(String key) {
Map map = (Map)threadLocal.get();
return (T)map.get(key);
}
public static <T> T get(String key,T defaultValue) {
Map map = (Map)threadLocal.get();
return (T)map.get(key) == null ? defaultValue : (T)map.get(key);
}
public static void set(String key, Object value) {
Map map = (Map)threadLocal.get();
map.put(key, value);
}
public static void set(Map<String, Object> keyValueMap) {
Map map = (Map)threadLocal.get();
map.putAll(keyValueMap);
}
public static void remove() {
threadLocal.remove();
}
public static <T> Map<String,T> fetchVarsByPrefix(String prefix) {
Map<String,T> vars = new HashMap<>();
if( prefix == null ){
return vars;
}
Map map = (Map)threadLocal.get();
Set<Map.Entry> set = map.entrySet();
for( Map.Entry entry : set ){
Object key = entry.getKey();
if( key instanceof String ){
if( ((String) key).startsWith(prefix) ){
vars.put((String)key,(T)entry.getValue());
}
}
}
return vars;
}
public static <T> T remove(String key) {
Map map = (Map)threadLocal.get();
return (T)map.remove(key);
}
public static void clear(String prefix) {
if( prefix == null ){
return;
}
Map map = (Map)threadLocal.get();
Set<Map.Entry> set = map.entrySet();
List<String> removeKeys = new ArrayList<>();
for( Map.Entry entry : set ){
Object key = entry.getKey();
if( key instanceof String ){
if( ((String) key).startsWith(prefix) ){
removeKeys.add((String)key);
}
}
}
for( String key : removeKeys ){
map.remove(key);
}
}
}
BigDecimalUtil
import cn.hutool.core.util.StrUtil;
import com.gw.fund.org.common.enums.ErrorCodeEnum;
import com.gw.fund.org.common.exception.BizException;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Objects;
public class BigDecimalUtil {
public final static BigDecimal ONE_HUNDRED = new BigDecimal("100.00");
public static String bigDecimal2String(BigDecimal decimal) {
return decimal == null ? StringUtils.EMPTY : decimal.toPlainString();
}
public static String bigDecimal2StringTrimZero(BigDecimal decimal) {
return decimal == null ? StringUtils.EMPTY : decimal.stripTrailingZeros().toPlainString();
}
/*直接舍去*/
public static String bigDecimal2String(BigDecimal decimal, int scale) {
return decimal == null ? StringUtils.EMPTY : decimal.setScale(scale, BigDecimal.ROUND_DOWN).toPlainString();
}
/*四舍五入*/
public static String bigDecimal2StringUp(BigDecimal decimal, int scale) {
return decimal == null ? StringUtils.EMPTY : decimal.setScale(scale, BigDecimal.ROUND_HALF_UP).toPlainString();
}
/**
* 金额前端展示格式化
*/
// TODO: 2021/8/4 建议前端金额展示都通过该方法来格式化,保证可以统一处理
public static String amountFrontShow(BigDecimal amount) {
BigDecimal decimal = amountFront(amount);
return decimal != null ? decimal.toPlainString() : null;
}
/**
* 金额前端展示格式化
*/
public static BigDecimal amountFront(BigDecimal amount) {
// 前端金额展示格式化(当前保留2位小数,多余精度舍去)
return amount != null ? amount.setScale(2, BigDecimal.ROUND_HALF_UP) : null;
}
public static String bigDecimalNull2String(BigDecimal decimal) {
return decimal == null ? null : decimal.stripTrailingZeros().toPlainString();
}
public static BigDecimal formatBigDecimal(BigDecimal decimal) {
return decimal == null ? BigDecimal.ZERO : decimal;
}
/**
* 当参数不为null的时候,设置精度,直接舍去
*
* @param decimal
* @param scale
* @return
*/
public static BigDecimal formatBigDecimalWhenNotnull(BigDecimal decimal, int scale) {
return decimal != null ? decimal.setScale(scale, BigDecimal.ROUND_DOWN) : null;
}
/**
* 当参数不为null的时候,设置精度,四舍五入
*
* @param decimal
* @param scale
* @return
*/
public static BigDecimal formatBigDecimalWhenNotnullUp(BigDecimal decimal, int scale) {
return decimal != null ? decimal.setScale(scale, BigDecimal.ROUND_HALF_UP) : null;
}
public static BigDecimal checkBigDecimal(BigDecimal decimal) {
return decimal == null ? BigDecimal.ZERO : decimal;
}
/**
* 返回折扣的描述信息
* 比如: decimal 为 0.45 ,返回 4.5折
* 比如: decimal 为 0.15 ,返回 1.5折
*/
public static String discountDescr(BigDecimal decimal) {
return decimal == null || BigDecimal.ZERO.compareTo(decimal) == 0 ? null : decimal.multiply(new BigDecimal("10")).stripTrailingZeros().toPlainString() + "折";
}
public static boolean isEmpty(BigDecimal decimal) {
return decimal == null || BigDecimal.ZERO.compareTo(decimal) == 0;
}
public static boolean isNullOrZero(BigDecimal decimal) {
return decimal == null || BigDecimal.ZERO.compareTo(decimal) == 0;
}
public static boolean isNotNull(BigDecimal decimal) {
return decimal != null;
}
/**
* 返回折扣的描述信息
* 比如: decimal 为 0.45 ,返回 4.5折
* 比如: decimal 为 0.15 ,返回 1.5折
*/
public static String discountDescr(String decimalStr) {
if (StringUtils.isBlank(decimalStr)) {
return null;
}
BigDecimal decimal = new BigDecimal(decimalStr);
return BigDecimal.ZERO.compareTo(decimal) == 0 ? null : decimal.multiply(new BigDecimal("10")).stripTrailingZeros().toPlainString() + "折";
}
/**
* 扣率值 * 100 后返回 T 类型
*/
public static <T> T multiply100Generic(String decimal, Class<T> t) {
if (StringUtils.isBlank(decimal)) {
return null;
}
if (t.getClass().equals(String.class)) {
return (T) new BigDecimal(decimal).multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString();
}
return (T) new BigDecimal(decimal).multiply(new BigDecimal("100"));
}
public static BigDecimal multiply(BigDecimal a, BigDecimal b) {
if (a == null || b == null) {
return null;
}
return a.multiply(b);
}
/**
* 指定精度
*/
public static String bigDecimalScale(String decimal, int scale) {
if (StringUtils.isBlank(decimal)) return null;
return new BigDecimal(decimal).setScale(scale, BigDecimal.ROUND_HALF_UP).toPlainString();
}
public static String formatPercentData2String(BigDecimal decimal, int scale) {
if (decimal == null) {
return null;
}
return BigDecimal.valueOf(100).multiply(decimal).setScale(scale, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
}
public static BigDecimal formatPercentData(BigDecimal decimal, int scale) {
if (decimal == null) {
return null;
}
return BigDecimal.valueOf(100).multiply(decimal).setScale(scale, BigDecimal.ROUND_HALF_UP);
}
public static BigDecimal formatPercentData(BigDecimal decimal) {
if (decimal == null) {
return null;
}
return BigDecimal.valueOf(100).multiply(decimal);
}
//省略0值
public static String string2BigDecimalStringTrimZero(String str) {
if (StringUtils.isBlank(str)) {
return null;
}
return new BigDecimal(str).stripTrailingZeros().stripTrailingZeros().toPlainString();
}
/**
* 费率格式化,返回给前端:
* 返回2位或者4位小数
* 例如:1 返回 1.00
* 例如:1.2 返回 1.20
* 例如:1.21 返回 1.21
* 例如:1.212 返回 1.2120
* 例如:1.2121 返回 1.2121
*/
public static String showRatio(String str) {
if (StringUtils.isBlank(str)) {
return null;
}
//
String calc = new BigDecimal(str).stripTrailingZeros().toPlainString();
String res = StringUtils.substringAfter(calc, ".");
if (StringUtils.isBlank(res)) {
return calc + ".00";
}
if (res.length() == 1) {
return calc + "0";
}
if (res.length() == 2) {
return calc;
}
if (res.length() == 3) {
return calc + "0";
}
if (res.length() == 4) {
return calc;
}
if (res.length() > 4) {
return StringUtils.substring(calc, 0, calc.length() - (res.length() - 4));
}
return calc;
}
/**
* 减法: 如果两个参数都是null返回null,否则返回运算后的值
*/
public static BigDecimal subtract(BigDecimal minuend, BigDecimal subtrahend) {
if (minuend == null) {
return null;
}
if (subtrahend == null) {
return minuend;
}
return minuend.subtract(subtrahend);
}
/**
* 加法: 如果两个参数都是null返回null,否则返回运算后的值
*/
public static BigDecimal add(BigDecimal a, BigDecimal b) {
if (a == null) {
return b;
}
if (b == null) {
return a;
}
return a.add(b);
}
/**
* 加法: 如果两个参数都是null返回null,否则返回运算后的值
*/
public static BigDecimal sumAdd(BigDecimal... arg) {
BigDecimal sum = BigDecimal.ZERO;
for (BigDecimal decimal : arg) {
sum = add(sum, decimal);
}
return sum;
}
/**
* 先截取两个小数,再累加
* 加法: 如果两个参数都是null返回null,否则返回运算后的值
*/
public static BigDecimal addSubFirst(BigDecimal a, BigDecimal b) {
if (a == null && b == null) {
return BigDecimal.ZERO;
}
if (b == null) {
return a.setScale(2, BigDecimal.ROUND_HALF_UP);
}
if (a == null) {
return b.setScale(2, BigDecimal.ROUND_HALF_UP);
}
return a.setScale(2, BigDecimal.ROUND_HALF_UP).add(b.setScale(2, BigDecimal.ROUND_HALF_UP));
}
/**
* 加法: 如果两个参数都是null返回null,否则返回运算后的值
*/
public static String addStr(String a, String b) {
if (StringUtils.trimToNull(a) == null) {
return StringUtils.trimToNull(b);
}
if (StringUtils.trimToNull(b) == null) {
return StringUtils.trimToNull(a);
}
return new BigDecimal(a).add(new BigDecimal(b)).toPlainString();
}
public static BigDecimal string2BigDecimal(String str, int scale) {
if (str == null || "".equals(str.trim())) {
return null;
}
return new BigDecimal(str).setScale(scale, BigDecimal.ROUND_HALF_UP);
}
public static BigDecimal string2BigDecimal(String str) {
if (str == null || "".equals(str.trim())) {
return BigDecimal.ZERO;
}
return new BigDecimal(str).setScale(2, BigDecimal.ROUND_HALF_UP);
}
public static BigDecimal string2PercentBigDecimal(String str, int scale) {
if (str == null || "".equals(str.trim())) {
return null;
}
return new BigDecimal(str).divide(new BigDecimal("100"), scale, BigDecimal.ROUND_HALF_UP);
}
public static String max(String buyLimitMin, String buyMinLimit) {
if (StringUtils.isBlank(buyLimitMin) && StringUtils.isBlank(buyMinLimit)) {
return BigDecimal.ZERO.toPlainString();
}
if (StringUtils.isBlank(buyLimitMin)) {
return buyMinLimit;
}
if (StringUtils.isBlank(buyMinLimit)) {
return buyLimitMin;
}
BigDecimal minLimit = new BigDecimal(buyLimitMin);
BigDecimal limitMin = new BigDecimal(buyMinLimit);
BigDecimal response = minLimit.compareTo(limitMin) >= 0 ? minLimit : limitMin;
return response.toPlainString();
}
public static BigDecimal max(BigDecimal b1, BigDecimal b2) {
if (b1 == null && b2 == null) {
return BigDecimal.ZERO;
}
if (b1 == null) {
return b2;
}
if (b2 == null) {
return b1;
}
BigDecimal response = b1.compareTo(b2) >= 0 ? b1 : b2;
return response;
}
public static String min(String buyLimitMin, String buyMinLimit) {
if (StringUtils.isBlank(buyLimitMin) && StringUtils.isBlank(buyMinLimit)) {
return BigDecimal.ZERO.toPlainString();
}
if (StringUtils.isBlank(buyLimitMin)) {
return buyMinLimit;
}
if (StringUtils.isBlank(buyMinLimit)) {
return buyLimitMin;
}
BigDecimal minLimit = new BigDecimal(buyLimitMin);
BigDecimal limitMin = new BigDecimal(buyMinLimit);
BigDecimal response = minLimit.compareTo(limitMin) >= 0 ? limitMin : minLimit;
return response.toPlainString();
}
public static BigDecimal formatBigDecimal(BigDecimal decimal, int scale) {
if (decimal == null) {
return BigDecimal.ZERO;
}
return decimal.setScale(scale, BigDecimal.ROUND_HALF_UP);
}
public static String min(BigDecimal source, BigDecimal target) {
if (source == null && target == null) {
return null;
}
if (source == null) {
return target.toPlainString();
}
if (target == null) {
return source.toPlainString();
}
BigDecimal response = source.compareTo(target) >= 0 ? target : source;
return response.toPlainString();
}
/**
* @return a / b ,结果保留4位小数
*/
public static BigDecimal divide(BigDecimal a, BigDecimal b) {
if (a == null || b == null) return null;
if (BigDecimal.ZERO.compareTo(b) == 0) return BigDecimal.ZERO;
return a.divide(b, 4, BigDecimal.ROUND_HALF_UP);
}
/**
* @param a
* @param b
* @param resultScale 指定结果的小数位数,必须大于0
* @return
*/
public static BigDecimal divide(BigDecimal a, BigDecimal b, int resultScale) {
if (a == null || b == null) return null;
if (BigDecimal.ZERO.compareTo(b) == 0) return BigDecimal.ZERO;
return a.divide(b, resultScale, BigDecimal.ROUND_HALF_UP);
}
/**
* @return 除后乘以100,结果保留2位小数
*/
public static BigDecimal divideThenMulti100(BigDecimal a, BigDecimal b) {
if (a == null || b == null) return null;
if (BigDecimal.ZERO.compareTo(b) == 0) return BigDecimal.ZERO;
return a.divide(b, 6, BigDecimal.ROUND_HALF_UP).multiply(ONE_HUNDRED).setScale(2, BigDecimal.ROUND_HALF_UP);
}
/**
* @return 乘以100,结果保留2位小数
*/
public static BigDecimal multi100(BigDecimal a) {
if (Objects.isNull(a)) return null;
return a.multiply(ONE_HUNDRED).setScale(2, BigDecimal.ROUND_HALF_UP);
}
public static String multi100(String a) {
if (StrUtil.isEmpty(a)) return null;
BigDecimal decimal = multi100(str2BigDecimal(a));
return bigDecimal2String(decimal, 2);
}
/**
* 值为null返回数值0
*/
public static BigDecimal null2zero(BigDecimal a) {
if (a == null) return BigDecimal.ZERO;
return a;
}
/**
* 值为null返回数值0
*/
public static BigDecimal null2NumberOne(BigDecimal a) {
if (a == null) return BigDecimal.ONE;
return a;
}
public static BigDecimal addThrowExceptionIfnull(BigDecimal a, BigDecimal b) {
if (a == null || b == null) {
throw new BizException(ErrorCodeEnum.PARAMETER_EMPTY);
}
return a.add(b);
}
public static BigDecimal addTreatAsZeroIfnull(BigDecimal a, BigDecimal b) {
if (a == null) {
return b;
}
if (b == null) {
return a;
}
return a.add(b);
}
/**
* 参数为null 或者 小于0
*
* @param a
* @return
*/
public static boolean lessThanZeroOrIsnull(BigDecimal a) {
if (a == null || BigDecimal.ZERO.compareTo(a) > 0) {
return true;
}
return false;
}
public static BigDecimal str2BigDecimal(String decimal) {
if (StringUtils.isEmpty(decimal)) {
return null;
}
if (decimal.contains(",")) {
decimal = decimal.replaceAll(",", "");
}
return new BigDecimal(decimal);
}
public static String docFormat(BigDecimal bigDecimal) {
if (Objects.isNull(bigDecimal)) {
return "0.00";
}
DecimalFormat decimal2 = new DecimalFormat("#,###,##0.00");
if (isNotNull(bigDecimal)) {
return decimal2.format(bigDecimal);
}
return "";
}
public static String docFormat2(BigDecimal bigDecimal) {
if (Objects.isNull(bigDecimal)) {
return "0.0000";
}
DecimalFormat decimal2 = new DecimalFormat("#,###,##0.0000");
if (isNotNull(bigDecimal)) {
return decimal2.format(bigDecimal);
}
return "";
}
/**
* 返回乘以100后的值,返回小数点后两位
* @param bigDecimal
* @return
*/
public static String multiply100(BigDecimal bigDecimal) {
return bigDecimal2String(BigDecimalUtil.multiply(bigDecimal, new BigDecimal("100")), 2);
}
/**
* 返回乘以1000后的值,返回小数点后两位
* @param bigDecimal
* @return
*/
public static String multiply1000(BigDecimal bigDecimal) {
return bigDecimal2String(BigDecimalUtil.multiply(bigDecimal, new BigDecimal("1000")), 2);
}
/**
* 返回乘以10000后的值,返回小数点后两位
* @param bigDecimal
* @return
*/
public static String multiply10000(BigDecimal bigDecimal) {
return bigDecimal2String(BigDecimalUtil.multiply(bigDecimal, new BigDecimal("10000")), 2);
}
/**
* 返回乘以10000后的值,返回小数点后两位
* @param bigDecimal
* @return
*/
public static String div10000(BigDecimal bigDecimal) {
return bigDecimal2String(BigDecimalUtil.divide(bigDecimal, new BigDecimal("10000")),0);
}
}