first commit

This commit is contained in:
jerryjzhang
2023-06-12 18:44:01 +08:00
commit dc4fc69b57
879 changed files with 573090 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
package com.tencent.supersonic.common.constant;
import java.util.regex.Pattern;
public class Constants {
public static final String COMMA = ",";
public static final String DOUBLE_SLASH = "//";
public static final String EMPTY = "";
public static final String AT_SYMBOL = "@";
public static final String DOT = ".";
public static String SPACE = " ";
public static final String COLON = ":";
public static final String MINUS = "-";
public static final String UNDERLINE = "_";
public static final String UNDERLINE_DOUBLE = "__";
public static final String PARENTHESES_START = "(";
public static final String PARENTHESES_END = ")";
public static final String APOSTROPHE = "'";
public static final String PERCENT_SIGN = "%";
public static String LIMIT_UPPER = "LIMIT";
public static String ORDER_UPPER = "ORDER";
public static String DESC_UPPER = "DESC";
public static String ASC_UPPER = "ASC";
public static String GROUP_UPPER = "GROUP";
public static String NULL_UPPER = "NULL";
public static String AND_UPPER = "AND";
public static String END_SUBQUERY = ") subq_";
public static String SYS_VAR = "sys_var";
public static final String NEW_LINE_CHAR = "\n";
public static final String UNIONALL = " union all ";
public static final String YAML_FILES_SUFFIX = ".yaml";
public static final String JDBC_PREFIX_FORMATTER = "jdbc:%s:";
public static final Pattern PATTERN_JDBC_TYPE = Pattern.compile("jdbc:\\w+");
public static final String STATISTIC = "statistic";
public static final String DORIS_LOWER = "doris";
public static final String MYSQL_LOWER = "mysql";
public static final String ADMIN_LOWER = "admin";
public static final String DAY = "DAY";
public static final String DAY_FORMAT = "yyyy-MM-dd";
public static final String DAY_FORMAT_INT = "YYYYMMDD";
public static final String MONTH = "MONTH";
public static final String WEEK = "WEEK";
public static final String YEAR = "YEAR";
public static final String JOIN_UNDERLINE = "__";
public static final String LIST_LOWER = "list";
public static final String TOTAL_LOWER = "total";
public static final String PAGESIZE_LOWER = "pageSize";
public static final String TRUE_LOWER = "true";
}

View File

@@ -0,0 +1,42 @@
package com.tencent.supersonic.common.enums;
public enum AggOperatorEnum {
MAX("MAX"),
MIN("MIN"),
AVG("AVG"),
SUM("SUM"),
DISTINCT("DISTINCT"),
TOPN("TOPN"),
PERCENTILE("PERCENTILE"),
UNKNOWN("UNKNOWN");
AggOperatorEnum(String operator) {
this.operator = operator;
}
private String operator;
public String getOperator() {
return operator;
}
public static AggOperatorEnum of(String agg) {
for (AggOperatorEnum aggOperatorEnum : AggOperatorEnum.values()) {
if (aggOperatorEnum.getOperator().equalsIgnoreCase(agg)) {
return aggOperatorEnum;
}
}
return AggOperatorEnum.UNKNOWN;
}
}

View File

@@ -0,0 +1,22 @@
package com.tencent.supersonic.common.enums;
public enum AggregateTypeEnum {
SUM,
AVG,
MAX,
MIN,
TOPN,
DISTINCT,
COUNT,
NONE;
public static AggregateTypeEnum of(String agg) {
for (AggregateTypeEnum aggEnum : AggregateTypeEnum.values()) {
if (aggEnum.name().equalsIgnoreCase(agg)) {
return aggEnum;
}
}
return AggregateTypeEnum.NONE;
}
}

View File

@@ -0,0 +1,17 @@
package com.tencent.supersonic.common.enums;
public enum ErrorCode {
MULTIPLE_ERRORS_PLACEHOLDER,
MULTIPLE_ERRORS,
NULL_POINTER,
ILLEGAL_ARGUMENT,
ILLEGAL_STATE,
NO_PERMISSION,
INDEX_OUT_OF_BOUND,
DUPLICATED_THEME,
UNKNOWN;
private ErrorCode() {
}
}

View File

@@ -0,0 +1,21 @@
package com.tencent.supersonic.common.enums;
public enum SensitiveLevelEnum {
LOW(0),
MID(1),
HIGH(2);
private Integer code;
SensitiveLevelEnum(Integer code) {
this.code = code;
}
public Integer getCode() {
return code;
}
}

View File

@@ -0,0 +1,33 @@
package com.tencent.supersonic.common.enums;
public enum SinkDbEnum {
TDW("TDW"),
DORIS("DORIS"),
ICEBERY("ICEBERY"),
NOT_SUPPORT("NOT_SUPPORT");
private String db;
SinkDbEnum(String db) {
this.db = db;
}
public String getDb() {
return db;
}
public static SinkDbEnum of(String name) {
for (SinkDbEnum item : SinkDbEnum.values()) {
if (item.db.equalsIgnoreCase(name)) {
return item;
}
}
return SinkDbEnum.NOT_SUPPORT;
}
}

View File

@@ -0,0 +1,45 @@
package com.tencent.supersonic.common.enums;
public enum StatusEnum {
INITIALIZED("INITIALIZED", 0),
ONLINE("ONLINE", 1),
OFFLINE("OFFLINE", 2),
DELETED("DELETED", 3),
UNKNOWN("UNKNOWN", -1);
private String status;
private Integer code;
StatusEnum(String status, Integer code) {
this.status = status;
this.code = code;
}
public String getStatus() {
return status;
}
public Integer getCode() {
return code;
}
public static StatusEnum of(String status) {
for (StatusEnum statusEnum : StatusEnum.values()) {
if (statusEnum.status.equalsIgnoreCase(status)) {
return statusEnum;
}
}
return StatusEnum.UNKNOWN;
}
public static StatusEnum of(Integer code) {
for (StatusEnum statusEnum : StatusEnum.values()) {
if (statusEnum.code.equals(code)) {
return statusEnum;
}
}
return StatusEnum.UNKNOWN;
}
}

View File

@@ -0,0 +1,47 @@
package com.tencent.supersonic.common.enums;
public enum TaskStatusEnum {
RUNNING("running", 0),
SUCCESS("success", 1),
ERROR("error", -1),
UNKNOWN("UNKNOWN", 2);
private String status;
private Integer code;
TaskStatusEnum(String status, Integer code) {
this.status = status;
this.code = code;
}
public String getStatus() {
return status;
}
public Integer getCode() {
return code;
}
public static TaskStatusEnum of(String status) {
for (TaskStatusEnum statusEnum : TaskStatusEnum.values()) {
if (statusEnum.status.equalsIgnoreCase(status)) {
return statusEnum;
}
}
return TaskStatusEnum.UNKNOWN;
}
public static TaskStatusEnum of(Integer code) {
for (TaskStatusEnum statusEnum : TaskStatusEnum.values()) {
if (statusEnum.code.equals(code)) {
return statusEnum;
}
}
return TaskStatusEnum.UNKNOWN;
}
}

View File

@@ -0,0 +1,32 @@
package com.tencent.supersonic.common.enums;
public enum TypeEnums {
DATASOURCE("datasource"),
METRIC("metric"),
DIMENSION("dimension"),
DOMAIN("domain"),
ENTITY("entity"),
UNKNOWN("unknown");
private String name;
TypeEnums(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static TypeEnums of(String type) {
for (TypeEnums typeEnum : TypeEnums.values()) {
if (typeEnum.name.equalsIgnoreCase(type)) {
return typeEnum;
}
}
return TypeEnums.UNKNOWN;
}
}

View File

@@ -0,0 +1,10 @@
package com.tencent.supersonic.common.exception;
public class AccessException extends RuntimeException {
private String message;
public AccessException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,12 @@
package com.tencent.supersonic.common.exception;
import lombok.AllArgsConstructor;
import lombok.Data;
@AllArgsConstructor
@Data
public class CommonException extends RuntimeException {
private Integer code;
private String message;
}

View File

@@ -0,0 +1,10 @@
package com.tencent.supersonic.common.exception;
public class InvalidArgumentException extends RuntimeException {
private String message;
public InvalidArgumentException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,10 @@
package com.tencent.supersonic.common.exception;
public class InvalidPermissionException extends RuntimeException {
private String message;
public InvalidPermissionException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,32 @@
package com.tencent.supersonic.common.nlp;
import java.io.Serializable;
import java.util.Objects;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Data
@Setter
@Getter
public class ItemDO implements Serializable {
private Integer domain;
private Integer itemId;
private String name;
private Long useCnt = 0L;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ItemDO itemDO = (ItemDO) o;
return Objects.equals(domain, itemDO.domain) && Objects.equals(itemId, itemDO.itemId)
&& Objects.equals(name, itemDO.name);
}
}

View File

@@ -0,0 +1,49 @@
package com.tencent.supersonic.common.nlp;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class MapResult implements Serializable {
private String name;
private List<String> natures;
private int offset = 0;
private double similarity;
public MapResult() {
}
public MapResult(String name, List<String> natures) {
this.name = name;
this.natures = natures;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MapResult that = (MapResult) o;
return Objects.equals(name, that.name) && Objects.equals(natures, that.natures);
}
@Override
public int hashCode() {
return Objects.hash(name, natures);
}
public void setOffset(int offset) {
this.offset = offset;
}
}

View File

@@ -0,0 +1,54 @@
package com.tencent.supersonic.common.nlp;
import org.apache.commons.lang3.StringUtils;
/***
* nature type
* such as : metric、dimension etc.
*/
public enum NatureType {
METRIC("metric"),
DIMENSION("dimension"),
VALUE("value"),
DOMAIN("dm"),
ENTITY("entity"),
NUMBER("m"),
SUFFIX("suffix");
private String type;
public static String NATURE_SPILT = "_";
public static String SPACE = " ";
NatureType(String type) {
this.type = type;
}
public String getType() {
return NATURE_SPILT + type;
}
public static NatureType getNatureType(String nature) {
if (StringUtils.isEmpty(nature) || !nature.startsWith(NATURE_SPILT)) {
return null;
}
for (NatureType natureType : values()) {
if (nature.endsWith(natureType.getType())) {
return natureType;
}
}
//domain
String[] natures = nature.split(NatureType.NATURE_SPILT);
if (natures.length == 2 && StringUtils.isNumeric(natures[1])) {
return DOMAIN;
}
//dimension value
if (natures.length == 3 && StringUtils.isNumeric(natures[1]) && StringUtils.isNumeric(natures[2])) {
return VALUE;
}
return null;
}
}

View File

@@ -0,0 +1,36 @@
package com.tencent.supersonic.common.nlp;
import java.util.Objects;
import lombok.Data;
import lombok.ToString;
/***
* word nature
*/
@Data
@ToString
public class WordNature {
private String word;
private String nature;
private String natureWithFrequency;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
WordNature that = (WordNature) o;
return Objects.equals(word, that.word) && Objects.equals(natureWithFrequency, that.natureWithFrequency);
}
@Override
public int hashCode() {
return Objects.hash(word, natureWithFrequency);
}
}

View File

@@ -0,0 +1,50 @@
package com.tencent.supersonic.common.pojo;
import com.tencent.supersonic.common.enums.AggOperatorEnum;
import java.util.List;
import javax.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class Aggregator {
@NotBlank(message = "Invalid aggregator column")
private String column;
private AggOperatorEnum func = AggOperatorEnum.SUM;
private String nameCh;
private List<String> args;
public Aggregator() {
}
public Aggregator(String column, AggOperatorEnum func) {
this.column = column;
this.func = func;
}
public Aggregator(String column, AggOperatorEnum func, List<String> args) {
this.column = column;
this.func = func;
this.args = args;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"column\":\"")
.append(column).append('\"');
sb.append(",\"func\":")
.append(func);
sb.append(",\"nameCh\":\"")
.append(nameCh).append('\"');
sb.append(",\"args\":")
.append(args);
sb.append('}');
return sb.toString();
}
}

View File

@@ -0,0 +1,29 @@
package com.tencent.supersonic.common.pojo;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ColumnOrder implements Serializable {
private String col;
private String order;
public static ColumnOrder buildAsc(String col) {
ColumnOrder columnOrder = new ColumnOrder();
columnOrder.setOrder("ASC");
columnOrder.setCol(col);
return columnOrder;
}
public static ColumnOrder buildDesc(String col) {
ColumnOrder columnOrder = new ColumnOrder();
columnOrder.setOrder("DESC");
columnOrder.setCol(col);
return columnOrder;
}
}

View File

@@ -0,0 +1,78 @@
package com.tencent.supersonic.common.pojo;
import static java.time.LocalDate.now;
import com.tencent.supersonic.common.constant.Constants;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
@Data
public class DateConf {
private static final long serialVersionUID = 3074129990945004340L;
private DateMode dateMode;
/**
* like 2021-10-22, dateMode=1
*/
private String startDate = now().plusDays(-1).toString();
private String endDate = now().toString();
/**
* [2021-10-22, 2022-01-22], dateMode=2
*/
private List<String> dateList = new ArrayList<>();
/**
* the last unit time unit,
* such as the last 7 days, unit = 7
*/
private Integer unit = 1;
/**
* DAY,WEEK,MONTH
*/
private String period = Constants.DAY;
/**
* the text parse from , example "last 7 days" , "last mouth"
*/
private String text;
public enum DateMode {
/**
* date mode
* 1 - between, continuous value,
* 2 - list discrete value,
* 3 - recent time units,
* 4 - advance time until data is available
*/
BETWEEN_CONTINUOUS, LIST_DISCRETE, RECENT_UNITS, AVAILABLE_TIME
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"dateMode\":")
.append(dateMode);
sb.append(",\"startDate\":\"")
.append(startDate).append('\"');
sb.append(",\"endDate\":\"")
.append(endDate).append('\"');
sb.append(",\"dateList\":")
.append(dateList);
sb.append(",\"unit\":")
.append(unit);
sb.append(",\"period\":\"")
.append(period).append('\"');
sb.append(",\"text\":\"")
.append(text).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@@ -0,0 +1,35 @@
package com.tencent.supersonic.common.pojo;
import static com.tencent.supersonic.common.constant.Constants.ASC_UPPER;
import javax.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class Order {
@NotBlank(message = "Invalid order column")
private String column;
private String direction = ASC_UPPER;
public Order(String column, String direction) {
this.column = column;
this.direction = direction;
}
public Order() {
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"column\":\"")
.append(column).append('\"');
sb.append(",\"direction\":\"")
.append(direction).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@@ -0,0 +1,27 @@
package com.tencent.supersonic.common.pojo;
import com.tencent.supersonic.common.enums.SensitiveLevelEnum;
import com.tencent.supersonic.common.enums.StatusEnum;
import com.tencent.supersonic.common.enums.TypeEnums;
import com.tencent.supersonic.common.util.RecordInfo;
import lombok.Data;
@Data
public class SchemaItem extends RecordInfo {
private Long id;
private String name;
private String bizName;
private String description;
private Integer status = StatusEnum.ONLINE.getCode();
private TypeEnums typeEnum;
private Integer sensitiveLevel = SensitiveLevelEnum.LOW.getCode();
}

View File

@@ -0,0 +1,23 @@
package com.tencent.supersonic.common.request;
import lombok.Data;
@Data
public class PageBaseReq {
private static final Integer MAX_PAGESIZE = 100;
private Integer current = 1;
private Integer pageSize = 10;
private String sort = "desc";
private String orderCondition;
public Integer getLimitStart() {
return this.pageSize * (this.current - 1);
}
public Integer getLimitSize() {
return this.pageSize;
}
}

View File

@@ -0,0 +1,35 @@
package com.tencent.supersonic.common.result;
import lombok.Data;
/***
* result data
*/
@Data
public class ResultData<T> {
private int code;
private String msg;
private T data;
private long timestamp;
public ResultData() {
this.timestamp = System.currentTimeMillis();
}
public static <T> ResultData<T> success(T data) {
ResultData<T> resultData = new ResultData<>();
resultData.setCode(ReturnCode.SUCCESS.getCode());
resultData.setMsg(ReturnCode.SUCCESS.getMessage());
resultData.setData(data);
return resultData;
}
public static <T> ResultData<T> fail(int code, String message) {
ResultData<T> resultData = new ResultData<>();
resultData.setCode(code);
resultData.setMsg(message);
return resultData;
}
}

View File

@@ -0,0 +1,25 @@
package com.tencent.supersonic.common.result;
public enum ReturnCode {
SUCCESS(200, "success"),
INVALID_PERMISSION(401, "invalid permission"),
ACCESS_ERROR(403, "access denied"),
SYSTEM_ERROR(500, "system error");
private final int code;
private final String message;
ReturnCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}

View File

@@ -0,0 +1,35 @@
package com.tencent.supersonic.common.util;
import java.util.Date;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class RecordInfo {
private String createdBy;
private String updatedBy;
private Date createdAt;
private Date updatedAt;
public RecordInfo createdBy(String userName) {
this.createdBy = userName;
this.createdAt = new Date();
this.updatedBy = userName;
this.updatedAt = new Date();
return this;
}
public RecordInfo updatedBy(String userName) {
this.updatedBy = userName;
this.updatedAt = new Date();
return this;
}
}

View File

@@ -0,0 +1,24 @@
package com.tencent.supersonic.common.util.cache;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Configuration
@Data
public class CacheCommonConfig {
@Value("${cache.common.app:supersonic}")
private String cacheCommonApp;
@Value("${cache.common.env:dev}")
private String cacheCommonEnv;
@Value("${cache.common.version:0}")
private Integer cacheCommonVersion;
@Value("${cache.common.expire.after.write:10}")
private Integer cacheCommonExpireAfterWrite;
}

View File

@@ -0,0 +1,14 @@
package com.tencent.supersonic.common.util.cache;
public interface CacheUtils {
Boolean put(String key, Object value);
Object get(String key);
String generateCacheKey(String prefix, String body);
Boolean removeCache(String key);
}

View File

@@ -0,0 +1,33 @@
package com.tencent.supersonic.common.util.cache;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CaffeineCacheConfig {
@Autowired
private CacheCommonConfig cacheCommonConfig;
@Value("${caffeine.initial.capacity:500}")
private Integer caffeineInitialCapacity;
@Value("${caffeine.max.size:5000}")
private Integer caffeineMaximumSize;
@Bean
public Cache<String, Object> caffeineCache() {
return Caffeine.newBuilder()
.expireAfterWrite(cacheCommonConfig.getCacheCommonExpireAfterWrite(), TimeUnit.MINUTES)
// 初始的缓存空间大小
.initialCapacity(caffeineInitialCapacity)
// 缓存的最大条数
.maximumSize(caffeineMaximumSize)
.build();
}
}

View File

@@ -0,0 +1,49 @@
package com.tencent.supersonic.common.util.cache;
import com.github.benmanes.caffeine.cache.Cache;
import com.google.common.base.Joiner;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class CaffeineCacheImpl implements CacheUtils {
@Autowired
private CacheCommonConfig cacheCommonConfig;
@Autowired
private Cache<String, Object> caffeineCache;
@Override
public Boolean put(String key, Object value) {
log.info("[put caffeineCache] key:{}, value:{}", key, value);
caffeineCache.put(key, value);
return true;
}
@Override
public Object get(String key) {
Object value = caffeineCache.asMap().get(key);
log.info("[get caffeineCache] key:{}, value:{}", key, value);
return value;
}
@Override
public String generateCacheKey(String prefix, String body) {
if (Strings.isEmpty(prefix)) {
prefix = "-1";
}
return Joiner.on(":").join(cacheCommonConfig.getCacheCommonApp(), cacheCommonConfig.getCacheCommonEnv(),
cacheCommonConfig.getCacheCommonVersion(), prefix, body);
}
@Override
public Boolean removeCache(String key) {
caffeineCache.asMap().remove(key);
return true;
}
}

View File

@@ -0,0 +1,71 @@
package com.tencent.supersonic.common.util.coder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
public class MD5Util {
public static final int BIT16 = 16;
public static final int BIT32 = 32;
public static final int BIT64 = 64;
public static final int BIT128 = 128;
public static final int BIT256 = 256;
/**
* MD5加密
*
* @param src 需要加密的字符串
* @param isUpper 大小写
* @param bit 加密长度16,32,64
* @return
*/
public static String getMD5(String src, boolean isUpper, Integer bit) {
String md5 = "";
try {
// 创建加密对象
MessageDigest md = MessageDigest.getInstance("md5");
if (bit == 64) {
Base64.Encoder encoder = Base64.getEncoder();
md5 = encoder.encodeToString(md.digest(src.getBytes(StandardCharsets.UTF_8)));
} else {
// 计算MD5函数
md.update(src.getBytes(StandardCharsets.UTF_8));
byte[] b = md.digest();
md5 = byteToString(b);
if (bit == 16) {
String md16 = md5.substring(8, 24);
md5 = md16;
if (isUpper) {
md5 = md5.toUpperCase();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (isUpper) {
md5 = md5.toUpperCase();
}
return md5;
}
public static String byteToString(byte[] bytes) {
int i;
StringBuffer buffer = new StringBuffer("");
for (int offset = 0; offset < bytes.length; offset++) {
i = bytes[offset];
if (i < 0) {
i += 256;
}
if (i < 16) {
buffer.append("0");
}
buffer.append(Integer.toHexString(i));
}
return buffer.toString();
}
}

View File

@@ -0,0 +1,88 @@
package com.tencent.supersonic.common.util.context;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class ContextUtils implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
/**
* 根据Bean名称获取Bean对象
*
* @param name Bean名称
* @return 对应名称的Bean对象
*/
public static Object getBean(String name) {
return context.getBean(name);
}
/**
* 根据Bean的类型获取对应的Bean
*
* @param requiredType Bean类型
* @return 对应类型的Bean对象
*/
public static <T> T getBean(Class<T> requiredType) {
return context.getBean(requiredType);
}
/**
* 根据Bean名称获取指定类型的Bean对象
*
* @param name Bean名称
* @param requiredType Bean类型可为空
* @return 获取对应Bean名称的指定类型Bean对象
*/
public static <T> T getBean(String name, Class<T> requiredType) {
return context.getBean(name, requiredType);
}
/**
* 判断是否包含对应名称的Bean对象
*
* @param name Bean名称
* @return 包含返回true否则返回false。
*/
public static boolean containsBean(String name) {
return context.containsBean(name);
}
/**
* 获取对应Bean名称的类型
*
* @param name Bean名称
* @return 返回对应的Bean类型
*/
public static Class<?> getType(String name) {
return context.getType(name);
}
/**
* 获取上下文对象可进行各种Spring的上下文操作
*
* @return Spring上下文对象
*/
public static ApplicationContext getContext() {
return context;
}
public static String getActiveProfile() {
String activeProfile = context.getEnvironment().getActiveProfiles()[0];
if (StringUtils.isEmpty(activeProfile)) {
activeProfile = "dev";
}
return activeProfile;
}
}

View File

@@ -0,0 +1,20 @@
package com.tencent.supersonic.common.util.context;
import com.alibaba.ttl.TransmittableThreadLocal;
public class S2ThreadContext {
private static final TransmittableThreadLocal<ThreadContext> context = new TransmittableThreadLocal<>();
public ThreadContext get() {
return context.get();
}
public void set(ThreadContext value) {
context.set(value);
}
public void remove() {
context.remove();
}
}

View File

@@ -0,0 +1,19 @@
package com.tencent.supersonic.common.util.context;
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
@Builder
@ToString
@Data
public class ThreadContext {
private String traceId;
private String userName;
private String token;
}

View File

@@ -0,0 +1,13 @@
package com.tencent.supersonic.common.util.context;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ThreadContextConfig {
@Bean
public S2ThreadContext s2ThreadContext() {
return new S2ThreadContext();
}
}

View File

@@ -0,0 +1,57 @@
package com.tencent.supersonic.common.util.http;
import java.io.Serializable;
public class HttpClientResult implements Serializable {
private static final long serialVersionUID = 2168152194164783950L;
/**
* 响应状态码
*/
private int code;
/**
* 响应数据
*/
private String content;
public HttpClientResult() {
}
public HttpClientResult(int code) {
this.code = code;
}
public HttpClientResult(String content) {
this.content = content;
}
public HttpClientResult(int code, String content) {
this.code = code;
this.content = content;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "HttpClientResult [code=" + code + ", content=" + content + "]";
}
}

View File

@@ -0,0 +1,692 @@
package com.tencent.supersonic.common.util.http;
import com.tencent.supersonic.common.util.retry.RetryUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.CharsetUtils;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
public class HttpClientUtils {
private static final Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
/***
* Encoding format. Unified sending encoding format using UTF-8
*/
private static final String ENCODING = "UTF-8";
/**
* Default number of connections per route
*/
private static final int DEFAULT_MAX_CONN_PERHOST = 100;
/**
* Maximum number of connections in the entire Connection pool
*/
private static final int DEFAULT_MAX_TOTAL_CONN = 200;
private static final int DEFAULT_CONNECTION_TIMEOUT = 15000;
private static final int DEFAULT_READ_TIMEOUT = 15000;
private static final int DEFAULT_CONN_REQUEST_TIMEOUT = 10000;
// httpClient singleton
private static CloseableHttpClient httpClient = null;
static {
init();
}
private static void init() {
try {
SSLConnectionSocketFactory sslConnectionSocketFactory =
new SSLConnectionSocketFactory(
SSLContexts.custom().loadTrustMaterial((chain, authType) -> true).build(),
new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"},
null,
NoopHostnameVerifier.INSTANCE);
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslConnectionSocketFactory).build()
);
connManager.setMaxTotal(DEFAULT_MAX_TOTAL_CONN);
connManager.setDefaultMaxPerRoute(DEFAULT_MAX_CONN_PERHOST);
RequestConfig requestConfig = RequestConfig.custom()
// 请求超时时间
.setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT)
// 等待数据超时时间
.setSocketTimeout(DEFAULT_READ_TIMEOUT)
// 连接不够用时等待超时时间
.setConnectionRequestTimeout(DEFAULT_CONN_REQUEST_TIMEOUT)
.build();
HttpRequestRetryHandler httpRequestRetryHandler = (exception, executionCount, context) -> {
// 如果已经重试了3次就放弃
if (executionCount > 3) {
logger.warn("Maximum tries reached, exception would be thrown to outer block");
return false;
}
if (exception instanceof NoHttpResponseException) {
// 如果服务器丢掉了连接,那么就重试
logger.warn("Retry, No response from server on {} error: {}", executionCount,
exception.getMessage());
return true;
} else if (exception instanceof SocketException) {
// 如果服务器断开了连接,那么就重试
logger.warn("Retry, No connection from server on {} error: {}", executionCount,
exception.getMessage());
return true;
}
return false;
};
httpClient = HttpClients.custom()
// 设置连接池
.setConnectionManager(connManager)
// 设置超时时间
.setDefaultRequestConfig(requestConfig)
// 设置连接存活时间
.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy() {
@Override
public long getKeepAliveDuration(final HttpResponse response, final HttpContext context) {
long keepAlive = super.getKeepAliveDuration(response, context);
if (keepAlive == -1) {
keepAlive = 5000;
}
return keepAlive;
}
})
.setRetryHandler(httpRequestRetryHandler)
// 设置连接存活时间
.setConnectionTimeToLive(5000L, TimeUnit.MILLISECONDS)
// 关闭无效和空闲的连接
.evictIdleConnections(5L, TimeUnit.SECONDS)
.build();
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
/**
* Send a post request; Without request header and request parameters
*
* @param url
* @return
* @throws Exception
*/
public static HttpClientResult doPost(String url) {
return doPost(url, null, null, null, null);
}
/**
* Send a post request; With request parameters
*
* @param url
* @param params
* @return
* @throws Exception
*/
public static HttpClientResult doPost(String url, Map<String, String> params) {
return doPost(url, null, null, null, params);
}
/**
* post
*
* @return
*/
public static HttpClientResult doPost(String url,
String proxyHost,
Integer proxyPort,
Map<String, String> headers,
Map<String, String> params) {
return RetryUtils.exec(() -> {
HttpPost httpPost = null;
CloseableHttpResponse response = null;
try {
httpPost = new HttpPost(url);
setProxy(httpPost, proxyHost, proxyPort);
// 封装header参数
packageHeader(headers, httpPost);
// 封装请求参数
packageParam(params, httpPost);
response = httpClient.execute(httpPost);
// 获取返回结果
HttpClientResult result = getHttpClientResult(response);
logger.info("uri:{}, req:{}, resp:{}", url,
"headers:" + getHeaders(httpPost) + "------params:" + params, result);
return result;
} catch (Exception e) {
logger.error("uri:{}, req:{}", url, "headers:" + headers + "------params:" + params, e);
throw new RuntimeException(e.getMessage());
} finally {
close(httpPost, response);
}
});
}
/**
* for us scheduling
*
* @param url
* @param header
* @param params
* @return
*/
public static HttpClientResult doPost(String url, Map<String, String> header, Map<String, String> params) {
return doPost(url, null, null, header, params);
}
/**
* Send a get request; Without request header and request parameters
*
* @param url
* @return
* @throws Exception
*/
public static HttpClientResult doGet(String url) {
return doGet(url, null, null, null, null);
}
/**
* Send a get request; With request parameters
*
* @param url
* @param params
* @return
* @throws Exception
*/
public static HttpClientResult doGet(String url, Map<String, String> params) {
return doGet(url, null, null, null, params);
}
/**
* Send a get request; With request header and request parameters
*
* @param url
* @param headers
* @param params
* @return
* @throws Exception
*/
public static HttpClientResult doGet(String url, String proxyHost, Integer proxyPort, Map<String, String> headers,
Map<String, String> params) {
return RetryUtils.exec(() -> {
HttpGet httpGet = null;
CloseableHttpResponse response = null;
try {
// 创建访问的地址
URIBuilder uriBuilder = new URIBuilder(url);
if (params != null) {
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
uriBuilder.setParameter(entry.getKey(), entry.getValue());
}
}
httpGet = new HttpGet(uriBuilder.build());
setProxy(httpGet, proxyHost, proxyPort);
// 设置请求头
packageHeader(headers, httpGet);
response = httpClient.execute(httpGet);
// 获取返回结果
HttpClientResult res = getHttpClientResult(response);
logger.debug("GET uri:{}, req:{}, resp:{}", url,
"headers:" + getHeaders(httpGet) + "------params:" + params, res);
return res;
} catch (Exception e) {
logger.error("GET error! uri:{}, req:{}", url, "headers:" + headers + "------params:" + params, e);
throw new RuntimeException(e.getMessage());
} finally {
close(httpGet, response);
}
});
}
/**
* for us scheduling
*
* @param url
* @param header
* @param params
* @return
*/
public static HttpClientResult doGet(String url, Map<String, String> header, Map<String, String> params) {
return doGet(url, null, null, header, params);
}
/**
*
*/
public static void close(HttpRequestBase httpRequest, CloseableHttpResponse response) {
if (response != null) {
try {
EntityUtils.consume(response.getEntity());
} catch (Throwable ex) {
logger.error("entity close error : ", ex);
}
try {
response.close();
} catch (Throwable ex) {
logger.error("response close error : ", ex);
}
}
if (httpRequest != null) {
try {
httpRequest.abort();
} catch (Throwable ex) {
logger.error("httpPost abort error : ", ex);
}
}
}
/**
* @param headers
* @param httpMethod
*/
public static void packageHeader(Map<String, String> headers, HttpRequestBase httpMethod) {
if (headers != null) {
Set<Map.Entry<String, String>> entrySet = headers.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
httpMethod.setHeader(entry.getKey(), entry.getValue());
}
}
}
public static String getHeaders(HttpRequestBase request) {
if (request == null) {
return "";
}
StringBuilder headsString = new StringBuilder("");
Header[] heads = request.getAllHeaders();
if (heads != null) {
for (int i = 0; i < heads.length; i++) {
headsString.append(heads[i]).append(" , ");
}
}
return headsString.toString();
}
/**
* Description: pack params
*
* @param params
* @param httpMethod
* @throws UnsupportedEncodingException
*/
public static void packageParam(Map<String, String> params, HttpEntityEnclosingRequestBase httpMethod)
throws UnsupportedEncodingException {
if (params != null) {
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
// 设置到请求的http对象中
httpMethod.setEntity(new UrlEncodedFormEntity(nvps, ENCODING));
}
}
public static void setProxy(HttpRequestBase httpMethod, String proxyHost, Integer proxyPort) {
if (!StringUtils.isEmpty(proxyHost) && proxyPort != null) {
RequestConfig config = RequestConfig.custom()
.setProxy(new HttpHost(proxyHost, proxyPort))
.setConnectTimeout(10000)
.setSocketTimeout(10000)
.setConnectionRequestTimeout(3000)
.build();
httpMethod.setConfig(config);
}
}
/**
* is respond successfully --200
*/
public static boolean isOK(HttpClientResult res) {
return res != null && res.getCode() == HttpStatus.SC_OK;
}
/**
* post json
*
* @return
*/
public static HttpClientResult doPostJSON(String url, String proxyHost, Integer proxyPort,
Map<String, String> headers, String req) {
return RetryUtils.exec(() -> {
HttpPost httpPost = null;
CloseableHttpResponse response = null;
try {
httpPost = new HttpPost(url);
setProxy(httpPost, proxyHost, proxyPort);
// 封装header参数
packageHeader(headers, httpPost);
httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
// 封装请求参数
StringEntity stringEntity = new StringEntity(req, ENCODING); // 解决中文乱码问题
stringEntity.setContentEncoding("UTF-8");
httpPost.setEntity(stringEntity);
response = httpClient.execute(httpPost);
// 获取返回结果
HttpClientResult res = getHttpClientResult(response);
logger.info("doPostJSON uri:{}, req:{}, resp:{}", url,
"headers:" + getHeaders(httpPost) + "------req:" + req, res);
return res;
} catch (Exception e) {
logger.error("doPostJSON error! uri:{}, req:{}", url, "headers:" + headers + "------req:" + req, e);
throw new RuntimeException(e.getMessage());
} finally {
close(httpPost, response);
}
});
}
public static HttpClientResult doPostJSON(String url, String req) {
return doPostJSON(url, null, null, null, req);
}
/**
* get json
*/
public static HttpClientResult doGetJSON(String url, String proxyHost, Integer proxyPort,
Map<String, String> headers, Map<String, String> params) {
return RetryUtils.exec(() -> {
HttpGet httpGet = null;
CloseableHttpResponse response = null;
try {
// 创建访问的地址
URIBuilder uriBuilder = new URIBuilder(url);
if (params != null) {
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
uriBuilder.setParameter(entry.getKey(), entry.getValue());
}
}
httpGet = new HttpGet(uriBuilder.build());
setProxy(httpGet, proxyHost, proxyPort);
// 设置请求头
packageHeader(headers, httpGet);
httpGet.setHeader("Content-Type", "application/json;charset=UTF-8");
response = httpClient.execute(httpGet);
// 获取返回结果
HttpClientResult res = getHttpClientResult(response);
logger.info("doGetJSON uri:{}, req:{}, resp:{}", url,
"headers:" + getHeaders(httpGet) + "------params:" + params, res);
return res;
} catch (Exception e) {
logger.warn("doGetJSON error! uri:{}, req:{}", url, "headers:" + headers + "------params:" + params, e);
throw new RuntimeException(e.getMessage());
} finally {
close(httpGet, response);
}
});
}
private static HttpClientResult getHttpClientResult(CloseableHttpResponse response) throws IOException {
HttpEntity entity;
HttpClientResult res = new HttpClientResult(HttpStatus.SC_INTERNAL_SERVER_ERROR);
if (response != null && response.getStatusLine() != null) {
String content = "";
entity = response.getEntity();
if (entity != null) {
content = EntityUtils.toString(entity, ENCODING);
}
res = new HttpClientResult(response.getStatusLine().getStatusCode(), content);
}
return res;
}
/**
* for us scheduling
*
* @param url
* @param headers
* @param bodyParams
* @param fullFilePath
* @return
*/
public static HttpClientResult doFileUploadBodyParams(String url, Map<String, String> headers,
Map<String, String> bodyParams,
String fullFilePath) {
return doFileUpload(url, null, null, headers, null, bodyParams, fullFilePath);
}
public static HttpClientResult doFileUpload(String url,
String proxyHost,
Integer proxyPort,
Map<String, String> headers,
Map<String, String> params,
Map<String, String> bodyParams,
String fullFilePath) {
return RetryUtils.exec(() -> {
InputStream inputStream = null;
CloseableHttpResponse response = null;
HttpPost httpPost = null;
try {
// File uploadFile = ResourceUtils.getFile("classpath:" + fullFilePath);
File uploadFile = new File(fullFilePath);
inputStream = new FileInputStream(uploadFile);
httpPost = new HttpPost(url);
setProxy(httpPost, proxyHost, proxyPort);
packageHeader(headers, httpPost);
HttpEntity entity = getFileUploadHttpEntity(params, bodyParams, inputStream, uploadFile.getName());
httpPost.setEntity(entity);
response = httpClient.execute(httpPost);
// 执行请求并获得响应结果
HttpClientResult res = getHttpClientResult(response);
logger.info("doFileUpload uri:{}, req:{}, resp:{}", url,
"params:" + params + ", fullFilePath:" + fullFilePath, res);
return res;
} catch (Exception e) {
logger.error("doFileUpload error! uri:{}, req:{}", url,
"params:" + params + ", fullFilePath:" + fullFilePath, e);
throw new RuntimeException(e.getMessage());
} finally {
try {
if (null != inputStream) {
inputStream.close();
}
// 释放资源
close(httpPost, response);
} catch (IOException e) {
logger.error("HttpClientUtils release error!", e);
}
}
});
}
private static HttpEntity getFileUploadHttpEntity(Map<String, String> params,
Map<String, String> bodyParams,
InputStream inputStream,
String fileName) throws UnsupportedEncodingException {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("file", inputStream, ContentType.create("multipart/form-data"), fileName);
if (!CollectionUtils.isEmpty(bodyParams)) {
for (String bodyParamsKey : bodyParams.keySet()) {
builder.addTextBody(bodyParamsKey, bodyParams.get(bodyParamsKey));
}
}
//构建请求参数 普通表单项
if (!CollectionUtils.isEmpty(params)) {
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.addPart(entry.getKey(), new StringBody(entry.getValue(), ContentType.MULTIPART_FORM_DATA));
}
}
builder.setCharset(CharsetUtils.get(ENCODING));
return builder.build();
}
/**
* for us scheduling send delete
*
* @param url
* @param headers
* @param req
* @return
*/
public static HttpClientResult doDelete(String url, Map<String, String> headers, String req) {
return RetryUtils.exec(() -> {
HttpDeleteWithBody httpDelete = null;
CloseableHttpResponse response = null;
try {
httpDelete = new HttpDeleteWithBody(url);
// 封装header参数
packageHeader(headers, httpDelete);
httpDelete.setHeader("Content-Type", "application/json;charset=UTF-8");
// 封装请求参数
StringEntity stringEntity = new StringEntity(req, ENCODING); // 解决中文乱码问题
stringEntity.setContentEncoding("UTF-8");
httpDelete.setEntity(stringEntity);
response = httpClient.execute(httpDelete);
HttpClientResult res = getHttpClientResult(response);
logger.info("doDeleteJSON uri:{}, req:{}, resp:{}", url,
"headers:" + getHeaders(httpDelete) + "------req:" + req, res);
return res;
} catch (Exception e) {
logger.error("doDeleteJSON error! uri:{}, req:{}", url, "headers:" + headers + "------req:" + req, e);
throw new RuntimeException(e.getMessage());
} finally {
close(httpDelete, response);
}
});
}
private static class HttpDeleteWithBody extends HttpEntityEnclosingRequestBase {
public static final String METHOD_NAME = "DELETE";
@Override
public String getMethod() {
return METHOD_NAME;
}
public HttpDeleteWithBody(final String uri) {
super();
setURI(URI.create(uri));
}
public HttpDeleteWithBody(final URI uri) {
super();
setURI(uri);
}
public HttpDeleteWithBody() {
super();
}
}
public static HttpClientResult doPutJson(String url, Map<String, String> headers, String req) {
return RetryUtils.exec(() -> {
HttpPut httpPut = null;
CloseableHttpResponse response = null;
try {
httpPut = new HttpPut(url);
// 封装header参数
packageHeader(headers, httpPut);
httpPut.setHeader("Content-Type", "application/json;charset=UTF-8");
// 封装请求参数
StringEntity stringEntity = new StringEntity(req, ENCODING); // 解决中文乱码问题
stringEntity.setContentEncoding("UTF-8");
httpPut.setEntity(stringEntity);
response = httpClient.execute(httpPut);
HttpClientResult res = getHttpClientResult(response);
logger.info("doPutJSON uri:{}, req:{}, resp:{}", url,
"headers:" + getHeaders(httpPut) + "------req:" + req, res);
return res;
} catch (Exception e) {
logger.error("doPutJSON error! uri:{}, req:{}", url, "headers:" + headers + "------req:" + req, e);
throw new RuntimeException(e.getMessage());
} finally {
close(httpPut, response);
}
});
}
}

