diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/controller/PortalController.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/controller/PortalController.java index a3fab0e..cac86e4 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/controller/PortalController.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/controller/PortalController.java @@ -57,6 +57,7 @@ public class PortalController { } @ApiOperation("新增接口") + @Encrypt @PostMapping @PreAuthorize("@ss.hasPermission('query:portal:add')") public Result add(@RequestBody @Validated PortalDto portalDto) { @@ -65,6 +66,7 @@ public class PortalController { } @ApiOperation("修改接口") + @Encrypt @PutMapping @PreAuthorize("@ss.hasPermission('query:portal:edit')") public Result edit(@RequestBody @Validated PortalDto portalDto) { diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/PortalDispatchServlet.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/PortalDispatchServlet.java index 73b30c3..fe80175 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/PortalDispatchServlet.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/PortalDispatchServlet.java @@ -53,10 +53,13 @@ public class PortalDispatchServlet { } private void doDispatch(HttpServletRequest request, HttpServletResponse response) { + //获取到请求路径 String path = request.getServletPath(); + //获取请求方法 String method = request.getMethod(); - + //从Redis中获取到当前的方法信息 PortalBo portalBo = redisTemplate.opsForValue().get(QueryConstant.PORTAL_KEY + path + ":" + method); + //判断是否为空,如果为空则从数据库中查找 if (portalBo == null) { Portal portal = portalMapper.selectByPath(path, method); if (portal == null) { @@ -67,10 +70,10 @@ public class PortalDispatchServlet { portalBo = PortalBo.toPortalBo(portal, portalMappings); redisTemplate.opsForValue().set(QueryConstant.PORTAL_KEY + portalBo.getPath() + ":" + portalBo.getRequestMethod(), portalBo); } - - + //自定义查询编辑查询对象 SearchInfo searchInfo = new SearchInfo(); List uniConList = new ArrayList<>(); + //根据映射关系从request中获取请求参数 for (PortalMapping portalMapping : portalBo.getMappings()) { UniConDto uniCon = new UniConDto(); String mappingValue = portalMapping.getMappingValue(); @@ -86,14 +89,16 @@ public class PortalDispatchServlet { uniConList.add(uniCon); } searchInfo.setList(uniConList); - + //获取当当前接口对应的数据适配器 DataAdapter dataAdapter = dataAdapterMapper.selectById(portalBo.getAdapterId()); + //进行数据适配器的执行逻辑 Object result = null; if (portalBo.getState() == 1 || portalBo.getState() == 2) { result = dataAdapterHandler.execute(dataAdapter, portalBo, searchInfo); } else { result = dataAdapterHandler.mockExecute(dataAdapter, portalBo, searchInfo); } + //将返回结果放入response ResponseRender.renderString(response, Result.ok(result)); } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/service/DispatchSyncService.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/service/DispatchSyncService.java index badb8c2..89d2705 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/service/DispatchSyncService.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/service/DispatchSyncService.java @@ -51,19 +51,25 @@ public class DispatchSyncService { public DispatchSyncService(NacosDiscoveryProperties nacosDiscoveryProperties, Environment environment, NacosRegistration nacosRegistration, ThreadPoolTaskExecutor taskExecuteExecutor, DubboServiceBean serviceBean) { + //获取当前主机地址 this.host = nacosRegistration.getHost(); + //获取到端口信息的bean this.serviceBean = serviceBean; NacosServiceManager nacosServiceManager = new NacosServiceManager(); Properties nacosProperties = nacosDiscoveryProperties.getNacosProperties(); + //获取dubbo的命名空间 String namespace = environment.getProperty("dubbo.registry.parameters.namespace"); + //获取到当前服务名称 this.serviceName = environment.getProperty("dubbo.application.name"); nacosProperties.setProperty(PropertyKeyConst.NAMESPACE, namespace); + //获取到nacos的管理服务 this.namingService = nacosServiceManager.getNamingService(nacosProperties); - + //启动单线程,监听阻塞队列 new Thread(() -> { while (true) { try { Runnable take = queue.take(); + //执行同步任务 taskExecuteExecutor.execute(take); } catch (InterruptedException e) { log.info("", e); @@ -80,24 +86,33 @@ public class DispatchSyncService { private void syncDispatch(String path, String requestMethod, Boolean publish) { try { + //获取nacos中的服务信息 List allInstances = namingService.getAllInstances(serviceName); for (Instance instance : allInstances) { + //判断当前服务是否为本服务 if (!(instance.getIp().equals(host) && instance.getPort() == serviceBean.getPort())) { + //不是本服务则需要发起同步任务 Task task = new Task(instance.getIp(), instance.getPort(), path, publish, requestMethod) { @Override public void run() { try { + //获取云端服务信息 List allInstances = namingService.getAllInstances(serviceName); + //如果没有则不进行同步 if (ObjectUtils.isEmpty(allInstances)) { return; } + //检查云端实例中是否还存在当前服务,不存在当前任务结束 Optional optional = allInstances.stream().filter(instance -> this.ip.equals(instance.getIp()) && this.port == instance.getPort()).findAny(); if (optional.isEmpty()) { return; } Instance instance = optional.get(); + //指定需要同步服务的ip + port UserSpecifiedAddressUtil.setAddress(new Address(instance.getIp(), instance.getPort(), true)); + //记录同步状态 Boolean state = null; + //是否为发布任务 if (publish) { log.info("dubboDispatchServletPublish.publish({}, {})", path, requestMethod); state = dubboDispatchServletPublish.publish(path, requestMethod); @@ -105,17 +120,22 @@ public class DispatchSyncService { log.info("dubboDispatchServletPublish.unpublish({}, {})", path, requestMethod); state = dubboDispatchServletPublish.unpublish(path, requestMethod); } + //如果为false,则将当前任务重新放入到队列中,等待下一次执行 if (state == null || !state) { queue.add(this); } } catch (NacosException e) { log.error("NacosException: {}", e.getMessage()); + //如果发生异常也是 + //todo 后续可以添加当前任务报错次数的处理 queue.add(this); } finally { + //将指定的地址恢复 UserSpecifiedAddressUtil.setAddress(null); } } }; + //像阻塞队列中添加任务 queue.add(task); } } @@ -126,15 +146,25 @@ public class DispatchSyncService { private static abstract class Task implements Runnable { - + /** + * 服务ip + */ protected final String ip; - + /** + * 服务端口 + */ protected final int port; - + /** + * 路径 + */ protected final String path; - + /** + * 是否为发布 + */ protected final Boolean publish; - + /** + * 方法类型 + */ protected final String requestMethod; diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/service/HandlerMethodService.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/service/HandlerMethodService.java index 7c8fe2b..0ad8866 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/service/HandlerMethodService.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/service/HandlerMethodService.java @@ -55,6 +55,7 @@ public class HandlerMethodService implements ApplicationContextAware { public HandlerMethodService() { + //固定PortalDispatchServlet为入口类,其中doDispatch为入口方法 Class portalDispatchServletClass = PortalDispatchServlet.class; Method[] declaredMethods = portalDispatchServletClass.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { @@ -65,11 +66,13 @@ public class HandlerMethodService implements ApplicationContextAware { if (mappingMethod == null) { log.error("mappingMethod is null"); } + //设置权限 mappingMethod.setAccessible(Boolean.TRUE); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + //获取到web mvc的接口存储mapping mapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping"); } @@ -95,7 +98,9 @@ public class HandlerMethodService implements ApplicationContextAware { throw new CustomException("path is exist"); } mapping.registerMapping(requestMappingInfo, "portalDispatchServlet", mappingMethod); + // 判断是否需要发起同步 if (sync) { + //使用事件监听机制,避免循环注入 SpringContextHolder.publishEvent(new DispatchSyncEvent(path, requestMethod.name(), Boolean.TRUE)); } } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/PortalService.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/PortalService.java index 1b94603..77fa46f 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/PortalService.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/PortalService.java @@ -15,16 +15,33 @@ public interface PortalService { /** * 根据id查询 + * * @param portalId id * @return 结果 */ PortalVo searchById(Long portalId); - + /** + * 查询接口列表 + * + * @param query 查询条件 + * @return 查询表格结果 + */ TableDataInfo searchList(PortalQuery query); - + /** + * 保存接口信息 + * + * @param portalDto 接口信息 + * @return 保存完成后接口id和数据适配器id + */ PortalIdWrapper save(PortalDto portalDto); + /** + * 修改接口信息 + * + * @param portalDto 接口信息 + * @return 修改完成后接口id和数据适配器id + */ PortalIdWrapper edit(PortalDto portalDto); } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/impl/PortalServiceImpl.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/impl/PortalServiceImpl.java index 7793a50..b41e856 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/impl/PortalServiceImpl.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/impl/PortalServiceImpl.java @@ -133,6 +133,7 @@ public class PortalServiceImpl implements PortalService { adapterIds.add(portal.getAdapterId()); } }); + //映射自定义擦洗名称 Map queryMap = new HashMap<>(); if (!ObjectUtils.isEmpty(queryIds)) { List queryList = queryMapper.selectListByIds(queryIds); @@ -140,6 +141,7 @@ public class PortalServiceImpl implements PortalService { queryMap.put(uniQuery.getId(), uniQuery); } } + //映射数据适配器名称 Map adapterMap = new HashMap<>(); if (!ObjectUtils.isEmpty(adapterIds)) { List adapterList = adapterMapper.selectListByIds(adapterIds); @@ -147,6 +149,7 @@ public class PortalServiceImpl implements PortalService { adapterMap.put(adapter.getAdapterId(), adapter.getAdapterName()); } } + //映射重组 return PageUtils.convertDataTable(list, portal -> { SimplePortalVo simplePortalVo = SimplePortalVo.toPortalVo(portal); UniQuery uniQuery = queryMap.getOrDefault(portal.getQueryId(), null); @@ -191,6 +194,7 @@ public class PortalServiceImpl implements PortalService { } portalMappingMapper.insertBatch(mappings); } + //发布接口 publishPortal(portal, mappings, Boolean.TRUE); return PortalIdWrapper.builder() .portalId(String.valueOf(portal.getPortalId())) @@ -215,12 +219,17 @@ public class PortalServiceImpl implements PortalService { } } PortalBo portalBo = PortalBo.toPortalBo(portal, portalDto.getMappings()); + //存在接口路径或者请求类型不同则需要重新发布 if (!old.getPath().equals(portal.getPath()) || !old.getRequestMethod().equals(portal.getRequestMethod())) { + //先卸载接口,需要进行数据同步 unpublishPortal(old, true); + //注册新的映射 methodService.registerMapping(portalBo.getPath(), RequestMethod.valueOf(portalBo.getRequestMethod()), true); } + //修改Redis中的数据信息 redisTemplate.opsForValue().set(QueryConstant.PORTAL_KEY + portalBo.getPath() + ":" + portalBo.getRequestMethod(), portalBo); + //返回接口id和适配器id return PortalIdWrapper.builder() .portalId(String.valueOf(portal.getPortalId())) .adapterId(String.valueOf(portal.getAdapterId())) @@ -254,19 +263,36 @@ public class PortalServiceImpl implements PortalService { return false; } - + /** + * 发布接口 + * + * @param portal 接口信息 + * @param mappings 映射信息 + * @param sync 是否同步 + */ private void publishPortal(Portal portal, List mappings, Boolean sync) { PortalBo portalBo = PortalBo.toPortalBo(portal, mappings); redisTemplate.opsForValue().set(QueryConstant.PORTAL_KEY + portalBo.getPath() + ":" + portalBo.getRequestMethod(), portalBo); methodService.registerMapping(portalBo.getPath(), RequestMethod.valueOf(portalBo.getRequestMethod()), sync); } - + /** + * 取消接口映射 + * + * @param portal 接口信息 + * @param sync 是否同步 + */ private void unpublishPortal(Portal portal, Boolean sync) { methodService.unregisterMapping(portal.getPath(), RequestMethod.valueOf(portal.getRequestMethod()), sync); redisTemplate.delete(QueryConstant.PORTAL_KEY + portal.getPath() + ":" + portal.getRequestMethod()); } + /** + * 创建数据适配器 + * + * @param portalDto 接口dto对象 + * @param portal 接口信息 + */ private void createDataAdapter(PortalDto portalDto, Portal portal) { DataAdapterDto dataAdapterDto = portalDto.getDataAdapter(); if (ObjectUtils.isEmpty(dataAdapterDto)) { @@ -278,12 +304,19 @@ public class PortalServiceImpl implements PortalService { } dataAdapter.setAdapterName(portal.getPortalName() + "专用数据适配器!"); dataAdapter.setCommon(Boolean.FALSE); + //初始化对应的数据适配器 dataAdapter.init(); + //插入数据适配器 adapterMapper.insert(dataAdapter); + //会写数据适配器id portal.setAdapterId(dataAdapter.getAdapterId()); } - + /** + * 检查接口类型是否正确 + * + * @param portal 接口信息 + */ private void checkPortalType(Portal portal) { if (PortalEnum.LOCAL.equals(portal.getType())) { if (ObjectUtils.isEmpty(portal.getQueryId())) { diff --git a/custom-query/custom-query-biz/src/main/resources/mapper/dynamic/OracleDynamicDataSourceMapper.xml b/custom-query/custom-query-biz/src/main/resources/mapper/dynamic/OracleDynamicDataSourceMapper.xml index 8dda83a..97e6ef3 100644 --- a/custom-query/custom-query-biz/src/main/resources/mapper/dynamic/OracleDynamicDataSourceMapper.xml +++ b/custom-query/custom-query-biz/src/main/resources/mapper/dynamic/OracleDynamicDataSourceMapper.xml @@ -13,9 +13,7 @@ and ${uniCon.ucKey} >= #{uniCon.ucMock} and ${uniCon.ucKey} < #{uniCon.ucMock} and ${uniCon.ucKey} <= #{uniCon.ucMock} - and ${uniCon.ucKey} like concat(concat('%', #{uniCon.ucMock}), - '%') - + and ${uniCon.ucKey} like concat(concat('%', #{uniCon.ucMock}),'%') and ${uniCon.ucKey} = #{uniCon.ucMock} @@ -24,9 +22,7 @@ and ${uniCon.ucKey} >= #{uniCon.ucMock} and ${uniCon.ucKey} < #{uniCon.ucMock} and ${uniCon.ucKey} <= #{uniCon.ucMock} - and ${uniCon.ucKey} like concat(concat('%', #{uniCon.ucMock}), - '%') - + and ${uniCon.ucKey} like concat(concat('%', #{uniCon.ucMock}), '%') and ${uniCon.ucKey} between #{uniCon.begin} and #{uniCon.end} diff --git a/custom-query/custom-query-biz/src/main/resources/mapper/dynamic/dm.sql b/custom-query/custom-query-biz/src/main/resources/mapper/dynamic/dm.sql new file mode 100644 index 0000000..bf341ba --- /dev/null +++ b/custom-query/custom-query-biz/src/main/resources/mapper/dynamic/dm.sql @@ -0,0 +1,51 @@ +select ut.table_name,utc.comments as table_comment,ut.last_analyzed as update_time +from user_tables ut + left join user_tab_comments utc on ut.table_name = utc.table_name + + + +SELECT * FROM dba_tables dt + LEFT JOIN user_tab_comments utc on dt.table_name = utc.table_name +WHERE owner = 'FATEVERSE_LOG' + + +-- 使用CURRENT_SCHEMA函数获取当前模式 +SELECT CURRENT_SCHEMA() AS current_schema; + +-- 使用CURRENT_USER函数获取当前用户及其默认模式 +SELECT CURRENT_USER AS current_user; + + + + +SELECT dt.table_name,utc.comments as table_comment FROM dba_tables dt + LEFT JOIN user_tab_comments utc on dt.table_name = utc.table_name +WHERE owner = 'FATEVERSE_LOG's + + + +SELECT * FROM user_tables + + +select distinct utc.column_name, + utc.table_name as remark, + CONCAT(CONCAT(CONCAT(lower(utc.data_type),'('), utc.data_length),')') as column_type, + utc.data_scale as column_scale, + utc.column_id as sort, + (case when uc.constraint_type = 'P' then '1' else '0' end) as pk , + ucc.comments as column_comment +from user_tab_columns utc + inner join user_col_comments ucc on ucc.column_name = utc.column_name and ucc.table_name = utc.table_name + left join user_cons_columns uccs on uccs.column_name = utc.column_name + left join user_constraints uc on uc.constraint_name = uccs.constraint_name + + +select ut.table_name,utc.comments as table_comment,ut.last_analyzed as update_time +from user_tables ut + left join user_tab_comments utc on ut.table_name = utc.table_name + + + +select 1 from dual + +