init
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
<?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>com.platform</groupId>
|
||||
<version>0.4.x</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<version>0.4.x</version>
|
||||
<artifactId>data-market-service</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>com.platform</groupId>
|
||||
<artifactId>common-mybatis</artifactId>
|
||||
<version>0.4.x</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.platform</groupId>
|
||||
<artifactId>common-redis</artifactId>
|
||||
<version>0.4.x</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.platform</groupId>
|
||||
<artifactId>common-security</artifactId>
|
||||
<version>0.4.x</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.platform</groupId>
|
||||
<artifactId>common-database</artifactId>
|
||||
<version>0.4.x</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.platform</groupId>
|
||||
<artifactId>common-log</artifactId>
|
||||
<version>0.4.x</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.platform</groupId>
|
||||
<artifactId>data-market-service-api</artifactId>
|
||||
<version>0.4.x</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.platform</groupId>
|
||||
<artifactId>common-rabbitmq</artifactId>
|
||||
<version>0.4.x</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.platform</groupId>
|
||||
<artifactId>data-metadata-service-api</artifactId>
|
||||
<version>0.4.x</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.datax.service.data.market;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
@EnableFeignClients(basePackages = {"cn.datax.service.system.api.feign"})
|
||||
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
|
||||
public class DataxMarketApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DataxMarketApplication.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package cn.datax.service.data.market.config;
|
||||
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import com.baomidou.dynamic.datasource.aop.DynamicDataSourceAnnotationAdvisor;
|
||||
import com.baomidou.dynamic.datasource.aop.DynamicDataSourceAnnotationInterceptor;
|
||||
import com.baomidou.dynamic.datasource.processor.DsProcessor;
|
||||
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
|
||||
import com.baomidou.dynamic.datasource.provider.YmlDynamicDataSourceProvider;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceCreatorAutoConfiguration;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
|
||||
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidDynamicDataSourceConfiguration;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Role;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 动态数据源核心自动配置类
|
||||
* @author AllDataDC
|
||||
* @date 2023/03/17
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
@EnableConfigurationProperties(DynamicDataSourceProperties.class)
|
||||
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
|
||||
@Import(value = {DruidDynamicDataSourceConfiguration.class, DynamicDataSourceCreatorAutoConfiguration.class})
|
||||
@ConditionalOnProperty(prefix = DynamicDataSourceProperties.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class DynamicDSConfiguration {
|
||||
|
||||
private final DynamicDataSourceProperties properties;
|
||||
|
||||
//读取多数据源配置,注入到spring容器中
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DynamicDataSourceProvider dynamicDataSourceProvider() {
|
||||
Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
|
||||
return new YmlDynamicDataSourceProvider(datasourceMap);
|
||||
}
|
||||
|
||||
//注册自己的动态多数据源DataSource
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
|
||||
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
|
||||
dataSource.setPrimary(properties.getPrimary());
|
||||
dataSource.setStrict(properties.getStrict());
|
||||
dataSource.setStrategy(properties.getStrategy());
|
||||
dataSource.setProvider(dynamicDataSourceProvider);
|
||||
dataSource.setP6spy(properties.getP6spy());
|
||||
dataSource.setSeata(properties.getSeata());
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
//AOP切面,对DS注解过的方法进行增强,达到切换数据源的目的
|
||||
@Role(value = BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DynamicDataSourceAnnotationAdvisor dynamicDatasourceAnnotationAdvisor(DsProcessor dsProcessor) {
|
||||
DynamicDataSourceAnnotationInterceptor interceptor = new DynamicDataSourceAnnotationInterceptor(properties.isAllowedPublicOnly(), dsProcessor);
|
||||
DynamicDataSourceAnnotationAdvisor advisor = new DynamicDataSourceAnnotationAdvisor(interceptor);
|
||||
advisor.setOrder(properties.getOrder());
|
||||
return advisor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package cn.datax.service.data.market.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class RabbitConfig {
|
||||
|
||||
@Bean
|
||||
public RabbitTemplate rabbitTemplate(CachingConnectionFactory connectionFactory) {
|
||||
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
|
||||
// 消息是否成功发送到Exchange
|
||||
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
|
||||
if (ack) {
|
||||
log.info("消息成功发送到Exchange");
|
||||
} else {
|
||||
log.info("消息发送到Exchange失败, {}, cause: {}", correlationData, cause);
|
||||
}
|
||||
});
|
||||
// 触发setReturnCallback回调必须设置mandatory=true, 否则Exchange没有找到Queue就会丢弃掉消息, 而不会触发回调
|
||||
rabbitTemplate.setMandatory(true);
|
||||
// 消息是否从Exchange路由到Queue, 注意: 这是一个失败回调, 只有消息从Exchange路由到Queue失败才会回调这个方法
|
||||
rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
|
||||
log.info("消息从Exchange路由到Queue失败: exchange: {}, route: {}, replyCode: {}, replyText: {}, message: {}", exchange, routingKey, replyCode, replyText, message);
|
||||
});
|
||||
return rabbitTemplate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package cn.datax.service.data.market.config;
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package cn.datax.service.data.market.config;
|
||||
|
||||
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
||||
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.context.annotation.Import;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
|
||||
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
|
||||
@EnableKnife4j
|
||||
@Import(BeanValidatorPluginsConfiguration.class)
|
||||
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()
|
||||
//设置安全认证
|
||||
;
|
||||
}
|
||||
/**
|
||||
* 创建该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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package cn.datax.service.data.market.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(ignoreUnknownFields = false, prefix = "swagger")
|
||||
public class SwaggerProperties {
|
||||
|
||||
private Boolean enable;
|
||||
private String title;
|
||||
private String description;
|
||||
private String version;
|
||||
private String termsOfServiceUrl;
|
||||
private String basePackage;
|
||||
private Contact contact;
|
||||
|
||||
public Boolean getEnable() {
|
||||
return enable;
|
||||
}
|
||||
|
||||
public void setEnable(Boolean enable) {
|
||||
this.enable = enable;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package cn.datax.service.data.market.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity(debug = false)
|
||||
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.csrf().disable().authorizeRequests().anyRequest().permitAll().and().logout().permitAll();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package cn.datax.service.data.market.controller;
|
||||
|
||||
import cn.datax.common.base.BaseController;
|
||||
import cn.datax.common.core.JsonPage;
|
||||
import cn.datax.common.core.R;
|
||||
import cn.datax.common.validate.ValidationGroups;
|
||||
import cn.datax.service.data.market.api.dto.ApiMaskDto;
|
||||
import cn.datax.service.data.market.api.entity.ApiMaskEntity;
|
||||
import cn.datax.service.data.market.api.query.ApiMaskQuery;
|
||||
import cn.datax.service.data.market.api.vo.ApiMaskVo;
|
||||
import cn.datax.service.data.market.mapstruct.ApiMaskMapper;
|
||||
import cn.datax.service.data.market.service.ApiMaskService;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据API脱敏信息表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
@Api(tags = {"数据API脱敏信息表"})
|
||||
@RestController
|
||||
@RequestMapping("/apiMasks")
|
||||
public class ApiMaskController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ApiMaskService apiMaskService;
|
||||
|
||||
@Autowired
|
||||
private ApiMaskMapper apiMaskMapper;
|
||||
|
||||
/**
|
||||
* 通过ID查询信息
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "获取详细信息", notes = "根据url的id来获取详细信息")
|
||||
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
|
||||
@GetMapping("/{id}")
|
||||
public R getApiMaskById(@PathVariable String id) {
|
||||
ApiMaskEntity apiMaskEntity = apiMaskService.getApiMaskById(id);
|
||||
return R.ok().setData(apiMaskMapper.toVO(apiMaskEntity));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过ID查询信息
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "获取详细信息", notes = "根据url的id来获取详细信息")
|
||||
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
|
||||
@GetMapping("/api/{id}")
|
||||
public R getApiMaskByApiId(@PathVariable String id) {
|
||||
ApiMaskEntity apiMaskEntity = apiMaskService.getApiMaskByApiId(id);
|
||||
return R.ok().setData(apiMaskMapper.toVO(apiMaskEntity));
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询信息
|
||||
*
|
||||
* @param apiMaskQuery
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "分页查询", notes = "")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "apiMaskQuery", value = "查询实体apiMaskQuery", required = true, dataTypeClass = ApiMaskQuery.class)
|
||||
})
|
||||
@GetMapping("/page")
|
||||
public R getApiMaskPage(ApiMaskQuery apiMaskQuery) {
|
||||
QueryWrapper<ApiMaskEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.like(StrUtil.isNotBlank(apiMaskQuery.getMaskName()), "mask_name", apiMaskQuery.getMaskName());
|
||||
IPage<ApiMaskEntity> page = apiMaskService.page(new Page<>(apiMaskQuery.getPageNum(), apiMaskQuery.getPageSize()), queryWrapper);
|
||||
List<ApiMaskVo> collect = page.getRecords().stream().map(apiMaskMapper::toVO).collect(Collectors.toList());
|
||||
JsonPage<ApiMaskVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
|
||||
return R.ok().setData(jsonPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
* @param apiMask
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "添加信息", notes = "根据apiMask对象添加信息")
|
||||
@ApiImplicitParam(name = "apiMask", value = "详细实体apiMask", required = true, dataType = "ApiMaskDto")
|
||||
@PostMapping()
|
||||
public R saveApiMask(@RequestBody @Validated({ValidationGroups.Insert.class}) ApiMaskDto apiMask) {
|
||||
apiMaskService.saveApiMask(apiMask);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改
|
||||
* @param apiMask
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "修改信息", notes = "根据url的id来指定修改对象,并根据传过来的信息来修改详细信息")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path"),
|
||||
@ApiImplicitParam(name = "apiMask", value = "详细实体apiMask", required = true, dataType = "ApiMaskDto")
|
||||
})
|
||||
@PutMapping("/{id}")
|
||||
public R updateApiMask(@PathVariable String id, @RequestBody @Validated({ValidationGroups.Update.class}) ApiMaskDto apiMask) {
|
||||
apiMaskService.updateApiMask(apiMask);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "删除", notes = "根据url的id来指定删除对象")
|
||||
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
|
||||
@DeleteMapping("/{id}")
|
||||
public R deleteApiMaskById(@PathVariable String id) {
|
||||
apiMaskService.deleteApiMaskById(id);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@ApiOperation(value = "批量删除", notes = "根据url的ids来批量删除对象")
|
||||
@ApiImplicitParam(name = "ids", value = "ID集合", required = true, dataType = "List", paramType = "path")
|
||||
@DeleteMapping("/batch/{ids}")
|
||||
public R deleteApiMaskBatch(@PathVariable List<String> ids) {
|
||||
apiMaskService.deleteApiMaskBatch(ids);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
package cn.datax.service.data.market.controller;
|
||||
|
||||
import cn.datax.common.base.BaseController;
|
||||
import cn.datax.common.core.JsonPage;
|
||||
import cn.datax.common.core.R;
|
||||
import cn.datax.common.security.annotation.DataInner;
|
||||
import cn.datax.common.validate.ValidationGroups;
|
||||
import cn.datax.service.data.market.api.dto.DataApiDto;
|
||||
import cn.datax.service.data.market.api.dto.SqlParseDto;
|
||||
import cn.datax.service.data.market.api.entity.DataApiEntity;
|
||||
import cn.datax.service.data.market.api.query.DataApiQuery;
|
||||
import cn.datax.service.data.market.api.vo.DataApiVo;
|
||||
import cn.datax.service.data.market.api.vo.SqlParseVo;
|
||||
import cn.datax.service.data.market.mapstruct.DataApiMapper;
|
||||
import cn.datax.service.data.market.service.DataApiService;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据API信息表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-31
|
||||
*/
|
||||
@Api(tags = {"数据API信息表"})
|
||||
@RestController
|
||||
@RequestMapping("/dataApis")
|
||||
public class DataApiController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private DataApiService dataApiService;
|
||||
|
||||
@Autowired
|
||||
private DataApiMapper dataApiMapper;
|
||||
|
||||
/**
|
||||
* 通过ID查询信息
|
||||
*
|
||||
* @param sourceId
|
||||
* @return
|
||||
*/
|
||||
@DataInner
|
||||
@GetMapping("/source/{sourceId}")
|
||||
public DataApiEntity getBySourceId(@PathVariable String sourceId) {
|
||||
return dataApiService.getBySourceId(sourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过ID查询信息
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "获取详细信息", notes = "根据url的id来获取详细信息")
|
||||
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
|
||||
@GetMapping("/{id}")
|
||||
public R getDataApiById(@PathVariable String id) {
|
||||
DataApiEntity dataApiEntity = dataApiService.getDataApiById(id);
|
||||
return R.ok().setData(dataApiMapper.toVO(dataApiEntity));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取列表", notes = "")
|
||||
@GetMapping("/list")
|
||||
public R getDataApiList() {
|
||||
QueryWrapper<DataApiEntity> queryWrapper = new QueryWrapper<>();
|
||||
List<DataApiEntity> list = dataApiService.list(queryWrapper);
|
||||
List<DataApiVo> collect = list.stream().map(dataApiMapper::toVO).collect(Collectors.toList());
|
||||
return R.ok().setData(collect);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询信息
|
||||
*
|
||||
* @param dataApiQuery
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "分页查询", notes = "")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "dataApiQuery", value = "查询实体dataApiQuery", required = true, dataTypeClass = DataApiQuery.class)
|
||||
})
|
||||
@GetMapping("/page")
|
||||
public R getDataApiPage(DataApiQuery dataApiQuery) {
|
||||
QueryWrapper<DataApiEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.like(StrUtil.isNotBlank(dataApiQuery.getApiName()), "api_name", dataApiQuery.getApiName());
|
||||
IPage<DataApiEntity> page = dataApiService.page(new Page<>(dataApiQuery.getPageNum(), dataApiQuery.getPageSize()), queryWrapper);
|
||||
List<DataApiVo> collect = page.getRecords().stream().map(dataApiMapper::toVO).collect(Collectors.toList());
|
||||
JsonPage<DataApiVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
|
||||
return R.ok().setData(jsonPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
* @param dataApi
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "添加信息", notes = "根据dataApi对象添加信息")
|
||||
@ApiImplicitParam(name = "dataApi", value = "详细实体dataApi", required = true, dataType = "DataApiDto")
|
||||
@PostMapping()
|
||||
public R saveDataApi(@RequestBody @Validated({ValidationGroups.Insert.class}) DataApiDto dataApi) {
|
||||
dataApiService.saveDataApi(dataApi);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*
|
||||
* @param dataApi
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "修改信息", notes = "根据url的id来指定修改对象,并根据传过来的信息来修改详细信息")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path"),
|
||||
@ApiImplicitParam(name = "dataApi", value = "详细实体dataApi", required = true, dataType = "DataApiDto")
|
||||
})
|
||||
@PutMapping("/{id}")
|
||||
public R updateDataApi(@PathVariable String id, @RequestBody @Validated({ValidationGroups.Update.class}) DataApiDto dataApi) {
|
||||
dataApiService.updateDataApi(dataApi);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "删除", notes = "根据url的id来指定删除对象")
|
||||
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
|
||||
@DeleteMapping("/{id}")
|
||||
public R deleteDataApiById(@PathVariable String id) {
|
||||
dataApiService.deleteDataApiById(id);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@ApiOperation(value = "批量删除", notes = "根据url的ids来批量删除对象")
|
||||
@ApiImplicitParam(name = "ids", value = "ID集合", required = true, dataType = "List", paramType = "path")
|
||||
@DeleteMapping("/batch/{ids}")
|
||||
public R deleteDataApiBatch(@PathVariable List<String> ids) {
|
||||
dataApiService.deleteDataApiBatch(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL解析
|
||||
*
|
||||
* @param sqlParseDto
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "SQL解析")
|
||||
@ApiImplicitParam(name = "sqlParseDto", value = "SQL解析实体sqlParseDto", required = true, dataType = "SqlParseDto")
|
||||
@PostMapping("/sql/parse")
|
||||
public R sqlParse(@RequestBody @Validated SqlParseDto sqlParseDto) {
|
||||
SqlParseVo sqlParseVo = dataApiService.sqlParse(sqlParseDto);
|
||||
return R.ok().setData(sqlParseVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拷贝接口
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/{id}/copy")
|
||||
public R copyDataApi(@PathVariable String id) {
|
||||
dataApiService.copyDataApi(id);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布接口
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "/{id}/release")
|
||||
public R releaseDataApi(@PathVariable String id) {
|
||||
dataApiService.releaseDataApi(id);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销接口
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "/{id}/cancel")
|
||||
public R cancelDataApi(@PathVariable String id) {
|
||||
dataApiService.cancelDataApi(id);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@ApiOperation(value = "接口文档", notes = "根据url的id来指定生成接口文档对象")
|
||||
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
|
||||
@PostMapping("/word/{id}")
|
||||
public R wordDataApi(@PathVariable String id, HttpServletResponse response) throws Exception {
|
||||
// 清空response
|
||||
response.reset();
|
||||
// 设置response的Header
|
||||
response.setContentType("application/octet-stream;charset=utf-8");
|
||||
// 设置content-disposition响应头控制浏览器以下载的形式打开文件
|
||||
response.addHeader("Content-Disposition", "attachment;filename=" + new String("接口文档.docx".getBytes()));
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/detail/{id}")
|
||||
public R getDataApiDetailById(@PathVariable String id) {
|
||||
Map<String, Object> map = dataApiService.getDataApiDetailById(id);
|
||||
return R.ok().setData(map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package cn.datax.service.data.market.controller;
|
||||
|
||||
import cn.datax.common.base.BaseController;
|
||||
import cn.datax.common.core.DataConstant;
|
||||
import cn.datax.common.security.annotation.DataInner;
|
||||
import cn.datax.service.data.market.api.entity.ApiMaskEntity;
|
||||
import cn.datax.service.data.market.api.entity.DataApiEntity;
|
||||
import cn.datax.service.data.market.service.ApiMaskService;
|
||||
import cn.datax.service.data.market.service.DataApiService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/inner")
|
||||
public class InnerController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private DataApiService dataApiService;
|
||||
|
||||
@Autowired
|
||||
private ApiMaskService apiMaskService;
|
||||
|
||||
@DataInner
|
||||
@GetMapping("/apis/{id}")
|
||||
public DataApiEntity getDataApiById(@PathVariable("id") String id) {
|
||||
DataApiEntity dataApiEntity = dataApiService.getDataApiById(id);
|
||||
return dataApiEntity;
|
||||
}
|
||||
|
||||
@DataInner
|
||||
@GetMapping("/apis/release/list")
|
||||
public List<DataApiEntity> getReleaseDataApiList() {
|
||||
QueryWrapper<DataApiEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("status", DataConstant.ApiState.RELEASE.getKey());
|
||||
List<DataApiEntity> dataApiEntityList = dataApiService.list(queryWrapper);
|
||||
return dataApiEntityList;
|
||||
}
|
||||
|
||||
@DataInner
|
||||
@GetMapping("/apiMasks/api/{id}")
|
||||
public ApiMaskEntity getApiMaskByApiId(@PathVariable("id") String id) {
|
||||
ApiMaskEntity apiMaskEntity = apiMaskService.getApiMaskByApiId(id);
|
||||
return apiMaskEntity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.datax.service.data.market.dao;
|
||||
|
||||
import cn.datax.common.base.BaseDao;
|
||||
import cn.datax.service.data.market.api.entity.ApiMaskEntity;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据API脱敏信息表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
@Mapper
|
||||
public interface ApiMaskDao extends BaseDao<ApiMaskEntity> {
|
||||
|
||||
@Override
|
||||
ApiMaskEntity selectById(Serializable id);
|
||||
|
||||
@Override
|
||||
<E extends IPage<ApiMaskEntity>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<ApiMaskEntity> queryWrapper);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package cn.datax.service.data.market.dao;
|
||||
|
||||
import cn.datax.common.base.BaseDao;
|
||||
import cn.datax.service.data.market.api.entity.DataApiEntity;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据API信息表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-31
|
||||
*/
|
||||
@Mapper
|
||||
public interface DataApiDao extends BaseDao<DataApiEntity> {
|
||||
|
||||
@Override
|
||||
DataApiEntity selectById(Serializable id);
|
||||
|
||||
@Override
|
||||
List<DataApiEntity> selectList(@Param(Constants.WRAPPER) Wrapper<DataApiEntity> queryWrapper);
|
||||
|
||||
@Override
|
||||
<E extends IPage<DataApiEntity>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<DataApiEntity> queryWrapper);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.datax.service.data.market.mapstruct;
|
||||
|
||||
import cn.datax.common.mapstruct.EntityMapper;
|
||||
import cn.datax.service.data.market.api.dto.ApiMaskDto;
|
||||
import cn.datax.service.data.market.api.entity.ApiMaskEntity;
|
||||
import cn.datax.service.data.market.api.vo.ApiMaskVo;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据API脱敏信息表 Mapper 实体映射
|
||||
* </p>
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface ApiMaskMapper extends EntityMapper<ApiMaskDto, ApiMaskEntity, ApiMaskVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.datax.service.data.market.mapstruct;
|
||||
|
||||
import cn.datax.common.mapstruct.EntityMapper;
|
||||
import cn.datax.service.data.market.api.dto.DataApiDto;
|
||||
import cn.datax.service.data.market.api.entity.DataApiEntity;
|
||||
import cn.datax.service.data.market.api.vo.DataApiVo;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据API信息表 Mapper 实体映射
|
||||
* </p>
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-31
|
||||
*/
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface DataApiMapper extends EntityMapper<DataApiDto, DataApiEntity, DataApiVo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.datax.service.data.market.service;
|
||||
|
||||
import cn.datax.common.base.BaseService;
|
||||
import cn.datax.service.data.market.api.dto.ApiMaskDto;
|
||||
import cn.datax.service.data.market.api.entity.ApiMaskEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据API脱敏信息表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
public interface ApiMaskService extends BaseService<ApiMaskEntity> {
|
||||
|
||||
void saveApiMask(ApiMaskDto dataApiMask);
|
||||
|
||||
void updateApiMask(ApiMaskDto dataApiMask);
|
||||
|
||||
ApiMaskEntity getApiMaskById(String id);
|
||||
|
||||
ApiMaskEntity getApiMaskByApiId(String apiId);
|
||||
|
||||
void deleteApiMaskById(String id);
|
||||
|
||||
void deleteApiMaskBatch(List<String> ids);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package cn.datax.service.data.market.service;
|
||||
|
||||
import cn.datax.service.data.market.api.dto.SqlParseDto;
|
||||
import cn.datax.service.data.market.api.entity.DataApiEntity;
|
||||
import cn.datax.service.data.market.api.dto.DataApiDto;
|
||||
import cn.datax.common.base.BaseService;
|
||||
import cn.datax.service.data.market.api.vo.SqlParseVo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据API信息表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-31
|
||||
*/
|
||||
public interface DataApiService extends BaseService<DataApiEntity> {
|
||||
|
||||
void saveDataApi(DataApiDto dataApi);
|
||||
|
||||
void updateDataApi(DataApiDto dataApi);
|
||||
|
||||
DataApiEntity getDataApiById(String id);
|
||||
|
||||
void deleteDataApiById(String id);
|
||||
|
||||
void deleteDataApiBatch(List<String> ids);
|
||||
|
||||
SqlParseVo sqlParse(SqlParseDto sqlParseDto);
|
||||
|
||||
void copyDataApi(String id);
|
||||
|
||||
void releaseDataApi(String id);
|
||||
|
||||
void cancelDataApi(String id);
|
||||
|
||||
Map<String, Object> getDataApiDetailById(String id);
|
||||
|
||||
DataApiEntity getBySourceId(String sourceId);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package cn.datax.service.data.market.service.impl;
|
||||
|
||||
import cn.datax.common.base.BaseServiceImpl;
|
||||
import cn.datax.common.core.RedisConstant;
|
||||
import cn.datax.common.exception.DataException;
|
||||
import cn.datax.service.data.market.api.dto.ApiMaskDto;
|
||||
import cn.datax.service.data.market.api.entity.ApiMaskEntity;
|
||||
import cn.datax.service.data.market.dao.ApiMaskDao;
|
||||
import cn.datax.service.data.market.mapstruct.ApiMaskMapper;
|
||||
import cn.datax.service.data.market.service.ApiMaskService;
|
||||
import cn.datax.service.system.api.entity.DeptEntity;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheConfig;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据API脱敏信息表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-14
|
||||
*/
|
||||
@Service
|
||||
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
|
||||
public class ApiMaskServiceImpl extends BaseServiceImpl<ApiMaskDao, ApiMaskEntity> implements ApiMaskService {
|
||||
|
||||
@Autowired
|
||||
private ApiMaskDao apiMaskDao;
|
||||
|
||||
@Autowired
|
||||
private ApiMaskMapper apiMaskMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveApiMask(ApiMaskDto apiMaskDto) {
|
||||
ApiMaskEntity apiMask = apiMaskMapper.toEntity(apiMaskDto);
|
||||
// 校验api唯一
|
||||
int n = apiMaskDao.selectCount(Wrappers.<ApiMaskEntity>lambdaQuery().eq(ApiMaskEntity::getApiId, apiMask.getApiId()));
|
||||
if(n > 0){
|
||||
throw new DataException("该api已进行过脱敏配置");
|
||||
}
|
||||
apiMaskDao.insert(apiMask);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateApiMask(ApiMaskDto apiMaskDto) {
|
||||
ApiMaskEntity apiMask = apiMaskMapper.toEntity(apiMaskDto);
|
||||
apiMaskDao.updateById(apiMask);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiMaskEntity getApiMaskById(String id) {
|
||||
ApiMaskEntity apiMaskEntity = super.getById(id);
|
||||
return apiMaskEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiMaskEntity getApiMaskByApiId(String apiId) {
|
||||
ApiMaskEntity apiMaskEntity = apiMaskDao.selectOne(new QueryWrapper<ApiMaskEntity>().eq("api_id", apiId));
|
||||
return apiMaskEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteApiMaskById(String id) {
|
||||
apiMaskDao.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteApiMaskBatch(List<String> ids) {
|
||||
apiMaskDao.deleteBatchIds(ids);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,461 @@
|
||||
package cn.datax.service.data.market.service.impl;
|
||||
|
||||
import cn.datax.common.base.BaseServiceImpl;
|
||||
import cn.datax.common.core.DataConstant;
|
||||
import cn.datax.common.core.RedisConstant;
|
||||
import cn.datax.common.exception.DataException;
|
||||
import cn.datax.common.rabbitmq.config.RabbitMqConstant;
|
||||
import cn.datax.common.redis.service.RedisService;
|
||||
import cn.datax.common.utils.MD5Util;
|
||||
import cn.datax.common.utils.SecurityUtil;
|
||||
import cn.datax.common.utils.ThrowableUtil;
|
||||
import cn.datax.service.data.market.api.dto.DataApiDto;
|
||||
import cn.datax.service.data.market.api.dto.ReqParam;
|
||||
import cn.datax.service.data.market.api.dto.ResParam;
|
||||
import cn.datax.service.data.market.api.dto.SqlParseDto;
|
||||
import cn.datax.service.data.market.api.entity.ApiMaskEntity;
|
||||
import cn.datax.service.data.market.api.entity.DataApiEntity;
|
||||
import cn.datax.service.data.market.api.enums.ConfigType;
|
||||
import cn.datax.service.data.market.api.vo.ApiHeader;
|
||||
import cn.datax.service.data.market.api.vo.SqlParseVo;
|
||||
import cn.datax.service.data.market.dao.ApiMaskDao;
|
||||
import cn.datax.service.data.market.dao.DataApiDao;
|
||||
import cn.datax.service.data.market.mapstruct.DataApiMapper;
|
||||
import cn.datax.service.data.market.service.DataApiService;
|
||||
import cn.datax.service.data.market.utils.SqlBuilderUtil;
|
||||
import cn.datax.service.data.metadata.api.entity.MetadataAuthorizeEntity;
|
||||
import cn.datax.service.data.metadata.api.entity.MetadataColumnEntity;
|
||||
import cn.datax.service.data.metadata.api.entity.MetadataSourceEntity;
|
||||
import cn.datax.service.data.metadata.api.entity.MetadataTableEntity;
|
||||
import cn.datax.service.data.metadata.api.enums.DataLevel;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sf.jsqlparser.JSQLParserException;
|
||||
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
|
||||
import net.sf.jsqlparser.expression.Function;
|
||||
import net.sf.jsqlparser.expression.JdbcNamedParameter;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||
import net.sf.jsqlparser.parser.SimpleNode;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import net.sf.jsqlparser.schema.Table;
|
||||
import net.sf.jsqlparser.statement.Statement;
|
||||
import net.sf.jsqlparser.statement.StatementVisitorAdapter;
|
||||
import net.sf.jsqlparser.statement.select.Join;
|
||||
import net.sf.jsqlparser.statement.select.PlainSelect;
|
||||
import net.sf.jsqlparser.statement.select.Select;
|
||||
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
|
||||
import net.sf.jsqlparser.statement.select.SelectItemVisitorAdapter;
|
||||
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;
|
||||
import net.sf.jsqlparser.util.SelectUtils;
|
||||
import net.sf.jsqlparser.util.TablesNamesFinder;
|
||||
import net.sf.jsqlparser.util.deparser.ExpressionDeParser;
|
||||
import net.sf.jsqlparser.util.deparser.SelectDeParser;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据API信息表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author AllDataDC
|
||||
* @date 2022-11-31
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
|
||||
public class DataApiServiceImpl extends BaseServiceImpl<DataApiDao, DataApiEntity> implements DataApiService {
|
||||
|
||||
@Autowired
|
||||
private DataApiDao dataApiDao;
|
||||
|
||||
@Autowired
|
||||
private ApiMaskDao apiMaskDao;
|
||||
|
||||
@Autowired
|
||||
private DataApiMapper dataApiMapper;
|
||||
|
||||
@Autowired
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveDataApi(DataApiDto dataApiDto) {
|
||||
DataApiEntity dataApi = shareCode(dataApiDto);
|
||||
dataApiDao.insert(dataApi);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateDataApi(DataApiDto dataApiDto) {
|
||||
DataApiEntity dataApi = shareCode(dataApiDto);
|
||||
dataApiDao.updateById(dataApi);
|
||||
}
|
||||
|
||||
private DataApiEntity shareCode(DataApiDto dataApiDto) {
|
||||
DataApiEntity dataApi = dataApiMapper.toEntity(dataApiDto);
|
||||
String configType = dataApi.getExecuteConfig().getConfigType();
|
||||
if (ConfigType.FORM.getKey().equals(configType)) {
|
||||
try {
|
||||
dataApi.getExecuteConfig().setSqlText(sqlJdbcNamedParameterBuild(dataApi));
|
||||
} catch (JSQLParserException e) {
|
||||
log.error("全局异常信息ex={}, StackTrace={}", e.getMessage(), ThrowableUtil.getStackTrace(e));
|
||||
throw new DataException("SQL语法有问题,解析出错");
|
||||
}
|
||||
} else if (ConfigType.SCRIPT.getKey().equals(configType)) {
|
||||
}
|
||||
return dataApi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataApiEntity getDataApiById(String id) {
|
||||
DataApiEntity dataApiEntity = super.getById(id);
|
||||
return dataApiEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteDataApiById(String id) {
|
||||
//zrx 判断有无脱敏依赖
|
||||
ApiMaskEntity apiMaskEntity = apiMaskDao.selectOne(new QueryWrapper<ApiMaskEntity>().eq("api_id", id).last("limit 1"));
|
||||
if (apiMaskEntity != null) {
|
||||
throw new RuntimeException("存在与之关联的数据脱敏服务,不允许删除!");
|
||||
}
|
||||
dataApiDao.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteDataApiBatch(List<String> ids) {
|
||||
//zrx check
|
||||
for (String id : ids) {
|
||||
deleteDataApiById(id);
|
||||
}
|
||||
//dataApiDao.deleteBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlParseVo sqlParse(SqlParseDto sqlParseDto) {
|
||||
String sourceId = sqlParseDto.getSourceId();
|
||||
String sql = sqlParseDto.getSqlText();
|
||||
sql = sql.replace(SqlBuilderUtil.getInstance().MARK_KEY_START, "");
|
||||
sql = sql.replace(SqlBuilderUtil.getInstance().MARK_KEY_END, "");
|
||||
Statement stmt;
|
||||
try {
|
||||
stmt = CCJSqlParserUtil.parse(sql);
|
||||
} catch (JSQLParserException e) {
|
||||
log.error("全局异常信息ex={}, StackTrace={}", e.getMessage(), ThrowableUtil.getStackTrace(e));
|
||||
throw new DataException("SQL语法有问题,解析出错");
|
||||
}
|
||||
// 维护元数据缓存数据
|
||||
TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
|
||||
List<String> tables = tablesNamesFinder.getTableList(stmt);
|
||||
// 查询字段
|
||||
final List<Map<String, String>> cols = new ArrayList<>();
|
||||
// 查询参数
|
||||
final List<String> vars = new ArrayList<>();
|
||||
if (tables.size() == 1) {
|
||||
// 单表解析
|
||||
singleSqlParse(stmt, cols, vars, tables.get(0));
|
||||
} else if (tables.size() > 1) {
|
||||
// 多表解析
|
||||
multipleSqlParse(stmt, cols, vars);
|
||||
}
|
||||
SqlParseVo sqlParseVo = new SqlParseVo();
|
||||
List<ReqParam> reqParams = vars.stream().map(s -> {
|
||||
ReqParam reqParam = new ReqParam();
|
||||
reqParam.setParamName(s);
|
||||
reqParam.setNullable(DataConstant.TrueOrFalse.FALSE.getKey());
|
||||
return reqParam;
|
||||
}).collect(Collectors.toList());
|
||||
sqlParseVo.setReqParams(reqParams);
|
||||
List<ResParam> resParams = new ArrayList<>();
|
||||
List<MetadataSourceEntity> sourceEntityList = (List<MetadataSourceEntity>) redisService.get(RedisConstant.METADATA_SOURCE_KEY);
|
||||
MetadataSourceEntity sourceEntity = sourceEntityList.stream().filter(s -> sourceId.equals(s.getId())).findFirst().orElse(null);
|
||||
boolean admin = SecurityUtil.isAdmin();
|
||||
if (sourceEntity != null) {
|
||||
List<MetadataTableEntity> tableEntityList = (List<MetadataTableEntity>) redisService.hget(RedisConstant.METADATA_TABLE_KEY, sourceEntity.getId());
|
||||
Map<String, List<Map<String, String>>> map = cols.stream().collect(Collectors.groupingBy(e -> e.get("tableName").toString()));
|
||||
for (Map.Entry<String, List<Map<String, String>>> entry : map.entrySet()) {
|
||||
String entryKey = entry.getKey().toLowerCase();
|
||||
List<Map<String, String>> entryValue = entry.getValue();
|
||||
MetadataTableEntity tableEntity = tableEntityList.stream().filter(t -> entryKey.equals(t.getTableName().toLowerCase())).findFirst().orElse(null);
|
||||
if (tableEntity != null) {
|
||||
List<MetadataColumnEntity> columnEntityList = (List<MetadataColumnEntity>) redisService.hget(RedisConstant.METADATA_COLUMN_KEY, tableEntity.getId());
|
||||
entryValue.stream().forEach(m -> {
|
||||
String columnName = m.get("columnName").toLowerCase();
|
||||
String columnAliasName = m.get("columnAliasName");
|
||||
Stream<MetadataColumnEntity> stream = columnEntityList.stream().filter(c -> columnName.equals(c.getColumnName().toLowerCase()));
|
||||
if (!admin) {
|
||||
Set<String> set = new HashSet<>();
|
||||
List<String> roleIds = SecurityUtil.getUserRoleIds();
|
||||
roleIds.stream().forEach(role -> {
|
||||
List<MetadataAuthorizeEntity> list = (List<MetadataAuthorizeEntity>) redisService.hget(RedisConstant.METADATA_AUTHORIZE_KEY, role);
|
||||
set.addAll(Optional.ofNullable(list).orElseGet(ArrayList::new).stream()
|
||||
.filter(s -> Objects.equals(DataLevel.COLUMN.getKey(), s.getObjectType()))
|
||||
.map(s -> s.getObjectId()).collect(Collectors.toSet()));
|
||||
});
|
||||
stream = stream.filter(s -> set.contains(s.getId()));
|
||||
}
|
||||
MetadataColumnEntity columnEntity = stream.findFirst().orElse(null);
|
||||
if (columnEntity != null) {
|
||||
ResParam resParam = new ResParam();
|
||||
resParam.setFieldName(columnEntity.getColumnName());
|
||||
resParam.setFieldComment(StrUtil.isNotBlank(columnEntity.getColumnComment()) ? columnEntity.getColumnComment() : "");
|
||||
resParam.setDataType(StrUtil.isNotBlank(columnEntity.getDataType()) ? columnEntity.getDataType() : "");
|
||||
resParam.setFieldAliasName(StrUtil.isNotBlank(columnAliasName) ? columnAliasName : "");
|
||||
resParams.add(resParam);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlParseVo.setResParams(resParams);
|
||||
return sqlParseVo;
|
||||
}
|
||||
|
||||
private void singleSqlParse(Statement stmt, List<Map<String, String>> cols, List<String> vars, String tableName) {
|
||||
stmt.accept(new StatementVisitorAdapter() {
|
||||
@Override
|
||||
public void visit(Select select) {
|
||||
select.getSelectBody().accept(new SelectVisitorAdapter() {
|
||||
@Override
|
||||
public void visit(PlainSelect plainSelect) {
|
||||
plainSelect.getSelectItems().stream().forEach(selectItem -> {
|
||||
selectItem.accept(new SelectItemVisitorAdapter() {
|
||||
@Override
|
||||
public void visit(SelectExpressionItem item) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
String columnName;
|
||||
SimpleNode node = item.getExpression().getASTNode();
|
||||
Object value = node.jjtGetValue();
|
||||
if (value instanceof Column) {
|
||||
Column column = (Column) value;
|
||||
columnName = column.getColumnName();
|
||||
if (item.getAlias() != null) {
|
||||
map.put("columnAliasName", item.getAlias().getName());
|
||||
}
|
||||
} else if (value instanceof Function) {
|
||||
columnName = value.toString();
|
||||
} else {
|
||||
// 增加对select 'aaa' from table; 的支持
|
||||
columnName = String.valueOf(value);
|
||||
columnName = columnName.replace("'", "");
|
||||
columnName = columnName.replace("\"", "");
|
||||
columnName = columnName.replace("`", "");
|
||||
}
|
||||
columnName = columnName.replace("'", "");
|
||||
columnName = columnName.replace("\"", "");
|
||||
columnName = columnName.replace("`", "");
|
||||
map.put("tableName", tableName);
|
||||
map.put("columnName", columnName);
|
||||
cols.add(map);
|
||||
}
|
||||
});
|
||||
});
|
||||
plainSelect.getWhere().accept(new ExpressionVisitorAdapter() {
|
||||
@Override
|
||||
public void visit(JdbcNamedParameter jdbcNamedParameter) {
|
||||
vars.add(jdbcNamedParameter.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void multipleSqlParse(Statement stmt, List<Map<String, String>> cols, List<String> vars) {
|
||||
stmt.accept(new StatementVisitorAdapter() {
|
||||
@Override
|
||||
public void visit(Select select) {
|
||||
select.getSelectBody().accept(new SelectVisitorAdapter() {
|
||||
@Override
|
||||
public void visit(PlainSelect plainSelect) {
|
||||
// 存储表名
|
||||
Map<String, String> map = new HashMap<>();
|
||||
Table table = (Table) plainSelect.getFromItem();
|
||||
if (table.getAlias() != null) {
|
||||
map.put(table.getName(), table.getAlias().getName());
|
||||
}
|
||||
for (Join join : plainSelect.getJoins()) {
|
||||
Table table1 = (Table) join.getRightItem();
|
||||
if (table1.getAlias() != null) {
|
||||
map.put(table1.getName(), table1.getAlias().getName());
|
||||
}
|
||||
}
|
||||
plainSelect.getSelectItems().stream().forEach(selectItem -> {
|
||||
selectItem.accept(new SelectItemVisitorAdapter() {
|
||||
@Override
|
||||
public void visit(SelectExpressionItem item) {
|
||||
Map<String, String> m = new HashMap<>();
|
||||
String tableName = "", columnName;
|
||||
SimpleNode node = item.getExpression().getASTNode();
|
||||
Object value = node.jjtGetValue();
|
||||
if (value instanceof Column) {
|
||||
Column column = (Column) value;
|
||||
Table table = column.getTable();
|
||||
if (table != null) {
|
||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||
if (table.getName().equals(entry.getValue())) {
|
||||
tableName = entry.getKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
columnName = column.getColumnName();
|
||||
if (item.getAlias() != null) {
|
||||
m.put("columnAliasName", item.getAlias().getName());
|
||||
}
|
||||
} else if (value instanceof Function) {
|
||||
columnName = value.toString();
|
||||
} else {
|
||||
// 增加对select 'aaa' from table; 的支持
|
||||
columnName = String.valueOf(value);
|
||||
columnName = columnName.replace("'", "");
|
||||
columnName = columnName.replace("\"", "");
|
||||
columnName = columnName.replace("`", "");
|
||||
}
|
||||
columnName = columnName.replace("'", "");
|
||||
columnName = columnName.replace("\"", "");
|
||||
columnName = columnName.replace("`", "");
|
||||
m.put("tableName", tableName);
|
||||
m.put("columnName", columnName);
|
||||
cols.add(m);
|
||||
}
|
||||
});
|
||||
});
|
||||
plainSelect.getWhere().accept(new ExpressionVisitorAdapter() {
|
||||
@Override
|
||||
public void visit(JdbcNamedParameter jdbcNamedParameter) {
|
||||
vars.add(jdbcNamedParameter.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String sqlJdbcNamedParameterBuild(DataApiEntity dataApi) throws JSQLParserException {
|
||||
Table table = new Table(dataApi.getExecuteConfig().getTableName());
|
||||
String[] resParams = dataApi.getResParams().stream().map(s -> s.getFieldName()).toArray(String[]::new);
|
||||
Select select = SelectUtils.buildSelectFromTableAndExpressions(table, resParams);
|
||||
return SqlBuilderUtil.getInstance().buildHql(select.toString(), dataApi.getReqParams());
|
||||
}
|
||||
|
||||
private String sqlJdbcNamedParameterParse(String sqlText) throws JSQLParserException {
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
ExpressionDeParser expressionDeParser = new ExpressionDeParser() {
|
||||
@Override
|
||||
public void visit(JdbcNamedParameter jdbcNamedParameter) {
|
||||
this.getBuffer().append("?");
|
||||
}
|
||||
};
|
||||
SelectDeParser deparser = new SelectDeParser(expressionDeParser, buffer);
|
||||
expressionDeParser.setSelectVisitor(deparser);
|
||||
expressionDeParser.setBuffer(buffer);
|
||||
Statement stmt = CCJSqlParserUtil.parse(sqlText);
|
||||
stmt.accept(new StatementVisitorAdapter() {
|
||||
@Override
|
||||
public void visit(Select select) {
|
||||
select.getSelectBody().accept(deparser);
|
||||
}
|
||||
});
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyDataApi(String id) {
|
||||
DataApiEntity dataApiEntity = Optional.ofNullable(super.getById(id)).orElseThrow(() -> new DataException("获取失败"));
|
||||
DataApiEntity copy = new DataApiEntity();
|
||||
copy.setApiName(dataApiEntity.getApiName() + "_副本" + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN));
|
||||
copy.setApiVersion(dataApiEntity.getApiVersion());
|
||||
copy.setApiUrl(dataApiEntity.getApiUrl() + "/copy" + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN));
|
||||
copy.setReqMethod(dataApiEntity.getReqMethod());
|
||||
copy.setResType(dataApiEntity.getResType());
|
||||
copy.setDeny(dataApiEntity.getDeny());
|
||||
copy.setRateLimit(dataApiEntity.getRateLimit());
|
||||
copy.setExecuteConfig(dataApiEntity.getExecuteConfig());
|
||||
copy.setReqParams(dataApiEntity.getReqParams());
|
||||
copy.setResParams(dataApiEntity.getResParams());
|
||||
copy.setStatus(DataConstant.ApiState.WAIT.getKey());
|
||||
dataApiDao.insert(copy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseDataApi(String id) {
|
||||
Map<String, Object> map = new HashMap<>(2);
|
||||
map.put("id", id);
|
||||
map.put("type", "1");
|
||||
rabbitTemplate.convertAndSend(RabbitMqConstant.FANOUT_EXCHANGE_API, "", map);
|
||||
LambdaUpdateWrapper<DataApiEntity> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.set(DataApiEntity::getStatus, DataConstant.ApiState.RELEASE.getKey());
|
||||
updateWrapper.eq(DataApiEntity::getId, id);
|
||||
dataApiDao.update(null, updateWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelDataApi(String id) {
|
||||
Map<String, Object> map = new HashMap<>(2);
|
||||
map.put("id", id);
|
||||
map.put("type", "2");
|
||||
rabbitTemplate.convertAndSend(RabbitMqConstant.FANOUT_EXCHANGE_API, "", map);
|
||||
LambdaUpdateWrapper<DataApiEntity> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.set(DataApiEntity::getStatus, DataConstant.ApiState.CANCEL.getKey());
|
||||
updateWrapper.eq(DataApiEntity::getId, id);
|
||||
dataApiDao.update(null, updateWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getDataApiDetailById(String id) {
|
||||
DataApiEntity dataApiEntity = super.getById(id);
|
||||
ApiHeader apiHeader = new ApiHeader();
|
||||
MD5Util mt = null;
|
||||
try {
|
||||
mt = MD5Util.getInstance();
|
||||
apiHeader.setApiKey(mt.encode(id));
|
||||
apiHeader.setSecretKey(mt.encode(SecurityUtil.getUserId()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>(2);
|
||||
map.put("data", dataApiMapper.toVO(dataApiEntity));
|
||||
map.put("header", apiHeader);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataApiEntity getBySourceId(String sourceId) {
|
||||
return dataApiDao.selectOne(new QueryWrapper<DataApiEntity>().eq("source_id", sourceId).last("limit 1"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package cn.datax.service.data.market.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package cn.datax.service.data.market.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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
package cn.datax.service.data.market.utils;
|
||||
|
||||
import cn.datax.service.data.market.api.dto.ReqParam;
|
||||
import cn.datax.service.data.market.api.enums.WhereType;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 用于动态构造sql语句
|
||||
* ${ segment... } 为一个条件代码块
|
||||
*
|
||||
* String sql = "select * from user where 1=1
|
||||
* ${ and username = :username }
|
||||
* ${ and password = :password }
|
||||
* ${ and age = :age }"
|
||||
*
|
||||
* Map filters = new HashMap();
|
||||
* filters.put("username", "yuwei");
|
||||
* filters.put("age", "12");
|
||||
* filters.put("id", "123");
|
||||
*
|
||||
* SqlFilterResult result = SqlBuilderUtil.applyFilters(sql, filters);
|
||||
*
|
||||
* result.getSql()结果
|
||||
* select * from user where 1=1 and username=:username and age=:age
|
||||
*
|
||||
* result.getAcceptedFilters()结果
|
||||
* {username=yuwei}
|
||||
* {age=12}
|
||||
*/
|
||||
@Slf4j
|
||||
public class SqlBuilderUtil {
|
||||
|
||||
private SqlBuilderUtil() {}
|
||||
|
||||
private static volatile SqlBuilderUtil instance;
|
||||
|
||||
public static SqlBuilderUtil getInstance() {
|
||||
if(instance == null) {
|
||||
synchronized (SqlBuilderUtil.class) {
|
||||
if(instance == null) {
|
||||
instance = new SqlBuilderUtil();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 空格
|
||||
*/
|
||||
private final String SPACE = " ";
|
||||
/**
|
||||
* 冒号占位符
|
||||
*/
|
||||
private final String COLON = ":";
|
||||
/**
|
||||
* 问号占位符
|
||||
*/
|
||||
private final String MARK = "?";
|
||||
/**
|
||||
* where关键字
|
||||
*/
|
||||
private final String WHERE_SQL = "WHERE";
|
||||
/**
|
||||
* AND连接符
|
||||
*/
|
||||
private final String WHERE_AND = "AND";
|
||||
/**
|
||||
* where 1=1条件
|
||||
*/
|
||||
private final String WHERE_INIT = WHERE_SQL + " 1 = 1";
|
||||
/**
|
||||
* 左括号
|
||||
*/
|
||||
private final String LEFT_BRACKET = "(";
|
||||
/**
|
||||
* 右括号
|
||||
*/
|
||||
private final String RIGHT_BRACKET = ")";
|
||||
/**
|
||||
* 百分号%
|
||||
*/
|
||||
private final String PERCENT_SIGN = "%";
|
||||
/**
|
||||
* 单引号 '
|
||||
*/
|
||||
private final String SINGLE_QUOTE = "'";
|
||||
/**
|
||||
* 条件代码块标记开始
|
||||
*/
|
||||
public final String MARK_KEY_START = "${";
|
||||
/**
|
||||
* 条件代码块标记结束
|
||||
*/
|
||||
public final String MARK_KEY_END = "}";
|
||||
|
||||
/**
|
||||
* 拼接命名参数sql
|
||||
* @param sql
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
public String buildHql(String sql, List<ReqParam> params){
|
||||
Assert.notNull(sql, "SQL must not be null");
|
||||
return buildHql(new StringBuffer(sql), params);
|
||||
}
|
||||
|
||||
private String buildHql(StringBuffer sql, List<ReqParam> params){
|
||||
if(CollUtil.isEmpty(params)){
|
||||
return sql.toString();
|
||||
}
|
||||
sql.append(SPACE).append(WHERE_INIT);
|
||||
for (int i = 0; i < params.size(); i++) {
|
||||
ReqParam reqParam = params.get(i);
|
||||
sql.append(SPACE).append(MARK_KEY_START).append(WHERE_AND).append(SPACE).append(reqParam.getParamName());
|
||||
if (WhereType.LIKE.getType() == reqParam.getWhereType()) {
|
||||
// LIKE '%' :username '%' ,:username 两边一定要有空格,如果没有空格,是查询不到数据的
|
||||
sql.append(SPACE).append(WhereType.getWhereType(reqParam.getWhereType()).getKey())
|
||||
.append(SPACE).append(SINGLE_QUOTE).append(PERCENT_SIGN).append(SINGLE_QUOTE).append(SPACE)
|
||||
.append(COLON).append(reqParam.getParamName())
|
||||
.append(SPACE).append(SINGLE_QUOTE).append(PERCENT_SIGN).append(SINGLE_QUOTE).append(MARK_KEY_END);
|
||||
} else if(WhereType.LIKE_LEFT.getType() == reqParam.getWhereType()) {
|
||||
sql.append(SPACE).append(WhereType.getWhereType(reqParam.getWhereType()).getKey())
|
||||
.append(SPACE).append(SINGLE_QUOTE).append(PERCENT_SIGN).append(SINGLE_QUOTE).append(SPACE)
|
||||
.append(COLON).append(reqParam.getParamName()).append(MARK_KEY_END);
|
||||
} else if(WhereType.LIKE_RIGHT.getType() == reqParam.getWhereType()) {
|
||||
sql.append(SPACE).append(WhereType.getWhereType(reqParam.getWhereType()).getKey())
|
||||
.append(SPACE).append(COLON).append(reqParam.getParamName())
|
||||
.append(SPACE).append(SINGLE_QUOTE).append(PERCENT_SIGN).append(SINGLE_QUOTE).append(MARK_KEY_END);
|
||||
} else if(WhereType.NULL.getType() == reqParam.getWhereType() || WhereType.NOT_NULL.getType() == reqParam.getWhereType()){
|
||||
// is null或is not null不需要参数值
|
||||
sql.append(SPACE).append(WhereType.getWhereType(reqParam.getWhereType()).getKey()).append(MARK_KEY_END);
|
||||
} else if(WhereType.IN.getType() == reqParam.getWhereType()){
|
||||
// in (:ids)
|
||||
sql.append(SPACE).append(WhereType.getWhereType(reqParam.getWhereType()).getKey())
|
||||
.append(SPACE).append(LEFT_BRACKET)
|
||||
.append(COLON).append(reqParam.getParamName())
|
||||
.append(RIGHT_BRACKET).append(MARK_KEY_END);
|
||||
} else {
|
||||
sql.append(SPACE).append(WhereType.getWhereType(reqParam.getWhereType()).getKey())
|
||||
.append(SPACE).append(COLON).append(reqParam.getParamName()).append(MARK_KEY_END);
|
||||
}
|
||||
}
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据入参动态构造sql语句
|
||||
* @param sql
|
||||
* @param filters
|
||||
* @return
|
||||
*/
|
||||
public SqlFilterResult applyFilters(String sql, Map<String, Object> filters){
|
||||
Assert.notNull(sql, "SQL must not be null");
|
||||
return applyFilters(new StringBuffer(sql), filters);
|
||||
}
|
||||
|
||||
private SqlFilterResult applyFilters(StringBuffer sql, Map<String, Object> filters){
|
||||
LinkedHashMap<String, Object> acceptedFilters = new LinkedHashMap<>();
|
||||
for (int i = 0, end = 0, start = sql.indexOf(MARK_KEY_START); ((start = sql.indexOf(MARK_KEY_START, end)) >= 0); i++) {
|
||||
end = sql.indexOf(MARK_KEY_END, start);
|
||||
// 封装该条件代码块中的NamedParameterSql
|
||||
ParsedSql parsedSql = getSegmentParsedSql(sql, start, end);
|
||||
if (CollUtil.isEmpty(parsedSql.getParamNames())){
|
||||
throw new IllegalArgumentException("Not key found in segment=" + sql.substring(start, end + MARK_KEY_END.length()));
|
||||
}
|
||||
// 判断输入参数filters中是否存在查询参数
|
||||
if (isAcceptedKeys(filters, parsedSql.getParamNames())) {
|
||||
// 动态构造可执行的sql语句,去掉条件代码块两边的${ }标记符
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("The filter namedParameters=" + parsedSql.getParamNames() + " is accepted on segment=" + sql.substring(start, end + MARK_KEY_END.length()));
|
||||
}
|
||||
// 下面方法2选1可以获取条件代码块
|
||||
// select id, name from user where 1 = 1 and id = :id
|
||||
// String segment = sql.substring(start + MARK_KEY_START.length(), end);
|
||||
String segment = parsedSql.getOriginalSql();
|
||||
// 转换命名参数:为?
|
||||
// select id, name from user where 1 = 1 and id = ?
|
||||
// String segment = NamedParameterUtil.substituteNamedParams(parsedSql, filters);
|
||||
// 获取传参中包含命名参数的数据
|
||||
LinkedHashMap<String, Object> linkAcceptedFilters = NamedParameterUtil.buildValueArray(parsedSql, filters);
|
||||
acceptedFilters.putAll(linkAcceptedFilters);
|
||||
sql.replace(start, end + MARK_KEY_END.length(), segment);
|
||||
end = start + segment.length();
|
||||
} else {
|
||||
// 抛弃该条件代码块
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("The filter namedParameters=" + parsedSql.getParamNames() + " is removed from the query on segment=" + sql.substring(start, end + MARK_KEY_END.length()));
|
||||
}
|
||||
sql.replace(start, end + MARK_KEY_END.length(), "");
|
||||
end = start;
|
||||
}
|
||||
}
|
||||
return new SqlFilterResult(sql.toString(), acceptedFilters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证入参,并过滤值为空的入参
|
||||
*/
|
||||
private boolean isAcceptedKeys(Map<String, Object> filters, List<String> keys) {
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String key = keys.get(i);
|
||||
Object value = getProperty(filters, key);
|
||||
if (!isValuePopulated(value, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 封装该条件代码块中的NamedParameterSql
|
||||
*/
|
||||
private ParsedSql getSegmentParsedSql(StringBuffer sql, int start, int end) {
|
||||
String segment = sql.substring(start + MARK_KEY_START.length(), end);
|
||||
ParsedSql parsedSql = NamedParameterUtil.parseSqlStatement(segment);
|
||||
return parsedSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取参数值
|
||||
* @param filters
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
private Object getProperty(Map<String, Object> filters, String key) {
|
||||
if (MapUtil.isEmpty(filters))
|
||||
return null;
|
||||
return filters.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证参数值是否空
|
||||
* @param value
|
||||
* @param isRemoveEmpty
|
||||
* @return
|
||||
*/
|
||||
private boolean isValuePopulated(Object value, boolean isRemoveEmpty) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
if (isRemoveEmpty) {
|
||||
return ObjectUtil.isNotEmpty(value);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class SqlFilterResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID=1L;
|
||||
|
||||
private String sql;
|
||||
|
||||
private Map<String, Object> acceptedFilters;
|
||||
|
||||
public SqlFilterResult(String sql, Map<String, Object> acceptedFilters) {
|
||||
this.setSql(sql);
|
||||
this.setAcceptedFilters(acceptedFilters);
|
||||
}
|
||||
|
||||
public String getSql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
public void setSql(String sql) {
|
||||
this.sql = sql;
|
||||
}
|
||||
|
||||
public Map<String, Object> getAcceptedFilters() {
|
||||
return acceptedFilters;
|
||||
}
|
||||
|
||||
public void setAcceptedFilters(Map<String, Object> acceptedFilters) {
|
||||
this.acceptedFilters = acceptedFilters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SqlFilterResult{" +
|
||||
"sql='" + sql + '\'' +
|
||||
", acceptedFilters=" + acceptedFilters +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.datax.service.data.market.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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
server:
|
||||
port: 8822
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: service-data-market
|
||||
profiles:
|
||||
active: dev
|
||||
cloud:
|
||||
config:
|
||||
label: master
|
||||
name: ${spring.application.name}
|
||||
profile: ${spring.profiles.active}
|
||||
discovery:
|
||||
enabled: true
|
||||
service-id: config
|
||||
|
||||
# 注册中心配置
|
||||
eureka:
|
||||
instance:
|
||||
lease-renewal-interval-in-seconds: 20
|
||||
prefer-ip-address: true
|
||||
ip-address: 192.168.1.169
|
||||
client:
|
||||
register-with-eureka: true
|
||||
fetch-registry: true
|
||||
instance-info-replication-interval-seconds: 30
|
||||
registry-fetch-interval-seconds: 3
|
||||
service-url:
|
||||
defaultZone: http://192.168.1.169:8610/eureka
|
||||
@@ -0,0 +1,78 @@
|
||||
<?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/service-data-market"/>
|
||||
<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>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.datax.service.data.market.dao.ApiMaskDao">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="cn.datax.service.data.market.api.entity.ApiMaskEntity">
|
||||
<result column="id" property="id" />
|
||||
<result column="status" property="status" />
|
||||
<result column="create_by" property="createBy" />
|
||||
<result column="create_time" property="createTime" />
|
||||
<result column="create_dept" property="createDept" />
|
||||
<result column="update_by" property="updateBy" />
|
||||
<result column="update_time" property="updateTime" />
|
||||
<result column="api_id" property="apiId" />
|
||||
<result column="mask_name" property="maskName" />
|
||||
<result column="remark" property="remark" />
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="ExtendResultMap" type="cn.datax.service.data.market.api.entity.ApiMaskEntity" extends="BaseResultMap">
|
||||
<result column="config_json" property="rules" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
id,
|
||||
status,
|
||||
create_by,
|
||||
create_time,
|
||||
create_dept,
|
||||
update_by,
|
||||
update_time,
|
||||
api_id, mask_name, remark
|
||||
</sql>
|
||||
|
||||
<sql id="Extend_Column_List">
|
||||
id,
|
||||
status,
|
||||
create_by,
|
||||
create_time,
|
||||
create_dept,
|
||||
update_by,
|
||||
update_time,
|
||||
api_id, mask_name, remark, config_json
|
||||
</sql>
|
||||
|
||||
<select id="selectById" resultMap="ExtendResultMap">
|
||||
SELECT
|
||||
<include refid="Extend_Column_List"></include>
|
||||
FROM market_api_mask
|
||||
WHERE 1=1 AND id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectPage" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
<include refid="Base_Column_List"></include>
|
||||
FROM market_api_mask
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.datax.service.data.market.dao.DataApiDao">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="cn.datax.service.data.market.api.entity.DataApiEntity">
|
||||
<result column="id" property="id" />
|
||||
<result column="status" property="status" />
|
||||
<result column="create_by" property="createBy" />
|
||||
<result column="create_time" property="createTime" />
|
||||
<result column="create_dept" property="createDept" />
|
||||
<result column="update_by" property="updateBy" />
|
||||
<result column="update_time" property="updateTime" />
|
||||
<result column="api_name" property="apiName" />
|
||||
<result column="api_version" property="apiVersion" />
|
||||
<result column="api_url" property="apiUrl" />
|
||||
<result column="remark" property="remark" />
|
||||
<result column="req_method" property="reqMethod" />
|
||||
<result column="res_type" property="resType" />
|
||||
<result column="deny" property="deny" />
|
||||
<result column="source_id" property="sourceId" />
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="ExtendResultMap" type="cn.datax.service.data.market.api.entity.DataApiEntity" extends="BaseResultMap">
|
||||
<result column="limit_json" property="rateLimit" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
|
||||
<result column="config_json" property="executeConfig" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
|
||||
<result column="req_json" property="reqParams" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
|
||||
<result column="res_json" property="resParams" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
id,
|
||||
status,
|
||||
create_by,
|
||||
create_time,
|
||||
create_dept,
|
||||
update_by,
|
||||
update_time,
|
||||
api_name, api_version, api_url, remark, req_method, res_type, deny, source_id
|
||||
</sql>
|
||||
|
||||
<sql id="Extend_Column_List">
|
||||
id,
|
||||
status,
|
||||
create_by,
|
||||
create_time,
|
||||
create_dept,
|
||||
update_by,
|
||||
update_time,
|
||||
api_name, api_version, api_url, remark, req_method, res_type, deny, source_id, limit_json, config_json, req_json, res_json
|
||||
</sql>
|
||||
|
||||
<select id="selectById" resultMap="ExtendResultMap">
|
||||
SELECT
|
||||
<include refid="Extend_Column_List"/>
|
||||
FROM market_api
|
||||
WHERE 1=1 AND id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectList" resultMap="ExtendResultMap">
|
||||
SELECT
|
||||
<include refid="Extend_Column_List"/>
|
||||
FROM market_api
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
<select id="selectPage" resultMap="BaseResultMap">
|
||||
SELECT
|
||||
<include refid="Base_Column_List"/>
|
||||
FROM market_api
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,25 @@
|
||||
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
|
||||
Binary file not shown.
Reference in New Issue
Block a user