mirror of
https://gitee.com/ssssssss-team/magic-api.git
synced 2026-06-04 12:59:35 +08:00
新增单表API操作拦截器
This commit is contained in:
@@ -100,6 +100,11 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer, WebSocketCon
|
||||
*/
|
||||
private final ObjectProvider<List<SQLInterceptor>> sqlInterceptorsProvider;
|
||||
|
||||
/**
|
||||
* 单表API拦截器
|
||||
*/
|
||||
private final ObjectProvider<List<NamedTableInterceptor>> namedTableInterceptorsProvider;
|
||||
|
||||
/**
|
||||
* 自定义的类型扩展
|
||||
*/
|
||||
@@ -164,6 +169,7 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer, WebSocketCon
|
||||
ObjectProvider<List<MagicFunction>> magicFunctionsProvider,
|
||||
ObjectProvider<MagicNotifyService> magicNotifyServiceProvider,
|
||||
ObjectProvider<AuthorizationInterceptor> authorizationInterceptorProvider,
|
||||
ObjectProvider<List<NamedTableInterceptor>> namedTableInterceptorsProvider,
|
||||
Environment environment,
|
||||
ApplicationContext applicationContext
|
||||
) {
|
||||
@@ -177,6 +183,7 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer, WebSocketCon
|
||||
this.magicFunctionsProvider = magicFunctionsProvider;
|
||||
this.magicNotifyServiceProvider = magicNotifyServiceProvider;
|
||||
this.authorizationInterceptorProvider = authorizationInterceptorProvider;
|
||||
this.namedTableInterceptorsProvider = namedTableInterceptorsProvider;
|
||||
this.environment = environment;
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
@@ -414,6 +421,7 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer, WebSocketCon
|
||||
sqlInterceptors.add(new DefaultSqlInterceptor());
|
||||
}
|
||||
sqlModule.setSqlInterceptors(sqlInterceptors);
|
||||
sqlModule.setNamedTableInterceptors(namedTableInterceptorsProvider.getIfAvailable(Collections::emptyList));
|
||||
ColumnMapperAdapter columnMapperAdapter = new ColumnMapperAdapter();
|
||||
this.columnMapperProvidersProvider.getIfAvailable(Collections::emptyList).stream().filter(mapperProvider -> !"default".equals(mapperProvider.name())).forEach(columnMapperAdapter::add);
|
||||
columnMapperAdapter.setDefault(properties.getSqlColumnCase());
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.ssssssss.magicapi.interceptor;
|
||||
|
||||
import org.ssssssss.magicapi.model.SqlMode;
|
||||
import org.ssssssss.magicapi.modules.table.NamedTable;
|
||||
|
||||
/**
|
||||
* 单表模块拦截器
|
||||
*
|
||||
* @since 1.5.3
|
||||
*/
|
||||
public interface NamedTableInterceptor {
|
||||
|
||||
/**
|
||||
* 执行之前
|
||||
*/
|
||||
void preHandle(SqlMode sqlMode, NamedTable namedTable);
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.ssssssss.magicapi.model;
|
||||
|
||||
import org.ssssssss.script.annotation.UnableCall;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -13,18 +15,31 @@ public class Attributes<T> {
|
||||
|
||||
protected Map<String, T> properties = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 设置属性
|
||||
* @param key key
|
||||
* @param value value
|
||||
*/
|
||||
@UnableCall
|
||||
public void setAttribute(String key, T value) {
|
||||
properties.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取属性
|
||||
* @param key key
|
||||
*/
|
||||
@UnableCall
|
||||
public Object getAttribute(String key) {
|
||||
return properties.get(key);
|
||||
}
|
||||
|
||||
@UnableCall
|
||||
public Map<String, T> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@UnableCall
|
||||
public void setProperties(Map<String, T> properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.ssssssss.magicapi.model;
|
||||
|
||||
/**
|
||||
* 单表API操作
|
||||
*/
|
||||
public enum SqlMode {
|
||||
|
||||
/**
|
||||
* 执行插入动作
|
||||
*/
|
||||
INSERT,
|
||||
/**
|
||||
* 执行修改动作
|
||||
*/
|
||||
UPDATE,
|
||||
/**
|
||||
* 执行删除动作
|
||||
*/
|
||||
DELETE,
|
||||
/**
|
||||
* 执行查询操作
|
||||
*/
|
||||
SELECT,
|
||||
/**
|
||||
* 执行查询单个操作
|
||||
*/
|
||||
SELECT_ONE,
|
||||
/**
|
||||
* 执行分页查询动作
|
||||
*/
|
||||
PAGE,
|
||||
/**
|
||||
* 执行count查询操作
|
||||
*/
|
||||
COUNT
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import org.ssssssss.magicapi.config.MagicDynamicDataSource.DataSourceNode;
|
||||
import org.ssssssss.magicapi.config.MagicModule;
|
||||
import org.ssssssss.magicapi.context.RequestContext;
|
||||
import org.ssssssss.magicapi.dialect.Dialect;
|
||||
import org.ssssssss.magicapi.interceptor.NamedTableInterceptor;
|
||||
import org.ssssssss.magicapi.interceptor.SQLInterceptor;
|
||||
import org.ssssssss.magicapi.model.Page;
|
||||
import org.ssssssss.magicapi.model.RequestEntity;
|
||||
@@ -76,6 +77,7 @@ public class SQLModule extends HashMap<String, SQLModule> implements MagicModule
|
||||
private SqlCache sqlCache;
|
||||
private String cacheName;
|
||||
private List<SQLInterceptor> sqlInterceptors;
|
||||
private List<NamedTableInterceptor> namedTableInterceptors;
|
||||
private long ttl;
|
||||
private String logicDeleteColumn;
|
||||
private String logicDeleteValue;
|
||||
@@ -127,6 +129,11 @@ public class SQLModule extends HashMap<String, SQLModule> implements MagicModule
|
||||
this.sqlInterceptors = sqlInterceptors;
|
||||
}
|
||||
|
||||
@UnableCall
|
||||
public void setNamedTableInterceptors(List<NamedTableInterceptor> namedTableInterceptors) {
|
||||
this.namedTableInterceptors = namedTableInterceptors;
|
||||
}
|
||||
|
||||
@UnableCall
|
||||
public void setDataSourceNode(DataSourceNode dataSourceNode) {
|
||||
this.dataSourceNode = dataSourceNode;
|
||||
@@ -194,6 +201,7 @@ public class SQLModule extends HashMap<String, SQLModule> implements MagicModule
|
||||
sqlModule.setSqlInterceptors(this.sqlInterceptors);
|
||||
sqlModule.setLogicDeleteValue(this.logicDeleteValue);
|
||||
sqlModule.setLogicDeleteColumn(this.logicDeleteColumn);
|
||||
sqlModule.setNamedTableInterceptors(this.namedTableInterceptors);
|
||||
return sqlModule;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
package org.ssssssss.magicapi.modules.table;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.ssssssss.magicapi.context.RequestContext;
|
||||
import org.ssssssss.magicapi.exception.MagicAPIException;
|
||||
import org.ssssssss.magicapi.interceptor.NamedTableInterceptor;
|
||||
import org.ssssssss.magicapi.model.Attributes;
|
||||
import org.ssssssss.magicapi.model.Page;
|
||||
import org.ssssssss.magicapi.model.RequestEntity;
|
||||
import org.ssssssss.magicapi.model.SqlMode;
|
||||
import org.ssssssss.magicapi.modules.BoundSql;
|
||||
import org.ssssssss.magicapi.modules.SQLModule;
|
||||
import org.ssssssss.script.annotation.Comment;
|
||||
import org.ssssssss.script.annotation.UnableCall;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
@@ -18,7 +24,7 @@ import java.util.stream.Collectors;
|
||||
*
|
||||
* @author mxd
|
||||
*/
|
||||
public class NamedTable {
|
||||
public class NamedTable extends Attributes<Object> {
|
||||
|
||||
String tableName;
|
||||
|
||||
@@ -48,6 +54,8 @@ public class NamedTable {
|
||||
|
||||
boolean withBlank = false;
|
||||
|
||||
List<NamedTableInterceptor> namedTableInterceptors;
|
||||
|
||||
Where where = new Where(this);
|
||||
|
||||
public NamedTable(String tableName, SQLModule sqlModule, Function<String, String> rowMapColumnMapper) {
|
||||
@@ -92,7 +100,8 @@ public class NamedTable {
|
||||
namedTable.defaultPrimaryValue = this.defaultPrimaryValue;
|
||||
namedTable.useLogic = this.useLogic;
|
||||
namedTable.withBlank = this.withBlank;
|
||||
namedTable.where = new Where(namedTable);
|
||||
namedTable.where = this.where == null ? null : this.where.clone();
|
||||
namedTable.namedTableInterceptors = this.namedTableInterceptors;
|
||||
return namedTable;
|
||||
}
|
||||
|
||||
@@ -211,20 +220,6 @@ public class NamedTable {
|
||||
return this;
|
||||
}
|
||||
|
||||
private Collection<Map.Entry<String, Object>> filterNotBlanks() {
|
||||
if (this.withBlank) {
|
||||
return this.columns.entrySet()
|
||||
.stream()
|
||||
.filter(it -> !excludeColumns.contains(it.getKey()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return this.columns.entrySet()
|
||||
.stream()
|
||||
.filter(it -> StringUtils.isNotBlank(Objects.toString(it.getValue(), "")))
|
||||
.filter(it -> !excludeColumns.contains(it.getKey()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Comment("执行插入,返回主键")
|
||||
public Object insert() {
|
||||
return insert(null);
|
||||
@@ -242,6 +237,7 @@ public class NamedTable {
|
||||
this.columns.put(this.primary, this.defaultPrimaryValue);
|
||||
}
|
||||
}
|
||||
preHandle(SqlMode.INSERT);
|
||||
Collection<Map.Entry<String, Object>> entries = filterNotBlanks();
|
||||
if (entries.isEmpty()) {
|
||||
throw new MagicAPIException("参数不能为空");
|
||||
@@ -259,6 +255,7 @@ public class NamedTable {
|
||||
|
||||
@Comment("执行delete语句")
|
||||
public int delete() {
|
||||
preHandle(SqlMode.DELETE);
|
||||
if (useLogic) {
|
||||
Map<String, Object> dataMap = new HashMap<>();
|
||||
dataMap.put(logicDeleteColumn, logicDeleteValue);
|
||||
@@ -321,62 +318,25 @@ public class NamedTable {
|
||||
|
||||
@Comment("执行`select`查询")
|
||||
public List<Map<String, Object>> select() {
|
||||
preHandle(SqlMode.SELECT);
|
||||
return sqlModule.select(buildSelect());
|
||||
}
|
||||
|
||||
@Comment("执行`selectOne`查询")
|
||||
public Map<String, Object> selectOne() {
|
||||
preHandle(SqlMode.SELECT_ONE);
|
||||
return sqlModule.selectOne(buildSelect());
|
||||
}
|
||||
|
||||
private BoundSql buildSelect() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("select ");
|
||||
List<String> fields = this.fields.stream()
|
||||
.filter(it -> !excludeColumns.contains(it))
|
||||
.collect(Collectors.toList());
|
||||
if (fields.isEmpty()) {
|
||||
builder.append("*");
|
||||
} else {
|
||||
builder.append(StringUtils.join(fields, ","));
|
||||
}
|
||||
builder.append(" from ").append(tableName);
|
||||
List<Object> params = buildWhere(builder);
|
||||
if (!orders.isEmpty()) {
|
||||
builder.append(" order by ");
|
||||
builder.append(String.join(",", orders));
|
||||
}
|
||||
if (!groups.isEmpty()) {
|
||||
builder.append(" group by ");
|
||||
builder.append(String.join(",", groups));
|
||||
}
|
||||
BoundSql boundSql = new BoundSql(builder.toString(), params, sqlModule);
|
||||
boundSql.setExcludeColumns(excludeColumns);
|
||||
return boundSql;
|
||||
}
|
||||
|
||||
private List<Object> buildWhere(StringBuilder builder) {
|
||||
List<Object> params = new ArrayList<>();
|
||||
if (!where.isEmpty()) {
|
||||
where.and();
|
||||
where.ne(useLogic, logicDeleteColumn, logicDeleteValue);
|
||||
builder.append(where.getSql());
|
||||
params.addAll(where.getParams());
|
||||
} else if (useLogic) {
|
||||
where.ne(logicDeleteColumn, logicDeleteValue);
|
||||
builder.append(where.getSql());
|
||||
params.addAll(where.getParams());
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
@Comment("执行分页查询")
|
||||
public Object page() {
|
||||
preHandle(SqlMode.PAGE);
|
||||
return sqlModule.page(buildSelect());
|
||||
}
|
||||
|
||||
@Comment("执行分页查询,分页条件手动传入")
|
||||
public Object page(@Comment("限制条数") long limit, @Comment("跳过条数") long offset) {
|
||||
preHandle(SqlMode.PAGE);
|
||||
return sqlModule.page(buildSelect(), new Page(limit, offset));
|
||||
}
|
||||
|
||||
@@ -395,6 +355,7 @@ public class NamedTable {
|
||||
primaryValue = this.columns.remove(this.primary);
|
||||
}
|
||||
this.withBlank = isUpdateBlank;
|
||||
preHandle(SqlMode.UPDATE);
|
||||
List<Map.Entry<String, Object>> entries = new ArrayList<>(filterNotBlanks());
|
||||
if (entries.isEmpty()) {
|
||||
throw new MagicAPIException("要修改的列不能为空");
|
||||
@@ -431,6 +392,7 @@ public class NamedTable {
|
||||
|
||||
@Comment("查询条数")
|
||||
public int count() {
|
||||
preHandle(SqlMode.COUNT);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("select count(1) from ").append(tableName);
|
||||
List<Object> params = buildWhere(builder);
|
||||
@@ -442,4 +404,254 @@ public class NamedTable {
|
||||
return count() > 0;
|
||||
}
|
||||
|
||||
private Collection<Map.Entry<String, Object>> filterNotBlanks() {
|
||||
if (this.withBlank) {
|
||||
return this.columns.entrySet()
|
||||
.stream()
|
||||
.filter(it -> !excludeColumns.contains(it.getKey()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return this.columns.entrySet()
|
||||
.stream()
|
||||
.filter(it -> StringUtils.isNotBlank(Objects.toString(it.getValue(), "")))
|
||||
.filter(it -> !excludeColumns.contains(it.getKey()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void preHandle(SqlMode sqlMode){
|
||||
if(this.namedTableInterceptors != null){
|
||||
this.namedTableInterceptors.forEach(interceptor -> interceptor.preHandle(sqlMode, this));
|
||||
}
|
||||
}
|
||||
|
||||
private BoundSql buildSelect() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("select ");
|
||||
List<String> fields = this.fields.stream()
|
||||
.filter(it -> !excludeColumns.contains(it))
|
||||
.collect(Collectors.toList());
|
||||
if (fields.isEmpty()) {
|
||||
builder.append("*");
|
||||
} else {
|
||||
builder.append(StringUtils.join(fields, ","));
|
||||
}
|
||||
builder.append(" from ").append(tableName);
|
||||
List<Object> params = buildWhere(builder);
|
||||
if (!orders.isEmpty()) {
|
||||
builder.append(" order by ");
|
||||
builder.append(String.join(",", orders));
|
||||
}
|
||||
if (!groups.isEmpty()) {
|
||||
builder.append(" group by ");
|
||||
builder.append(String.join(",", groups));
|
||||
}
|
||||
BoundSql boundSql = new BoundSql(builder.toString(), params, sqlModule);
|
||||
boundSql.setExcludeColumns(excludeColumns);
|
||||
return boundSql;
|
||||
}
|
||||
|
||||
|
||||
private List<Object> buildWhere(StringBuilder builder) {
|
||||
List<Object> params = new ArrayList<>();
|
||||
if (!where.isEmpty()) {
|
||||
where.and();
|
||||
where.ne(useLogic, logicDeleteColumn, logicDeleteValue);
|
||||
builder.append(where.getSql());
|
||||
params.addAll(where.getParams());
|
||||
} else if (useLogic) {
|
||||
where.ne(logicDeleteColumn, logicDeleteValue);
|
||||
builder.append(where.getSql());
|
||||
params.addAll(where.getParams());
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取查询的表名
|
||||
* @return 表名
|
||||
*/
|
||||
@UnableCall
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取SQL模块
|
||||
*
|
||||
*/
|
||||
@UnableCall
|
||||
public SQLModule getSqlModule() {
|
||||
return sqlModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主键列
|
||||
*/
|
||||
@UnableCall
|
||||
public String getPrimary() {
|
||||
return primary;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取逻辑删除列
|
||||
*/
|
||||
@UnableCall
|
||||
public String getLogicDeleteColumn() {
|
||||
return logicDeleteColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取逻辑删除值
|
||||
*/
|
||||
@UnableCall
|
||||
public Object getLogicDeleteValue() {
|
||||
return logicDeleteValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设置的columns
|
||||
*/
|
||||
@UnableCall
|
||||
public Map<String, Object> getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设置的fields
|
||||
*/
|
||||
@UnableCall
|
||||
public List<String> getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设置的group
|
||||
*/
|
||||
@UnableCall
|
||||
public List<String> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设置的order
|
||||
*/
|
||||
@UnableCall
|
||||
public List<String> getOrders() {
|
||||
return orders;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设置的排除的列
|
||||
*/
|
||||
@UnableCall
|
||||
public Set<String> getExcludeColumns() {
|
||||
return excludeColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* 主键默认值
|
||||
* @return
|
||||
*/
|
||||
@UnableCall
|
||||
public Object getDefaultPrimaryValue() {
|
||||
return defaultPrimaryValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否设逻辑了逻辑删除
|
||||
*/
|
||||
@UnableCall
|
||||
public boolean isUseLogic() {
|
||||
return useLogic;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取是否不过滤空参数
|
||||
*/
|
||||
@UnableCall
|
||||
public boolean isWithBlank() {
|
||||
return withBlank;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取where
|
||||
*/
|
||||
@UnableCall
|
||||
public Where getWhere() {
|
||||
return where;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置表名
|
||||
* @param tableName 表名
|
||||
*/
|
||||
@UnableCall
|
||||
public void setTableName(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置columns
|
||||
*/
|
||||
@UnableCall
|
||||
public void setColumns(Map<String, Object> columns) {
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 fields
|
||||
*/
|
||||
@UnableCall
|
||||
public void setFields(List<String> fields) {
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 group
|
||||
*/
|
||||
@UnableCall
|
||||
public void setGroups(List<String> groups) {
|
||||
this.groups = groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 order
|
||||
*/
|
||||
@UnableCall
|
||||
public void setOrders(List<String> orders) {
|
||||
this.orders = orders;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置排除的列
|
||||
*/
|
||||
@UnableCall
|
||||
public void setExcludeColumns(Set<String> excludeColumns) {
|
||||
this.excludeColumns = excludeColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否使用逻辑删除
|
||||
*/
|
||||
@UnableCall
|
||||
public void setUseLogic(boolean useLogic) {
|
||||
this.useLogic = useLogic;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否不过滤空参数
|
||||
*/
|
||||
@UnableCall
|
||||
public void setWithBlank(boolean withBlank) {
|
||||
this.withBlank = withBlank;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取RequestEntity
|
||||
*/
|
||||
@UnableCall
|
||||
public RequestEntity getRequestEntity() {
|
||||
return RequestContext.getRequestEntity();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user