1
0

feat(all): 搭建基本框架和模块

This commit is contained in:
2024-11-15 15:35:08 +08:00
commit 1900265075
174 changed files with 87868 additions and 0 deletions

46
gringotts-forest/pom.xml Normal file
View File

@@ -0,0 +1,46 @@
<?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>
<groupId>com.eshore</groupId>
<artifactId>gringotts</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>gringotts-forest</artifactId>
<dependencies>
<dependency>
<groupId>com.eshore</groupId>
<artifactId>gringotts-configuration</artifactId>
</dependency>
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,68 @@
package com.eshore.gringotts.forest.configuration;
import com.dtflys.forest.converter.text.DefaultTextConverter;
import com.dtflys.forest.utils.StringUtils;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
/**
* Forest增强文本类型转换
*
* @author lanyuanxiaoyao
* @date 2024-05-06
*/
@SuppressWarnings("unchecked")
public class EnhanceTextConverter extends DefaultTextConverter {
private Object convert(byte[] source, Charset charset, String type) throws Exception {
return convert(StringUtils.fromBytes(source, charset), type);
}
private Object convert(String source, String type) throws Exception {
switch (type) {
case "boolean":
case "java.lang.Boolean":
return Boolean.valueOf(source);
case "int":
case "java.lang.Integer":
return Integer.valueOf(source);
case "long":
case "java.lang.Long":
return Long.valueOf(source);
case "float":
case "java.lang.Float":
return Float.valueOf(source);
case "double":
case "java.lang.Double":
return Double.valueOf(source);
default:
throw new Exception("the source may not be primary type");
}
}
@Override
public <T> T convertToJavaObject(String source, Type targetType) {
try {
return (T) convert(source, targetType.getTypeName());
} catch (Exception e) {
return super.convertToJavaObject(source, targetType);
}
}
@Override
public <T> T convertToJavaObject(byte[] source, Class<T> targetType, Charset charset) {
try {
return (T) convert(source, charset, targetType.getName());
} catch (Exception e) {
return super.convertToJavaObject(source, targetType, charset);
}
}
@Override
public <T> T convertToJavaObject(byte[] source, Type targetType, Charset charset) {
try {
return (T) convert(source, charset, targetType.getTypeName());
} catch (Exception e) {
return super.convertToJavaObject(source, targetType, charset);
}
}
}

View File

@@ -0,0 +1,30 @@
package com.eshore.gringotts.forest.configuration;
import com.dtflys.forest.converter.json.ForestJacksonConverter;
import com.dtflys.forest.converter.text.DefaultTextConverter;
import com.dtflys.forest.springboot.annotation.ForestScan;
import com.fasterxml.jackson.datatype.eclipsecollections.EclipseCollectionsModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author lanyuanxiaoyao
* @date 2023-04-24
*/
@ForestScan(basePackages = {"com.eshore.gringotts.forest.service"})
@Configuration
public class ForestsConfiguration {
@Bean
public ForestJacksonConverter forestJacksonConverter() {
ForestJacksonConverter converter = new ForestJacksonConverter();
converter.getMapper().registerModule(new EclipseCollectionsModule());
converter.getMapper().registerModule(new JavaTimeModule());
return converter;
}
@Bean
public DefaultTextConverter defaultTextConverter() {
return new EnhanceTextConverter();
}
}

View File

