lzq 2025-09-25 18:56:24 +08:00
commit 2b3e56352c
29 changed files with 2143 additions and 0 deletions

7
.gitignore vendored 100644
View File

@ -0,0 +1,7 @@
/**/logs
/**/*.iml
/**/.idea
/**/target
/**/.DS_Store
/**/.back*
db-model/*/

94
pom.xml 100644
View File

@ -0,0 +1,94 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.njzscloud</groupId>
<artifactId>gps</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.51</version>
</dependency>
<!--<editor-fold desc="hutool">-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-cache</artifactId>
<version>5.8.28</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.8.28</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-extra</artifactId>
<version>5.8.28</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
<version>5.8.28</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>5.8.28</version>
</dependency>
<!--</editor-fold>-->
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
<!-- slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<!-- logback -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
<!--<editor-fold desc="jackson">-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.13.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>2.13.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.13.4</version>
</dependency>
<!--</editor-fold>-->
</dependencies>
</project>

View File

@ -0,0 +1,25 @@
package com.njzscloud.common.ex;
import cn.hutool.core.util.StrUtil;
/**
* ,
*/
public class CliException extends SysThrowable {
/**
*
*
* @param cause
* @param expect
* @param msg
* @param message
*/
protected CliException(Throwable cause, Object expect, ExceptionMsg msg, Object message) {
super(cause, expect, msg, message);
}
@Override
public String getMessage() {
return StrUtil.format("客户端错误, 错误码: {}, 错误信息: {}, 详细信息: {}", this.msg.code, this.msg.msg, this.message);
}
}

View File

@ -0,0 +1,93 @@
package com.njzscloud.common.ex;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.SimpleCache;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
/**
* <p></p>
* <p></p>
*
* @see org.springframework.core.ExceptionDepthComparator
*/
public class ExceptionDepthComparator implements Comparator<Class<? extends Throwable>> {
/**
*
*/
private static final SimpleCache<Class<? extends Throwable>, ExceptionDepthComparator> CACHE = new SimpleCache<>();
/**
*
*/
private final Class<? extends Throwable> targetException;
/**
*
*
* @param exception
*/
public ExceptionDepthComparator(Throwable exception) {
Assert.notNull(exception, "目标异常不能为空");
this.targetException = exception.getClass();
}
/**
*
*
* @param exceptionType
*/
public ExceptionDepthComparator(Class<? extends Throwable> exceptionType) {
Assert.notNull(exceptionType, "目标异常类型不能为空");
this.targetException = exceptionType;
}
/**
*
*
* @param exceptionTypes
* @param targetException
* @return
*/
public static Class<? extends Throwable> findClosestMatch(Collection<Class<? extends Throwable>> exceptionTypes, Throwable targetException) {
Assert.notEmpty(exceptionTypes, "不能为空");
Assert.notNull(targetException, "不能为空");
if (exceptionTypes.size() == 1) {
return exceptionTypes.iterator().next();
}
List<Class<? extends Throwable>> handledExceptions = new ArrayList<>(exceptionTypes);
ExceptionDepthComparator comparator = CACHE.get(targetException.getClass(), () -> new ExceptionDepthComparator(targetException));
handledExceptions.sort(comparator);
return handledExceptions.get(0);
}
@Override
public int compare(Class<? extends Throwable> o1, Class<? extends Throwable> o2) {
int depth1 = getDepth(o1, this.targetException);
int depth2 = getDepth(o2, this.targetException);
return depth1 - depth2;
}
/**
*
*
* @param declaredException
* @param exceptionToMatch
* @return 0
*/
private int getDepth(Class<?> declaredException, Class<?> exceptionToMatch) {
int depth = 0;
do {
if (exceptionToMatch.equals(declaredException)) return depth;
if (exceptionToMatch == Throwable.class) return Integer.MAX_VALUE;
depth++;
exceptionToMatch = exceptionToMatch.getSuperclass();
} while (true);
}
}

View File

@ -0,0 +1,53 @@
package com.njzscloud.common.ex;
/**
*
* <p></p>
* <p>SYS_EXP_MSG</p>
* <p>CLI_ERR_MSG</p>
* <p>SYS_ERR_MSG</p>
*/
public final class ExceptionMsg {
/**
*
*/
public static final ExceptionMsg SYS_EXP_MSG = new ExceptionMsg(ExceptionType.SYS_EXP, 1111, "操作失败");
/**
*
*/
public static final ExceptionMsg CLI_ERR_MSG = new ExceptionMsg(ExceptionType.CLI_ERR, 5555, "操作失败");
/**
*
*/
public static final ExceptionMsg SYS_ERR_MSG = new ExceptionMsg(ExceptionType.SYS_ERR, 9999, "系统错误");
/**
* 0< code 9999
*/
public final int code;
/**
*
*/
public final String msg;
/**
* {@link ExceptionType}
*/
public final ExceptionType type;
/**
*
*
* @param type {@link ExceptionType}
* @param code 0< code 9999
* @param msg
*/
private ExceptionMsg(ExceptionType type, int code, String msg) {
this.code = code;
this.type = type;
this.msg = msg;
}
}

View File

@ -0,0 +1,21 @@
package com.njzscloud.common.ex;
import lombok.RequiredArgsConstructor;
/**
*
*/
@RequiredArgsConstructor
public enum ExceptionType {
SYS_EXP(1, "系统异常"),
CLI_ERR(5, "客户端错误"),
SYS_ERR(9, "系统错误");
public final int code;
public final String name;
}

View File

@ -0,0 +1,77 @@
package com.njzscloud.common.ex;
import cn.hutool.core.util.StrUtil;
/**
*
*
*/
public class Exceptions {
public static SysThrowable clierr(Object message, Object... param) {
return build(null, ExpectData.NULL_DATA, ExceptionMsg.CLI_ERR_MSG, message, param);
}
public static SysThrowable clierr(Object message) {
return build(null, ExpectData.NULL_DATA, ExceptionMsg.CLI_ERR_MSG, message, null);
}
public static SysThrowable exception(Object message, Object... param) {
return build(null, ExpectData.NULL_DATA, ExceptionMsg.SYS_EXP_MSG, message, param);
}
public static SysThrowable exception(Object message) {
return build(null, ExpectData.NULL_DATA, ExceptionMsg.SYS_EXP_MSG, message, null);
}
public static SysThrowable error(Object message, Object... param) {
return build(null, ExpectData.NULL_DATA, ExceptionMsg.SYS_ERR_MSG, message, param);
}
public static SysThrowable error(Object message) {
return build(null, ExpectData.NULL_DATA, ExceptionMsg.SYS_ERR_MSG, message, null);
}
public static SysThrowable error(Throwable cause, Object message, Object... param) {
return build(cause, ExpectData.NULL_DATA, ExceptionMsg.SYS_ERR_MSG, message, param);
}
public static SysThrowable error(Throwable cause, Object message) {
return build(cause, ExpectData.NULL_DATA, ExceptionMsg.SYS_ERR_MSG, message, null);
}
/**
* <p></p>
*
* @param cause
* @param expect
* @param msg
* @param message (, : {})
* @param param
* @see SysThrowable
* @see ExceptionMsg
* @see ExpectData
*/
private static SysThrowable build(Throwable cause, ExpectData expect, ExceptionMsg msg, Object message, Object[] param) {
if (message instanceof String
&& !StrUtil.isBlank((String) message)
&& param != null
&& param.length > 0) {
message = StrUtil.format((String) message, param);
}
SysThrowable sysThrowable;
if (msg.type == ExceptionType.SYS_EXP) {
sysThrowable = new SysException(cause, expect, msg, message);
} else if (msg.type == ExceptionType.CLI_ERR) {
sysThrowable = new CliException(cause, expect, msg, message);
} else {
sysThrowable = new SysError(cause, expect, msg, message);
}
return sysThrowable;
}
}

View File

@ -0,0 +1,60 @@
package com.njzscloud.common.ex;
import lombok.AllArgsConstructor;
import java.util.Collections;
/**
*
* <p>HTTP JSON </p>
*/
@AllArgsConstructor
public enum ExpectData {
/**
* : null
*/
NULL_DATA(null),
/**
* : []
*/
ARR_DATA(Collections.emptyList()),
/**
* : {}
*/
KV_DATA(Collections.emptyMap()),
/**
* : ""
*/
STR_BLANK_DATA(""),
/**
* : 0
*/
NUM_ZERO_DATA(0),
/**
* : false
*/
BOOL_FALSE_DATA(Boolean.FALSE),
/**
* : true
*/
BOOL_TRUE_DATA(Boolean.TRUE),
/**
*
*/
VOID_DATA(Void.TYPE);
private final Object data;
@SuppressWarnings("unchecked")
public <T> T getData() {
return (T) data;
}
}

View File

@ -0,0 +1,26 @@
package com.njzscloud.common.ex;
import cn.hutool.core.util.StrUtil;
/**
* ,
*/
public class SysError extends SysThrowable {
/**
*
*
* @param cause
* @param expect
* @param msg
* @param message
*/
protected SysError(Throwable cause, Object expect, ExceptionMsg msg, Object message) {
super(cause, expect, msg, message);
}
@Override
public String getMessage() {
return StrUtil.format("内部服务错误, 错误码: {}, 错误信息: {}, 详细信息: {}", this.msg.code, this.msg.msg, this.message);
}
}

View File

@ -0,0 +1,25 @@
package com.njzscloud.common.ex;
import cn.hutool.core.util.StrUtil;
/**
* ,
*/
public class SysException extends SysThrowable {
/**
*
*
* @param cause
* @param expect
* @param msg
* @param message
*/
protected SysException(Throwable cause, Object expect, ExceptionMsg msg, Object message) {
super(cause, expect, msg, message);
}
@Override
public String getMessage() {
return StrUtil.format("系统异常, 错误码: {}, 错误信息: {}, 详细信息: {}", this.msg.code, this.msg.msg, this.message);
}
}

View File

@ -0,0 +1,52 @@
package com.njzscloud.common.ex;
import cn.hutool.core.map.MapUtil;
import com.njzscloud.common.jackson.Jackson;
/**
*
*/
public abstract class SysThrowable extends RuntimeException {
/**
*
*
* @see ExpectData
*/
public final Object expect;
/**
* ()
*/
public final ExceptionMsg msg;
/**
* ()
*/
public final Object message;
/**
*
*
* @param cause
* @param expect
* @param msg
* @param message
*/
protected SysThrowable(Throwable cause, Object expect, ExceptionMsg msg, Object message) {
super(msg.msg, cause);
this.msg = msg;
this.message = message == null ? "" : message;
this.expect = expect;
}
@Override
public String toString() {
return Jackson.toJsonStr(MapUtil.builder()
.put("code", msg.code)
.put("expect", expect)
.put("msg", msg.msg)
.put("message", message)
.build());
}
}

View File

@ -0,0 +1,139 @@
package com.njzscloud.common.fastjson;
import cn.hutool.core.date.DatePattern;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.filter.Filter;
import com.alibaba.fastjson2.filter.ValueFilter;
import com.alibaba.fastjson2.reader.ObjectReader;
import lombok.extern.slf4j.Slf4j;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import static com.alibaba.fastjson2.JSONReader.Feature.IgnoreCheckClose;
/**
* <p>Fastjson </p>
* <p>/</p>
*/
@Slf4j
public class Fastjson {
private static final JSONWriter.Context JSON_WRITER_CONTEXT;
private static final JSONReader.Context JSON_READER_CONTEXT;
static {
JSON_WRITER_CONTEXT = new JSONWriter.Context(
JSONWriter.Feature.WriteNulls, // 序列化输出空值字段
JSONWriter.Feature.BrowserCompatible, // 在大范围超过JavaScript支持的整数输出为字符串格式
JSONWriter.Feature.WriteClassName, // 序列化时输出类型信息
// JSONWriter.Feature.PrettyFormat, // 格式化输出
JSONWriter.Feature.SortMapEntriesByKeys, // 对Map中的KeyValue按照Key做排序后再输出。在有些验签的场景需要使用这个Feature
JSONWriter.Feature.WriteBigDecimalAsPlain, // 序列化BigDecimal使用toPlainString避免科学计数法
JSONWriter.Feature.WriteNullListAsEmpty, // 将List类型字段的空值序列化输出为空数组"[]"
JSONWriter.Feature.WriteNullStringAsEmpty, // 将String类型字段的空值序列化输出为空字符串""
JSONWriter.Feature.WriteLongAsString // 将 Long 作为字符串输出
);
ZoneId zoneId = ZoneId.of("GMT+8");
JSON_WRITER_CONTEXT.setZoneId(zoneId);
JSON_WRITER_CONTEXT.setDateFormat(DatePattern.NORM_DATETIME_PATTERN);
JSON_WRITER_CONTEXT.configFilter((ValueFilter) (object, name, value) -> {
if (value != null) {
Class<?> clazz = value.getClass();
if (clazz == LocalDate.class) {
return DateTimeFormatter.ofPattern(DatePattern.PURE_DATE_PATTERN).withZone(zoneId).format((LocalDate) value);
} else if (clazz == LocalTime.class) {
return DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN).withZone(zoneId).format((LocalTime) value);
} else if (clazz == BigDecimal.class) {
return ((BigDecimal) value).toPlainString();
}
}
return value;
});
JSON_READER_CONTEXT = new JSONReader.Context(
JSONReader.Feature.IgnoreSetNullValue, // 忽略输入为null的字段
JSONReader.Feature.SupportAutoType // 支持自动类型,要读取带"@type"类型信息的JSON数据需要显示打开SupportAutoType
);
JSON_READER_CONTEXT.setZoneId(zoneId);
JSON_READER_CONTEXT.setDateFormat(DatePattern.NORM_DATETIME_PATTERN);
}
/**
* JSON
*
* @param object
* @return String
* @see JSON#toJSONString(Object, JSONWriter.Context)
*/
public static String toJsonStr(Object object) {
return JSON.toJSONString(object, JSON_WRITER_CONTEXT);
}
/**
* JSON
*
* @param object
* @return byte[]
* @see JSON#toJSONBytes(Object, Filter...)
*/
public static byte[] toJsonBytes(Object object) {
return JSON.toJSONBytes(object, StandardCharsets.UTF_8, JSON_WRITER_CONTEXT);
}
/**
*
*
* @param json JSON
* @param type
* @return T
* @see JSON#parseObject(String, Class, JSONReader.Context)
*/
@SuppressWarnings("unchecked")
public static <T> T toBean(String json, Type type) {
if (json == null || json.isEmpty()) {
return null;
}
return toBean(JSONReader.of(json, JSON_READER_CONTEXT), type);
}
public static <T> T toBean(InputStream json, Type type) {
if (json == null) {
return null;
}
return toBean(JSONReader.of(json, StandardCharsets.UTF_8, JSON_READER_CONTEXT), type);
}
public static <T> T toBean(byte[] json, Type type) {
if (json == null || json.length == 0) {
return null;
}
return toBean(JSONReader.of(json, JSON_READER_CONTEXT), type);
}
@SuppressWarnings("unchecked")
private static <T> T toBean(JSONReader reader, Type type) {
ObjectReader<T> objectReader = JSON_READER_CONTEXT.getObjectReader(type);
try {
T object = objectReader.readObject(reader, type, null, 0);
reader.handleResolveTasks(object);
if (!reader.isEnd() && (JSON_READER_CONTEXT.getFeatures() & IgnoreCheckClose.mask) == 0) {
throw new JSONException(reader.info("input not end"));
}
return object;
} finally {
reader.close();
}
}
}

View File

@ -0,0 +1,107 @@
package com.njzscloud.common.fastjson.serializer;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import com.alibaba.fastjson2.util.TypeUtils;
import com.njzscloud.common.ex.Exceptions;
import com.njzscloud.common.ienum.Dict;
import com.njzscloud.common.ienum.DictInt;
import com.njzscloud.common.ienum.DictStr;
import com.njzscloud.common.ienum.IEnum;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Type;
import java.util.Map;
/**
* Dict Fastjson <br/>
* 使: <br/>
* 1使 JSONField <br/>
* @JSONField(deserializeUsing = DictObjectSerializer.class)<br/>
* 2使 JSONType <br/>
* @JSONType(writeEnumAsJavaBean = true, deserializer = DictObjectSerializer.class)<br/><br/>
* JSON {@link DictObjectSerializer}
*
* @see Dict
* @see DictInt
* @see DictStr
* @see DictObjectSerializer
*/
@Slf4j
public class DictObjectDeserializer implements ObjectReader<Dict> {
private static final ClassLoader CLASSLOADER = DictObjectDeserializer.class.getClassLoader();
@Override
public Dict readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
try {
if (jsonReader.isObject()) {
Map<String, Object> map = jsonReader.readObject();
String typeField = (String) map.get(IEnum.ENUM_TYPE);
Object valField = map.get(Dict.ENUM_VAL);
Class<?> clazz = CLASSLOADER.loadClass(typeField);
if (valField instanceof String) {
if (DictStr.class.isAssignableFrom(clazz)) {
DictStr[] constants = (DictStr[]) clazz.getEnumConstants();
return Dict.parse((String) valField, constants);
} else if (DictInt.class.isAssignableFrom(clazz)) {
DictInt[] constants = (DictInt[]) clazz.getEnumConstants();
return Dict.parse(Integer.parseInt((String) valField), constants);
} else {
return null;
}
} else if (valField instanceof Integer) {
if (DictStr.class.isAssignableFrom(clazz)) {
DictStr[] constants = (DictStr[]) clazz.getEnumConstants();
return Dict.parse(String.valueOf(valField), constants);
} else if (DictInt.class.isAssignableFrom(clazz)) {
DictInt[] constants = (DictInt[]) clazz.getEnumConstants();
return Dict.parse((Integer) valField, constants);
} else {
return null;
}
} else {
return null;
}
} else {
if (jsonReader.isString()) {
Class<?> clazz = TypeUtils.getClass(fieldType);
if (DictStr.class.isAssignableFrom(clazz)) {
String val = jsonReader.readString();
DictStr[] constants = (DictStr[]) clazz.getEnumConstants();
return Dict.parse(val, constants);
} else if (DictInt.class.isAssignableFrom(clazz)) {
String val = jsonReader.readString();
DictInt[] constants = (DictInt[]) clazz.getEnumConstants();
return Dict.parse(Integer.parseInt(val), constants);
} else {
return null;
}
} else if (jsonReader.isInt()) {
Class<?> clazz = TypeUtils.getClass(fieldType);
if (DictStr.class.isAssignableFrom(clazz)) {
String val = jsonReader.readString();
DictStr[] constants = (DictStr[]) clazz.getEnumConstants();
return Dict.parse(val, constants);
} else if (DictInt.class.isAssignableFrom(clazz)) {
Integer val = jsonReader.readInt32();
DictInt[] constants = (DictInt[]) clazz.getEnumConstants();
return Dict.parse(val, constants);
} else {
return null;
}
} else {
return null;
}
}
} catch (Exception e) {
log.error("字典枚举反序列化失败", e);
throw Exceptions.error(e, "字典枚举反序列化失败,类型:{},字段名:{}", fieldType, fieldName);
}
}
}

View File

@ -0,0 +1,97 @@
package com.njzscloud.common.fastjson.serializer;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.util.TypeUtils;
import com.alibaba.fastjson2.writer.ObjectWriter;
import com.njzscloud.common.ienum.Dict;
import com.njzscloud.common.ienum.DictInt;
import com.njzscloud.common.ienum.DictStr;
import com.njzscloud.common.ienum.IEnum;
import java.lang.reflect.Type;
/**
* Dict Fastjson <br/>
* 使: <br/>
* 1使 JSONField <br/>
* @JSONField(serializeUsing = DictObjectSerializer.class)<br/>
* 2使 JSONType <br/>
* @JSONType(writeEnumAsJavaBean = true, serializer = DictObjectSerializer.class)<br/><br/>
* JSON <br/>
* 1<br/>
* <pre>
* {
* "type": "", // 枚举全限定类名, 反序列化时会用到
* "name": "", // name 属性
* "ordinal": 0, // ordinal 属性
* "val": 1, // val 属性(字符串/数字), 反序列化时会用到
* "txt": "1" // txt 属性
* }</pre>
* 2<br/>
* <pre>
* {
* // ... 其他属性
* "原字段名称": 1, // val 属性(字符串/数字), 反序列化时会用到
* "原字段名称Txt": "1" // txt 属性
* }</pre>
*
* @see Dict
* @see DictInt
* @see DictStr
*/
public class DictObjectSerializer implements ObjectWriter<Dict> {
@Override
public void write(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
if (object == null) {
jsonWriter.writeNull();
return;
}
if (fieldType == null) {
Dict<?> dict = (Dict<?>) object;
jsonWriter.startObject();
jsonWriter.writeName(IEnum.ENUM_TYPE);
jsonWriter.writeColon();
jsonWriter.writeString(dict.getClass().getName());
jsonWriter.writeName(IEnum.ENUM_NAME);
jsonWriter.writeColon();
jsonWriter.writeString(((Enum<?>) dict).name());
jsonWriter.writeName(IEnum.ENUM_ORDINAL);
jsonWriter.writeColon();
jsonWriter.writeInt32(((Enum<?>) dict).ordinal());
jsonWriter.writeName(Dict.ENUM_VAL);
jsonWriter.writeColon();
jsonWriter.writeAny(dict.getVal());
jsonWriter.writeName(Dict.ENUM_TXT);
jsonWriter.writeColon();
jsonWriter.writeString(dict.getTxt());
jsonWriter.endObject();
} else {
Class<?> clazz = TypeUtils.getClass(fieldType);
if (DictInt.class.isAssignableFrom(clazz)) {
DictInt dictInt = (DictInt) object;
jsonWriter.writeInt32(dictInt.getVal());
jsonWriter.writeName(fieldName + "Txt");
jsonWriter.writeColon();
jsonWriter.writeString(dictInt.getTxt());
} else if (DictStr.class.isAssignableFrom(clazz)) {
DictStr dictStr = (DictStr) object;
jsonWriter.writeString(dictStr.getVal());
jsonWriter.writeName(fieldName + "Txt");
jsonWriter.writeColon();
jsonWriter.writeString(dictStr.getTxt());
} else {
jsonWriter.writeNull();
}
}
}
}

View File

@ -0,0 +1,70 @@
package com.njzscloud.common.ienum;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.njzscloud.common.fastjson.serializer.DictObjectDeserializer;
import com.njzscloud.common.fastjson.serializer.DictObjectSerializer;
import com.njzscloud.common.jackson.serializer.DictDeserializer;
import com.njzscloud.common.jackson.serializer.DictSerializer;
/**
* <br/>
* DictIntDictStr<br/>
*
* @see DictInt
* @see DictStr
* @see DictDeserializer
* @see DictSerializer
* @see DictObjectDeserializer
* @see DictObjectSerializer
*/
@JsonDeserialize(using = DictDeserializer.class)
@JsonSerialize(using = DictSerializer.class)
public interface Dict<T> extends IEnum {
/**
* <br/>
* val
*/
String ENUM_VAL = "val";
/**
* <br/>
* txt
*/
String ENUM_TXT = "txt";
/**
* "值"
*
* @param val
* @param ds
* @param <V>
* @param <D>
* @return Dict
*/
static <V, D extends Dict<V>> D parse(V val, D[] ds) {
for (D d : ds) {
if (d.getVal().equals(val)) {
return d;
}
}
return null;
}
/**
*
*
* @return T
*/
T getVal();
/**
*
*
* @return String
*/
String getTxt();
}

View File

@ -0,0 +1,11 @@
package com.njzscloud.common.ienum;
/**
* "值" Integer<br/>
*
*
* @see DictStr
*/
public interface DictInt extends Dict<Integer> {
}

View File

@ -0,0 +1,10 @@
package com.njzscloud.common.ienum;
/**
* "值" String<br/>
*
*
* @see DictInt
*/
public interface DictStr extends Dict<String> {
}

View File

@ -0,0 +1,24 @@
package com.njzscloud.common.ienum;
/**
*
*/
public interface IEnum {
/**
* <br/>
*
*/
String ENUM_TYPE = "type";
/**
* <br/>
* name
*/
String ENUM_NAME = "name";
/**
* <br/>
* ordinal
*/
String ENUM_ORDINAL = "ordinal";
}

View File

@ -0,0 +1,214 @@
package com.njzscloud.common.jackson;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.njzscloud.common.ex.Exceptions;
import com.njzscloud.common.jackson.serializer.BigDecimalModule;
import com.njzscloud.common.jackson.serializer.LongModule;
import com.njzscloud.common.jackson.serializer.TimeModule;
import lombok.extern.slf4j.Slf4j;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
/**
* Jackson <br/>
* Spring ObjectMapper
*/
@Slf4j
public class Jackson {
private static final ObjectMapper objectMapper;
private static final XmlMapper xmlMapper;
static {
objectMapper = createObjectMapper();
xmlMapper = createXmlMapper();
}
/**
* JSON
*
* @param o
* @return String
*/
public static String toJsonStr(Object o) {
try {
return objectMapper.writeValueAsString(o);
} catch (JsonProcessingException e) {
log.error("Jackson 序列化失败", e);
throw Exceptions.error(e, "Jackson 序列化失败");
}
}
/**
* JSON
*
* @param o
* @return byte[]
*/
public static byte[] toJsonBytes(Object o) {
try {
return objectMapper.writeValueAsBytes(o);
} catch (JsonProcessingException e) {
log.error("Jackson 序列化失败", e);
throw Exceptions.error(e, "Jackson 序列化失败");
}
}
/**
* ()<br/>
* : new TypeReference&lt;List&lt;String&gt;&gt;(){},
*
* @param json json JSON
* @param type
* @return T
* @see TypeReference
*/
public static <T> T toBean(String json, Type type) {
try {
return objectMapper.readValue(json, objectMapper.getTypeFactory().constructType(type));
} catch (JsonProcessingException e) {
log.error("Jackson 反序列化失败", e);
throw Exceptions.error(e, "Jackson 反序列化失败");
}
}
public static <T> T toBean(InputStream json, Type type) {
try {
return objectMapper.readValue(json, objectMapper.getTypeFactory().constructType(type));
} catch (Exception e) {
log.error("Jackson 反序列化失败", e);
throw Exceptions.error(e, "Jackson 反序列化失败");
}
}
public static <T> T toBean(byte[] json, Type type) {
try {
return objectMapper.readValue(json, objectMapper.getTypeFactory().constructType(type));
} catch (Exception e) {
log.error("Jackson 反序列化失败", e);
throw Exceptions.error(e, "Jackson 反序列化失败");
}
}
/**
* JSON
*
* @param o
* @return String
*/
public static String toXmlStr(Object o) {
try {
return xmlMapper.writeValueAsString(o);
} catch (JsonProcessingException e) {
log.error("Jackson 序列化失败", e);
throw Exceptions.error(e, "Jackson 序列化失败");
}
}
/**
* JSON
*
* @param o
* @return byte[]
*/
public static byte[] toXmlBytes(Object o) {
try {
return xmlMapper.writeValueAsBytes(o);
} catch (JsonProcessingException e) {
log.error("Jackson 序列化失败", e);
throw Exceptions.error(e, "Jackson 序列化失败");
}
}
public static <T> T xmlToBean(String json, Type type) {
try {
return xmlMapper.readValue(json, xmlMapper.getTypeFactory().constructType(type));
} catch (JsonProcessingException e) {
log.error("Jackson 反序列化失败", e);
throw Exceptions.error(e, "Jackson 反序列化失败");
}
}
public static <T> T xmlToBean(InputStream json, Type type) {
try {
return xmlMapper.readValue(json, xmlMapper.getTypeFactory().constructType(type));
} catch (Exception e) {
log.error("Jackson 反序列化失败", e);
throw Exceptions.error(e, "Jackson 反序列化失败");
}
}
public static <T> T xmlToBean(byte[] json, Type type) {
try {
return xmlMapper.readValue(json, xmlMapper.getTypeFactory().constructType(type));
} catch (Exception e) {
log.error("Jackson 反序列化失败", e);
throw Exceptions.error(e, "Jackson 反序列化失败");
}
}
/**
* ObjectMapper
*
* @return ObjectMapper
*/
private static ObjectMapper createObjectMapper() {
return new ObjectMapper()
.setLocale(Locale.CHINA)
.setTimeZone(TimeZone.getTimeZone("GMT+8"))
.setDateFormat(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN))
.setSerializationInclusion(JsonInclude.Include.ALWAYS)
// .configure(SerializationFeature.INDENT_OUTPUT, true) // 格式化输出
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true) // 对Map中的KeyValue按照Key做排序后再输出。在有些验签的场景需要使用这个Feature
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
// .configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true)
.configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true)
.registerModules(new TimeModule(), new LongModule(), new BigDecimalModule())
;
}
private static XmlMapper createXmlMapper() {
return XmlMapper.xmlBuilder()
.defaultLocale(Locale.CHINA)
.defaultTimeZone(TimeZone.getTimeZone("GMT+8"))
.defaultDateFormat(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN))
.serializationInclusion(JsonInclude.Include.ALWAYS)
.configure(SerializationFeature.INDENT_OUTPUT, true)
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true) // 对Map中的KeyValue按照Key做排序后再输出。在有些验签的场景需要使用这个Feature
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.addModules(new TimeModule(), new LongModule(), new BigDecimalModule())
.build()
;
}
/**
* objectMapper
*
* @return ObjectMapper
*/
public static ObjectMapper objectMapper() {
return objectMapper;
}
public static XmlMapper xmlMapper() {
return xmlMapper;
}
}

View File

@ -0,0 +1,16 @@
package com.njzscloud.common.jackson.serializer;
import com.fasterxml.jackson.databind.deser.std.NumberDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.math.BigDecimal;
/**
* BigDecimal
*/
public class BigDecimalModule extends SimpleModule {
{
this.addSerializer(BigDecimal.class, new BigDecimalSerializer())
.addDeserializer(BigDecimal.class, new NumberDeserializers.BigDecimalDeserializer());
}
}

View File

@ -0,0 +1,22 @@
package com.njzscloud.common.jackson.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.math.BigDecimal;
/**
* BigDecimal
*/
public class BigDecimalSerializer extends JsonSerializer<BigDecimal> {
@Override
public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value != null) {
gen.writeString(value.toPlainString());
} else {
gen.writeNull();
}
}
}

View File

@ -0,0 +1,102 @@
package com.njzscloud.common.jackson.serializer;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.node.IntNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.njzscloud.common.ex.Exceptions;
import com.njzscloud.common.ienum.Dict;
import com.njzscloud.common.ienum.DictInt;
import com.njzscloud.common.ienum.DictStr;
import com.njzscloud.common.ienum.IEnum;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.lang.reflect.Field;
/**
* Dict Jackson <br/><br/>
* JSON {@link DictSerializer}
*
* @see Dict
* @see DictInt
* @see DictStr
* @see DictSerializer
*/
@Slf4j
public class DictDeserializer extends JsonDeserializer<Dict> {
private static final ClassLoader CLASSLOADER = DictDeserializer.class.getClassLoader();
@Override
public Dict deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
JsonToken currentToken = p.getCurrentToken();
if (currentToken == JsonToken.START_OBJECT) {
TreeNode treeNode = p.getCodec().readTree(p);
TreeNode enumType_node = treeNode.get(IEnum.ENUM_TYPE);
String enumTypeField = ((TextNode) enumType_node).textValue();
TreeNode val_node = treeNode.get(Dict.ENUM_VAL);
Class<?> clazz;
try {
clazz = CLASSLOADER.loadClass(enumTypeField);
} catch (ClassNotFoundException e) {
throw Exceptions.error(e, "类型加载失败:{}", enumTypeField);
}
if (val_node instanceof TextNode) {
if (DictStr.class.isAssignableFrom(clazz)) {
String val = ((TextNode) val_node).textValue();
DictStr[] constants = (DictStr[]) clazz.getEnumConstants();
return Dict.parse(val, constants);
} else if (DictInt.class.isAssignableFrom(clazz)) {
String val = ((TextNode) val_node).textValue();
DictInt[] constants = (DictInt[]) clazz.getEnumConstants();
return Dict.parse(Integer.parseInt(val), constants);
} else {
return null;
}
} else if (val_node instanceof IntNode) {
if (DictStr.class.isAssignableFrom(clazz)) {
int val = ((IntNode) val_node).intValue();
DictStr[] constants = (DictStr[]) clazz.getEnumConstants();
return Dict.parse(String.valueOf(val), constants);
} else if (DictInt.class.isAssignableFrom(clazz)) {
int val = ((IntNode) val_node).intValue();
DictInt[] constants = (DictInt[]) clazz.getEnumConstants();
return Dict.parse(val, constants);
} else {
return null;
}
} else {
return null;
}
} else {
JsonStreamContext context = p.getParsingContext();
String currentName = context.getCurrentName();
Object currentValue = p.getCurrentValue();
Class<?> valueClazz = currentValue.getClass();
try {
Field field = valueClazz.getDeclaredField(currentName);
Class<?> clazz = field.getType();
if (DictStr.class.isAssignableFrom(clazz)) {
String val = p.getValueAsString();
DictStr[] constants = (DictStr[]) clazz.getEnumConstants();
return Dict.parse(val, constants);
} else if (DictInt.class.isAssignableFrom(clazz)) {
int val = p.getValueAsInt();
DictInt[] constants = (DictInt[]) clazz.getEnumConstants();
return Dict.parse(val, constants);
} else {
return null;
}
} catch (Exception e) {
log.error("字典枚举反序列化失败", e);
throw Exceptions.error(e, "字典枚举反序列化失败,字段名:{},值:{}", currentName, currentValue);
}
}
}
}

View File

