31 Commits
Author SHA1 Message Date
蓝白 25cabceca2 更新版本4.4.0 2026-04-06 22:23:56 +08:00
蓝白 65b9622666 更新版本4.4.0 2026-04-06 22:22:37 +08:00
蓝白 7cc3a9fd20 更新页面 2026-04-06 22:21:32 +08:00
蓝白 b80d8b293b 数据源菜单拆分 2026-04-06 22:04:46 +08:00
蓝白 79c1ce8e11 升级spring boot4版本 2026-04-06 13:03:27 +08:00
蓝白 2423ffd7ae 更新 4.3版本 2026-03-21 15:20:45 +08:00
蓝白 6cf3c47d09 更新 4.3版本 2026-03-21 15:12:07 +08:00
蓝白 6e2a0e2cb3 优化页面 2026-03-21 15:11:25 +08:00
蓝白 6d83e16b1c 修复序列化问题 2026-03-21 15:10:25 +08:00
蓝白 25b991c13a 更新脚本 2026-03-10 13:58:04 +08:00
蓝白 32b1c1045b 更新版本 4.2 2026-03-07 15:39:14 +08:00
蓝白 458266297c 表下拉框添加悬浮提示表名 2026-03-07 15:38:25 +08:00
蓝白 4139d5bd7b 修复post请求异常 2026-03-07 15:33:55 +08:00
蓝白 8b09976db3 更新版本 2026-02-04 14:03:01 +08:00
蓝白 8e61b43c3f 更新版本 2026-02-04 14:01:21 +08:00
蓝白 b2f2772a17 更新页面 2026-02-04 13:59:58 +08:00
蓝白 4314d3410f 更新描述 2026-02-04 13:57:12 +08:00
蓝白 a2a07a2549 修复调用失效问题 2026-02-04 13:56:34 +08:00
蓝白 25c6b49775 修复调用失效问题 2026-02-04 13:56:19 +08:00
蓝白 ee9e51947e 修复连接泄露问题 2026-02-03 21:37:16 +08:00
蓝白 49e05081f9 修复连接池泄露问题 2026-02-03 21:33:09 +08:00
蓝白 9420a17bcc 修复bug 2026-02-03 12:56:29 +08:00
蓝白 3b6a95c731 更新 2026-01-20 19:54:45 +08:00
蓝白 c59192c144 更新版本至4.0 2026-01-18 16:18:50 +08:00
蓝白 299bec29e0 更新版本至4.0 2026-01-18 15:58:26 +08:00
蓝白 86bb9c2f2a 更新版本至4.0 2026-01-18 15:56:05 +08:00
蓝白 121b6653ab 更新版本至4.0 2026-01-18 15:45:01 +08:00
蓝白 9fc3990411 更新描述 2026-01-13 23:03:46 +08:00
蓝白 7a53390946 更新描述 2026-01-04 16:47:29 +08:00
蓝白 2e8a930b16 修复ck链接问题 2025-12-30 14:32:01 +08:00
蓝白 444c288079 更新描述 2025-12-26 13:04:25 +08:00
249 changed files with 5248 additions and 438 deletions

No files matched your search

+5 -3
View File
@@ -45,13 +45,13 @@ buildNumber.properties
####################### svn ##############################
.svn
####################### eclipse ##############################
.project
.settings
bin/
logs/
.classpath
db/
.classpathc
####################### idea ##############################
@@ -67,4 +67,6 @@ logs/
.flattened-pom.xml
*.log
tmp/
AGENTS.md
tmp/
/crabc-web/
+1 -1
View File
@@ -1,5 +1,5 @@
FROM eclipse-temurin:21-jdk-alpine
LABEL version="3.5.2"
LABEL version="4.4.0"
COPY crabc-admin.jar /app.jar
ENV LANG="en_US.UTF-8"
+54 -46
View File
@@ -3,18 +3,19 @@
crabc由create + abc 组合而来,意在为项目系统构建的通用的接口底座。
# 介绍
**crabc** 是低代码接口开发平台,企业数据服务平台,深度整合SpringBoot和Mybatis实现动态数据源和动态SQL、函数和存储过程。
**crabc-api** 是接口快速开发平台,企业数据服务平台,sql2Api,数据预览等。深度整合SpringBoot和Mybatis实现动态数据源和动态SQL、函数和存储过程。
支持接入(mysql、oracle、postgresql、sqlserver、达梦、TiDB、es和hive)等SQL或/NoSQL数据源,
在线可视化编写SQL后即可快速生成接口对外提供服务,接口一键上下线。减少通用接口的SQL编写,让开发人员专注更复杂的业务逻辑实现。
支持Mybatis中if等标签语法、数据脱敏、数据转换、国密加密、协同开发等功能,可集成微服务网关支持接入第三方接口、权限认证、限流、缓存、告警监控和统一日志等一站式API数据服务,
支持Mybatis中if等标签语法、数据脱敏、数据转换、国密加密、协同开发、接口编排等功能,可集成微服务网关支持接入第三方接口、权限认证、限流、缓存、告警监控和统一日志等一站式API数据服务,
助力于企业数据资产价值升级,成为企业数字化转型的重要推动力。
![img.png](doc/home.png)
## 功能
## 社区版功能
- **工作台**:可视化编写SQL快速的对外发布成API接口,支持多SQL同时执行、Mybatis标签语法,实现动态SQL和动态标签
- **数据源管理**:动态加载数据库,支持多种SQL/NoSQL数据库。
- **应用列表**:AppKey认证、签名认证的应用创建管理以及对API调用在线授权。
- **数据源**:数据源列表和数据查询,支持多种SQL/NoSQL数据库添加。
- **应用凭证**:AppKey认证、签名认证的应用创建管理以及对API调用在线授权。
- **接口列表**:查看开发中和已发布的API接口,可进行上下线管理,编辑升级等
- **接口文档**:生成在线接口文档,支持在线测试。
- **接口日志**:查看发布的接口被调用日志列表和请求详情。
## 接口开发流程
@@ -31,11 +32,11 @@ cn.crabc
├── crabc-spring-boot-starter // 第三方项目maven集成依赖包
├── db // SQL脚本
├──pom.xml // 依赖
~~~
~~~
## 版本说明
dev分支框架SpringBoot已升级至3.5,jdk需17及以上版本 \
2.x分支框架SpringBoot还是2.x
dev分支框架SpringBoot已升级至4.0,jdk需21及以上版本 \
jdk8分支框架SpringBoot是2.x + jdk8
## 企业版
https://pingapi.cn
@@ -59,9 +60,6 @@ github:https://github.com/pingapi/crabc-api
已申请软件著作,开源版仅供个人学习使用 \
企业版功能更强大,商用请加群联系\
## 数据库脚本
加群获取最新数据库脚本
## 源码地址
github: https://github.com/pingapi/crabc-api \
gitee: https://gitee.com/linebyte/crabc
@@ -72,7 +70,7 @@ gitee: https://gitee.com/linebyte/crabc
<dependency>
<groupId>cn.crabc</groupId>
<artifactId>crabc-spring-boot-starter</artifactId>
<version>3.5.2</version>
<version>4.4.0</version>
</dependency>
```
在程序启动类中添加下面注解
@@ -83,8 +81,13 @@ gitee: https://gitee.com/linebyte/crabc
## Docker启动
先执行db/dml.sql脚本,创建库表和初始化数据,建议mysql 8.0+版本
X86/AMD架构
```
docker run -p 9377:9377 -e DB_URL=jdbc:mysql://localhost:3306/crabc -e DB_USER=root -e DB_PWD=root -d --name crabc-api crabc/crabc-api:latest
```
ARM架构
```
docker pull crabc/crabc-admin:latest
docker run -p 9377:9377 -e DB_URL=jdbc:mysql://localhost:3306/crabc -e DB_USER=root -e DB_PWD=root -d --name crabc-admin crabc/crabc-admin:latest
```
访问地址:http://127.0.0.1:9377
@@ -93,24 +96,28 @@ docker run -p 9377:9377 -e DB_URL=jdbc:mysql://localhost:3306/crabc -e DB_USER=r
_## Windows桌面运行
先执行db/dml.sql脚本,创建库表和初始化数据,建议mysql 8.0+版本
```
java -jar crabc-admin.jar --spring.datasource.url=jdbc:mysql://127.0.0.1:3306/crabc --spring.datasource.username=root --spring.datasource.password=root
java -jar crabc-api.jar --spring.datasource.url=jdbc:mysql://127.0.0.1:3306/crabc --spring.datasource.username=root --spring.datasource.password=root
```
## 效果截图
### 接口开发
![img.png](doc/sql.png)
![img.png](doc/dev.png)
#### 接口属性
![img.png](doc/detail.png)
#### 请求参数
#### 返回参数
![img.png](doc/param.png)
#### 在线预览
![img_2.png](doc/img_test.png)
#### 接口列表
![img.png](doc/api.png)
#### 数据库类型
![img.png](doc/apis.png)
#### 日志管理
![img.png](doc/logs.png)
#### 数据源列表
![img.png](doc/dbs.png)
#### 数据查询
![img.png](doc/data.png)
#### 数据源类型
![img.png](doc/db.png)
### 限流熔断
![img.png](doc/flow.png)
## 交流群
**进群前请先点【Star】谢谢**
@@ -136,31 +143,32 @@ QQ群(请先Star):748993036
| 鹭栖技术信息公司 |
| 循脉医疗科技有限公司 |
| 云上贵州大数据有限公司 |
| 巨元瀚洋有限公司 |
## 企业版和开源版对比
| 功能 | 社区版 | 企业版 |
|--------|------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
| 架构设计 | 单体 | 微服务 |
| 接口创建模式 | SQL脚本 | SQL脚本、图表、接口转发 |
| 动态标签 | 支持 | 支持 |
| 动态路由 | 不支持 | 支持 |
| 数据库 | SQL:mysql/oracle/postgresql/sqlserver <br>TiDB/OpenGauss/Doris | SQL:mysql/oracle/postgresql/sqlserver/tidb<br>/opengauss/doris/oceanbase/dm/gbase <br> NoSQL:es/mongodb <br> TSDB: TDengine |
| 认证方式 | 无/Code认证/签名认证 | 无/Code认证/签名认证 |
| SQL类型 | 查询SQL | 查询/插入/更新/删除等SQL |
| 结果类型 | json | json/Excel |
| 接口日志 | 支持 | 支持 |
| 数据模型 | 不支持 | 支持 |
| 协同开发 | 不支持 | 支持 |
| 结果转换 | 不支持 | 支持 |
| 接口市场 | 不支持 | 支持 |
| 申请审批 | 不支持 | 支持 |
| 接口授权 | 不支持 | 支持 |
| 系统权限 | 不支持 | 支持 |
| 用户管理 | 不支持 | 支持 |
| 数据脱敏 | 不支持 | 支持 |
| 版本管理 | 不支持 | 支持
| 接口缓存 | 不支持 | 支持 |
| 限流熔断 | 不支持 | 支持 |
| IP控制 | 不支持 | 支持 |
| 监控报表 | 支持 | 支持 |
| 集群模式 | 不支持 | 支持 |
| 功能 | 社区版 | 企业版 |
|-------|--------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
| 架构设计 | 单体 | 微服务 |
| 开发模式 | SQL脚本 | SQL脚本、图表、接口转发、原生脚本 |
| 接口编排 | 不支持 | 支持 |
| 动态标签 | 支持 | 支持 |
| 动态路由 | 不支持 | 支持 |
| 数据库 | SQL:mysql/oracle/postgresql/sqlserver <br>TiDB/OpenGauss/Doris | SQL:mysql/oracle/postgresql/sqlserver/tidb<br>/opengauss/doris/oceanbase/dm/gbase <br> NoSQL:es/mongodb/hbase <br> TSDB: TDengine |
| 认证方式 | 无/Code认证/签名认证 | 无/Code认证/签名认证 |
| SQL类型 | 查询SQL | 查询/插入/更新/删除等SQL |
| 结果类型 | json | json/Excel |
| 接口日志 | 支持 | 支持 |
| 协同开发 | 不支持 | 支持 |
| 插件市场 | 不支持 | 支持 |
| 接口市场 | 不支持 | 支持 |
| 申请审批 | 不支持 | 支持 |
| 接口授权 | 不支持 | 支持 |
| 系统权限 | 不支持 | 支持 |
| 用户管理 | 不支持 | 支持 |
| 数据脱敏 | 不支持 | 支持 |
| 版本管理 | 不支持 | 支持
| 接口缓存 | 不支持 | 支持 |
| 限流熔断 | 不支持 | 支持 |
| IP控制 | 不支持 | 支持 |
| 监控报表 | 支持 | 支持 |
| 集群模式 | 不支持 | 支持 |
@@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.crabc</groupId>
<artifactId>crabc-boot</artifactId>
<artifactId>crabc-api</artifactId>
<version>${revision}</version>
</parent>
@@ -19,7 +19,7 @@ package cn.crabc.core.admin;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
/**
@@ -3,17 +3,23 @@ server:
port: 9377
spring:
application:
name: crabc-admin
name: crabc-api
main:
banner-mode: off
threads:
virtual:
enabled: true # 全局启用虚拟线程
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
default-property-inclusion: non_null
core:
recycler-pool: thread-local # Jackson3性能恢复
datasource:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://127.0.0.1:3306/crabc?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
password:
# mybatis配置
mybatis:
# 搜索指定包别名
@@ -25,14 +31,4 @@ mybatis:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
pagehelper:
autoRuntimeDialect: true # 开启多数据源分页识别
# es健康检查
management:
health:
elasticsearch:
enabled: false
# 签名认证过期时间
crabc:
auth:
expiresTime: 10
autoRuntimeDialect: true # 开启多数据源分页识别
@@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>crabc-boot</artifactId>
<artifactId>crabc-api</artifactId>
<groupId>cn.crabc</groupId>
<version>${revision}</version>
</parent>
@@ -97,7 +97,7 @@ public class ApiServiceController {
Object value = paramMap.get(paramName);
// 必填参数校验
if (param.getRequired() && !paramMap.containsKey(paramName)) {
if ("Y".equals(param.getRequired()) && !paramMap.containsKey(paramName)) {
return false;
}
@@ -1,5 +1,6 @@
package cn.crabc.core.app.config;
import cn.crabc.core.app.entity.dto.ApiInfoDTO;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
@@ -28,9 +29,9 @@ public class CacheConfig {
* @return
*/
@Bean("apiCache")
public Cache<String, Object> apiCaffeine() {
public Cache<String, ApiInfoDTO> apiCaffeine() {
return Caffeine.newBuilder()
.expireAfterAccess(10, TimeUnit.HOURS)
.expireAfterAccess(1, TimeUnit.MINUTES)
.build();
}
@@ -56,7 +56,10 @@ public class DataSourceConfig {
dataSource.setTestWhileIdle(true);
dataSource.setTestOnBorrow(false);
dataSource.setTestOnReturn(false);
dataSource.setTestOnReturn(false);
// 连接泄漏检测配置
dataSource.setRemoveAbandoned(true);
dataSource.setRemoveAbandonedTimeout(300);
dataSource.setLogAbandoned(true);
JdbcDataSourceRouter dynamic = new JdbcDataSourceRouter();
dynamic.setTargetDataSources(new HashMap<>());
// 设置默认数据源
@@ -1,8 +1,8 @@
package cn.crabc.core.app.config;
import org.springframework.boot.web.error.ErrorPage;
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -15,8 +15,6 @@ import org.springframework.web.bind.annotation.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
@@ -41,7 +39,7 @@ public class ApiInfoController {
* @return
*/
@GetMapping("/page")
public Result page(String keyword, String devType, Integer pageNum, Integer pageSize) {
public Result page(@RequestParam(required = false) String keyword, String devType, Integer pageNum, Integer pageSize) {
PageInfo<BaseApiInfo> page = apiInfoService.getApiPage(keyword, devType, pageNum, pageSize);
return Result.success(page);
}
@@ -6,9 +6,9 @@ import cn.crabc.core.app.enums.ResultTypeEnum;
import cn.crabc.core.app.service.core.IBaseDataService;
import cn.crabc.core.app.util.Result;
import cn.crabc.core.datasource.enums.ErrorStatusEnum;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import tools.jackson.databind.json.JsonMapper;
import java.util.Arrays;
import java.util.HashMap;
@@ -27,7 +27,7 @@ public class ApiTestController {
@Autowired
private IBaseDataService baseDataService;
@Autowired
private ObjectMapper objectMapper;
private JsonMapper jsonMapper;
/**
* 运行预览
@@ -74,11 +74,7 @@ public class ApiTestController {
);
// 处理返回结果
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("code", 0);
resultMap.put("data", formatResultData(data, params.getResultType()));
return Result.success(resultMap);
return Result.success(formatResultData(data, params.getResultType()));
} catch (Exception e) {
return Result.error("测试异常,请检查参数或者SQL是否正常!");
@@ -93,7 +89,10 @@ public class ApiTestController {
// 处理body参数
if (params.getBodyData() != null && params.getBodyData().startsWith("{")) {
paramsMap = objectMapper.readValue(params.getBodyData(), HashMap.class);
paramsMap = jsonMapper.readValue(params.getBodyData(), HashMap.class);
}else if (params.getBodyData() != null && params.getBodyData().startsWith("[")) {
List list = jsonMapper.readValue(params.getBodyData(), List.class);
paramsMap.put("list", list);
}
// 处理query参数
@@ -110,7 +109,9 @@ public class ApiTestController {
List<Map<String,Object>> paramsList = (List<Map<String, Object>>) requestParams;
for (Map<String, Object> entry : paramsList) {
if (validateParams(entry)) {
paramsMap.put(entry.get("name").toString(), entry.get("value"));
if (entry.containsKey("name")) {
paramsMap.put(entry.get("name").toString(), entry.get("value"));
}
} else {
throw new IllegalArgumentException("参数校验失败");
}
@@ -128,9 +129,9 @@ public class ApiTestController {
private String formatResultData(Object data, String resultType) throws Exception {
if (ResultTypeEnum.ONE.getName().equals(resultType) && data instanceof List) {
List<Object> list = (List<Object>) data;
return objectMapper.writeValueAsString(Result.success(list.isEmpty() ? null : list.get(0)));
return jsonMapper.writeValueAsString(Result.success(list.isEmpty() ? null : list.get(0)));
}
return objectMapper.writeValueAsString(Result.success(data));
return jsonMapper.writeValueAsString(Result.success(data));
}
/**
@@ -35,9 +35,6 @@ public class CommonController {
public Result detail(Long apiId) {
Integer applyCount = 1;
BaseApiInfoVO apiDetail = apiInfoService.getApiDetail(apiId);
if ("0".equals(apiDetail.getShowSqlScript())){
apiDetail.setSqlScript("***");
}
apiDetail.setApplyed(applyCount);
return Result.success(apiDetail);
}
@@ -5,14 +5,16 @@ import cn.crabc.core.app.entity.param.UserParam;
import cn.crabc.core.app.service.system.IBaseUserService;
import cn.crabc.core.app.util.*;
import com.github.benmanes.caffeine.cache.Cache;
import org.apache.tomcat.util.codec.binary.Base64;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import tools.jackson.databind.json.JsonMapper;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -26,7 +28,8 @@ public class SysUserController {
@Autowired
@Qualifier("dataCache")
Cache<String, Object> caffeineCache;
@Autowired
private JsonMapper jsonMapper;
/**
* 登录
*
@@ -75,6 +78,17 @@ public class SysUserController {
BaseUser userInfo = iBaseUserService.getUserById(Long.parseLong(UserThreadLocal.getUserId()));
return Result.success(userInfo);
}
/**
* 用户菜单
* @return
*/
@GetMapping("/menus")
public Result userMenus(){
// 固定菜单
String menus ="[{\"name\":\"API Hub\",\"checked\":null,\"id\":2,\"parentId\":1,\"open\":null,\"path\":null,\"url\":\"/hub\",\"sort\":2,\"menuType\":1,\"code\":\"Home\",\"hidden\":false,\"permission\":\"/api/box/sys/user/info;/api/box/sys/user/menus;/api/box/sys/message/**;/api/box/sys/user/update/pwd\",\"subMenus\":[{\"name\":\"接口详情\",\"checked\":null,\"id\":7,\"parentId\":2,\"open\":null,\"path\":null,\"url\":\"/doc\",\"sort\":6,\"menuType\":1,\"code\":\"DataCatelogApiDetails\",\"hidden\":true,\"permission\":\"doc\",\"subMenus\":[]}]},{\"name\":\"工作台\",\"checked\":null,\"id\":3,\"parentId\":1,\"open\":null,\"path\":null,\"url\":\"/working\",\"sort\":3,\"menuType\":1,\"code\":\"DataService\",\"hidden\":false,\"permission\":\"/api/box/sys/common/**;/api/box/sys/api/info/**;/api/box/sys/metadata/**;/api/box/sys/test/**;/api/box/sys/group/**;/api/box/sys/user/check/name\",\"subMenus\":[]},{\"name\":\"服务台\",\"checked\":null,\"id\":4,\"parentId\":1,\"open\":null,\"path\":null,\"url\":\"/manage\",\"sort\":4,\"menuType\":1,\"code\":\"Manage\",\"hidden\":false,\"permission\":\"manage\",\"subMenus\":[{\"name\":\"应用管理\",\"checked\":null,\"id\":8,\"parentId\":4,\"open\":null,\"path\":null,\"url\":\"/manage/keys\",\"sort\":1,\"menuType\":1,\"code\":\"Application\",\"hidden\":true,\"permission\":\"/api/box/sys/app/**\",\"subMenus\":[]},{\"name\":\"接口列表\",\"checked\":null,\"id\":9,\"parentId\":4,\"open\":null,\"path\":null,\"url\":\"/manage/apis\",\"sort\":1,\"menuType\":1,\"code\":\"MyApi\",\"hidden\":true,\"permission\":\"/api/box/sys/api/info/**\",\"subMenus\":[]},{\"name\":\"日志管理\",\"checked\":null,\"id\":12,\"parentId\":4,\"open\":null,\"path\":null,\"url\":\"/manage/logs\",\"sort\":1,\"menuType\":1,\"code\":\"UseLog\",\"hidden\":true,\"permission\":\"/api/box/sys/api/log/**\",\"subMenus\":[{\"name\":\"日志列表\",\"checked\":null,\"id\":13,\"parentId\":12,\"open\":null,\"path\":null,\"url\":\"/manage/logs/list\",\"sort\":1,\"menuType\":1,\"code\":\"UseLogList\",\"hidden\":true,\"permission\":\"/api/box/sys/api/log/**\",\"subMenus\":[]},{\"name\":\"日志详情\",\"checked\":null,\"id\":14,\"parentId\":12,\"open\":null,\"path\":null,\"url\":\"/manage/logs/detail\",\"sort\":1,\"menuType\":1,\"code\":\"DetailUesLog\",\"hidden\":true,\"permission\":null,\"subMenus\":[]}]},{\"name\":\"分类管理\",\"checked\":null,\"id\":30,\"parentId\":4,\"open\":null,\"path\":null,\"url\":\"/manage/classification\",\"sort\":1,\"menuType\":1,\"code\":\"Classification\",\"hidden\":true,\"permission\":\"manage:classification\",\"subMenus\":[]},{\"name\":\"数据源\",\"checked\":null,\"id\":31,\"parentId\":4,\"open\":null,\"path\":null,\"url\":\"/manage/datasource\",\"sort\":1,\"menuType\":1,\"code\":\"DataSource\",\"hidden\":true,\"permission\":\"/api/box/sys/datasource/**;/api/box/sys/user/pubKey\",\"subMenus\":[]},{\"checked\":null,\"code\":\"datasource\",\"hidden\":false,\"id\":33,\"menuType\":1,\"name\":\"数据源\",\"open\":null,\"parentId\":1,\"path\":null,\"permission\":\"/api/box/sys/datasource/**;/api/box/sys/user/pubKey\",\"sort\":4,\"subMenus\":[],\"url\":\"/datasource\"},{\"name\":\"密码重置\",\"checked\":null,\"id\":32,\"parentId\":4,\"open\":null,\"path\":null,\"url\":\"/manage/edit-pwd\",\"sort\":1,\"menuType\":1,\"code\":\"ChangePassword\",\"hidden\":true,\"permission\":\"/api/box/sys/user/update/pwd\",\"subMenus\":[]}]}]";
List<Map<String, Object>> list = jsonMapper.readValue(menus, List.class);
return Result.success(list);
}
/**
* 修改密码
@@ -80,11 +80,6 @@ public class BaseApiInfo extends BaseEntity {
*/
private String sqlScript;
/**
* 是否显示脚本1/0
*/
private String showSqlScript;
/**
* 分页设置,不分页:0、只分页:page、分页并统计:pageCount
*/
@@ -104,6 +99,8 @@ public class BaseApiInfo extends BaseEntity {
* schema
*/
private String schemaName;
// 表名
private String tableName;
/**
* 数据源类型
@@ -120,4 +117,7 @@ public class BaseApiInfo extends BaseEntity {
*/
private Long parentId;
/** 分组名称 */
private String groupName;
}
@@ -40,7 +40,7 @@ public class BaseApiParam {
/**
* 是否必填
*/
private Boolean required;
private String required;
/**
* 操作
@@ -40,6 +40,8 @@ public class BaseApiSql extends BaseEntity {
*/
private String schemaName;
private String tableName;
/**
* 数据源类型
*/
@@ -3,6 +3,8 @@ package cn.crabc.core.app.entity.param;
import lombok.Getter;
import lombok.Setter;
import java.util.Map;
@Setter
@Getter
public class ApiTestParam {
@@ -25,4 +27,5 @@ public class ApiTestParam {
private String bodyData;
private Map<String,Object> queryParam;
}
@@ -71,8 +71,6 @@ public class BaseApiInfoVO extends BaseEntity {
private Integer pageSetup;
private String sqlScript;
private String showSqlScript;
/**
* 发布时间
*/
@@ -79,6 +79,7 @@ public class ExceptionHandler {
@org.springframework.web.bind.annotation.ExceptionHandler(value = HttpMessageNotReadableException.class)
@ResponseBody
public Result exceptionHandler(HttpServletRequest req, HttpMessageNotReadableException e) {
e.printStackTrace();
return Result.error(50002, "Body参数异常,请检查Body/json是否正确传参");
}
}
@@ -23,7 +23,7 @@ public class ApiFilter implements Filter {
ContentCachingResponseWrapper responseWrapper = null;
try {
// 包装类
if (request.getContentType() != null && request.getContentType().contains(MediaType.APPLICATION_JSON_VALUE)) {
if (request.getContentType() == null || request.getContentType().contains(MediaType.APPLICATION_JSON_VALUE)) {
BaseRequestWrapper requestWrapper = new BaseRequestWrapper(request);
responseWrapper = new ContentCachingResponseWrapper(response);
filterChain.doFilter(requestWrapper, responseWrapper);
@@ -40,6 +40,7 @@ public class ApiFilter implements Filter {
@Override
public void destroy() {
ApiThreadLocal.remove();
Filter.super.destroy();
}
@@ -3,14 +3,13 @@ package cn.crabc.core.app.filter;
import cn.crabc.core.app.entity.BaseApiLog;
import cn.crabc.core.app.entity.BaseApp;
import cn.crabc.core.app.entity.dto.ApiInfoDTO;
import cn.crabc.core.app.service.system.IBaseApiInfoService;
import cn.crabc.core.app.service.system.IBaseApiLogService;
import cn.crabc.core.app.util.ApiThreadLocal;
import cn.crabc.core.app.util.RequestUtils;
import cn.crabc.core.app.util.Result;
import cn.crabc.core.app.util.SM3Util;
import cn.crabc.core.datasource.enums.ErrorStatusEnum;
import cn.crabc.core.datasource.exception.CustomException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.benmanes.caffeine.cache.Cache;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@@ -22,10 +21,9 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.Nullable;
import org.springframework.util.StreamUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.ContentCachingResponseWrapper;
import tools.jackson.databind.json.JsonMapper;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
@@ -42,25 +40,30 @@ public class AuthInterceptor implements HandlerInterceptor {
private static final String API_PRE = "/api/web/";
@Autowired
private IBaseApiLogService iBaseApiLogService;
@Autowired
private IBaseApiInfoService iBaseApiInfoService;
@Value("${crabc.auth.expiresTime:10}")
private Integer expiresTime;
@Autowired
private ObjectMapper objectMapper;
private JsonMapper jsonMapper;
@Autowired
@Qualifier("apiCache")
private Cache<String, Object> apiCache;
private Cache<String, ApiInfoDTO> apiCache;
private ApiInfoDTO getApiData(String key) {
String[] split = key.split("_");
return iBaseApiInfoService.getApiInfoCache(split[0], split[1]);
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String path = request.getRequestURI();
String method = request.getMethod();
Object apiData = apiCache.getIfPresent(method + "_" + path.replace(API_PRE, ""));
if (apiData == null) {
ApiInfoDTO apiInfo = apiCache.get(method + "_" + path.replace(API_PRE, ""), this::getApiData);
if (apiInfo == null) {
setErrorResponse(request, response,ErrorStatusEnum.API_INVALID.getCode(),ErrorStatusEnum.API_INVALID.getMassage());
return false;
}
ApiInfoDTO apiInfo = (ApiInfoDTO) apiData;
if (apiInfo.getEnabled() == 0) {
setErrorResponse(request, response,ErrorStatusEnum.API_OFFLINE.getCode(),ErrorStatusEnum.API_OFFLINE.getMassage());
return false;
@@ -107,7 +110,7 @@ public class AuthInterceptor implements HandlerInterceptor {
response.setStatus(400);
response.setContentType("application/json;charset=UTF-8");
Result result = Result.error(status, message);
String json = objectMapper.writeValueAsString(result);
String json = jsonMapper.writeValueAsString(result);
// 日记记录
addLog(request, response, json);
response.getWriter().write(json);
@@ -132,6 +135,7 @@ public class AuthInterceptor implements HandlerInterceptor {
apiLog.setCostTime(endTime - apiInfo.getRequestTime());
}
int status = response.getStatus();
apiLog.setAppName(RequestUtils.getAppKey(request));
apiLog.setApiPath(request.getRequestURI());
apiLog.setRequestIp(RequestUtils.getIp(request));
apiLog.setResponseTime(new Date());
@@ -74,6 +74,13 @@ public interface BaseApiInfoMapper {
*/
List<ApiInfoDTO> selectApiDetail(@Param("apiId") Long apiId);
/**
* 根据apiId查询信息
* @param
* @return
*/
ApiInfoDTO getApiDetail(@Param("method") String method, @Param("apiPath") String apiPath);
/**
* 插入API
*
@@ -38,6 +38,7 @@ public class BaseDataServiceImpl implements IBaseDataService {
params.put(BaseConstant.DATA_SOURCE_TYPE, datasourceType);
}
params.put(BaseConstant.BASE_API_EXEC_TYPE, "preview");
params.put(BaseConstant.PAGE_SETUP, 1);
Object result = this.execute(datasourceId, datasourceType, schema, sql, params);
PreviewVO preview = new PreviewVO();
if (result instanceof List) {
@@ -18,7 +18,13 @@ import java.util.List;
*/
public interface IBaseApiInfoService {
void initApi();
/**
* 根据接口url获取API关联数据
*
* @param
* @return
*/
ApiInfoDTO getApiInfoCache(String method, String apiPath);
/**
* 获取API关联数据
@@ -49,11 +49,23 @@ public class BaseApiInfoServiceImpl implements IBaseApiInfoService {
private BaseApiParamMapper apiParamMapper;
@Autowired
@Qualifier("apiCache")
Cache<String, Object> apiInfoCache;
Cache<String, ApiInfoDTO> apiInfoCache;
@Override
public void initApi() {
updateCache(null);
public ApiInfoDTO getApiInfoCache(String method, String apiPath) {
ApiInfoDTO apiInfo = apiInfoMapper.getApiDetail(method, apiPath);
if (apiInfo == null) {
return null;
}
// 应用
List<BaseApp> appApis = baseAppMapper.selectApiApp(apiInfo.getApiId());
// 请求参数
List<BaseApiParam> baseApiParams = apiParamMapper.selectReqParams(apiInfo.getApiId());
apiInfo.setAppList(appApis == null ? new ArrayList<>() : appApis);
apiInfo.setRequestParams(baseApiParams == null ? new ArrayList<>() : baseApiParams);
return apiInfo;
}
public void updateCache(Long apiId) {
@@ -150,6 +162,7 @@ public class BaseApiInfoServiceImpl implements IBaseApiInfoService {
api.setApiType("SQL");
api.setDatasourceId(sql.getDatasourceId());
api.setSchemaName(sql.getSchemaName());
api.setTableName(sql.getTableName());
api.setDatasourceType(sql.getDatasourceType());
api.setSqlScript(sql.getSqlScript());
api.setCreateTime(date);
@@ -183,6 +196,7 @@ public class BaseApiInfoServiceImpl implements IBaseApiInfoService {
api.setEnabled(0);
api.setDatasourceId(sql.getDatasourceId());
api.setSchemaName(sql.getSchemaName());
api.setTableName(sql.getTableName());
api.setDatasourceType(sql.getDatasourceType());
api.setSqlScript(sql.getSqlScript());
api.setUpdateTime(updateTime);
@@ -62,7 +62,7 @@ public class BaseApiParamServiceImpl implements IBaseApiParamService {
responseCode.setParamDesc("状态码:0 成功");
responseCode.setParamType("Int");
responseCode.setExample("0");
responseCode.setRequired("1");
responseCode.setRequired("Y");
list.add(responseCode);
RequestParamsVO responseMsg = new RequestParamsVO();
@@ -71,7 +71,7 @@ public class BaseApiParamServiceImpl implements IBaseApiParamService {
responseMsg.setParamType("String");
responseMsg.setExample("");
responseMsg.setChildren(null);
responseCode.setRequired("1");
responseCode.setRequired("Y");
list.add(responseMsg);
RequestParamsVO responseData = new RequestParamsVO();
@@ -79,7 +79,7 @@ public class BaseApiParamServiceImpl implements IBaseApiParamService {
responseData.setParamDesc("数据");
responseData.setParamType("Array");
responseData.setExample("");
responseCode.setRequired("1");
responseCode.setRequired("Y");
responseData.setChildren(responseParams);
list.add(responseData);
return list;
@@ -61,7 +61,7 @@ public class BaseDataSourceServiceImpl implements IBaseDataSourceService {
public void init() {
List<BaseDataSource> baseDataSources = this.getList();
for (BaseDataSource dataSource : baseDataSources) {
DataSource ds = DataSourceManager.DATA_SOURCE_POOL_JDBC.get(dataSource.getDatasourceId());
DataSource ds = DataSourceManager.DATA_SOURCE_POOL_JDBC.get(dataSource.getDatasourceId().toString());
try {
String jdbcUrl = null;
String username = null;
@@ -113,6 +113,7 @@ public class BaseDataSourceServiceImpl implements IBaseDataSourceService {
dataSource.setClassify("jdbc");
dataSource.setCreateBy(UserThreadLocal.getUserId());
dataSource.setCreateTime(new Date());
dataSource.setUpdateTime(new Date());
// 判断是否是自定义
if ("custom".equals(dataSource.getDatasourceType())){
String dataSourceType = SQLUtil.getDataSourceType(dataSource.getJdbcUrl());
@@ -176,7 +177,7 @@ public class BaseDataSourceServiceImpl implements IBaseDataSourceService {
byte[] decode = Base64.getDecoder().decode(password);
pwd = new String(decode);
}else if (dataSource.getDatasourceId() != null){
BaseDatasource baseDatasource = dataSourceMapper.selectOne(Integer.parseInt(dataSource.getDatasourceId()));
BaseDatasource baseDatasource = dataSourceMapper.selectOne(dataSource.getDatasourceId());
byte[] decode = Base64.getDecoder().decode(baseDatasource.getPassword());
pwd = new String(decode);
}
@@ -1,12 +1,6 @@
package cn.crabc.core.app.util;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -18,36 +12,6 @@ import java.util.Set;
*/
public class RequestUtils {
private static ObjectMapper objectMapper = new ObjectMapper();
/**
* 获取body
*
* @param req
* @return
*/
public static Map<String, Object> getBodyMap(HttpServletRequest req) {
BufferedReader reader = null;
Map<String, Object> bodyMap = new HashMap<>();
try {
reader = req.getReader();
StringBuilder builder = new StringBuilder();
String line = reader.readLine();
while (line != null) {
builder.append(line);
line = reader.readLine();
}
reader.close();
String bodyString = builder.toString();
if (!"".equals(bodyString)) {
bodyMap = objectMapper.readValue(bodyString, Map.class);
}
} catch (Exception e) {
}
return bodyMap;
}
/**
* 获取 params 参数
*
@@ -148,57 +112,4 @@ public class RequestUtils {
}
return ip == null ? "" : ip.trim();
}
/**
* 根据关键字解析json
*
* @param @param jsonObject
* @param @param keyName 支持逗号分隔
* @return Object
*/
public static Object decodeJsonObject(String jsonObject, String keyName) {
Object result = null;
if (jsonObject == null || "".equals(jsonObject)) {
return null;
}
JsonFactory jasonFactory = new JsonFactory();
JsonParser parser = null;
try {
parser = jasonFactory.createParser(jsonObject);
JsonToken firstToken = parser.nextToken();
if (!JsonToken.START_OBJECT.equals(firstToken)) {
return result;
}
while (!parser.isClosed()) {
JsonToken t = parser.nextToken();
if (JsonToken.FIELD_NAME.equals(t) && keyName.equals(parser.getCurrentName())) {
JsonToken v = parser.nextToken();
if (JsonToken.VALUE_NULL.equals(v)) {
return null;
} else if (JsonToken.VALUE_STRING.equals(v)) {
return parser.getValueAsString();
} else if (JsonToken.VALUE_TRUE.equals(v) || JsonToken.VALUE_FALSE.equals(v)) {
return parser.getBooleanValue();
} else if (JsonToken.VALUE_NUMBER_INT.equals(v)) {
return parser.getLongValue();
} else if (JsonToken.VALUE_NUMBER_FLOAT.equals(v)) {
return parser.getDoubleValue();
}
} else if (JsonToken.START_OBJECT.equals(t) || JsonToken.START_ARRAY.equals(t)) {
parser.skipChildren();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (parser != null) {
parser.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
}
@@ -330,10 +330,10 @@ public class SQLUtil {
if (reqParams instanceof Map) {
Map<String, Object> paramMap = (Map<String, Object>) reqParams;
for (BaseApiParam param : paramsConfig) {
if (param.getRequired() && !paramMap.containsKey(param.getParamName())) {
if ("Y".equals(param.getRequired()) && !paramMap.containsKey(param.getParamName())) {
// 必传参数没有传,则报错提示
throw new CustomException(52005, "请求参数缺少!");
} else if (!param.getRequired() && !paramMap.containsKey(param.getParamName())) {
} else if ("N".equals(param.getRequired()) && !paramMap.containsKey(param.getParamName())) {
// 非比传参数,去掉SQL中相应的条件
sql = regexSql(sql, param.getParamName());
}
@@ -23,12 +23,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
i.update_by,
i.update_time,
i.release_time,
i.show_sql_script,
d.datasource_name
g.group_name
FROM
base_api_info i
left join base_datasource d
on i.datasource_id = d.datasource_id
left join base_group g
on i.group_id = g.group_id
<where>
<if test="apiName !=null and apiName !=''">
(i.api_name like concat('%',#{apiName},'%')
@@ -90,7 +89,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
remarks,
version,
page_setup,
show_sql_script,
datasource_id,
datasource_type,
schema_name,
@@ -106,6 +104,33 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if>
</select>
<select id="getApiDetail" resultType="cn.crabc.core.app.entity.dto.ApiInfoDTO">
SELECT
api_id,
api_name,
api_path,
api_type,
api_method,
auth_type,
api_status,
enabled,
group_id,
tenant_id,
remarks,
version,
page_setup,
datasource_id,
datasource_type,
schema_name,
sql_script,
sql_type,
result_type
FROM
base_api_info
WHERE
parent_id = 0 AND api_status ='release' and api_path =#{apiPath} and api_method =#{method}
</select>
<select id="selectApiById" resultType="cn.crabc.core.app.entity.BaseApiInfo">
SELECT
api_id,
@@ -127,8 +152,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
datasource_id,
datasource_type,
schema_name,
table_name,
sql_script,
show_sql_script,
page_setup,
sql_type,
result_type
@@ -153,7 +178,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
b.page_setup,
b.create_time,
b.sql_script,
b.show_sql_script,
b.update_time,
b.release_time,
b.version
@@ -186,14 +210,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="sqlType != null and sqlType != ''">sql_type,</if>
<if test="resultType != null and resultType != ''">result_type,</if>
<if test="sqlScript != null and sqlScript !=''">sql_script,</if>
<if test="showSqlScript != null and showSqlScript !=''">show_sql_script,</if>
<if test="datasourceId != null and datasourceId != ''">datasource_id,</if>
<if test="datasourceType != null and datasourceType != ''">datasource_type,</if>
<if test="schemaName != null and schemaName != ''">schema_name,</if>
<if test="tableName != null and tableName != ''">table_name,</if>
<if test="pageSetup != null">page_setup,</if>
enabled,
create_by,
create_time
create_time,
update_time
)values(
<if test="apiName != null and apiName != ''">#{apiName},</if>
<if test="apiPath != null and apiPath != ''">#{apiPath},</if>
@@ -209,14 +234,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="sqlType != null and sqlType != ''">#{sqlType},</if>
<if test="resultType != null and resultType != ''">#{resultType},</if>
<if test="sqlScript != null and sqlScript !=''">#{sqlScript},</if>
<if test="showSqlScript != null and showSqlScript !=''">#{showSqlScript},</if>
<if test="datasourceId != null and datasourceId != ''">#{datasourceId},</if>
<if test="datasourceType != null and datasourceType != ''">#{datasourceType},</if>
<if test="schemaName != null and schemaName != ''">#{schemaName},</if>
<if test="tableName != null and tableName != ''">#{tableName},</if>
<if test="pageSetup != null">#{pageSetup},</if>
#{enabled},
#{createBy},
#{createTime}
#{createTime},
#{updateTime}
)
</insert>
@@ -238,10 +264,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="sqlType != null and sqlType != ''">sql_type = #{sqlType},</if>
<if test="resultType != null and resultType != ''">result_type = #{resultType},</if>
<if test="sqlScript != null and sqlScript !=''">sql_script = #{sqlScript},</if>
<if test="showSqlScript != null and showSqlScript !=''">show_sql_script =#{showSqlScript},</if>
<if test="datasourceId != null and datasourceId != ''">datasource_id =#{datasourceId},</if>
<if test="datasourceType != null and datasourceType != ''">datasource_type =#{datasourceType},</if>
<if test="schemaName != null and schemaName != ''">schema_name =#{schemaName},</if>
<if test="tableName != null and tableName != ''">table_name =#{tableName},</if>
<if test="pageSetup != null">page_setup =#{pageSetup},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
update_time = #{updateTime}
@@ -262,7 +288,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</update>
<delete id="deleteApiInfo">
DELETE FROM base_api_info where api_status ='edit' and api_id =#{apiId} and create_by =#{userId}
DELETE FROM base_api_info where api_id =#{apiId} and create_by =#{userId}
</delete>
<select id="countApi" resultType="java.lang.Integer">
@@ -22,6 +22,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectList" resultType="cn.crabc.core.app.entity.BaseApiParam">
SELECT
param_id,
api_id,
param_name,
column_name,
@@ -16,7 +16,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
password,
remarks,
extend,
secret_key
secret_key,
min_idle,
max_active,
connect_timeout,
idle_timeout,
max_lifetime,
keepalive_time
FROM
base_datasource ORDER BY datasource_id DESC
</select>
@@ -33,6 +39,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
'******' as password,
remarks,
extend,
min_idle,
max_active,
connect_timeout,
idle_timeout,
max_lifetime,
keepalive_time,
update_time
FROM
base_datasource
@@ -56,6 +68,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
username,
password,
extend,
min_idle,
max_active,
connect_timeout,
idle_timeout,
max_lifetime,
keepalive_time,
secret_key
FROM
base_datasource WHERE datasource_id=#{datasourceId}
@@ -79,7 +97,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="remarks != null and remarks != ''">remarks,</if>
<if test="secretKey != null and secretKey != ''">secret_key,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
create_time
<if test="minIdle != null">min_idle,</if>
<if test="maxActive != null">max_active,</if>
<if test="connectTimeout != null">connect_timeout,</if>
<if test="idleTimeout != null">idle_timeout,</if>
<if test="maxLifetime != null">max_lifetime,</if>
<if test="keepaliveTime != null">keepalive_time,</if>
create_time,
update_time
)values(
<if test="datasourceId != null and datasourceId != ''">#{datasourceId},</if>
<if test="datasourceName != null and datasourceName != ''">#{datasourceName},</if>
@@ -93,7 +118,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="remarks != null and remarks != ''">#{remarks},</if>
<if test="secretKey != null and secretKey != ''">#{secretKey},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
#{createTime}
<if test="minIdle != null">#{minIdle},</if>
<if test="maxActive != null">#{maxActive},</if>
<if test="connectTimeout != null">#{connectTimeout},</if>
<if test="idleTimeout != null">#{idleTimeout},</if>
<if test="maxLifetime != null">#{maxLifetime},</if>
<if test="keepaliveTime != null">#{keepaliveTime},</if>
#{createTime},
#{updateTime}
)
</insert>
@@ -110,6 +142,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="classify != null and classify != ''">classify = #{classify},</if>
<if test="secretKey != null and secretKey != ''">secret_key = #{secretKey},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
<if test="minIdle != null">min_idle=#{minIdle},</if>
<if test="maxActive != null">max_active=#{maxActive},</if>
<if test="connectTimeout != null">connect_timeout=#{connectTimeout},</if>
<if test="idleTimeout != null">idle_timeout=#{idleTimeout},</if>
<if test="maxLifetime != null">max_lifetime=#{maxLifetime},</if>
<if test="keepaliveTime != null">keepalive_time=#{keepaliveTime},</if>
update_time =#{updateTime},remarks = #{remarks}
</set>
WHERE datasource_id = #{datasourceId}
Loaded 100 of 249 files, more files were not shown because too many files have changed in this diff. Show more