mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-13 21:17:08 +00:00
first commit
This commit is contained in:
@@ -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";
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.tencent.supersonic.common.exception;
|
||||
|
||||
public class AccessException extends RuntimeException {
|
||||
|
||||
private String message;
|
||||
|
||||
public AccessException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.tencent.supersonic.common.exception;
|
||||
|
||||
public class InvalidArgumentException extends RuntimeException {
|
||||
|
||||
private String message;
|
||||
|
||||
public InvalidArgumentException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.tencent.supersonic.common.exception;
|
||||
|
||||
public class InvalidPermissionException extends RuntimeException {
|
||||
|
||||
private String message;
|
||||
|
||||
public InvalidPermissionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
24
common/src/main/java/com/tencent/supersonic/common/util/cache/CacheCommonConfig.java
vendored
Normal file
24
common/src/main/java/com/tencent/supersonic/common/util/cache/CacheCommonConfig.java
vendored
Normal 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;
|
||||
|
||||
|
||||
}
|
||||
14
common/src/main/java/com/tencent/supersonic/common/util/cache/CacheUtils.java
vendored
Normal file
14
common/src/main/java/com/tencent/supersonic/common/util/cache/CacheUtils.java
vendored
Normal 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);
|
||||
|
||||
}
|
||||
33
common/src/main/java/com/tencent/supersonic/common/util/cache/CaffeineCacheConfig.java
vendored
Normal file
33
common/src/main/java/com/tencent/supersonic/common/util/cache/CaffeineCacheConfig.java
vendored
Normal 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();
|
||||
}
|
||||
}
|
||||
49
common/src/main/java/com/tencent/supersonic/common/util/cache/CaffeineCacheImpl.java
vendored
Normal file
49
common/src/main/java/com/tencent/supersonic/common/util/cache/CaffeineCacheImpl.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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 + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user