@ -0,0 +1,61 @@
package com.njzscloud.common.jackson.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.njzscloud.common.ienum.Dict;
import com.njzscloud.common.ienum.DictInt;
import com.njzscloud.common.ienum.DictStr;
import com.njzscloud.common.ienum.IEnum;
import java.io.IOException;
/**
* Dict Jackson <br/><br/>
* JSON <br/>
* 1<br/>
* <pre>
* {
* "type": "", // 枚举全限定类名, 反序列化时会用到
* "name": "", // name 属性
* "ordinal": 0, // ordinal 属性
* "val": 1, // val 属性(字符串/数字), 反序列化时会用到
* "txt": "1" // txt 属性
* }</pre>
* 2<br/>
* <pre>
* {
* // ... 其他属性
* "原字段名称": 1, // val 属性(字符串/数字), 反序列化时会用到
* "原字段名称Txt": "1" // txt 属性
* }</pre>
*
* @see Dict
* @see DictInt
* @see DictStr
* @see DictDeserializer
*/
public class DictSerializer extends JsonSerializer<Dict> {
@Override
public void serialize(Dict value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value == null) {
gen.writeNull();
} else {
JsonStreamContext ctx = gen.getOutputContext();
if (ctx.inRoot()) {
gen.writeStartObject();
gen.writeStringField(IEnum.ENUM_TYPE, value.getClass().getName());
gen.writeStringField(IEnum.ENUM_NAME, ((Enum<?>) value).name());
gen.writeNumberField(IEnum.ENUM_ORDINAL, ((Enum<?>) value).ordinal());
gen.writeObjectField(Dict.ENUM_VAL, value.getVal());
gen.writeStringField(Dict.ENUM_TXT, value.getTxt());
gen.writeEndObject();
} else {
gen.writeObject(value.getVal());
String currentName = ctx.getCurrentName();
gen.writeStringField(currentName + "Txt", value.getTxt());
}
}
}
}

View File

@ -0,0 +1,15 @@
package com.njzscloud.common.jackson.serializer;
import com.fasterxml.jackson.databind.deser.std.NumberDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
/**
* Long
*/
public class LongModule extends SimpleModule {
{
this.addSerializer(Long.class, new LongSerializer())
.addDeserializer(Long.class, new NumberDeserializers.LongDeserializer(Long.class, null));
}
}

View File

@ -0,0 +1,21 @@
package com.njzscloud.common.jackson.serializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
/**
* Long
*/
public class LongSerializer extends JsonSerializer<Long> {
@Override
public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value != null) {
gen.writeString(value.toString());
} else {
gen.writeNull();
}
}
}

View File

@ -0,0 +1,29 @@
package com.njzscloud.common.jackson.serializer;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
/**
*
*/
public class TimeModule extends SimpleModule {
{
this.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)))
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN)));
}
}

View File