View File

@@ -0,0 +1,626 @@
package com.tencent.supersonic.common.util.json;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@Slf4j
public class JsonUtil {
public static final JsonUtil INSTANCE = new JsonUtil();
@Setter
@Getter
private final ObjectMapper objectMapper = new ObjectMapper();
public JsonUtil() {
// 当属性为null时不参与序列化
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//允许使用未带引号的字段名
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
//允许使用单引号
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 遇到空对象不抛异常
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// 遇到未知属性时不会抛一个JsonMappingException
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 允许JSON整数以多个0开始
objectMapper.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
// Java8日期时间类支持
objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
}
/**
* jsonNode转object
*
* @param jsonNode jsonNode
* @param clazz 被转对象的class
* @param <T> 通配符
* @return string
*/
public static <T> T toObject(JsonNode jsonNode, Class<T> clazz) {
return INSTANCE.asObject(jsonNode, clazz);
}
/**
* json转object
*
* @param json json字符串
* @param clazz 被转对象的类型
* @param <T> 通配符
* @return string
*/
public static <T> T toObject(String json, Class<T> clazz) {
return INSTANCE.asObject(json, clazz);
}
/**
* json转object
*
* @param json json字符串
* @param wrapperClass 包装类对象类型
* @param typeClass 类型类对象类型
* @param <W> 包装类通配符
* @param <T> 类型类通配符
* @return string
*/
public static <T, W> W toObject(String json, Class<W> wrapperClass, Class<T> typeClass) {
return INSTANCE.asObject(json, wrapperClass, typeClass);
}
/**
* 通过typeReference和json转对象
*
* @param json json串
* @param typeReference 类型
* @param <T> 通配符
* @return 对象
*/
public static <T> T toObject(String json, TypeReference<T> typeReference) {
return INSTANCE.asObject(json, typeReference);
}
/**
* bytes转对象
*
* @param json json二进制数组
* @param clazz 被转对象的类型
* @param <T> 通配符
* @return string
*/
public static <T> T toObject(byte[] json, Class<T> clazz) {
return INSTANCE.asObject(json, clazz);
}
/**
* json转list
*
* @param json json字符串
* @param clazz 被转对象的类
* @param <T> 被转对象的类型
* @return 列表
*/
public static <T> List<T> toList(String json, Class<T> clazz) {
return INSTANCE.asList(json, clazz);
}
/**
* json转set
*
* @param json json字符串
* @param clazz 被转对象的类型
* @param <T> 通配符
* @return string
*/
public static <T> Set<T> toSet(String json, Class<T> clazz) {
return INSTANCE.asSet(json, clazz);
}
/**
* json转map
*
* @param json json字符串
* @param keyClass key类型
* @param valueClass value类型
* @param <K> 键类型
* @param <V> 值类型
* @return map
*/
public static <K, V> Map<K, V> toMap(String json, Class<K> keyClass, Class<V> valueClass) {
return INSTANCE.asMap(json, keyClass, valueClass);
}
public static Map<String, Object> objectToMap(Object obj) {
return INSTANCE.asobjectToMap(obj);
}
public static Map<String, String> objectToMapString(Object obj) {
return INSTANCE.asObjectToMapString(obj);
}
public static <V> List<Map<String, V>> jsonToListMap(String json, Class<V> clazz) {
return INSTANCE.asjsonToListMap(json, clazz);
}
public static <T> T mapToObject(Map<?, ?> map, Class<T> clazz) {
return INSTANCE.asmapToObject(map, clazz);
}
/**
* 对象转json
*
* @param object 被转换的对象
* @return 对象的json字符串
*/
public static String toString(Object object) {
return INSTANCE.asString(object);
}
public static String toString(Object object, boolean pretty) {
return INSTANCE.asString(object, pretty);
}
/**
* 对象转带缩进的json
*
* @param object 被转换的对象
* @return 对象的json字符串
*/
public static String prettyToString(Object object) {
return INSTANCE.prettyAsString(object);
}
/**
* json转jsonNode
*
* @param json json字符串
* @return jsonnode
*/
public static JsonNode readTree(String json) {
return INSTANCE.asTree(json);
}
/**
* clone一个新的对象
*
* @param object 被克隆对象
* @param clazz 目标类型
* @param <T> 类型参数
* @return 新的对象
*/
public static <T> T clone(T object, Class<T> clazz) {
return INSTANCE.asClone(object, clazz);
}
/**
* 对象转objectNode
*
* @param object 对象
* @return objectNode
*/
public static ObjectNode getNode(Object object) {
return INSTANCE.asNode(object);
}
/**
* 判断字符串格式是否合法
*
* @param json
* @return
*/
public static boolean isJson(String json) {
return INSTANCE.isJsonValid(json);
}
/**
* jsonNode转object
*
* @param jsonNode jsonNode
* @param clazz 被转对象的class
* @param <T> 通配符
* @return string
*/
public <T> T asObject(JsonNode jsonNode, Class<T> clazz) {
if (jsonNode == null) {
return null;
}
try {
notNull(clazz, "class is null");
return objectMapper.treeToValue(jsonNode, clazz);
} catch (Exception e) {
throw new JsonException(e);
}
}
/**
* json转object
*
* @param json json字符串
* @param clazz 被转对象的类型
* @param <T> 通配符
* @return string
*/
public <T> T asObject(String json, Class<T> clazz) {
try {
if (StringUtils.isBlank(json)) {
return null;
}
notNull(clazz, "class is null");
if (clazz == String.class) {
return (T) json;
}
return objectMapper.readValue(json, clazz);
} catch (Exception e) {
throw new JsonException(e);
}
}
/**
* json转object
*
* @param json json字符串
* @param wrapperClass 包装类对象类型
* @param typeClass 类型类对象类型
* @param <W> 包装类通配符
* @param <T> 类型类通配符
* @return string
*/
public <T, W> W asObject(String json, Class<W> wrapperClass, Class<T> typeClass) {
if (StringUtils.isBlank(json)) {
return null;
}
try {
notNull(wrapperClass, "wrapperClass is null");
notNull(typeClass, "typeClass is null");
JavaType type = objectMapper.getTypeFactory().constructParametricType(wrapperClass, typeClass);
return objectMapper.readValue(json, type);
} catch (Exception e) {
throw new JsonException(e);
}
}
/**
* 通过typeReference和json转对象
*
* @param json json串
* @param typeReference 类型
* @param <T> 通配符
* @return 对象
*/
public <T> T asObject(String json, TypeReference<T> typeReference) {
if (StringUtils.isBlank(json)) {
return null;
}
try {
notNull(typeReference, "typeReference is null");
return objectMapper.readValue(json, typeReference);
} catch (Exception e) {
throw new JsonException(e);
}
}
/**
* bytes转对象
*
* @param bytes json二进制数组
* @param clazz 被转对象的类型
* @param <T> 通配符
* @return string
*/
public <T> T asObject(byte[] bytes, Class<T> clazz) {
if (bytes == null || bytes.length <= 0) {
return null;
}
return asObject(new String(bytes, Charset.forName("utf-8")), clazz);
}
/**
* json转list
*
* @param json json字符串
* @param clazz 被转对象的类
* @param <T> 被转对象的类型
* @return 列表
*/
public <T> List<T> asList(String json, Class<T> clazz) {
if (StringUtils.isBlank(json)) {
return new ArrayList<>();
}
try {
notNull(clazz, "class is null");
JavaType type = objectMapper.getTypeFactory().constructCollectionType(List.class, clazz);
return objectMapper.readValue(json, type);
} catch (Exception e) {
throw new JsonException(e);
}
}
/**
* json转set
*
* @param json json字符串
* @param clazz 被转对象的类型
* @param <T> 通配符
* @return string
*/
public <T> Set<T> asSet(String json, Class<T> clazz) {
if (StringUtils.isBlank(json)) {
return null;
}
try {
notNull(clazz, "class is null");
JavaType type = objectMapper.getTypeFactory().constructCollectionType(Set.class, clazz);
return objectMapper.readValue(json, type);
} catch (Exception e) {
throw new JsonException(e);
}
}
/**
* json转map
*
* @param json json字符串
* @param keyClass key类型
* @param valueClass value类型
* @param <K> 键类型
* @param <V> 值类型
* @return map
*/
public <K, V> Map<K, V> asMap(String json, Class<K> keyClass, Class<V> valueClass) {
if (StringUtils.isBlank(json)) {
return null;
}
try {
notNull(keyClass, "key class is null");
notNull(valueClass, "value class is null");
JavaType type =
objectMapper.getTypeFactory().constructParametricType(Map.class, keyClass, valueClass);
return objectMapper.readValue(json, type);
} catch (Exception e) {
throw new JsonException(e);
}
}
/**
* 对象转换成Map
*/
public Map<String, Object> asobjectToMap(Object obj) {
if (obj == null) {
return null;
}
return objectMapper.convertValue(obj, new TypeReference<Map<String, Object>>() {
});
}
/**
* 对象转换成Map
*/
public Map<String, String> asObjectToMapString(Object obj) {
if (obj == null) {
return null;
}
return objectMapper.convertValue(obj, new TypeReference<Map<String, String>>() {
});
}
/**
* map转换成bean对象
*
* @param map map对象
* @param clazz bean对象类型
* @param <T> 泛型
* @return bean对象
*/
public <T> T asmapToObject(Map<?, ?> map, Class<T> clazz) {
if (map == null) {
return null;
}
return objectMapper.convertValue(map, clazz);
}
/**
* Json转换成ListMap
*
* @param json 序列化字符串
* @param <V> map value泛型
* @return 反序列化对象
*/
public <V> List<Map<String, V>> asjsonToListMap(String json, Class<V> clazz) {
try {
final TypeFactory typeFactory = getObjectMapper().getTypeFactory();
final MapType mapType = typeFactory.constructMapType(Map.class, String.class, clazz);
final CollectionType collectionType = typeFactory.constructCollectionType(List.class, mapType);
return getObjectMapper().readValue(json, collectionType);
} catch (Exception e) {
log.error("json:{} to listMap error:", json, e);
return null;
}
}
/**
* 对象转json
*
* @param object 被转换的对象
* @return 对象的json字符串
*/
public String asString(Object object) {
if (object == null) {
return "";
}
if (object instanceof String) {
return (String) object;
}
try {
return objectMapper.writeValueAsString(object);
} catch (Exception e) {
throw new JsonException(e);
}
}
public String asString(Object object, boolean pretty) {
return pretty ? prettyAsString(object) : asString(object);
}
/**
* 对象转带缩进的json
*
* @param object 被转换的对象
* @return 对象的json字符串
*/
public String prettyAsString(Object object) {
if (object == null) {
return "";
}
try {
if (object instanceof String) {
String string = (String) object;
if (!string.startsWith("{") || !string.endsWith("}")) {
return string;
}
try {
JsonNode jsonNode = readTree(string);
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
} catch (Exception e) {
return string;
}
}
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
} catch (Exception e) {
throw new JsonException(e);
}
}
/**
* json转jsonNode
*
* @param json json字符串
* @return jsonnode
*/
public JsonNode asTree(String json) {
if (StringUtils.isBlank(json)) {
return null;
}
try {
return objectMapper.readTree(json);
} catch (Exception e) {
throw new JsonException(e);
}
}
/**
* clone一个新的对象
*
* @param object 被克隆对象
* @param clazz 目标类型
* @param <T> 类型参数
* @return 新的对象
*/
public <T> T asClone(T object, Class<T> clazz) {
if (object == null) {
return null;
}
try {
notNull(clazz, "class is null");
String json = toString(object);
return toObject(json, clazz);
} catch (Exception e) {
throw new JsonException(e);
}
}
/***
* 判断字符串是否合格的json格式
*
* @param json
* @return
*/
public boolean isJsonValid(String json) {
if (StringUtils.isBlank(json)) {
return false;
}
try {
objectMapper.readTree(json);
return true;
} catch (IOException e) {
return false;
}
}
/**
* 对象转objectNode
*
* @param object 对象
* @return objectNode
*/
public ObjectNode asNode(Object object) {
if (object == null) {
return null;
}
return objectMapper.convertValue(object, ObjectNode.class);
}
/**
* 判断某个参数是否为空
*
* @param object 参数
* @param description 参数描述
*/
public static void notNull(Object object, String description) {
if (object == null) {
description = StringUtils.isBlank(description) ? "参数" : description;
throw new InvalidParameterException(description + "为空");
}
}
/**
* json序列化,或者反序列化发生的异常
*/
public static class JsonException extends RuntimeException {
private static final long serialVersionUID = 1L;
private JsonException() {
}
private JsonException(String message) {
super(message);
}
private JsonException(String message, Throwable cause) {
super(message, cause);
}
private JsonException(Throwable cause) {
super(cause);
}
private JsonException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
}

View File

@@ -0,0 +1,33 @@
package com.tencent.supersonic.common.util.mapper;
import java.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
public class BeanMapper<T> {
public static void mapper(Object object1, Object object2) {
BeanUtils.copyProperties(object1, object2, getNullPropertyNames(object1));
}
public static String[] getNullPropertyNames(Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
PropertyDescriptor[] pds = src.getPropertyDescriptors();
Set emptyNames = new HashSet();
for (java.beans.PropertyDescriptor pd : pds) {
//check if value of this property is null then add it to the collection
Object srcValue = src.getPropertyValue(pd.getName());
if (srcValue == null) {
emptyNames.add(pd.getName());
}
}
String[] result = new String[emptyNames.size()];
return (String[]) emptyNames.toArray(result);
}
}

View File

@@ -0,0 +1,16 @@
package com.tencent.supersonic.common.util.mybatis;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
public class PageUtils {
/**
* convert PageInfo Po to Vo
*/
public static <P, V> PageInfo<V> pageInfo2PageInfoVo(PageInfo<P> pageInfoPo) {
Page<V> page = new Page<>(pageInfoPo.getPageNum(), pageInfoPo.getPageSize());
page.setTotal(pageInfoPo.getTotal());
return new PageInfo<>(page);
}
}

View File

@@ -0,0 +1,42 @@
package com.tencent.supersonic.common.util.retry;
import java.util.function.Supplier;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class RetryUtils {
private static final int RETRY_NUM = 3;
public static <T> T exec(Supplier<T> supplier) {
return exec(supplier, RETRY_NUM);
}
public static <T> T exec(Supplier<T> supplier, int retryNum) {
T result = null;
for (int index = 1; index <= retryNum; index++) {
try {
result = supplier.get();
} catch (Exception ex) {
if (index < retryNum) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
log.error("e", e);
}
log.warn("Retry exec {}, {}", index, ex.getMessage());
continue;
}
log.warn("Retry {} times all fail, err: {}", retryNum, ex.getMessage());
throw ex;
}
break;
}
return result;
}
}

View File

@@ -0,0 +1,86 @@
package com.tencent.supersonic.common.util.yaml;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
public class YamlUtils {
/**
* 将yaml字符串转成类对象
*
* @param yamlStr 字符串
* @param clazz 目标类
* @param <T> 泛型
* @return 目标类
*/
public static <T> T toObject(String yamlStr, Class<T> clazz) {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
mapper.findAndRegisterModules();
try {
return mapper.readValue(yamlStr, clazz);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 将类对象转yaml字符串
*
* @param object 对象
* @return yaml字符串
*/
public static String toYaml(Object object) {
YAMLMapper mapper = new YAMLMapper();
mapper.findAndRegisterModules();
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES).disable(YAMLGenerator.Feature.LITERAL_BLOCK_STYLE);
try {
String yaml = mapper.writeValueAsString(object);
return yaml.replaceAll("\"True\"", "true")
.replaceAll("\"true\"", "true")
.replaceAll("\"false\"", "false")
.replaceAll("\"False\"", "false");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static String toYamlWithoutNull(Object object) {
String jsonStr = JSONObject.toJSONString(object);
if (object instanceof List) {
return toYaml(JSONObject.parseObject(jsonStr, List.class, Feature.OrderedField));
} else {
return toYaml(JSONObject.parseObject(jsonStr, LinkedHashMap.class, Feature.OrderedField));
}
}
/**
* (此方法非必要)
* json 2 yaml
*
* @param jsonStr json
* @return yaml
* @throws JsonProcessingException Exception
*/
public static String json2Yaml(String jsonStr) throws JsonProcessingException {
JsonNode jsonNode = new ObjectMapper().readTree(jsonStr);
return new YAMLMapper().writeValueAsString(jsonNode);
}
}