@@ -0,0 +1,95 @@
package com.eshore.gringotts.forest.configuration;
import cn.hutool.core.util.ObjectUtil;
import com.dtflys.forest.exceptions.ForestRuntimeException;
import com.dtflys.forest.http.ForestQueryMap;
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.http.ForestResponse;
import com.dtflys.forest.interceptor.Interceptor;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.MutableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 指标
*
* @author lanyuanxiaoyao
* @date 2024-01-31
*/
@SuppressWarnings("unchecked")
@Component
public class MetricsInterceptor implements Interceptor<Object> {
public static final String FOREST_SEND_REQUEST = "service_forest_send_request";
public static final String FOREST_SEND_REQUEST_SECONDS = "service_forest_send_request_seconds";
private static final Logger logger = LoggerFactory.getLogger(MetricsInterceptor.class);
private static final String PARSED_TAGS = "parsed_tags";
private final MeterRegistry meterRegistry;
public MetricsInterceptor(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
private Iterable<Tag> parseTags(ForestRequest<?> request) {
MutableList<Tag> tags = Lists.mutable.of(
Tag.of("host", request.getHost()),
Tag.of("port", String.valueOf(request.getPort())),
Tag.of("path", request.getPath()),
Tag.of("schema", request.getScheme())
);
ForestQueryMap query = request.getQuery();
if (ObjectUtil.isNotEmpty(query)) {
for (Map.Entry<String, Object> entry : query.entrySet()) {
tags.add(Tag.of("query_" + entry.getKey(), String.valueOf(entry.getValue())));
}
}
return tags;
}
private void increaseCounter(Integer code, MutableList<Tag> tags) {
meterRegistry.counter(
MetricsInterceptor.FOREST_SEND_REQUEST,
tags.with(Tag.of("code", String.valueOf(code)))
).increment();
}
@Override
public boolean beforeExecute(ForestRequest request) {
addAttribute(request, PARSED_TAGS, parseTags(request));
return Interceptor.super.beforeExecute(request);
}
@Override
public void afterExecute(ForestRequest request, ForestResponse response) {
Interceptor.super.afterExecute(request, response);
MutableList<Tag> tags = (MutableList<Tag>) getAttribute(request, PARSED_TAGS);
meterRegistry.timer(FOREST_SEND_REQUEST_SECONDS, tags)
.record(response.getTimeAsMillisecond(), TimeUnit.MILLISECONDS);
}
@Override
public void onSuccess(Object data, ForestRequest request, ForestResponse response) {
Interceptor.super.onSuccess(data, request, response);
MutableList<Tag> tags = (MutableList<Tag>) getAttribute(request, PARSED_TAGS);
if (ObjectUtil.isNotNull(tags)) {
increaseCounter(response.statusCode(), tags);
}
}
@Override
public void onError(ForestRuntimeException ex, ForestRequest request, ForestResponse response) {
Interceptor.super.onError(ex, request, response);
MutableList<Tag> tags = (MutableList<Tag>) getAttribute(request, PARSED_TAGS);
if (ObjectUtil.isNotNull(tags)) {
increaseCounter(response.statusCode(), tags);
}
}
}

View File

@@ -0,0 +1,44 @@
package com.eshore.gringotts.forest.configuration;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.dtflys.forest.http.ForestAddress;
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.interceptor.Interceptor;
import java.net.URL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.stereotype.Component;
/**
* @author lanyuanxiaoyao
* @date 2023-04-24
*/
@Component
public class SpringCloudDiscoveryInterceptor implements Interceptor<Object> {
private static final Logger logger = LoggerFactory.getLogger(SpringCloudDiscoveryInterceptor.class);
private final LoadBalancerClient loadBalancerClient;
public SpringCloudDiscoveryInterceptor(LoadBalancerClient loadBalancerClient) {
this.loadBalancerClient = loadBalancerClient;
}
@Override
public boolean beforeExecute(ForestRequest request) {
// Load
URL url = URLUtil.url(request.getUrl());
String host = url.getHost();
if (StrUtil.isNotBlank(host)) {
ServiceInstance instance = loadBalancerClient.choose(host);
if (ObjectUtil.isNotNull(instance)) {
request.setAddress(new ForestAddress(instance.getScheme(), instance.getHost(), instance.getPort()));
}
}
// TODO 内网访问参数加密
return Interceptor.super.beforeExecute(request);
}
}

View File

@@ -0,0 +1,28 @@
package com.eshore.gringotts.forest.service;
import com.dtflys.forest.annotation.BaseRequest;
import com.dtflys.forest.annotation.Body;
import com.dtflys.forest.annotation.BodyType;
import com.dtflys.forest.annotation.JSONBody;
import com.dtflys.forest.annotation.Query;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
/**
* 区块链服务
*
* @author lanyuanxiaoyao
* @date 2024-11-15
*/
@BaseRequest(baseURL = "http://gringotts-chain")
public interface ChainService {
@GetMapping("/kv_datasource/create")
String create();
@PostMapping("/kv_datasource/set")
@BodyType("text")
String set(@Query("address")String address, @Query("key") String key, @Body String json);
@GetMapping("/kv_datasource/get")
String get(@Query("address")String address, @Query("key") String key);
}