@ -0,0 +1,625 @@
package com.njzscloud.common.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.njzscloud.common.ex.Exceptions;
import com.njzscloud.common.fastjson.Fastjson;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
*
*/
public class GroupUtil {
// region K-O
// region Collection
/**
* <p></p>
* <p>Map HashMap, kf, </p>
*
* @param src
* @param kf
* @param <SV> /
* @param <K>
* @return Map&lt;K, SV&gt;
*/
public static <SV, K> Map<K, SV> k_o(Collection<SV> src, Function<SV, K> kf) {
return k_o(src, kf, it -> it, HashMap::new);
}
/**
* <p></p>
* <p>Map HashMap, kf, vf</p>
*
* @param src
* @param kf
* @param vf
* @param <SV>
* @param <K>
* @param <V>
* @return Map&lt;K, V&gt;
*/
public static <SV, K, V> Map<K, V> k_o(Collection<SV> src, Function<SV, K> kf, Function<SV, V> vf) {
return k_o(src, kf, vf, HashMap::new);
}
/**
* <p></p>
* <p>Map mf, kf, </p>
*
* @param src
* @param kf
* @param mf Map
* @param <SV> /
* @param <K>
* @param <M> Map
* @return Map&lt;K, SV&gt;
*/
public static <SV, K, M extends Map<K, SV>> M k_o(Collection<SV> src, Function<SV, K> kf, Supplier<M> mf) {
return k_o(src, kf, it -> it, mf);
}
/**
* <p></p>
* <p>Map mf, kf, vf</p>
*
* @param src
* @param kf
* @param vf
* @param mf Map
* @param <SV>
* @param <K>
* @param <V>
* @param <M> Map
* @return Map&lt;K, V&gt;
*/
public static <SV, K, V, M extends Map<K, V>> M k_o(Collection<SV> src, Function<SV, K> kf, Function<SV, V> vf, Supplier<M> mf) {
if (CollUtil.isEmpty(src)) return MapUtil.empty(null);
return k_o(src.stream(), kf, vf, mf);
}
// endregion
// region Collection 索引
/**
* <p></p>
* <p>Map HashMap, kf, </p>
* <p>kf </p>
*
* @param src
* @param kf
* @param <SV>
* @param <K>
* @return Map&lt;K, VT&gt;
*/
public static <SV, K> Map<K, SV> k_o(Collection<SV> src, BiFunction<Integer, SV, K> kf) {
return k_o(src, kf, it -> it, HashMap::new);
}
/**
* <p></p>
* Map HashMap, kf, vf</p>
* <p>kf </p>
*
* @param src
* @param kf K
* @param vf V
* @param <SV>
* @param <K>
* @param <V>
* @return Map&lt;K, V&gt;
*/
public static <SV, K, V> Map<K, V> k_o(Collection<SV> src, BiFunction<Integer, SV, K> kf, Function<SV, V> vf) {
return k_o(src, kf, vf, HashMap::new);
}
/**
* <p></p>
* <p>Map mf, kf, </p>
* <p>kf </p>
*
* @param src
* @param kf K
* @param mf Map
* @param <SV>
* @param <K>
* @param <M> Map
* @return Map&lt;K, SV&gt;
*/
public static <SV, K, M extends Map<K, SV>> M k_o(Collection<SV> src, BiFunction<Integer, SV, K> kf, Supplier<M> mf) {
return k_o(src, kf, it -> it, mf);
}
/**
* <p></p>
* <p>Map mf, kf, vf</p>
* <p>kf </p>
*
* @param src
* @param kf K
* @param vf V
* @param mf Map
* @param <SV>
* @param <K>
* @param <V>
* @param <M> Map
* @return Map&lt;K, V&gt;
*/
public static <SV, K, V, M extends Map<K, V>> M k_o(Collection<SV> src, BiFunction<Integer, SV, K> kf, Function<SV, V> vf, Supplier<M> mf) {
if (CollUtil.isEmpty(src)) return MapUtil.empty(null);
M map = mf.get();
int i = 0;
for (SV sv : src) {
K k = kf.apply(i, sv);
if (map.containsKey(k)) throw Exceptions.error("重复键:{}", sv);
V v = vf.apply(sv);
map.put(k, v);
i++;
}
return map;
}
/**
* <p></p>
* Map HashMap, kf, vf</p>
* <p>vf </p>
*
* @param src
* @param kf
* @param vf
* @param <SV>
* @param <K>
* @param <V>
* @return Map&lt;K, V&gt;
*/
public static <SV, K, V> Map<K, V> k_o(Collection<SV> src, Function<SV, K> kf, BiFunction<Integer, SV, V> vf) {
return k_o(src, kf, vf, HashMap::new);
}
/**
* <p></p>
* Map mf, kf, vf</p>
* <p>vf </p>
*
* @param src
* @param kf
* @param vf
* @param mf Map
* @param <SV>
* @param <K>
* @param <V>
* @param <M> Map
* @return Map&lt;K, V&gt;
*/
public static <SV, K, V, M extends Map<K, V>> M k_o(Collection<SV> src, Function<SV, K> kf, BiFunction<Integer, SV, V> vf, Supplier<M> mf) {
if (CollUtil.isEmpty(src)) return MapUtil.empty(null);
M map = mf.get();
int i = 0;
for (SV sv : src) {
K k = kf.apply(sv);
if (map.containsKey(k)) throw Exceptions.error("重复键:{}", sv);
V v = vf.apply(i, sv);
map.put(k, v);
i++;
}
return map;
}
/**
* <p></p>
* Map HashMap, kf, vf</p>
* <p>kf vf </p>
*
* @param src
* @param kf
* @param vf
* @param <SV>
* @param <K>
* @param <V>
* @return Map&lt;K, V&gt;
*/
public static <SV, K, V> Map<K, V> k_o(Collection<SV> src, BiFunction<Integer, SV, K> kf, BiFunction<Integer, SV, V> vf) {
return k_o(src, kf, vf, HashMap::new);
}
/**
* <p></p>
* Map mf, kf, vf</p>
* <p>kf vf </p>
*
* @param src
* @param kf
* @param vf
* @param mf Map
* @param <SV>
* @param <K>
* @param <V>
* @param <M> Map
* @return Map&lt;K, V&gt;
*/
public static <SV, K, V, M extends Map<K, V>> M k_o(Collection<SV> src, BiFunction<Integer, SV, K> kf, BiFunction<Integer, SV, V> vf, Supplier<M> mf) {
if (CollUtil.isEmpty(src)) return MapUtil.empty(null);
M map = mf.get();
int i = 0;
for (SV sv : src) {
K k = kf.apply(i, sv);
if (map.containsKey(k)) throw Exceptions.error("重复键:{}", sv);
V v = vf.apply(i, sv);
map.put(k, v);
i++;
}
return map;
}
// endregion
// region Stream
/**
* <p></p>
* <p>Map HashMap, kf, </p>
*
* @param stream
* @param kf
* @param <SV>
* @param <K>
* @return Map&lt;K, SV&gt;
*/
public static <SV, K> Map<K, SV> k_o(Stream<SV> stream, Function<SV, K> kf) {
return k_o(stream, kf, it -> it, HashMap::new);
}
/**
* <p></p>
* <p>Map HashMap, kf, vf</p>
*
* @param stream
* @param kf
* @param vf
* @param <SV>
* @param <K>
* @param <V>
* @return Map&lt;K, V&gt;
*/
public static <SV, K, V> Map<K, V> k_o(Stream<SV> stream, Function<SV, K> kf, Function<SV, V> vf) {
return k_o(stream, kf, vf, HashMap::new);
}
/**
* <p></p>
* <p>Map mf, kf, vf</p>
*
* @param stream
* @param kf
* @param mf Map
* @param <SV>
* @param <K>
* @param <M> Map
* @return Map&lt;K, SV&gt;
*/
public static <SV, K, M extends Map<K, SV>> M k_o(Stream<SV> stream, Function<SV, K> kf, Supplier<M> mf) {
return k_o(stream, kf, it -> it, mf);
}
/**
* <p></p>
* <p>Map mf, kf, vf</p>
*
* @param stream
* @param kf
* @param vf
* @param mf Map
* @param <SV>
* @param <K>
* @param <V>
* @param <M> Map
* @return Map&lt;K, V&gt;
*/
public static <SV, K, V, M extends Map<K, V>> M k_o(Stream<SV> stream, Function<SV, K> kf, Function<SV, V> vf, Supplier<M> mf) {
if (stream == null) return MapUtil.empty(null);
BinaryOperator<V> op = (oldVal, val) -> {
throw Exceptions.error("值【{}】与【{}】对应的键重复", Fastjson.toJsonStr(oldVal), Fastjson.toJsonStr(val));
};
return stream.collect(Collectors.toMap(kf, vf, op, mf));
}
// endregion
// endregion
// region K-A
// region Collection
/**
* <p></p>
* <p>Map HashMap, kf, </p>
*
* @param src
* @param kf
* @param <K>
* @param <SV>
* @return Map&lt;K, List&lt;V&gt;&gt;
*/
public static <SV, K> Map<K, List<SV>> k_a(Collection<SV> src, Function<SV, K> kf) {
return k_a(src, kf, it -> it, HashMap::new);
}
/**
* <p></p>
* <p>Map HashMap, kf, vf</p>
*
* @param src
* @param kf
* @param vf
* @param <SV>
* @param <K>
* @param <V>
* @return Map&lt;K, List&lt;V&gt;&gt;
*/
public static <SV, K, V> Map<K, List<V>> k_a(Collection<SV> src, Function<SV, K> kf, Function<SV, V> vf) {
return k_a(src, kf, vf, HashMap::new);
}
/**
* <p></p>
* <p>Map mf, kf, </p>
*
* @param src
* @param kf
* @param mf Map
* @param <SV>
* @param <K>
* @param <M> Map
* @return Map&lt;K, List&lt;SV&gt;&gt;
*/
public static <SV, K, M extends Map<K, List<SV>>> M k_a(Collection<SV> src, Function<SV, K> kf, Supplier<M> mf) {
return k_a(src, kf, it -> it, mf);
}
/**
* <p></p>
* <p>Map mf, kf, vf</p>
*
* @param src
* @param kf
* @param vf
* @param mf Map
* @param <SV>
* @param <K>
* @param <V>
* @param <M> Map
* @return Map&lt;K, List&lt;V&gt;&gt;
*/
public static <SV, K, V, M extends Map<K, List<V>>> M k_a(Collection<SV> src, Function<SV, K> kf, Function<SV, V> vf, Supplier<M> mf) {
if (CollUtil.isEmpty(src)) return MapUtil.empty(null);
return src.stream().collect(Collectors.groupingBy(kf, mf, Collectors.mapping(vf, Collectors.toList())));
}
// endregion
// region Stream
/**
* <p></p>
* <p>Map HashMap, kf, </p>
*
* @param stream
* @param kf
* @param <K>
* @param <SV>
* @return Map&lt;K, List&lt;V&gt;&gt;
*/
public static <SV, K> Map<K, List<SV>> k_a(Stream<SV> stream, Function<SV, K> kf) {
return k_a(stream, kf, it -> it, HashMap::new);
}
/**
* <p></p>
* <p>Map HashMap, kf, vf</p>
*
* @param stream
* @param kf
* @param vf
* @param <SV>
* @param <K>
* @param <V>
* @return Map&lt;K, List&lt;V&gt;&gt;
*/
public static <SV, K, V> Map<K, List<V>> k_a(Stream<SV> stream, Function<SV, K> kf, Function<SV, V> vf) {
return k_a(stream, kf, vf, HashMap::new);
}
/**
* <p></p>
* <p>Map mf, kf, </p>
*
* @param stream
* @param kf
* @param mf Map
* @param <SV>
* @param <K>
* @param <M> Map
* @return Map&lt;K, List&lt;SV&gt;&gt;
*/
public static <SV, K, M extends Map<K, List<SV>>> M k_a(Stream<SV> stream, Function<SV, K> kf, Supplier<M> mf) {
return k_a(stream, kf, it -> it, mf);
}
/**
* <p></p>
* <p>Map mf, kf, vf</p>
*
* @param stream
* @param kf
* @param vf
* @param mf Map
* @param <SV>
* @param <K>
* @param <V>
* @param <M> Map
* @return Map&lt;K, List&lt;V&gt;&gt;
*/
public static <SV, K, V, M extends Map<K, List<V>>> M k_a(Stream<SV> stream, Function<SV, K> kf, Function<SV, V> vf, Supplier<M> mf) {
if (stream == null) return MapUtil.empty(null);
return stream.collect(Collectors.groupingBy(kf, mf, Collectors.mapping(vf, Collectors.toList())));
}
// endregion
// endregion
// region K-S
// region Collection
/**
* <p></p>
* <p>Map HashMap, kf, </p>
*
* @param src
* @param kf
* @param <SV>
* @param <K>
* @return Map&lt;K, Set&lt;SV&gt;&gt;
*/
public static <SV, K> Map<K, Set<SV>> k_s(Collection<SV> src, Function<SV, K> kf) {
return k_s(src, kf, it -> it, HashMap::new);
}
/**
* <p></p>
* <p>Map HashMap, kf, vf</p>
*
* @param src
* @param kf
* @param vf
* @param <SV>
* @param <K>
* @param <V>
* @return Map&lt;K, Set&lt;V&gt;&gt;
*/
public static <SV, K, V> Map<K, Set<V>> k_s(Collection<SV> src, Function<SV, K> kf, Function<SV, V> vf) {
return k_s(src, kf, vf, HashMap::new);
}
/**
* <p></p>
* <p>Map mf, kf, vf</p>
*
* @param src
* @param kf
* @param mf Map
* @param <K>
* @param <SV>
* @param <M> Map
* @return Map&lt;K, Set&lt;SV&gt;&gt;
*/
public static <SV, K, M extends Map<K, Set<SV>>> M k_s(Collection<SV> src, Function<SV, K> kf, Supplier<M> mf) {
return k_s(src, kf, it -> it, mf);
}
/**
* <p></p>
* <p>Map mf, kf, vf</p>
*
* @param src
* @param kf
* @param vf
* @param mf Map
* @param <SV>
* @param <K>
* @param <V>
* @param <M> Map
* @return Map&lt;K, Set&lt;V&gt;&gt;
*/
public static <SV, K, V, M extends Map<K, Set<V>>> M k_s(Collection<SV> src, Function<SV, K> kf, Function<SV, V> vf, Supplier<M> mf) {
if (CollUtil.isEmpty(src)) return MapUtil.empty(null);
return src.stream().collect(Collectors.groupingBy(kf, mf, Collectors.mapping(vf, Collectors.toSet())));
}
// endregion
// region Stream
/**
* <p></p>
* <p>Map HashMap, kf, </p>
*
* @param stream
* @param kf
* @param <SV>
* @param <K>
* @return Map&lt;K, Set&lt;SV&gt;&gt;
*/
public static <SV, K> Map<K, Set<SV>> k_s(Stream<SV> stream, Function<SV, K> kf) {
return k_s(stream, kf, it -> it, HashMap::new);
}
/**
* <p></p>
* <p>Map HashMap, kf, vf</p>
*
* @param stream
* @param kf
* @param vf
* @param <SV>
* @param <K>
* @param <V>
* @return Map&lt;K, Set&lt;V&gt;&gt;
*/
public static <SV, K, V> Map<K, Set<V>> k_s(Stream<SV> stream, Function<SV, K> kf, Function<SV, V> vf) {
return k_s(stream, kf, vf, HashMap::new);
}
/**
* <p></p>
* <p>Map mf, kf, vf</p>
*
* @param stream
* @param kf
* @param mf Map
* @param <K>
* @param <SV>
* @param <M> Map
* @return Map&lt;K, Set&lt;SV&gt;&gt;
*/
public static <SV, K, M extends Map<K, Set<SV>>> M k_s(Stream<SV> stream, Function<SV, K> kf, Supplier<M> mf) {
return k_s(stream, kf, it -> it, mf);
}
/**
* <p></p>
* <p>Map mf, kf, vf</p>
*
* @param stream
* @param kf
* @param vf
* @param mf Map
* @param <SV>
* @param <K>
* @param <V>
* @param <M> Map
* @return Map&lt;K, Set&lt;V&gt;&gt;
*/
public static <SV, K, V, M extends Map<K, Set<V>>> M k_s(Stream<SV> stream, Function<SV, K> kf, Function<SV, V> vf, Supplier<M> mf) {
if (stream == null) return MapUtil.empty(null);
return stream.collect(Collectors.groupingBy(kf, mf, Collectors.mapping(vf, Collectors.toSet())));
}
// endregion
// endregion
}

View File

@ -0,0 +1,11 @@
package com.njzscloud.gps;
/**
* Hello world!
*
*/
public class App {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<property name="log_path" value="logs"/>
<property name="service_name" value="${project.artifactId}"/>
<property name="console_pattern" value="%magenta(%d{yyyy-MM-dd HH:mm:ss.SSS}) %clr(%-5p) %blue([%t]) %cyan(%c) %blue([%M:%L]): %clr(%m%n)"/>
<property name="file_pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%t] %c [%M:%L] : %m%n"/>
<appender name="console_appender" class="ch.qos.logback.core.ConsoleAppender">
<withJansi>false</withJansi>
<encoder>
<pattern>${console_pattern}</pattern>
</encoder>
</appender>
<appender name="file_appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log_path}/${service_name}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log_path}/%d{yyyy-MM, aux}/${service_name}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>15</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${file_pattern}</pattern>
</encoder>
</appender>
<!-- TRACE < DEBUG < INFO < WARN < ERROR -->
<root level="WARN">
<appender-ref ref="console_appender"/>
<appender-ref ref="file_appender"/>
</root>
</configuration>