Commit 12d3492e by yuwei

项目初始化

parent 2566a1de
package cn.datax.common.rabbitmq.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
public class RabbitMqConfig implements BeanPostProcessor {
@Autowired
private RabbitAdmin rabbitAdmin;
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
// 只有设置为 true,spring 才会加载 RabbitAdmin 这个类
rabbitAdmin.setAutoStartup(true);
return rabbitAdmin;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
rabbitAdmin.declareExchange(rabbitmqApiReleaseFanoutExchange());
rabbitAdmin.declareQueue(fanoutExchangeQueueApiRelease());
rabbitAdmin.declareExchange(rabbitmqApiCancelFanoutExchange());
rabbitAdmin.declareQueue(fanoutExchangeQueueApiCancel());
return null;
}
/**
* 队列API发布
* @return
*/
@Bean
public Queue fanoutExchangeQueueApiRelease() {
/**
* 1、name: 队列名称
* 2、durable: 是否持久化
* 3、exclusive: 是否独享、排外的。如果设置为true,定义为排他队列。则只有创建者可以使用此队列。也就是private私有的。
* 4、autoDelete: 是否自动删除。也就是临时队列。当最后一个消费者断开连接后,会自动删除。
* */
return new Queue(RabbitMqConstant.FANOUT_EXCHANGE_QUEUE_TOPIC_API_RELEASE, true, false, false);
}
/**
* 创建队列API发布FanoutExchange类型交换机
* @return
*/
@Bean
public FanoutExchange rabbitmqApiReleaseFanoutExchange() {
return new FanoutExchange(RabbitMqConstant.FANOUT_EXCHANGE_API_RELEASE_NAME, true, false);
}
/**
* 队列API发布绑定到FanoutExchange交换机
* @return
*/
@Bean
public Binding bindFanoutApiRelease() {
return BindingBuilder.bind(fanoutExchangeQueueApiRelease()).to(rabbitmqApiReleaseFanoutExchange());
}
/**
* 队列API注销
* @return
*/
@Bean
public Queue fanoutExchangeQueueApiCancel() {
/**
* 1、name: 队列名称
* 2、durable: 是否持久化
* 3、exclusive: 是否独享、排外的。如果设置为true,定义为排他队列。则只有创建者可以使用此队列。也就是private私有的。
* 4、autoDelete: 是否自动删除。也就是临时队列。当最后一个消费者断开连接后,会自动删除。
* */
return new Queue(RabbitMqConstant.FANOUT_EXCHANGE_QUEUE_TOPIC_API_CANCEL, true, false, false);
}
/**
* 创建队列API注销FanoutExchange类型交换机
* @return
*/
@Bean
public FanoutExchange rabbitmqApiCancelFanoutExchange() {
return new FanoutExchange(RabbitMqConstant.FANOUT_EXCHANGE_API_CANCEL_NAME, true, false);
}
/**
* 队列API注销绑定到FanoutExchange交换机
* @return
*/
@Bean
public Binding bindFanoutApiCancel() {
return BindingBuilder.bind(fanoutExchangeQueueApiCancel()).to(rabbitmqApiCancelFanoutExchange());
}
}
......@@ -3,22 +3,24 @@ package cn.datax.common.rabbitmq.config;
public class RabbitMqConstant {
/**
* RabbitMQ的FANOUT_EXCHANG交换机类型的队列API发布的名称
*/
public static final String FANOUT_EXCHANGE_QUEUE_TOPIC_API_RELEASE = "fanout.api.release";
/**
* RabbitMQ的FANOUT_EXCHANG交换机类型的名称
*/
public static final String FANOUT_EXCHANGE_API_RELEASE_NAME = "fanout.exchange.api.release.name";
/**
* RabbitMQ的FANOUT_EXCHANG交换机类型的队列API注销的名称
* RabbitMQ的FANOUT_EXCHANG交换机类型的队列API发布的名称
* 消费者1
*/
public static final String FANOUT_EXCHANGE_QUEUE_TOPIC_API_CANCEL = "fanout.api.cancel";
public static final String FANOUT_EXCHANGE_QUEUE_TOPIC_API_RELEASE1 = "fanout.api.release1";
/**
* RabbitMQ的FANOUT_EXCHANG交换机类型的名称
*/
public static final String FANOUT_EXCHANGE_API_CANCEL_NAME = "fanout.exchange.api.cancel.name";
/**
* RabbitMQ的FANOUT_EXCHANG交换机类型的队列API注销的名称
* 消费者1
*/
public static final String FANOUT_EXCHANGE_QUEUE_TOPIC_API_CANCEL1 = "fanout.api.cancel1";
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.datax.common.rabbitmq.config.RabbitMqConfig
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
......@@ -29,10 +29,5 @@
<artifactId>redisson</artifactId>
<version>${redisson.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package cn.datax.common.redis.aspectj;
import cn.datax.common.redis.annotation.RedisCacheAop;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
......@@ -92,9 +91,9 @@ public class RedisCacheAspect {
* 可以直接针对mapper进行缓存,如果mapper查询返回的List<Objec> 需要isArray 为true 否则转换异常
*/
if (isArray){
return JSON.parseArray(value, objectType);
// return JSON.parseArray(value, objectType);
}else {
return JSON.parseObject(value,objectType);
// return JSON.parseObject(value,objectType);
}
}
} catch (Throwable e) {
......
......@@ -64,6 +64,15 @@ hystrix:
isolation:
thread:
timeoutInMilliseconds: 60000 #断路器超时时间,默认1000ms
dataApiMappingHystrix: #api调用方法的超时时间 60s
fallback:
enabled: true
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 60000 #断路器超时时间,默认1000ms
shareSecurityContext: true
#请求处理的超时时间
......
......@@ -2,7 +2,7 @@
spring:
redis:
database: 1
host: 192.168.234.101
host: localhost
port: 6379
password: 1234@abcd # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
......@@ -42,6 +42,6 @@ spring:
datasource:
mysql:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.234.100:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:mysql://localhost:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 1234@abcd
......@@ -72,6 +72,18 @@ spring:
args:
name: dataFactoryHystrix
fallbackUri: forward:/fallback
# 数据SQL工作台
- id: datax-service-data-sql-console
uri: lb://datax-service-data-sql-console
predicates:
- Path=/data/console/**
filters:
- SwaggerHeaderFilter
- StripPrefix=2
- name: Hystrix
args:
name: dataSqlConsoleHystrix
fallbackUri: forward:/fallback
# 数据市场中心
- id: datax-service-data-market
uri: lb://datax-service-data-market
......@@ -84,17 +96,17 @@ spring:
args:
name: dataMarketHystrix
fallbackUri: forward:/fallback
# 数据SQL工作台
- id: datax-service-data-sql-console
uri: lb://datax-service-data-sql-console
# 数据API注册
- id: datax-service-data-api-mapping
uri: lb://datax-service-data-api-mapping
predicates:
- Path=/data/console/**
- Path=/data/api/**
filters:
- SwaggerHeaderFilter
- StripPrefix=2
- name: Hystrix
args:
name: dataSqlConsoleHystrix
name: dataApiMappingHystrix
fallbackUri: forward:/fallback
# 定时任务
- id: datax-service-quartz
......
......@@ -2,7 +2,7 @@
spring:
redis:
database: 1
host: 192.168.234.101
host: localhost
port: 6379
password: 1234@abcd # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
......@@ -42,7 +42,7 @@ spring:
datasource:
mysql:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://192.168.234.100:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:p6spy:mysql://localhost:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 1234@abcd
......
# 数据源配置
spring:
redis:
database: 1
host: localhost
port: 6379
password: 1234@abcd # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
lettuce:
pool:
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
rabbitmq:
host: localhost
port: 5672
username: admin
password: 1234@abcd
datasource:
dynamic:
type: com.zaxxer.hikari.HikariDataSource
hikari:
auto-commit: false
connection-timeout: 30000
idle-timeout: 25000
login-timeout: 5
max-lifetime: 30000
read-only: false
validation-timeout: 3000
maximum-pool-size: 15
minimum-idle: 5
pool-name: DataxHikariCP
connection-test-query: SELECT 1 FROM DUAL
data-source-properties:
cachePrepStmts: true
prepStmtCacheSize: 250
prepStmtCacheSqlLimit: 2048
useServerPrepStmts: true
useLocalSessionState: true
rewriteBatchedStatements: true
cacheResultSetMetadata: true
cacheServerConfiguration: true
elideSetAutoCommits: true
maintainTimeStats: false
primary: mysql
datasource:
mysql:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://localhost:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 1234@abcd
mybatis-plus:
mapper-locations: classpath*:mapper/*Mapper.xml
type-aliases-package: cn.datax.service.data.factory.api.entity
global-config:
db-config:
id-type: ASSIGN_ID
banner: false
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
call-setters-on-nulls: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# spring security 配置
security:
oauth2:
client:
access-token-uri: http://localhost:8612/auth/oauth/token
user-authorization-uri: http://localhost:8612/auth/oauth/authorize
client-id: datax
client-secret: 123456
scope: all
resource:
loadBalanced: true
token-info-uri: http://localhost:8612/auth/oauth/check_token
# Swagger界面内容配置
swagger:
title: API接口文档
description: Api Documentation
version: 1.0.0
basePackage: cn.datax.service.data.market.api.mapping.controller
termsOfServiceUrl: http://www.baidu.com
contact:
name: yuwei
url: http://www.baidu.com
email: 312075478@qq.com
\ No newline at end of file
......@@ -2,7 +2,7 @@
spring:
redis:
database: 1
host: 192.168.234.101
host: localhost
port: 6379
password: 1234@abcd # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
......@@ -42,7 +42,7 @@ spring:
datasource:
mysql:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://192.168.234.100:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:p6spy:mysql://localhost:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 1234@abcd
......
......@@ -2,7 +2,7 @@
spring:
redis:
database: 1
host: 192.168.234.101
host: localhost
port: 6379
password: 1234@abcd # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
......@@ -13,7 +13,7 @@ spring:
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
rabbitmq:
host: 192.168.234.106
host: localhost
port: 5672
username: admin
password: 1234@abcd
......@@ -47,7 +47,7 @@ spring:
datasource:
mysql:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://192.168.234.100:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:p6spy:mysql://localhost:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 1234@abcd
......
......@@ -2,7 +2,7 @@
spring:
redis:
database: 1
host: 192.168.234.101
host: localhost
port: 6379
password: 1234@abcd # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
......@@ -42,7 +42,7 @@ spring:
datasource:
mysql:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://192.168.234.100:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:p6spy:mysql://localhost:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 1234@abcd
......
......@@ -13,7 +13,7 @@ spring:
properties.mail.smtp.ssl.enable: true
redis:
database: 1
host: 192.168.234.101
host: localhost
port: 6379
password: 1234@abcd # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
......@@ -53,7 +53,7 @@ spring:
datasource:
mysql:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://192.168.234.100:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:p6spy:mysql://localhost:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 1234@abcd
......
......@@ -2,7 +2,7 @@
spring:
redis:
database: 1
host: 192.168.234.101
host: localhost
port: 6379
password: 1234@abcd # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
......@@ -42,7 +42,7 @@ spring:
datasource:
mysql:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://192.168.234.100:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:p6spy:mysql://localhost:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 1234@abcd
......
......@@ -2,7 +2,7 @@
spring:
redis:
database: 1
host: 192.168.234.101
host: localhost
port: 6379
password: 1234@abcd # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
......@@ -15,12 +15,12 @@ spring:
datasource:
mysql:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://192.168.234.100:3306/data_cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:p6spy:mysql://localhost:3306/data_cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 1234@abcd
quartz:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.234.100:3306/data_cloud_quartz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:mysql://localhost:3306/data_cloud_quartz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 1234@abcd
type: com.zaxxer.hikari.HikariDataSource
......
......@@ -2,7 +2,7 @@
spring:
redis:
database: 1
host: 192.168.234.101
host: localhost
port: 6379
password: 1234@abcd # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
......@@ -42,7 +42,7 @@ spring:
datasource:
mysql:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://192.168.234.100:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:p6spy:mysql://localhost:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 1234@abcd
......
<?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">
<parent>
<artifactId>data-market-service-parent</artifactId>
<groupId>cn.datax</groupId>
<version>2.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>2.0.0</version>
<artifactId>data-market-service-api-mapping</artifactId>
<dependencies>
<!--web 模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--配置中心客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>datax-common-mybatis</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>datax-common-redis</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>datax-common-security</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>datax-common-database</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>datax-common-log</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>data-market-service-api</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>data-factory-service-api</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>datax-common-rabbitmq</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package cn.datax.service.data.market.api.mapping;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients(basePackages = {"cn.datax.service.system.api.feign", "cn.datax.service.data.factory.api.feign", "cn.datax.service.data.market.api.feign"})
@SpringCloudApplication
public class DataxApiMappingApplication {
public static void main(String[] args) {
SpringApplication.run(DataxApiMappingApplication.class);
}
}
package cn.datax.service.data.market.config;
package cn.datax.service.data.market.api.mapping.config;
import cn.datax.service.data.market.service.ApiCallEngine;
import cn.datax.service.data.market.service.ApiLogService;
import cn.datax.service.data.market.api.mapping.service.ApiLogService;
import cn.datax.service.data.market.api.mapping.service.impl.ApiMappingEngine;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
......@@ -9,21 +9,24 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
@Configuration
public class ApiHandlerConfig {
public class ApiMappingConfig {
@Bean
public MappingHandlerMapping mappingHandlerMapping(RequestMappingHandlerMapping requestMappingHandlerMapping, ObjectMapper objectMapper,
ApiCallEngine apiCallEngine, RedisTemplate redisTemplate, ApiLogService apiLogService) {
public MappingHandlerMapping mappingHandlerMapping(RequestMappingHandlerMapping requestMappingHandlerMapping,
ApiMappingEngine apiMappingEngine,
RedisTemplate redisTemplate,
ObjectMapper objectMapper,
ApiLogService apiLogService) {
MappingHandlerMapping mappingHandlerMapping = new MappingHandlerMapping();
mappingHandlerMapping.setHandler(requestHandler(apiCallEngine, redisTemplate, apiLogService, objectMapper));
mappingHandlerMapping.setHandler(requestHandler(apiMappingEngine, redisTemplate, objectMapper, apiLogService));
mappingHandlerMapping.setRequestMappingHandlerMapping(requestMappingHandlerMapping);
return mappingHandlerMapping;
}
@Bean
public RequestHandler requestHandler(ApiCallEngine apiCallEngine, RedisTemplate redisTemplate, ApiLogService apiLogService, ObjectMapper objectMapper) {
public RequestHandler requestHandler(ApiMappingEngine apiMappingEngine, RedisTemplate redisTemplate, ObjectMapper objectMapper, ApiLogService apiLogService) {
RequestHandler handler = new RequestHandler();
handler.setApiCallEngine(apiCallEngine);
handler.setApiMappingEngine(apiMappingEngine);
handler.setApiLogService(apiLogService);
handler.setObjectMapper(objectMapper);
handler.setRequestInterceptor(new RequestInterceptor(redisTemplate));
......
package cn.datax.service.data.market.api.mapping.config;
import cn.datax.common.security.handler.DataAccessDeniedHandler;
import cn.datax.common.security.handler.DataAuthExceptionEntryPoint;
import cn.datax.common.security.utils.DataRedisTokenServices;
import cn.datax.common.security.utils.RedisTokenStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class DataResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private DataAccessDeniedHandler accessDeniedHandler;
@Autowired
private DataAuthExceptionEntryPoint exceptionEntryPoint;
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore redisTokenStore() {
return new RedisTokenStore(redisConnectionFactory);
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
DataRedisTokenServices dataTokenServices = new DataRedisTokenServices();
dataTokenServices.setTokenStore(redisTokenStore());
resources
.tokenStore(redisTokenStore())
.tokenServices(dataTokenServices)
.authenticationEntryPoint(exceptionEntryPoint)
.accessDeniedHandler(accessDeniedHandler);
}
@Override
public void configure(HttpSecurity http) throws Exception {
//允许使用iframe 嵌套,避免swagger-ui 不被加载的问题
http.headers().frameOptions().disable();
http.authorizeRequests()
.antMatchers(
"/actuator/**",
"/v2/api-docs/**",
"/swagger-ui.html",
"/doc.html",
"/swagger-resources/**",
"/webjars/**",
// feign 内部调用不用授权
"/inner/**"
).permitAll()
.anyRequest().authenticated()
.and().csrf().disable();
}
}
package cn.datax.service.data.market.api.mapping.config;
import cn.datax.common.rabbitmq.config.RabbitMqConstant;
import cn.datax.common.utils.ThrowableUtil;
import cn.datax.service.data.market.api.entity.DataApiEntity;
import cn.datax.service.data.market.api.feign.DataApiServiceFeign;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class RabbitMqListenerConfig {
@Autowired
private DataApiServiceFeign dataApiServiceFeign;
@Autowired
private MappingHandlerMapping mappingHandlerMapping;
@Autowired
private ObjectMapper objectMapper;
/**
* Fanout 交换机
* 消费注册
*/
@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(name = RabbitMqConstant.FANOUT_EXCHANGE_API_RELEASE_NAME, type = "fanout", durable = "true", autoDelete = "false"),
value = @Queue(value = RabbitMqConstant.FANOUT_EXCHANGE_QUEUE_TOPIC_API_RELEASE1, durable = "true", exclusive = "false", autoDelete = "false")))
public void fanoutQueueRelease(String id, Channel channel, Message message) throws Exception {
try {
System.out.println("fanoutQueueRelease接收到了:" + id);
DataApiEntity dataApiEntity = dataApiServiceFeign.getDataApiById(id);
if(dataApiEntity != null){
log.info("api={}", dataApiEntity);
}
}catch (Exception e){
log.error("全局异常信息ex={}, StackTrace={}", e.getMessage(), ThrowableUtil.getStackTrace(e));
}
}
/**
* Fanout 交换机
* 消费注销
*/
@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(name = RabbitMqConstant.FANOUT_EXCHANGE_API_CANCEL_NAME, type = "fanout", durable = "true", autoDelete = "false"),
value = @Queue(value = RabbitMqConstant.FANOUT_EXCHANGE_QUEUE_TOPIC_API_CANCEL1, durable = "true", exclusive = "false", autoDelete = "false")))
public void fanoutQueueCancel(String id, Channel channel, Message message) throws Exception {
try {
System.out.println("fanoutQueueCancel接收到了:" + id);
}catch (Exception e){
log.error("全局异常信息ex={}, StackTrace={}", e.getMessage(), ThrowableUtil.getStackTrace(e));
}
}
}
package cn.datax.service.data.market.config;
package cn.datax.service.data.market.api.mapping.config;
import cn.datax.common.core.DataConstant;
import cn.datax.common.core.R;
......@@ -6,9 +6,9 @@ import cn.datax.common.database.core.PageResult;
import cn.datax.common.utils.ThrowableUtil;
import cn.datax.service.data.market.api.dto.ApiLogDto;
import cn.datax.service.data.market.api.entity.DataApiEntity;
import cn.datax.service.data.market.service.ApiCallEngine;
import cn.datax.service.data.market.service.ApiLogService;
import cn.datax.service.data.market.utils.ThreadUtil;
import cn.datax.service.data.market.api.mapping.service.ApiLogService;
import cn.datax.service.data.market.api.mapping.service.impl.ApiMappingEngine;
import cn.datax.service.data.market.api.mapping.utils.ThreadUtil;
import cn.hutool.core.map.MapUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
......@@ -27,28 +27,28 @@ public class RequestHandler {
private RequestInterceptor requestInterceptor;
private ApiCallEngine apiCallEngine;
private ApiLogService apiLogService;
private ApiMappingEngine apiMappingEngine;
private ObjectMapper objectMapper;
private ApiLogService apiLogService;
public void setRequestInterceptor(RequestInterceptor requestInterceptor) {
this.requestInterceptor = requestInterceptor;
}
public void setApiCallEngine(ApiCallEngine apiCallEngine) {
this.apiCallEngine = apiCallEngine;
}
public void setApiLogService(ApiLogService apiLogService) {
this.apiLogService = apiLogService;
public void setApiMappingEngine(ApiMappingEngine apiMappingEngine) {
this.apiMappingEngine = apiMappingEngine;
}
public void setObjectMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
public void setApiLogService(ApiLogService apiLogService) {
this.apiLogService = apiLogService;
}
@ResponseBody
public Object invoke(HttpServletRequest request, HttpServletResponse response,
@PathVariable(required = false) Map<String, Object> pathVariables,
......@@ -78,7 +78,7 @@ public class RequestHandler {
if (obj != null) {
return obj;
}
PageResult<Map<String, Object>> value = apiCallEngine.execute(api, params);
PageResult<Map<String, Object>> value = apiMappingEngine.execute(api, params);
// 执行后置拦截器
requestInterceptor.postHandle(request, response, api, params, value);
ThreadUtil.getInstance().get().setCallerSize(value.getData().size());
......
package cn.datax.service.data.market.config;
package cn.datax.service.data.market.api.mapping.config;
import cn.datax.common.core.DataConstant;
import cn.datax.common.core.R;
......@@ -7,7 +7,7 @@ import cn.datax.common.utils.MD5Util;
import cn.datax.service.data.market.api.dto.ApiLogDto;
import cn.datax.service.data.market.api.entity.DataApiEntity;
import cn.datax.service.data.market.api.enums.ParamType;
import cn.datax.service.data.market.utils.ThreadUtil;
import cn.datax.service.data.market.api.mapping.utils.ThreadUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
......
package cn.datax.service.data.market.api.mapping.config;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Component
@RequiredArgsConstructor
public class StartedUpRunner implements ApplicationRunner {
private final ConfigurableApplicationContext context;
private final Environment environment;
@Override
public void run(ApplicationArguments args) {
if (context.isActive()) {
String banner = "-----------------------------------------\n" +
"服务启动成功,时间:" + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()) + "\n" +
"服务名称:" + environment.getProperty("spring.application.name") + "\n" +
"端口号:" + environment.getProperty("server.port") + "\n" +
"-----------------------------------------";
System.out.println(banner);
}
}
}
package cn.datax.service.data.market.api.mapping.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMethod;
import springfox.documentation.builders.*;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@ConditionalOnProperty(prefix = "swagger", name = "enable", havingValue = "true")
@EnableConfigurationProperties(SwaggerProperties.class)
@EnableSwagger2
public class SwaggerConfig {
@Autowired
private SwaggerProperties swaggerProperties;
/**
* 创建API应用
* apiInfo() 增加API相关信息
* 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现,
* 本例采用指定扫描的包路径来定义指定要建立API的目录。
*
* @return
*/
@Bean
public Docket createRestApi(){
//版本类型是swagger2
return new Docket(DocumentationType.SWAGGER_2)
//通过调用自定义方法apiInfo,获得文档的主要信息
.apiInfo(apiInfo())
//设置全局参数
.globalOperationParameters(globalParamBuilder())
//设置全局响应参数
.globalResponseMessage(RequestMethod.GET,responseBuilder())
.globalResponseMessage(RequestMethod.POST,responseBuilder())
.globalResponseMessage(RequestMethod.PUT,responseBuilder())
.globalResponseMessage(RequestMethod.DELETE,responseBuilder())
.select()
//扫描该包下面的API注解
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
.paths(PathSelectors.any())
.build()
//设置安全认证
.securitySchemes(security());
}
/**
* 创建该API的基本信息(这些基本信息会展现在文档页面中)
* 访问地址:http://项目实际地址/swagger-ui.html
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
.termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
.version(swaggerProperties.getVersion())
.contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail()))
.build();
}
/**
* 安全认证参数
* @return
*/
private List<ApiKey> security() {
List<ApiKey> apiKeys = new ArrayList<>();
apiKeys.add(new ApiKey("Authorization", "Authorization", "header"));
return apiKeys;
}
/**
* 构建全局参数列表
* @return
*/
private List<Parameter> globalParamBuilder(){
List<Parameter> pars = new ArrayList<>();
pars.add(parameterBuilder("Authorization","令牌","string","header",false).build());
return pars;
}
/**
* 创建参数
* @return
*/
private ParameterBuilder parameterBuilder(String name, String desc, String type, String parameterType, boolean required) {
ParameterBuilder tokenPar = new ParameterBuilder();
tokenPar.name(name).description(desc).modelRef(new ModelRef(type)).parameterType(parameterType).required(required).build();
return tokenPar;
}
/**
* 创建全局响应值
* @return
*/
private List<ResponseMessage> responseBuilder() {
List<ResponseMessage> responseMessageList = new ArrayList<>();
responseMessageList.add(new ResponseMessageBuilder().code(200).message("响应成功").build());
responseMessageList.add(new ResponseMessageBuilder().code(500).message("服务器内部错误").build());
return responseMessageList;
}
}
package cn.datax.service.data.market.api.mapping.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(ignoreUnknownFields = false, prefix = "swagger")
public class SwaggerProperties {
private String title;
private String description;
private String version;
private String termsOfServiceUrl;
private String basePackage;
private Contact contact;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getTermsOfServiceUrl() {
return termsOfServiceUrl;
}
public void setTermsOfServiceUrl(String termsOfServiceUrl) {
this.termsOfServiceUrl = termsOfServiceUrl;
}
public String getBasePackage() {
return basePackage;
}
public void setBasePackage(String basePackage) {
this.basePackage = basePackage;
}
public Contact getContact() {
return contact;
}
public void setContact(Contact contact) {
this.contact = contact;
}
public static class Contact {
private String name;
private String url;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
}
package cn.datax.service.data.market.api.mapping.controller;
import cn.datax.common.base.BaseController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/inner")
public class InnerController extends BaseController {
}
package cn.datax.service.data.market.dao;
package cn.datax.service.data.market.api.mapping.dao;
import cn.datax.common.base.BaseDao;
import cn.datax.service.data.market.api.entity.ApiLogEntity;
......
package cn.datax.service.data.market.factory;
package cn.datax.service.data.market.api.mapping.factory;
import cn.datax.service.data.market.factory.crypto.Crypto;
import cn.datax.service.data.market.api.mapping.factory.crypto.Crypto;
public abstract class AbstractFactory {
......
package cn.datax.service.data.market.factory;
package cn.datax.service.data.market.api.mapping.factory;
import cn.datax.service.data.market.api.enums.AlgorithmCrypto;
import cn.datax.service.data.market.factory.crypto.AlgorithmRegistry;
import cn.datax.service.data.market.factory.crypto.Crypto;
import cn.datax.service.data.market.api.mapping.factory.crypto.AlgorithmRegistry;
import cn.datax.service.data.market.api.mapping.factory.crypto.Crypto;
public class AlgorithmFactory extends AbstractFactory {
......
package cn.datax.service.data.market.factory;
package cn.datax.service.data.market.api.mapping.factory;
import cn.datax.service.data.market.api.enums.RegexCrypto;
import cn.datax.service.data.market.factory.crypto.Crypto;
import cn.datax.service.data.market.factory.crypto.RegexRegistry;
import cn.datax.service.data.market.api.mapping.factory.crypto.Crypto;
import cn.datax.service.data.market.api.mapping.factory.crypto.RegexRegistry;
public class RegexFactory extends AbstractFactory {
......
package cn.datax.service.data.market.mapstruct;
package cn.datax.service.data.market.api.mapping.mapstruct;
import cn.datax.common.mapstruct.EntityMapper;
import cn.datax.service.data.market.api.dto.ApiLogDto;
......
package cn.datax.service.data.market.service.impl;
package cn.datax.service.data.market.api.mapping.service.impl;
import cn.datax.common.base.BaseServiceImpl;
import cn.datax.service.data.market.api.dto.ApiLogDto;
import cn.datax.service.data.market.api.entity.ApiLogEntity;
import cn.datax.service.data.market.dao.ApiLogDao;
import cn.datax.service.data.market.mapstruct.ApiLogMapper;
import cn.datax.service.data.market.service.ApiLogService;
import cn.datax.service.data.market.api.mapping.dao.ApiLogDao;
import cn.datax.service.data.market.api.mapping.mapstruct.ApiLogMapper;
import cn.datax.service.data.market.api.mapping.service.ApiLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
......
package cn.datax.service.data.market.service;
package cn.datax.service.data.market.api.mapping.service.impl;
import cn.datax.common.core.R;
import cn.datax.common.database.DataSourceFactory;
......@@ -14,14 +14,13 @@ import cn.datax.service.data.factory.api.feign.DataSourceServiceFeign;
import cn.datax.service.data.market.api.dto.FieldRule;
import cn.datax.service.data.market.api.entity.ApiMaskEntity;
import cn.datax.service.data.market.api.entity.DataApiEntity;
import cn.datax.service.data.market.dao.ApiMaskDao;
import cn.datax.service.data.market.factory.AbstractFactory;
import cn.datax.service.data.market.factory.FactoryProducer;
import cn.datax.service.data.market.factory.crypto.Crypto;
import cn.datax.service.data.market.utils.SqlBuilderUtil;
import cn.datax.service.data.market.api.feign.ApiMaskServiceFeign;
import cn.datax.service.data.market.api.mapping.factory.AbstractFactory;
import cn.datax.service.data.market.api.mapping.factory.FactoryProducer;
import cn.datax.service.data.market.api.mapping.factory.crypto.Crypto;
import cn.datax.service.data.market.api.mapping.utils.SqlBuilderUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
......@@ -34,7 +33,7 @@ import java.util.Optional;
@Slf4j
@Service
public class ApiCallEngine {
public class ApiMappingEngine {
@Autowired
private DataSourceFactory dataSourceFactory;
......@@ -43,7 +42,7 @@ public class ApiCallEngine {
private DataSourceServiceFeign dataSourceServiceFeign;
@Autowired
private ApiMaskDao apiMaskDao;
private ApiMaskServiceFeign apiMaskServiceFeign;
@Autowired
private ObjectMapper objectMapper;
......@@ -77,12 +76,16 @@ public class ApiCallEngine {
Map<String, Object> acceptedFilters = sqlFilterResult.getAcceptedFilters();
// 数据脱敏
List<FieldRule> rules = null;
ApiMaskEntity apiMaskEntity = apiMaskDao.selectOne(new QueryWrapper<ApiMaskEntity>().eq("api_id", dataApi.getId()));
if (apiMaskEntity != null) {
R apiMaskResult = apiMaskServiceFeign.getApiMaskByApiId(dataApi.getId());
if(apiMaskResult == null || !apiMaskResult.isSuccess() || ObjectUtil.isEmpty(apiMaskResult.getData())){
throw new DataException("API调用查询数据脱敏出错");
}
ApiMaskEntity apiMaskEntity = null;
try {
apiMaskEntity = objectMapper.readValue(objectMapper.writeValueAsString(apiMaskEntity), ApiMaskEntity.class);
apiMaskEntity = objectMapper.readValue(objectMapper.writeValueAsString(apiMaskResult.getData()), ApiMaskEntity.class);
} catch (JsonProcessingException e) {
}
if (apiMaskEntity != null) {
rules = apiMaskEntity.getRules();
}
PageResult<Map<String, Object>> pageResult;
......
package cn.datax.service.data.market.api.mapping.utils;
import cn.datax.common.exception.DataException;
import org.springframework.util.Assert;
import java.util.*;
/**
* 带参数sql处理工具类
*/
public class NamedParameterUtil {
// public static void main(String[] args) {
// String sql = "select * from user where 1 = 1 ${ and id = :id } ${and name = :name}";
// int start = sql.indexOf("${");
// int end = sql.indexOf("}", start);
// String key = sql.substring(start + 2, end);
// System.out.println(key);
// Map<String, Object> params = new HashMap<>();
// params.put("name", "yuwei");
// params.put("id", "123");
// params.put("age", 12);
// ParsedSql parsedSql = NamedParameterUtil.parseSqlStatement(key);
// System.out.println(parsedSql);
// String actualSql = NamedParameterUtil.substituteNamedParams(parsedSql, params);
// Map<String, Object> acceptedFilters = NamedParameterUtil.buildValueArray(parsedSql, params);
// System.out.println(actualSql);
// System.out.println(acceptedFilters);
// SqlBuilderUtil.SqlFilterResult sqlFilterResult = SqlBuilderUtil.getInstance().applyFilters(sql, params);
// System.out.println(sqlFilterResult.getSql());
// Object[] array = new Object[] {};
// array = sqlFilterResult.getAcceptedFilters().values().toArray();
// Arrays.stream(array).forEach(s -> System.out.println(s));
// }
private NamedParameterUtil() {}
/**
* 定义特殊字符(增加最后的自定义的'}')
*/
private static final char[] PARAMETER_SEPARATORS =
new char[] {'"', '\'', ':', '&', ',', ';', '(', ')', '|', '=', '+', '-', '*', '%', '/', '\\', '<', '>', '^', '}'};
/**
* 对带参数sql的统计式封装,便于后续肢解拼装
* @param originalSql
* @return
*/
public static ParsedSql parseSqlStatement(String originalSql) {
Assert.notNull(originalSql, "SQL must not be null");
ParsedSql parsedSql = new ParsedSql(originalSql);
Set<String> namedParameters = new HashSet();
char[] sqlchars = originalSql.toCharArray();
int namedParamCount = 0;
int unNamedParamCount = 0;
int totalParamCount = 0;
int i = 0;
while (i < sqlchars.length) {
char statement = sqlchars[i];
if (statement == ':') {
int j = i + 1;
while (j < sqlchars.length && !isSeparatorsChar(sqlchars[j])) {
j++;
}
if (j - i > 1) {
String paramName = originalSql.substring(i + 1, j);
if (!namedParameters.contains(paramName)) {
namedParameters.add(paramName);
namedParamCount++;
}
parsedSql.addParamNames(paramName, i, j);
totalParamCount++;
}
i = j - 1;
} else if (statement == '?') {
unNamedParamCount++;
totalParamCount++;
}
i++;
}
parsedSql.setNamedParamCount(namedParamCount);
parsedSql.setUnnamedParamCount(unNamedParamCount);
parsedSql.setTotalParamCount(totalParamCount);
return parsedSql;
}
/**
* 获得不带参数的sql,即替换参数为?
* @param parsedSql
* @param params
* @return
*/
public static String substituteNamedParams(ParsedSql parsedSql, Map<String, Object> params){
String original = parsedSql.getOriginalSql();
StringBuffer actual = new StringBuffer("");
int lastIndex = 0;
List<String> paramNames = parsedSql.getParamNames();
for (int i = 0; i < paramNames.size(); i++) {
int[] indexs = parsedSql.getParamIndexs(i);
int startIndex = indexs[0];
int endIndex = indexs[1];
String paramName = paramNames.get(i);
actual.append(original.substring(lastIndex, startIndex));
if (params != null && params.containsKey(paramName)) {
actual.append("?");
} else{
actual.append("?");
}
lastIndex = endIndex;
}
actual.append(original.subSequence(lastIndex, original.length()));
return actual.toString();
}
/**
* 获得sql所需参数K,V
* @param parsedSql
* @param params
* @return
*/
public static LinkedHashMap<String, Object> buildValueArray(ParsedSql parsedSql, Map<String, Object> params){
List<String> paramNames = parsedSql.getParamNames();
LinkedHashMap<String, Object> acceptedFilters = new LinkedHashMap<>(parsedSql.getTotalParamCount());
if (parsedSql.getNamedParamCount() > 0 && parsedSql.getUnnamedParamCount() > 0) {
throw new DataException("parameter方式与?方式不能混合!");
}
for (int i = 0; i < paramNames.size(); i++) {
String keyName = paramNames.get(i);
if (params.containsKey(keyName)) {
acceptedFilters.put(keyName, params.get(keyName));
}
}
return acceptedFilters;
}
private static boolean isSeparatorsChar(char statement){
if (Character.isWhitespace(statement)) {
return true;
}
for (int i = 0; i < PARAMETER_SEPARATORS.length; i++) {
if (statement == PARAMETER_SEPARATORS[i]) {
return true;
}
}
return false;
}
}
package cn.datax.service.data.market.api.mapping.utils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 此类封装NamedParameterSql
*/
public class ParsedSql implements Serializable {
private static final long serialVersionUID=1L;
private String originalSql;
//参数名
private List<String> paramNames = new ArrayList<>();
//参数在sql中对应的位置
private List<int[]> paramIndexs = new ArrayList<>();
//统计参数个数(不包含重复)
private int namedParamCount;
//统计sql中?的个数
private int unnamedParamCount;
private int totalParamCount;
public ParsedSql(String originalSql){
this.originalSql = originalSql;
}
public List<String> getParamNames() {
return paramNames;
}
public void addParamNames(String paramName,int startIndex,int endIndex) {
paramNames.add(paramName);
paramIndexs.add(new int[]{startIndex,endIndex});
}
public int[] getParamIndexs(int position) {
return paramIndexs.get(position);
}
public String getOriginalSql() {
return originalSql;
}
public int getNamedParamCount() {
return namedParamCount;
}
public void setNamedParamCount(int namedParamCount) {
this.namedParamCount = namedParamCount;
}
public int getUnnamedParamCount() {
return unnamedParamCount;
}
public void setUnnamedParamCount(int unnamedParamCount) {
this.unnamedParamCount = unnamedParamCount;
}
public int getTotalParamCount() {
return totalParamCount;
}
public void setTotalParamCount(int totalParamCount) {
this.totalParamCount = totalParamCount;
}
@Override
public String toString() {
return "ParsedSql{" +
"originalSql='" + originalSql + '\'' +
", paramNames=" + paramNames +
", paramIndexs=" + paramIndexs +
", namedParamCount=" + namedParamCount +
", unnamedParamCount=" + unnamedParamCount +
", totalParamCount=" + totalParamCount +
'}';
}
}
package cn.datax.service.data.market.api.mapping.utils;
import cn.datax.service.data.market.api.dto.ApiLogDto;
public class ThreadUtil {
private ThreadUtil() {}
private static volatile ThreadUtil instance;
public static ThreadUtil getInstance() {
if(instance == null) {
synchronized (ThreadUtil.class) {
if(instance == null) {
instance = new ThreadUtil();
}
}
}
return instance;
}
private final static ThreadLocal<ApiLogDto> logHolder = new ThreadLocal<>();
public void set(ApiLogDto log){
logHolder.set(log);
}
public void remove(){
logHolder.remove();
}
public ApiLogDto get(){
return logHolder.get();
}
}
server:
port: 8819
spring:
application:
name: datax-service-data-api-mapping
profiles:
active: dev
cloud:
config:
fail-fast: true
name: ${spring.application.name}
profile: ${spring.profiles.active}
discovery:
enabled: true
service-id: datax-config
# 注册中心配置
eureka:
instance:
lease-renewal-interval-in-seconds: 20
client:
register-with-eureka: true
fetch-registry: true
instance-info-replication-interval-seconds: 30
registry-fetch-interval-seconds: 3
service-url:
defaultZone: http://localhost:8610/eureka
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<springProperty scope="context" name="springAppName" source="spring.application.name"/>
<property name="log.path" value="logs/datax-service-data-api-mapping"/>
<property name="log.maxHistory" value="15"/>
<property name="log.totalSizeCap" value="500MB"/>
<property name="log.maxFileSize" value="10MB"/>
<property name="log.colorPattern"
value="%magenta(%d{yyyy-MM-dd HH:mm:ss}) %highlight(%-5level) %boldCyan(${springAppName:-}) %yellow(%thread) %green(%logger) %msg%n"/>
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5level ${springAppName:-} %thread %logger %msg%n"/>
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.colorPattern}</pattern>
</encoder>
</appender>
<!--输出到文件-->
<!-- RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<!-- 以下的大概意思是:1.先按日期存日志,日期变了,将前一天的日志文件名重命名为XXX%日期%索引,新的日志仍然是project_info.log -->
<!-- 2.如果日期没有发生变化,但是当前日志的文件大小超过10MB时,对当前日志进行分割 重命名-->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件路径和名称-->
<File>${log.path}/info/info.log</File>
<!--是否追加到文件末尾,默认为true-->
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 日志文件的名字会根据fileNamePattern的值,每隔一段时间改变一次 -->
<!-- 文件名:logs/project_info.2017-12-05.0.log -->
<!-- 注意:SizeAndTimeBasedRollingPolicy中 %i和%d令牌都是强制性的,必须存在,要不会报错 -->
<fileNamePattern>${log.path}/info/info.%d.%i.log</fileNamePattern>
<!-- 每产生一个日志文件,该日志文件的保存期限为30天, ps:maxHistory的单位是根据fileNamePattern中的翻转策略自动推算出来的,例如上面选用了yyyy-MM-dd,则单位为天
如果上面选用了yyyy-MM,则单位为月,另外上面的单位默认为yyyy-MM-dd-->
<MaxHistory>${log.maxHistory}</MaxHistory>
<!-- 每个日志文件到2mb的时候开始切分,最多保留30天,但最大到500MB,哪怕没到30天也要删除多余的日志 -->
<totalSizeCap>${log.totalSizeCap}</totalSizeCap>
<!-- maxFileSize:这是活动文件的大小,默认值是10MB,测试时可改成5KB看效果 -->
<maxFileSize>${log.maxFileSize}</maxFileSize>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${log.path}/error/error.log</File>
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/error.%d.%i.log</fileNamePattern>
<MaxHistory>${log.maxHistory}</MaxHistory>
<totalSizeCap>${log.totalSizeCap}</totalSizeCap>
<maxFileSize>${log.maxFileSize}</maxFileSize>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<root level="debug">
<appender-ref ref="console"/>
</root>
<root level="info">
<appender-ref ref="file_info"/>
<appender-ref ref="file_error"/>
</root>
</configuration>
\ No newline at end of file
module.log=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,batch,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2
# 开启过滤
filter=true
# 配置不打印的内容
exclude=select 1
\ No newline at end of file
package cn.datax.service.data.market.api.feign;
import cn.datax.common.core.R;
import cn.datax.service.data.market.api.feign.factory.ApiMaskServiceFeignFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(contextId = "apiMaskServiceFeign", value = "datax-service-data-market", fallbackFactory = ApiMaskServiceFeignFallbackFactory.class)
public interface ApiMaskServiceFeign {
@GetMapping("/apiMasks/api/{apiId}")
R getApiMaskByApiId(@PathVariable("apiId") String apiId);
}
package cn.datax.service.data.market.api.feign;
import cn.datax.service.data.market.api.entity.DataApiEntity;
import cn.datax.service.data.market.api.feign.factory.DataApiServiceFeignFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(contextId = "dataApiServiceFeign", value = "datax-service-data-market", fallbackFactory = DataApiServiceFeignFallbackFactory.class)
public interface DataApiServiceFeign {
@GetMapping("/inner/apis/{id}")
DataApiEntity getDataApiById(@PathVariable("id") String id);
}
package cn.datax.service.data.market.api.feign.factory;
import cn.datax.service.data.market.api.feign.ApiMaskServiceFeign;
import cn.datax.service.data.market.api.feign.fallback.ApiMaskServiceFeignFallbackImpl;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
@Component
public class ApiMaskServiceFeignFallbackFactory implements FallbackFactory<ApiMaskServiceFeign> {
@Override
public ApiMaskServiceFeign create(Throwable throwable) {
ApiMaskServiceFeignFallbackImpl apiMaskServiceFeignFallbackImpl = new ApiMaskServiceFeignFallbackImpl();
apiMaskServiceFeignFallbackImpl.setCause(throwable);
return apiMaskServiceFeignFallbackImpl;
}
}
package cn.datax.service.data.market.api.feign.factory;
import cn.datax.service.data.market.api.feign.DataApiServiceFeign;
import cn.datax.service.data.market.api.feign.fallback.DataApiServiceFeignFallbackImpl;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
@Component
public class DataApiServiceFeignFallbackFactory implements FallbackFactory<DataApiServiceFeign> {
@Override
public DataApiServiceFeign create(Throwable throwable) {
DataApiServiceFeignFallbackImpl dataApiServiceFeignFallback = new DataApiServiceFeignFallbackImpl();
dataApiServiceFeignFallback.setCause(throwable);
return dataApiServiceFeignFallback;
}
}
package cn.datax.service.data.market.api.feign.fallback;
import cn.datax.common.core.R;
import cn.datax.service.data.market.api.feign.ApiMaskServiceFeign;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class ApiMaskServiceFeignFallbackImpl implements ApiMaskServiceFeign {
@Setter
private Throwable cause;
@Override
public R getApiMaskByApiId(String id) {
log.error("feign 调用{}出错", id, cause);
return null;
}
}
package cn.datax.service.data.market.api.feign.fallback;
import cn.datax.service.data.market.api.entity.DataApiEntity;
import cn.datax.service.data.market.api.feign.DataApiServiceFeign;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class DataApiServiceFeignFallbackImpl implements DataApiServiceFeign {
@Setter
private Throwable cause;
@Override
public DataApiEntity getDataApiById(String id) {
log.error("feign 调用{}出错", id, cause);
return null;
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.datax.service.data.market.api.feign.factory.DataApiServiceFeignFallbackFactory,\
cn.datax.service.data.market.api.feign.fallback.DataApiServiceFeignFallbackImpl,\
cn.datax.service.data.market.api.feign.factory.ApiMaskServiceFeignFallbackFactory,\
cn.datax.service.data.market.api.feign.fallback.ApiMaskServiceFeignFallbackImpl
package cn.datax.service.data.market.config;
import cn.datax.common.core.DataConstant;
import cn.datax.service.data.market.api.entity.DataApiEntity;
import cn.datax.service.data.market.dao.DataApiDao;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ConfigurableApplicationContext;
......@@ -15,7 +9,6 @@ import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
@Component
@RequiredArgsConstructor
......@@ -24,12 +17,6 @@ public class StartedUpRunner implements ApplicationRunner {
private final ConfigurableApplicationContext context;
private final Environment environment;
@Autowired
private DataApiDao dataApiDao;
@Autowired
private MappingHandlerMapping mappingHandlerMapping;
@Override
public void run(ApplicationArguments args) {
if (context.isActive()) {
......@@ -39,13 +26,6 @@ public class StartedUpRunner implements ApplicationRunner {
"端口号:" + environment.getProperty("server.port") + "\n" +
"-----------------------------------------";
System.out.println(banner);
// 项目启动时,初始化已发布的接口
// QueryWrapper<DataApiEntity> queryWrapper = new QueryWrapper<>();
// queryWrapper.eq("status", DataConstant.ApiState.RELEASE.getKey());
// List<DataApiEntity> dataApiEntityList = dataApiDao.selectList(queryWrapper);
// if (CollUtil.isNotEmpty(dataApiEntityList)) {
// dataApiEntityList.stream().forEach(api -> mappingHandlerMapping.registerMapping(api));
// }
}
}
}
......@@ -19,16 +19,4 @@ public class ApiExecuteController extends BaseController {
ApiHeader apiHeader = apiExecuteService.getApiHeader(id);
return R.ok().setData(apiHeader);
}
@PostMapping(value = "/{id}/register")
public R apiRegister(@PathVariable String id){
apiExecuteService.registerApi(id);
return R.ok();
}
@PostMapping(value = "/{id}/unregister")
public R apiUnRegister(@PathVariable String id){
apiExecuteService.unRegisterApi(id);
return R.ok();
}
}
package cn.datax.service.data.market.controller;
import cn.datax.common.base.BaseController;
import cn.datax.common.core.R;
import cn.datax.common.security.annotation.DataInner;
import cn.datax.service.data.market.api.entity.DataApiEntity;
import cn.datax.service.data.market.mapstruct.DataApiMapper;
import cn.datax.service.data.market.service.DataApiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/inner")
public class InnerController extends BaseController {
@Autowired
private DataApiService dataApiService;
@DataInner
@GetMapping("/apis/{id}")
public DataApiEntity getDataApiById(@PathVariable String id) {
DataApiEntity dataApiEntity = dataApiService.getDataApiById(id);
return dataApiEntity;
}
}
......@@ -5,8 +5,4 @@ import cn.datax.service.data.market.api.vo.ApiHeader;
public interface ApiExecuteService {
ApiHeader getApiHeader(String id);
void registerApi(String id);
void unRegisterApi(String id);
}
package cn.datax.service.data.market.service.impl;
import cn.datax.common.core.DataConstant;
import cn.datax.common.utils.MD5Util;
import cn.datax.common.utils.SecurityUtil;
import cn.datax.service.data.market.api.entity.DataApiEntity;
import cn.datax.service.data.market.api.vo.ApiHeader;
import cn.datax.service.data.market.config.MappingHandlerMapping;
import cn.datax.service.data.market.dao.DataApiDao;
import cn.datax.service.data.market.service.ApiExecuteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
......@@ -17,12 +12,6 @@ import org.springframework.transaction.annotation.Transactional;
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class ApiExecuteServiceImpl implements ApiExecuteService {
@Autowired
private MappingHandlerMapping mappingHandlerMapping;
@Autowired
private DataApiDao dataApiDao;
@Override
public ApiHeader getApiHeader(String id) {
ApiHeader apiHeader = new ApiHeader();
......@@ -34,24 +23,4 @@ public class ApiExecuteServiceImpl implements ApiExecuteService {
}
return apiHeader;
}
@Override
public void registerApi(String id) {
DataApiEntity dataApiEntity = dataApiDao.selectById(id);
if (dataApiEntity != null) {
mappingHandlerMapping.registerMapping(dataApiEntity);
dataApiEntity.setStatus(DataConstant.ApiState.RELEASE.getKey());
dataApiDao.updateById(dataApiEntity);
}
}
@Override
public void unRegisterApi(String id) {
DataApiEntity dataApiEntity = dataApiDao.selectById(id);
if (dataApiEntity != null) {
mappingHandlerMapping.unregisterMapping(dataApiEntity);
dataApiEntity.setStatus(DataConstant.ApiState.CANCEL.getKey());
dataApiDao.updateById(dataApiEntity);
}
}
}
......@@ -13,8 +13,6 @@ import cn.datax.service.data.market.mapstruct.DataApiMapper;
import cn.datax.service.data.market.dao.DataApiDao;
import cn.datax.common.base.BaseServiceImpl;
import cn.datax.service.data.market.utils.SqlBuilderUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
......@@ -63,9 +61,6 @@ public class DataApiServiceImpl extends BaseServiceImpl<DataApiDao, DataApiEntit
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private ObjectMapper objectMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public void saveDataApi(DataApiDto dataApiDto) {
......@@ -229,17 +224,11 @@ public class DataApiServiceImpl extends BaseServiceImpl<DataApiDao, DataApiEntit
@Override
public void releaseDataApi(String id) {
DataApiEntity dataApiEntity = super.getById(id);
try {
rabbitTemplate.convertAndSend(RabbitMqConstant.FANOUT_EXCHANGE_API_RELEASE_NAME, "", objectMapper.writeValueAsString(dataApiEntity));
} catch (JsonProcessingException e) {}
rabbitTemplate.convertAndSend(RabbitMqConstant.FANOUT_EXCHANGE_API_RELEASE_NAME, "", id);
}
@Override
public void cancelDataApi(String id) {
DataApiEntity dataApiEntity = super.getById(id);
try {
rabbitTemplate.convertAndSend(RabbitMqConstant.FANOUT_EXCHANGE_API_CANCEL_NAME, "", objectMapper.writeValueAsString(dataApiEntity));
} catch (JsonProcessingException e) {}
rabbitTemplate.convertAndSend(RabbitMqConstant.FANOUT_EXCHANGE_API_CANCEL_NAME, "", id);
}
}
......@@ -16,5 +16,6 @@
<modules>
<module>data-market-service</module>
<module>data-market-service-api</module>
<module>data-market-service-api-mapping</module>
</modules>
</project>
\ No newline at end of file
......@@ -3,7 +3,7 @@
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">
<parent>
<artifactId>system-service-parent</artifactId>
<artifactId>quartz-service-parent</artifactId>
<groupId>cn.datax</groupId>
<version>2.0.0</version>
</parent>
......
......@@ -157,14 +157,14 @@
type="text"
icon="el-icon-upload2"
@click="handleRegister(scope.row)"
v-hasPerm="['market:dataapi:register']"
v-hasPerm="['market:dataapi:release']"
>发布</el-button>
<el-button v-if="scope.row.status === '2'"
size="mini"
type="text"
icon="el-icon-download"
@click="handleUnRegister(scope.row)"
v-hasPerm="['market:dataapi:unregister']"
v-hasPerm="['market:dataapi:cancel']"
>注销</el-button>
<el-button slot="reference">操作</el-button>
</el-popover>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment