feat : portal模块添加注释信息

This commit is contained in:
clay
2024-04-19 21:50:24 +08:00
parent 286e7cf2b8
commit fe89df9aa1
8 changed files with 160 additions and 21 deletions

View File

@@ -57,6 +57,7 @@ public class PortalController {
}
@ApiOperation("新增接口")
@Encrypt
@PostMapping
@PreAuthorize("@ss.hasPermission('query:portal:add')")
public Result<PortalIdWrapper> add(@RequestBody @Validated PortalDto portalDto) {
@@ -65,6 +66,7 @@ public class PortalController {
}
@ApiOperation("修改接口")
@Encrypt
@PutMapping
@PreAuthorize("@ss.hasPermission('query:portal:edit')")
public Result<PortalIdWrapper> edit(@RequestBody @Validated PortalDto portalDto) {

View File

@@ -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<UniConDto> 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));
}

View File

@@ -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<Instance> 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<Instance> allInstances = namingService.getAllInstances(serviceName);
//如果没有则不进行同步
if (ObjectUtils.isEmpty(allInstances)) {
return;
}
//检查云端实例中是否还存在当前服务,不存在当前任务结束
Optional<Instance> 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;

View File

@@ -55,6 +55,7 @@ public class HandlerMethodService implements ApplicationContextAware {
public HandlerMethodService() {
//固定PortalDispatchServlet为入口类,其中doDispatch为入口方法
Class<PortalDispatchServlet> 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));
}
}

View File

@@ -15,16 +15,33 @@ public interface PortalService {
/**
* 根据id查询
*
* @param portalId id
* @return 结果
*/
PortalVo searchById(Long portalId);
/**
* 查询接口列表
*
* @param query 查询条件
* @return 查询表格结果
*/
TableDataInfo<SimplePortalVo> searchList(PortalQuery query);
/**
* 保存接口信息
*
* @param portalDto 接口信息
* @return 保存完成后接口id和数据适配器id
*/
PortalIdWrapper save(PortalDto portalDto);
/**
* 修改接口信息
*
* @param portalDto 接口信息
* @return 修改完成后接口id和数据适配器id
*/
PortalIdWrapper edit(PortalDto portalDto);
}

View File

@@ -133,6 +133,7 @@ public class PortalServiceImpl implements PortalService {
adapterIds.add(portal.getAdapterId());
}
});
//映射自定义擦洗名称
Map<Long, UniQuery> queryMap = new HashMap<>();
if (!ObjectUtils.isEmpty(queryIds)) {
List<UniQuery> queryList = queryMapper.selectListByIds(queryIds);
@@ -140,6 +141,7 @@ public class PortalServiceImpl implements PortalService {
queryMap.put(uniQuery.getId(), uniQuery);
}
}
//映射数据适配器名称
Map<Long, String> adapterMap = new HashMap<>();
if (!ObjectUtils.isEmpty(adapterIds)) {
List<DataAdapter> 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<PortalMapping> 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())) {

View File

@@ -13,9 +13,7 @@
<if test="uniCon.ucCon == 'GTE'">and ${uniCon.ucKey} >= #{uniCon.ucMock}</if>
<if test="uniCon.ucCon == 'LT'">and ${uniCon.ucKey} &lt; #{uniCon.ucMock}</if>
<if test="uniCon.ucCon == 'LTE'">and ${uniCon.ucKey} &lt;= #{uniCon.ucMock}</if>
<if test="uniCon.ucCon == 'LIKE'">and ${uniCon.ucKey} like concat(concat('%', #{uniCon.ucMock}),
'%')
</if>
<if test="uniCon.ucCon == 'LIKE'">and ${uniCon.ucKey} like concat(concat('%', #{uniCon.ucMock}),'%') </if>
</if>
<if test="uniCon.ucMock != null and uniCon.ucType != 'input'">
<if test="uniCon.ucCon == 'EQ'">and ${uniCon.ucKey} = #{uniCon.ucMock}</if>
@@ -24,9 +22,7 @@
<if test="uniCon.ucCon == 'GTE'">and ${uniCon.ucKey} >= #{uniCon.ucMock}</if>
<if test="uniCon.ucCon == 'LT'">and ${uniCon.ucKey} &lt; #{uniCon.ucMock}</if>
<if test="uniCon.ucCon == 'LTE'">and ${uniCon.ucKey} &lt;= #{uniCon.ucMock}</if>
<if test="uniCon.ucCon == 'LIKE'">and ${uniCon.ucKey} like concat(concat('%', #{uniCon.ucMock}),
'%')
</if>
<if test="uniCon.ucCon == 'LIKE'">and ${uniCon.ucKey} like concat(concat('%', #{uniCon.ucMock}), '%')</if>
<if test="uniCon.ucCon == 'BETWEEN'">and ${uniCon.ucKey} between #{uniCon.begin} and #{uniCon.end}
</if>
</if>

View File

@@ -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