Commit d7a480a1 by yuwei

项目初始化

parent c45748a3
package cn.datax.common.utils;
import cn.datax.common.core.DataUser;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.Optional;
public class SecurityUtil {
/**
......@@ -13,10 +12,13 @@ public class SecurityUtil {
* @return user
*/
public static DataUser getDataUser() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof DataUser) {
DataUser user = (DataUser) principal;
return user;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
Object principal = authentication.getPrincipal();
if (principal instanceof DataUser) {
DataUser user = (DataUser) principal;
return user;
}
}
return null;
}
......@@ -27,9 +29,8 @@ public class SecurityUtil {
* @return id
*/
public static String getUserId() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof DataUser) {
DataUser user = (DataUser) principal;
DataUser user = getDataUser();
if (user != null){
return user.getId();
}
return null;
......@@ -41,9 +42,8 @@ public class SecurityUtil {
* @return id
*/
public static String getUserDeptId() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof DataUser) {
DataUser user = (DataUser) principal;
DataUser user = getDataUser();
if (user != null){
return user.getDept();
}
return null;
......@@ -55,9 +55,8 @@ public class SecurityUtil {
* @return username
*/
public static String getUserName() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof DataUser) {
DataUser user = (DataUser) principal;
DataUser user = getDataUser();
if (user != null){
return user.getUsername();
}
return null;
......
......@@ -24,10 +24,5 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>${redisson.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
</project>
package cn.datax.common.redis.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisCacheAop {
// 缓存名
String cacheName() default "";
// 过期时间(秒) time要大于0 如果time小于等于0 将设置无限期
long expire() default -1;
// 缓存反序列化获取的对象
Class clazz() default Object.class;
// 序列化后的对象是否是数组 比如 List<Object>
boolean isArray() default false;
}
package cn.datax.common.redis.aspectj;
import cn.datax.common.redis.annotation.RedisCacheAop;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Aspect
@Slf4j
public class RedisCacheAspect {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private ObjectMapper objectMapper;
/**
* 分隔符 生成key 格式为 类全类名|方法名|参数所属类全类名
*/
private static final String DELIMITER = ":";
/**
* Service层切点 使用到了我们定义的 RedisCacheAspect 作为切点表达式。
* 而且我们可以看出此表达式基于 annotation。
* 并且用于内建属性为查询的方法之上
*/
@Pointcut("@annotation(cn.datax.common.redis.annotation.RedisCacheAop)")
public void redisCacheAspect() {
}
/**
* Around 手动控制调用核心业务逻辑,以及调用前和调用后的处理,
* <p>
* 注意:当核心业务抛异常后,立即退出,转向AfterAdvice 执行完AfterAdvice,再转到ThrowingAdvice
*/
@Around(value = "redisCacheAspect()")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
// 得到类名、方法名和参数
String clazzName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
// 根据类名、方法名和参数生成Key
log.info("key参数: " + clazzName + "." + methodName);
String key = getKey(clazzName, methodName, args);
log.info("生成key: " + key);
// 得到被代理的方法
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
String cacheName = method.getAnnotation(RedisCacheAop.class).cacheName();
long expire = method.getAnnotation(RedisCacheAop.class).expire();
Class objectType = method.getAnnotation(RedisCacheAop.class).clazz();
boolean isArray = method.getAnnotation(RedisCacheAop.class).isArray();
// 检查Redis中是否有缓存
String value = (String) redisTemplate.opsForValue().get(key + DELIMITER + cacheName);
// result是方法的最终返回结果
Object result = null;
try {
if (null == value) {
log.info("缓存未命中");
// 调用数据库查询方法
result = joinPoint.proceed(args);
// 结果放入缓存
if (expire > 0) {
redisTemplate.opsForValue().set(key + DELIMITER + cacheName, objectMapper.writeValueAsString(result), expire, TimeUnit.SECONDS);
} else {
redisTemplate.opsForValue().set(key + DELIMITER + cacheName, objectMapper.writeValueAsString(result));
}
} else {
/**
* 可以直接针对mapper进行缓存,如果mapper查询返回的List<Objec> 需要isArray 为true 否则转换异常
*/
if (isArray){
JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, objectType);
return objectMapper.readValue(value, javaType);
}else {
return objectMapper.readValue(value, objectType);
}
}
} catch (Throwable e) {
log.error("程序异常", e.getMessage());
throw e;
}
return result;
}
/**
* 根据类名、方法名和参数生成Key
* @param clazzName
* @param methodName
* @param args
* @return key格式:全类名:方法名:参数类型
*/
private String getKey(String clazzName, String methodName, Object[] args) {
StringBuilder key = new StringBuilder(clazzName);
key.append(DELIMITER);
key.append(methodName);
key.append(DELIMITER);
key.append(Arrays.stream(args).map(x -> x.toString()).collect(Collectors.joining(DELIMITER)));
return key.toString();
}
}
package cn.datax.common.redis.config;
import cn.datax.common.redis.service.impl.RedissonLocker;
import cn.datax.common.redis.utils.LockUtil;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@EnableConfigurationProperties({RedisProperties.class})
@AllArgsConstructor
public class RedissonConfig {
private RedisProperties redisProperties;
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
if(redisProperties.getCluster() != null){
// 集群模式配置
config.useClusterServers()
.addNodeAddress(redisProperties.getCluster().getNodes().stream().toArray(String[]::new))
.setPassword(StringUtils.isBlank(redisProperties.getPassword()) ? null : redisProperties.getPassword());
}else if(redisProperties.getSentinel() != null){
//添加哨兵配置
config.useMasterSlaveServers().setMasterAddress(redisProperties.getSentinel().getMaster())
.addSlaveAddress(redisProperties.getSentinel().getNodes().stream().toArray(String[]::new))
.setPassword(StringUtils.isBlank(redisProperties.getPassword()) ? null : redisProperties.getPassword());
}else {
//单节点
config.useSingleServer().setAddress("redis://" + redisProperties.getHost() + ":" + redisProperties.getPort())
.setPassword(StringUtils.isBlank(redisProperties.getPassword()) ? null : redisProperties.getPassword());
}
return Redisson.create(config);
}
@Bean
public RedissonLocker redissonLocker(RedissonClient redissonClient) {
RedissonLocker locker = new RedissonLocker(redissonClient);
// 设置LockUtil的锁处理对象
LockUtil.setLocker(locker);
return locker;
}
}
package cn.datax.common.redis.service;
import org.redisson.api.RLock;
import java.util.concurrent.TimeUnit;
/**
* 锁接口
*/
public interface Locker {
/**
* 获取锁,如果锁不可用,则当前线程处于休眠状态,直到获得锁为止。
*
* @param lockKey
*/
RLock lock(String lockKey);
/**
* 释放锁
*
* @param lockKey
*/
RLock unlock(String lockKey);
/**
* 获取锁,如果锁不可用,则当前线程处于休眠状态,直到获得锁为止。如果获取到锁后,执行结束后解锁或达到超时时间后会自动释放锁
*
* @param lockKey
* @param timeout
*/
RLock lock(String lockKey, int timeout);
/**
* 获取锁,如果锁不可用,则当前线程处于休眠状态,直到获得锁为止。如果获取到锁后,执行结束后解锁或达到超时时间后会自动释放锁
*
* @param lockKey
* @param unit
* @param timeout
*/
RLock lock(String lockKey, TimeUnit unit, int timeout);
/**
* 尝试获取锁,获取到立即返回true,未获取到立即返回false
*
* @param lockKey
* @return
*/
boolean tryLock(String lockKey);
/**
* 尝试获取锁,在等待时间内获取到锁则返回true,否则返回false,如果获取到锁,则要么执行完后程序释放锁,
* 要么在给定的超时时间leaseTime后释放锁
*
* @param lockKey
* @param waitTime
* @param leaseTime
* @param unit
* @return
*/
boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit);
/**
* 锁是否被任意一个线程锁持有
*
* @param lockKey
* @return
*/
boolean isLocked(String lockKey);
}
package cn.datax.common.redis.service.impl;
import cn.datax.common.redis.service.Locker;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
/**
* 基于Redisson的分布式锁
*/
public class RedissonLocker implements Locker {
private RedissonClient redissonClient;
public RedissonLocker(RedissonClient redissonClient) {
super();
this.redissonClient = redissonClient;
}
public void setRedissonClient(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
@Override
public RLock lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
return lock;
}
@Override
public RLock unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
return lock;
}
@Override
public RLock lock(String lockKey, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(leaseTime, TimeUnit.SECONDS);
return lock;
}
@Override
public RLock lock(String lockKey, TimeUnit unit, int timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
return lock;
}
@Override
public boolean tryLock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
return lock.tryLock();
}
@Override
public boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
return false;
}
}
@Override
public boolean isLocked(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
return lock.isLocked();
}
}
package cn.datax.common.redis.utils;
import cn.datax.common.redis.service.Locker;
import java.util.concurrent.TimeUnit;
/**
* redis分布式锁工具类
*/
public final class LockUtil {
private static Locker locker;
/**
* 设置工具类使用的locker
*
* @param locker
*/
public static void setLocker(Locker locker) {
LockUtil.locker = locker;
}
/**
* 获取锁
*
* @param lockKey
*/
public static void lock(String lockKey) {
locker.lock(lockKey);
}
/**
* 释放锁
*
* @param lockKey
*/
public static void unlock(String lockKey) {
locker.unlock(lockKey);
}
/**
* 获取锁,超时释放
*
* @param lockKey
* @param timeout
*/
public static void lock(String lockKey, int timeout) {
locker.lock(lockKey, timeout);
}
/**
* 获取锁,超时释放,指定时间单位
*
* @param lockKey
* @param unit
* @param timeout
*/
public static void lock(String lockKey, TimeUnit unit, int timeout) {
locker.lock(lockKey, unit, timeout);
}
/**
* 尝试获取锁,获取到立即返回true,获取失败立即返回false
*
* @param lockKey
* @return
*/
public static boolean tryLock(String lockKey) {
return locker.tryLock(lockKey);
}
/**
* 尝试获取锁,在给定的waitTime时间内尝试,获取到返回true,获取失败返回false,获取到后再给定的leaseTime时间超时释放
*
* @param lockKey
* @param waitTime
* @param leaseTime
* @param unit
* @return
* @throws InterruptedException
*/
public static boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) {
return locker.tryLock(lockKey, waitTime, leaseTime, unit);
}
/**
* 锁释放被任意一个线程持有
*
* @param lockKey
* @return
*/
public static boolean isLocked(String lockKey) {
return locker.isLocked(lockKey);
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.datax.common.redis.config.RedisConfig,\
cn.datax.common.redis.aspectj.RedisCacheAspect,\
cn.datax.common.redis.config.RedissonConfig
cn.datax.common.redis.config.RedisConfig
......@@ -30,4 +30,7 @@ public class ResParam implements Serializable {
@ApiModelProperty(value = "示例值")
@NotBlank(message = "示例值不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
private String exampleValue;
@ApiModelProperty(value = "字段别名")
private String fieldAliasName;
}
package cn.datax.service.data.market.mapping.config;
import cn.datax.common.core.DataConstant;
import cn.datax.common.core.R;
import cn.datax.common.database.core.PageResult;
import cn.datax.common.utils.IPUtil;
import cn.datax.common.utils.MD5Util;
import cn.datax.common.utils.RequestHolder;
import cn.datax.service.data.market.api.dto.ApiLogDto;
import cn.datax.service.data.market.mapping.async.AsyncTask;
import cn.hutool.core.map.MapUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
......@@ -18,6 +23,8 @@ import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Aspect
......@@ -40,10 +47,14 @@ public class ApiLogAspect {
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
System.out.println("endTime:" + endTime);
// ApiLogDto log = getLog();
// log.setTime(endTime - startTime);
// handleLog(joinPoint, log);
ApiLogDto log = getLog();
log.setTime(endTime - startTime);
if (result instanceof R) {
if (((R) result).getData() instanceof PageResult) {
log.setCallerSize(((PageResult) ((R) result).getData()).getData().size());
}
}
handleLog(joinPoint, log);
return result;
}
......@@ -56,10 +67,10 @@ public class ApiLogAspect {
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
log.error("出错{}", e.getMessage());
// ApiLogDto log = getLog();
// log.setStatus(DataConstant.EnableState.DISABLE.getKey());
// log.setMsg(e.getMessage());
// handleLog(joinPoint, log);
ApiLogDto log = getLog();
log.setStatus(DataConstant.EnableState.DISABLE.getKey());
log.setMsg(e.getMessage());
handleLog(joinPoint, log);
}
private ApiLogDto getLog() {
......@@ -67,9 +78,8 @@ public class ApiLogAspect {
HttpServletRequest request = RequestHolder.getHttpServletRequest();
String apiKey = request.getHeader("api_key");
String secretKey = request.getHeader("secret_key");
MD5Util mt = null;
try {
mt = MD5Util.getInstance();
MD5Util mt = MD5Util.getInstance();
String apiId = mt.decode(apiKey);
String userId = mt.decode(secretKey);
log.setCallerId(userId);
......@@ -85,6 +95,22 @@ public class ApiLogAspect {
}
protected void handleLog(final JoinPoint joinPoint, ApiLogDto log) {
// asyncTask.doTask(log);
Map<String, Object> pathVariables = (Map<String, Object>) joinPoint.getArgs()[2];
Map<String, Object> requestParams = (Map<String, Object>) joinPoint.getArgs()[3];
Map<String, Object> requestBodys = (Map<String, Object>) joinPoint.getArgs()[4];
Map<String, Object> params = new HashMap<>();
if (MapUtil.isNotEmpty(pathVariables)) {
params.putAll(pathVariables);
}
if (MapUtil.isNotEmpty(requestParams)) {
params.putAll(requestParams);
}
if (MapUtil.isNotEmpty(requestBodys)) {
params.putAll(requestBodys);
}
try {
log.setCallerParams(new ObjectMapper().writeValueAsString(params));
} catch (JsonProcessingException e) {}
asyncTask.doTask(log);
}
}
package cn.datax.service.data.market.mapping.config;
import cn.datax.service.data.market.mapping.async.AsyncTask;
import cn.datax.service.data.market.mapping.handler.MappingHandlerMapping;
import cn.datax.service.data.market.mapping.handler.RequestHandler;
import cn.datax.service.data.market.mapping.handler.RequestInterceptor;
......@@ -18,19 +17,17 @@ public class ApiMappingConfig {
public MappingHandlerMapping mappingHandlerMapping(RequestMappingHandlerMapping requestMappingHandlerMapping,
ApiMappingEngine apiMappingEngine,
RedisTemplate redisTemplate,
ObjectMapper objectMapper,
AsyncTask asyncTask) {
ObjectMapper objectMapper) {
MappingHandlerMapping mappingHandlerMapping = new MappingHandlerMapping();
mappingHandlerMapping.setHandler(requestHandler(apiMappingEngine, redisTemplate, objectMapper, asyncTask));
mappingHandlerMapping.setHandler(requestHandler(apiMappingEngine, redisTemplate, objectMapper));
mappingHandlerMapping.setRequestMappingHandlerMapping(requestMappingHandlerMapping);
return mappingHandlerMapping;
}
@Bean
public RequestHandler requestHandler(ApiMappingEngine apiMappingEngine, RedisTemplate redisTemplate, ObjectMapper objectMapper, AsyncTask asyncTask) {
public RequestHandler requestHandler(ApiMappingEngine apiMappingEngine, RedisTemplate redisTemplate, ObjectMapper objectMapper) {
RequestHandler handler = new RequestHandler();
handler.setApiMappingEngine(apiMappingEngine);
handler.setAsyncTask(asyncTask);
handler.setObjectMapper(objectMapper);
handler.setRequestInterceptor(new RequestInterceptor(redisTemplate));
return handler;
......
package cn.datax.service.data.market.mapping.handler;
import cn.datax.common.core.DataConstant;
import cn.datax.common.core.R;
import cn.datax.common.database.core.PageResult;
import cn.datax.common.utils.ThrowableUtil;
import cn.datax.service.data.market.api.dto.ApiLogDto;
import cn.datax.service.data.market.api.entity.DataApiEntity;
import cn.datax.service.data.market.mapping.async.AsyncTask;
import cn.datax.service.data.market.mapping.service.impl.ApiMappingEngine;
import cn.datax.service.data.market.mapping.utils.ThreadUtil;
import cn.hutool.core.map.MapUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
......@@ -31,8 +27,6 @@ public class RequestHandler {
private ObjectMapper objectMapper;
private AsyncTask asyncTask;
public void setRequestInterceptor(RequestInterceptor requestInterceptor) {
this.requestInterceptor = requestInterceptor;
}
......@@ -45,57 +39,34 @@ public class RequestHandler {
this.objectMapper = objectMapper;
}
public void setAsyncTask(AsyncTask asyncTask) {
this.asyncTask = asyncTask;
}
@SneakyThrows
@ResponseBody
public Object invoke(HttpServletRequest request, HttpServletResponse response,
@PathVariable(required = false) Map<String, Object> pathVariables,
@RequestParam(required = false) Map<String, Object> requestParams,
@RequestBody(required = false) Map<String, Object> requestBodys) {
try {
long start = System.currentTimeMillis();
DataApiEntity api;
Map<String, Object> params = new HashMap<>();
if (MapUtil.isNotEmpty(pathVariables)) {
log.info("pathVariables:{}", pathVariables.toString());
params.putAll(pathVariables);
}
if (MapUtil.isNotEmpty(requestParams)) {
log.info("requestParams:{}", requestParams.toString());
params.putAll(requestParams);
}
if (MapUtil.isNotEmpty(requestBodys)) {
log.info("requestBodys:{}", requestBodys.toString());
params.putAll(requestBodys);
}
api = MappingHandlerMapping.getMappingApiInfo(request);
// 序列化出错
api = objectMapper.readValue(objectMapper.writeValueAsString(api), DataApiEntity.class);
// 执行前置拦截器
Object obj = requestInterceptor.preHandle(request, response, api, params);
if (obj != null) {
return obj;
}
PageResult<Map<String, Object>> value = apiMappingEngine.execute(api, params);
// 执行后置拦截器
requestInterceptor.postHandle(request, response, api, params, value);
ThreadUtil.getInstance().get().setCallerSize(value.getData().size());
ThreadUtil.getInstance().get().setTime(System.currentTimeMillis() - start);
return R.ok().setData(value);
} catch (Exception e) {
log.error("全局异常信息ex={}, StackTrace={}", e.getMessage(), ThrowableUtil.getStackTrace(e));
ThreadUtil.getInstance().get().setStatus(DataConstant.EnableState.DISABLE.getKey());
ThreadUtil.getInstance().get().setMsg(e.getMessage());
return R.error(e.getMessage());
} finally {
ApiLogDto apiLogDto = ThreadUtil.getInstance().get();
log.info("ApiLogDto信息={}", apiLogDto);
if (apiLogDto != null) {
asyncTask.doTask(apiLogDto);
}
ThreadUtil.getInstance().remove();
DataApiEntity api;
Map<String, Object> params = new HashMap<>();
if (MapUtil.isNotEmpty(pathVariables)) {
log.info("pathVariables:{}", pathVariables.toString());
params.putAll(pathVariables);
}
if (MapUtil.isNotEmpty(requestParams)) {
log.info("requestParams:{}", requestParams.toString());
params.putAll(requestParams);
}
if (MapUtil.isNotEmpty(requestBodys)) {
log.info("requestBodys:{}", requestBodys.toString());
params.putAll(requestBodys);
}
api = MappingHandlerMapping.getMappingApiInfo(request);
// 序列化
api = objectMapper.readValue(objectMapper.writeValueAsString(api), DataApiEntity.class);
// 执行前置拦截器
requestInterceptor.preHandle(request, response, api, params);
PageResult<Map<String, Object>> value = apiMappingEngine.execute(api, params);
// 执行后置拦截器
requestInterceptor.postHandle(request, response, api, params, value);
return R.ok().setData(value);
}
}
package cn.datax.service.data.market.mapping.handler;
import cn.datax.common.core.DataConstant;
import cn.datax.common.core.R;
import cn.datax.common.exception.DataException;
import cn.datax.common.utils.IPUtil;
import cn.datax.common.utils.MD5Util;
import cn.datax.service.data.market.api.dto.ApiLogDto;
......@@ -39,37 +39,23 @@ public class RequestInterceptor {
* @return 当返回对象时,直接将此对象返回到页面,返回null时,继续执行后续操作
* @throws Exception
*/
public Object preHandle(HttpServletRequest request, HttpServletResponse response, DataApiEntity api, Map<String, Object> params) throws Exception {
public void preHandle(HttpServletRequest request, HttpServletResponse response, DataApiEntity api, Map<String, Object> params) throws Exception {
System.out.println("************ApiInterceptor preHandle executed**********");
String uri = request.getRequestURI();
log.info("getRequestURI的值:" + uri);
String ipAddr = IPUtil.getIpAddr(request);
log.info("ipAddr的值:" + ipAddr);
// 记录日志
ApiLogDto log = new ApiLogDto();
log.setCallerIp(ipAddr);
log.setCallerUrl(uri);
log.setCallerParams(new ObjectMapper().writeValueAsString(params));
log.setCallerDate(LocalDateTime.now());
log.setStatus(DataConstant.EnableState.ENABLE.getKey());
ThreadUtil.getInstance().set(log);
// 密钥校验
String apiKey = request.getHeader("api_key");
String secretKey = request.getHeader("secret_key");
if (StrUtil.isBlank(apiKey) || StrUtil.isBlank(secretKey)) {
ThreadUtil.getInstance().get().setStatus(DataConstant.EnableState.DISABLE.getKey());
ThreadUtil.getInstance().get().setMsg("api_key或secret_key空");
return R.error("api_key或secret_key空");
throw new DataException("api_key或secret_key空");
}
MD5Util mt = MD5Util.getInstance();
String apiId = mt.decode(apiKey);
String userId = mt.decode(secretKey);
ThreadUtil.getInstance().get().setApiId(apiId);
ThreadUtil.getInstance().get().setCallerId(userId);
// 黑名单校验
String deny = api.getDeny();
if (StrUtil.isNotBlank(deny)) {
......@@ -77,33 +63,23 @@ public class RequestInterceptor {
if (CollUtil.isNotEmpty(denyList)) {
for (String ip : denyList) {
if(ip.equals(ipAddr)){
ThreadUtil.getInstance().get().setStatus(DataConstant.EnableState.DISABLE.getKey());
ThreadUtil.getInstance().get().setMsg("此IP已被加入API调用黑名单");
return R.error("此IP已被加入API调用黑名单");
throw new DataException(ip + "已被加入IP黑名单");
}
}
}
}
// 参数校验
if (MapUtil.isNotEmpty(params)) {
try {
api.getReqParams().stream().forEach(param -> {
if (params.containsKey(param.getParamName())) {
// 参数类型是否正确
ParamType.parse(ParamType.getParamType(param.getParamType()), params.get(param.getParamName()));
}
});
} catch (Exception e) {
ThreadUtil.getInstance().get().setStatus(DataConstant.EnableState.DISABLE.getKey());
ThreadUtil.getInstance().get().setMsg(e.getMessage());
return R.error(e.getMessage());
}
api.getReqParams().stream().forEach(param -> {
if (params.containsKey(param.getParamName())) {
// 参数类型是否正确
ParamType.parse(ParamType.getParamType(param.getParamType()), params.get(param.getParamName()));
}
});
}
// 限流校验
String apiName = api.getApiName();
ThreadUtil.getInstance().get().setApiName(apiName);
// 限流校验
String rateLimit = api.getRateLimit();
rateLimit = Optional.ofNullable(rateLimit).orElse(DataConstant.TrueOrFalse.TRUE.getKey());
if (DataConstant.TrueOrFalse.TRUE.getKey().equals(rateLimit)) {
......@@ -123,13 +99,9 @@ public class RequestInterceptor {
} else if (maxTimes < times) {
redisTemplate.opsForValue().set(key, maxTimes + 1, seconds, TimeUnit.SECONDS);
} else {
// 请求过于频繁
ThreadUtil.getInstance().get().setStatus(DataConstant.EnableState.DISABLE.getKey());
ThreadUtil.getInstance().get().setMsg("API调用过于频繁");
return R.error("API调用过于频繁");
throw new DataException("API调用过于频繁");
}
}
return null;
}
/**
......
......@@ -49,8 +49,8 @@ public class ApiMappingEngine {
dbSchema.getUsername(), dbSchema.getPassword(), dbSchema.getPort(), dbSchema.getDbName(), dbSchema.getSid());
DbQuery dbQuery = dataSourceFactory.createDbQuery(dbQueryProperty);
// 参数
Integer pageNum = (Integer) params.getOrDefault("pageNum", 1);
Integer pageSize = (Integer) params.getOrDefault("pageSize", 20);
Integer pageNum = Integer.parseInt((String) params.getOrDefault("pageNum", 1));
Integer pageSize = Integer.parseInt((String) params.getOrDefault("pageSize", 20));
PageUtil pageUtil = new PageUtil(pageNum, pageSize);
Integer offset = pageUtil.getOffset();
SqlBuilderUtil.SqlFilterResult sqlFilterResult;
......@@ -62,11 +62,9 @@ public class ApiMappingEngine {
}
Map<String, Object> acceptedFilters = sqlFilterResult.getAcceptedFilters();
// 数据脱敏
List<FieldRule> rules;
List<FieldRule> rules = null;
ApiMaskEntity apiMaskEntity = apiMaskServiceFeign.getApiMaskByApiId(dataApi.getId());
if (apiMaskEntity == null) {
throw new DataException("API调用查询数据脱敏出错");
} else {
if (apiMaskEntity != null) {
rules = apiMaskEntity.getRules();
}
PageResult<Map<String, Object>> pageResult;
......
......@@ -37,6 +37,7 @@ import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.StatementVisitorAdapter;
import net.sf.jsqlparser.statement.select.*;
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;
......@@ -46,12 +47,9 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
......@@ -137,8 +135,47 @@ public class DataApiServiceImpl extends BaseServiceImpl<DataApiDao, DataApiEntit
log.error("全局异常信息ex={}, StackTrace={}", e.getMessage(), ThrowableUtil.getStackTrace(e));
throw new DataException("SQL语法有问题,解析出错");
}
final List<String> variables = new ArrayList<>();
final List<String> cols = new ArrayList<>();
// 维护元数据缓存数据
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);
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();
// 根据entryKey找到数据库表
List<Map<String, String>> entryValue = entry.getValue();
entryValue.stream().map(m -> m.get("columnName"));
}
// List<ResParam> resParams = cols.stream().map(s -> {
// ResParam resParam = new ResParam();
// resParam.setFieldName(s);
// return resParam;
// }).collect(Collectors.toList());
// 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) {
......@@ -149,56 +186,116 @@ public class DataApiServiceImpl extends BaseServiceImpl<DataApiDao, DataApiEntit
selectItem.accept(new SelectItemVisitorAdapter() {
@Override
public void visit(SelectExpressionItem item) {
Map<String,String> map = new HashMap<>();
String columnName;
if (item.getAlias() == null) {
SimpleNode node = item.getExpression().getASTNode();
Object value = node.jjtGetValue();
if (value instanceof Column) {
columnName = ((Column) value).getColumnName();
} 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("`", "");
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 {
columnName = item.getAlias().getName();
// 增加对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("`", "");
cols.add(columnName);
map.put("tableName", tableName);
map.put("columnName", columnName);
cols.add(map);
}
});
});
plainSelect.getWhere().accept(new ExpressionVisitorAdapter() {
@Override
public void visit(JdbcNamedParameter jdbcNamedParameter) {
variables.add(jdbcNamedParameter.getName());
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());
}
});
}
});
}
});
SqlParseVo sqlParseVo = new SqlParseVo();
List<ReqParam> reqParams = variables.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 = cols.stream().map(s -> {
ResParam resParam = new ResParam();
resParam.setFieldName(s);
return resParam;
}).collect(Collectors.toList());
sqlParseVo.setResParams(resParams);
return sqlParseVo;
}
private String sqlJdbcNamedParameterBuild(DataApiEntity dataApi) throws JSQLParserException {
......
......@@ -69,6 +69,7 @@ export default {
.main-container{
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track-piece {
background: #d3dce6;
......
......@@ -4,17 +4,17 @@
<div slot="header" class="clearfix">
<span>{{ title }}</span>
<el-button-group style="float: right;">
<el-button size="mini" icon="el-icon-plus" round @click="submitForm" :loading="loadingOptions.loading" :disabled="loadingOptions.isDisabled">{{loadingOptions.loadingText}}</el-button>
<el-button size="mini" icon="el-icon-plus" round :loading="loadingOptions.loading" :disabled="loadingOptions.isDisabled" @click="submitForm">{{ loadingOptions.loadingText }}</el-button>
<el-button size="mini" icon="el-icon-back" round @click="showCard">返回</el-button>
</el-button-group>
</div>
<div :style="classCardbody">
<el-steps :active="active" finish-status="success" align-center>
<el-step title="属性配置"></el-step>
<el-step title="执行配置"></el-step>
<el-step title="参数配置"></el-step>
<el-step title="属性配置" />
<el-step title="执行配置" />
<el-step title="参数配置" />
</el-steps>
<el-form ref="form1" :model="form1" :rules="rules1" label-width="80px" v-if="active == 1">
<el-form v-if="active == 1" ref="form1" :model="form1" :rules="rules1" label-width="80px">
<el-form-item label="API名称" prop="apiName">
<el-input v-model="form1.apiName" placeholder="请输入API名称" />
</el-form-item>
......@@ -31,7 +31,7 @@
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
></el-option>
/>
</el-select>
</el-form-item>
<el-form-item label="返回格式" prop="resType">
......@@ -41,7 +41,7 @@
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
></el-option>
/>
</el-select>
</el-form-item>
<el-form-item label="IP黑名单" prop="deny">
......@@ -53,14 +53,14 @@
v-for="dict in whetherOptions"
:key="dict.id"
:label="dict.itemText"
>{{dict.itemValue}}</el-radio>
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="请求次数" prop="times" v-if="form1.rateLimit === '1'">
<el-form-item v-if="form1.rateLimit === '1'" label="请求次数" prop="times">
<el-input-number v-model="form1.times" controls-position="right" :min="1" />
</el-form-item>
<el-form-item label="请求时间范围" prop="seconds" v-if="form1.rateLimit === '1'">
<el-input-number v-model="form1.seconds" controls-position="right" :min="1"/>
<el-form-item v-if="form1.rateLimit === '1'" label="请求时间范围" prop="seconds">
<el-input-number v-model="form1.seconds" controls-position="right" :min="1" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form1.status" disabled>
......@@ -68,14 +68,14 @@
v-for="dict in statusOptions"
:key="dict.id"
:label="dict.itemText"
>{{dict.itemValue}}</el-radio>
>{{ dict.itemValue }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form1.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<el-form ref="form2" :model="form2" :rules="rules2" label-width="80px" v-if="active == 2">
<el-form v-if="active == 2" ref="form2" :model="form2" :rules="rules2" label-width="80px">
<el-form-item label="配置方式" prop="configType">
<el-select v-model="form2.configType" placeholder="请选择配置方式" @change="configTypeSelectChanged">
<el-option
......@@ -83,7 +83,7 @@
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
></el-option>
/>
</el-select>
</el-form-item>
<el-form-item label="数据源" prop="sourceId">
......@@ -94,59 +94,55 @@
:label="source.sourceName"
:value="source.id"
:disabled="source.status === '0'"
></el-option>
/>
</el-select>
</el-form-item>
<el-form-item label="数据库表" prop="tableName" v-if="form2.configType === '1'">
<el-form-item v-if="form2.configType === '1'" label="数据库表" prop="tableName">
<el-select v-model="form2.table" value-key="id" placeholder="请选择数据库表" @change="tableSelectChanged">
<el-option
v-for="item in tableOptions"
:key="item.id"
:label="item.tableComment ? item.tableComment : item.tableName"
:value="item">
</el-option>
:value="item"
/>
</el-select>
</el-form-item>
<el-form-item label="字段列表" v-if="form2.configType === '1'">
<el-table :data="form2.fieldParams" stripe border
:max-height="300"
style="width: 100%; margin: 15px 0;">
<el-table-column prop="columnPosition" label="序号" width="55" align="center" >
</el-table-column>
<el-table-column prop="columnName" label="列名" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataLength" label="数据长度" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataPrecision" label="数据精度" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="dataScale" label="数据小数位" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="columnKey" label="是否主键" align="center" show-overflow-tooltip >
<el-form-item v-if="form2.configType === '1'" label="字段列表">
<el-table
:data="form2.fieldParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column prop="columnPosition" label="序号" width="55" align="center" />
<el-table-column prop="columnName" label="列名" align="center" show-overflow-tooltip />
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip />
<el-table-column prop="dataLength" label="数据长度" align="center" show-overflow-tooltip />
<el-table-column prop="dataPrecision" label="数据精度" align="center" show-overflow-tooltip />
<el-table-column prop="dataScale" label="数据小数位" align="center" show-overflow-tooltip />
<el-table-column prop="columnKey" label="是否主键" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.columnKey === '1'">Y</span>
<span v-if="scope.row.columnKey === '0'">N</span>
</template>
</el-table-column>
<el-table-column prop="columnNullable" label="是否允许为空" align="center" show-overflow-tooltip >
<el-table-column prop="columnNullable" label="是否允许为空" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.columnNullable === '1'">Y</span>
<span v-if="scope.row.columnNullable === '0'">N</span>
</template>
</el-table-column>
<el-table-column prop="dataDefault" label="列默认值" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="columnComment" label="列注释" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="reqable" label="是否作为请求参数" align="center" width="50" >
<el-table-column prop="dataDefault" label="列默认值" align="center" show-overflow-tooltip />
<el-table-column prop="columnComment" label="列注释" align="center" show-overflow-tooltip />
<el-table-column prop="reqable" label="是否作为请求参数" align="center" width="50">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.reqable" true-label="1" false-label="0" @change="checked=>reqCheckChange(scope.row, checked)"></el-checkbox>
<el-checkbox v-model="scope.row.reqable" true-label="1" false-label="0" @change="checked=>reqCheckChange(scope.row, checked)" />
</template>
</el-table-column>
<el-table-column prop="resable" label="是否作为返回参数" align="center" width="50" >
<el-table-column prop="resable" label="是否作为返回参数" align="center" width="50">
<template slot-scope="scope">
<el-checkbox v-model="scope.row.resable" true-label="1" false-label="0" @change="checked=>resCheckChange(scope.row, checked)"></el-checkbox>
<el-checkbox v-model="scope.row.resable" true-label="1" false-label="0" @change="checked=>resCheckChange(scope.row, checked)" />
</template>
</el-table-column>
</el-table>
......@@ -156,35 +152,41 @@
<sql-editor
ref="sqleditor"
:value="form2.sqlText"
@changeTextarea="changeTextarea($event)"
style="height: 300px;margin: 10px 10px;"
></sql-editor>
@changeTextarea="changeTextarea($event)"
/>
</el-col>
</el-row>
<el-form-item v-if="form2.configType === '2'">
<el-button size="mini" type="primary" @click="sqlParse">SQL解析</el-button>
</el-form-item>
</el-form>
<el-form ref="form3" :model="form3" label-width="80px" v-if="active == 3">
<el-form v-if="active == 3" ref="form3" :model="form3" label-width="80px">
<el-divider content-position="left">请求参数</el-divider>
<el-table :data="form3.reqParams" stripe border
:max-height="300"
style="width: 100%; margin: 15px 0;">
<el-table
:data="form3.reqParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="paramName" label="参数名称" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="nullable" label="是否允许为空" align="center" show-overflow-tooltip >
<el-table-column prop="paramName" label="参数名称" align="center" show-overflow-tooltip />
<el-table-column prop="nullable" label="是否允许为空" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-checkbox v-model="scope.row.nullable" true-label="1" false-label="0"></el-checkbox>
<el-checkbox v-model="scope.row.nullable" true-label="1" false-label="0" />
</template>
</el-table-column>
<el-table-column prop="paramComment" label="描述" align="center" show-overflow-tooltip >
<el-table-column prop="paramComment" label="描述" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.paramComment" placeholder="请输入描述" />
</template>
</el-table-column>
<el-table-column prop="paramType" label="参数类型" align="center" show-overflow-tooltip >
<el-table-column prop="paramType" label="参数类型" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-select v-model="scope.row.paramType" placeholder="请选择参数类型">
<el-option
......@@ -192,11 +194,11 @@
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
></el-option>
/>
</el-select>
</template>
</el-table-column>
<el-table-column prop="whereType" label="操作符" align="center" show-overflow-tooltip >
<el-table-column prop="whereType" label="操作符" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-select v-model="scope.row.whereType" placeholder="请选择操作符">
<el-option
......@@ -204,45 +206,54 @@
:key="dict.id"
:label="dict.itemValue"
:value="dict.itemText"
></el-option>
/>
</el-select>
</template>
</el-table-column>
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip >
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.exampleValue" placeholder="请输入示例值" />
</template>
</el-table-column>
<el-table-column prop="defaultValue" label="默认值" align="center" show-overflow-tooltip >
<el-table-column prop="defaultValue" label="默认值" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.defaultValue" placeholder="请输入默认值" />
</template>
</el-table-column>
</el-table>
<el-divider content-position="left">返回字段</el-divider>
<el-table :data="form3.resParams" stripe border
:max-height="300"
style="width: 100%; margin: 15px 0;">
<el-table
:data="form3.resParams"
stripe
border
:max-height="300"
style="width: 100%; margin: 15px 0;"
>
<el-table-column label="序号" width="55" align="center">
<template slot-scope="scope">
<span>{{ scope.$index +1 }}</span>
</template>
</el-table-column>
<el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip >
</el-table-column>
<el-table-column prop="fieldComment" label="描述" align="center" show-overflow-tooltip >
<el-table-column prop="fieldName" label="字段名称" align="center" show-overflow-tooltip />
<el-table-column prop="fieldComment" label="描述" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.fieldComment" placeholder="请输入描述" />
</template>
</el-table-column>
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip >
<el-table-column prop="dataType" label="数据类型" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.dataType" placeholder="请输入数据类型" />
</template>
</el-table-column>
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip >
<el-table-column prop="exampleValue" label="示例值" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.exampleValue" placeholder="请输入示例值" />
</template>
</el-table-column>
</el-table>
</el-form>
<el-button style="margin-top: 12px;" @click="handleNextStep" v-if="active < 3">下一步</el-button>
<el-button style="margin-top: 12px;" @click="handleLastStep" v-if="active > 1">上一步</el-button>
<el-button v-if="active < 3" style="margin-top: 12px;" @click="handleNextStep">下一步</el-button>
<el-button v-if="active > 1" style="margin-top: 12px;" @click="handleLastStep">上一步</el-button>
</div>
</el-card>
</div>
......@@ -263,12 +274,12 @@ export default {
props: {
data: {
type: Object,
default: function () {
default: function() {
return {}
}
}
},
data () {
data() {
return {
classCardbody: {
overflow: 'auto',
......@@ -367,7 +378,7 @@ export default {
paramTypeOptions: []
}
},
created () {
created() {
this.getDicts('data_req_method').then(response => {
if (response.success) {
this.reqMethodOptions = response.data
......@@ -406,10 +417,10 @@ export default {
})
},
methods: {
showCard () {
showCard() {
this.$emit('showCard', this.showOptions)
},
getDataSourceList () {
getDataSourceList() {
listDataSource().then(response => {
if (response.success) {
this.sourceOptions = response.data
......@@ -417,7 +428,7 @@ export default {
})
},
/** 步骤条下一步 */
handleNextStep () {
handleNextStep() {
if (this.active === 1) {
this.$refs['form1'].validate(valid => {
if (valid) {
......@@ -433,15 +444,15 @@ export default {
}
},
/** 步骤条上一步 */
handleLastStep () {
handleLastStep() {
this.active--
},
changeTextarea (val) {
changeTextarea(val) {
this.form2.sqlText = val
},
configTypeSelectChanged (val) {
configTypeSelectChanged(val) {
if (this.form2.configType === '1' && this.form2.sourceId && this.tableOptions.length <= 0) {
let data = {}
const data = {}
data.sourceId = this.form2.sourceId
listDataTable(data).then(response => {
if (response.success) {
......@@ -451,9 +462,9 @@ export default {
})
}
},
sourceSelectChanged (val) {
sourceSelectChanged(val) {
if (this.form2.configType && this.form2.configType === '1') {
let data = {}
const data = {}
data.sourceId = val
listDataTable(data).then(response => {
if (response.success) {
......@@ -463,8 +474,8 @@ export default {
})
}
},
tableSelectChanged (item) {
let data = {}
tableSelectChanged(item) {
const data = {}
data.sourceId = item.sourceId
data.tableId = item.id
this.form2.tableId = item.id
......@@ -477,7 +488,7 @@ export default {
}
})
},
sqlParse () {
sqlParse() {
if (!this.form2.sourceId) {
this.$message.error('数据源不能为空')
return
......@@ -486,21 +497,21 @@ export default {
this.$message.error('解析SQL不能为空')
return
}
let data = {}
const data = {}
data.sqlText = this.form2.sqlText
sqlParse(data).then(response => {
if (response.success) {
const { data } = response
let reqParams = data.reqParams
let resParams = data.resParams
this.form3.reqParams = reqParams.map(function (item) {
let json = {}
const reqParams = data.reqParams
const resParams = data.resParams
this.form3.reqParams = reqParams.map(function(item) {
const json = {}
json.paramName = item.paramName
json.nullable = '0'
return json
})
this.form3.resParams = resParams.map(function (item) {
let json = {}
this.form3.resParams = resParams.map(function(item) {
const json = {}
json.fieldName = item.fieldName
return json
})
......@@ -508,9 +519,9 @@ export default {
}
})
},
reqCheckChange (row, checked) {
reqCheckChange(row, checked) {
if (checked === '1') {
let json = {}
const json = {}
json.paramName = row.columnName
json.paramComment = row.columnComment || undefined
json.nullable = '0'
......@@ -519,9 +530,9 @@ export default {
this.form3.reqParams.splice(this.form3.reqParams.findIndex(item => item.paramName === row.columnName), 1)
}
},
resCheckChange (row, checked) {
resCheckChange(row, checked) {
if (checked === '1') {
let json = {}
const json = {}
json.fieldName = row.columnName
json.fieldComment = row.columnComment || undefined
json.dataType = row.dataType || undefined
......@@ -531,7 +542,7 @@ export default {
}
},
/** 提交按钮 */
submitForm: function () {
submitForm: function() {
this.$refs['form3'].validate(valid => {
if (valid) {
if (this.form3.reqParams.length <= 0) {
......
......@@ -83,7 +83,7 @@
<el-checkbox v-model="scope.row.nullable" true-label="1" false-label="0" disabled />
</template>
</el-table-column>
<el-table-column prop="remark" label="描述" align="center" show-overflow-tooltip />
<el-table-column prop="paramComment" label="描述" align="center" show-overflow-tooltip />
<el-table-column prop="paramType" label="参数类型" align="center" show-overflow-tooltip>
<template slot-scope="scope">
<el-select v-model="scope.row.paramType" placeholder="请选择参数类型" disabled>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment