fix bugs
This commit is contained in:
37
blade-starter-mongo/pom.xml
Normal file
37
blade-starter-mongo/pom.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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>
|
||||
<parent>
|
||||
<artifactId>BladeX-Tool</artifactId>
|
||||
<groupId>org.springblade</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>blade-starter-mongo</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<version>${project.parent.version}</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-tool</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-json</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-auto</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.springblade.core.mongo.config;
|
||||
|
||||
import org.springblade.core.mongo.converter.DBObjectToJsonNodeConverter;
|
||||
import org.springblade.core.mongo.converter.JsonNodeToDocumentConverter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* mongo 配置
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@AutoConfiguration
|
||||
public class MongoConfiguration {
|
||||
|
||||
@Bean
|
||||
public MongoCustomConversions customConversions() {
|
||||
List<Converter<?,?>> converters = new ArrayList<>(2);
|
||||
converters.add(DBObjectToJsonNodeConverter.INSTANCE);
|
||||
converters.add(JsonNodeToDocumentConverter.INSTANCE);
|
||||
return new MongoCustomConversions(converters);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.springblade.core.mongo.converter;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.bson.BasicBSONObject;
|
||||
import org.springblade.core.tool.jackson.JsonUtil;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.convert.ReadingConverter;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* mongo DBObject 转 jsonNode
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@ReadingConverter
|
||||
public enum DBObjectToJsonNodeConverter implements Converter<BasicBSONObject, JsonNode> {
|
||||
/**
|
||||
* 实例
|
||||
*/
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public JsonNode convert(@Nullable BasicBSONObject source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
return JsonUtil.getInstance().valueToTree(source);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.springblade.core.mongo.converter;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.bson.Document;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* JsonNode 转 mongo Document
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@WritingConverter
|
||||
public enum JsonNodeToDocumentConverter implements Converter<ObjectNode, Document> {
|
||||
/**
|
||||
* 实例
|
||||
*/
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public Document convert(@Nullable ObjectNode source) {
|
||||
return source == null ? null : Document.parse(source.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.springblade.core.mongo.utils;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.Getter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* json tree 节点信息
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public class JsonNodeInfo {
|
||||
/**
|
||||
* mongo keys: class1.class2.item
|
||||
*/
|
||||
private volatile String nodeKeys;
|
||||
/**
|
||||
* jsonPath语法:/class1/class2/item
|
||||
*/
|
||||
private volatile String nodePath;
|
||||
/**
|
||||
* 节点关系
|
||||
*/
|
||||
@Getter
|
||||
private final LinkedList<String> elements;
|
||||
/**
|
||||
* tree 的 叶子节点,此处为引用
|
||||
*/
|
||||
@Getter
|
||||
private final JsonNode leafNode;
|
||||
|
||||
public JsonNodeInfo(LinkedList<String> elements, JsonNode leafNode) {
|
||||
Assert.notNull(elements, "elements can not be null.");
|
||||
this.nodeKeys = null;
|
||||
this.nodePath = null;
|
||||
this.elements = elements;
|
||||
this.leafNode = leafNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 mongo db的 key 语法
|
||||
* @return mongo db的 key 语法
|
||||
*/
|
||||
public String getNodeKeys() {
|
||||
if (nodeKeys == null) {
|
||||
synchronized (this) {
|
||||
if (nodeKeys == null) {
|
||||
StringJoiner nodeKeysJoiner = new StringJoiner(".");
|
||||
elements.forEach(nodeKeysJoiner::add);
|
||||
nodeKeys = nodeKeysJoiner.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodeKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 json path 语法路径
|
||||
* @return jsonPath 路径
|
||||
*/
|
||||
public String getNodePath() {
|
||||
if (nodePath == null) {
|
||||
synchronized (this) {
|
||||
if (nodePath == null) {
|
||||
StringJoiner nodePathJoiner = new StringJoiner("/", "/", "");
|
||||
elements.forEach(nodePathJoiner::add);
|
||||
nodePath = nodePathJoiner.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取第一个元素
|
||||
* @return element
|
||||
*/
|
||||
public String getFirst() {
|
||||
return elements.getFirst();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package org.springblade.core.mongo.utils;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 处理 mongo json 数据结构
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public class MongoJsonUtils {
|
||||
|
||||
/**
|
||||
* 获取所有的叶子节点和路径信息
|
||||
*
|
||||
* @param jsonNode jsonTree
|
||||
* @return tree叶子信息
|
||||
*/
|
||||
public static List<JsonNodeInfo> getLeafNodes(JsonNode jsonNode) {
|
||||
if (jsonNode == null || !jsonNode.isObject()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<JsonNodeInfo> list = new ArrayList<>();
|
||||
// 双向的队列 Deque 代替 Stack,Stack 性能不好
|
||||
LinkedList<String> deque = new LinkedList<>();
|
||||
// 递归获取叶子 🍃🍃🍃 节点
|
||||
getLeafNodes(jsonNode, null, deque, list);
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void getLeafNodes(JsonNode jsonNode, JsonNode parentNode, LinkedList<String> deque, List<JsonNodeInfo> list) {
|
||||
Iterator<Map.Entry<String, JsonNode>> iterator;
|
||||
if (parentNode == null) {
|
||||
iterator = jsonNode.fields();
|
||||
} else {
|
||||
iterator = parentNode.fields();
|
||||
}
|
||||
// tree 子节点
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, JsonNode> entry = iterator.next();
|
||||
String fieldName = entry.getKey();
|
||||
JsonNode nextNode = entry.getValue();
|
||||
// 如果不是值节点
|
||||
if (nextNode.isObject()) {
|
||||
// 添加到队列尾,先进先出
|
||||
deque.addLast(fieldName);
|
||||
getLeafNodes(parentNode, nextNode, deque, list);
|
||||
}
|
||||
// 如果是值节点,也就是到叶子节点了,取叶子节点上级即可
|
||||
if (nextNode.isValueNode()) {
|
||||
// 封装节点列表
|
||||
LinkedList<String> elements = new LinkedList<>(deque);
|
||||
// tree 的 叶子节点,此处为引用
|
||||
list.add(new JsonNodeInfo(elements, parentNode));
|
||||
break;
|
||||
}
|
||||
// 栈非空时弹出
|
||||
if (!deque.isEmpty()) {
|
||||
deque.removeLast();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建树形节点
|
||||
*
|
||||
* @param jsonNode 父级节点
|
||||
* @param elements tree节点列表
|
||||
* @return JsonNode 叶子节点,返回用于塞数据
|
||||
*/
|
||||
public static ObjectNode buildNode(ObjectNode jsonNode, List<String> elements) {
|
||||
ObjectNode newNode = jsonNode;
|
||||
for (String element : elements) {
|
||||
// 如果已经存在节点,这不生成新的
|
||||
if (newNode.has(element)) {
|
||||
newNode = (ObjectNode) newNode.get(element);
|
||||
} else {
|
||||
newNode = newNode.putObject(element);
|
||||
}
|
||||
}
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有 🍃🍃🍃 节点的值,并构建成 mongodb update 语句
|
||||
* @param prefix 前缀
|
||||
* @param nodeKeys mongo keys
|
||||
* @param objectNode tree 🍃 节点
|
||||
* @return tree 节点信息
|
||||
*/
|
||||
public static Map<String, Object> getAllUpdate(String prefix, String nodeKeys, ObjectNode objectNode) {
|
||||
Map<String, Object> values = new HashMap<>(8);
|
||||
Iterator<String> iterator = objectNode.fieldNames();
|
||||
while (iterator.hasNext()) {
|
||||
String fieldName = iterator.next();
|
||||
JsonNode valueNode = objectNode.get(fieldName);
|
||||
if (valueNode.isValueNode()) {
|
||||
Object value;
|
||||
if (valueNode.isShort()) {
|
||||
value = valueNode.shortValue();
|
||||
} else if (valueNode.isInt()) {
|
||||
value = valueNode.intValue();
|
||||
} else if (valueNode.isLong()) {
|
||||
value = valueNode.longValue();
|
||||
} else if (valueNode.isBoolean()) {
|
||||
value = valueNode.booleanValue();
|
||||
} else if (valueNode.isFloat()) {
|
||||
value = valueNode.floatValue();
|
||||
} else if (valueNode.isDouble()) {
|
||||
value = valueNode.doubleValue();
|
||||
} else if (valueNode.isMissingNode()) {
|
||||
value = null;
|
||||
} else {
|
||||
value = valueNode.textValue();
|
||||
}
|
||||
if (value != null) {
|
||||
String valueKey = prefix + '.' + nodeKeys + '.' + fieldName;
|
||||
values.put(valueKey, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user