Commit 02897568 authored by liang.tang's avatar liang.tang
Browse files

magic-api

parents
Pipeline #222 failed with stages
in 0 seconds
package org.ssssssss.magicapi.modules.db.provider;
/**
* 帕斯卡命名转换
*
* @author mxd
*/
public class PascalColumnMapperProvider implements ColumnMapperProvider {
@Override
public String name() {
return "pascal";
}
@Override
public String mapping(String columnName) {
if (columnName == null) {
return null;
}
columnName = columnName.toLowerCase();
boolean upperCase = false;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < columnName.length(); i++) {
char ch = columnName.charAt(i);
if (ch == '_') {
upperCase = true;
} else if (upperCase || i == 0) {
sb.append(Character.toUpperCase(ch));
upperCase = false;
} else {
sb.append(ch);
}
}
return sb.toString();
}
@Override
public String unmapping(String name) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < name.length(); i++) {
char ch = name.charAt(i);
if (i > 0 && Character.isUpperCase(ch)) {
sb.append("_");
}
sb.append(Character.toLowerCase(ch));
}
return sb.toString();
}
}
package org.ssssssss.magicapi.modules.db.provider;
/**
* 全大写命名
*
* @author mxd
*/
public class UpperColumnMapperProvider implements ColumnMapperProvider {
@Override
public String name() {
return "upper";
}
@Override
public String mapping(String columnName) {
return columnName == null ? null : columnName.toUpperCase();
}
}
package org.ssssssss.magicapi.modules.db.table;
import org.apache.commons.lang3.StringUtils;
import org.ssssssss.magicapi.core.context.RequestContext;
import org.ssssssss.magicapi.core.exception.MagicAPIException;
import org.ssssssss.magicapi.core.model.Attributes;
import org.ssssssss.magicapi.core.context.RequestEntity;
import org.ssssssss.magicapi.modules.db.BoundSql;
import org.ssssssss.magicapi.modules.db.inteceptor.NamedTableInterceptor;
import org.ssssssss.magicapi.modules.db.SQLModule;
import org.ssssssss.magicapi.modules.db.model.Page;
import org.ssssssss.magicapi.modules.db.model.SqlMode;
import org.ssssssss.script.annotation.Comment;
import org.ssssssss.script.runtime.RuntimeContext;
import java.beans.Transient;
import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* 单表操作API
*
* @author mxd
*/
public class NamedTable extends Attributes<Object> {
String tableName;
SQLModule sqlModule;
String primary;
String logicDeleteColumn;
Object logicDeleteValue;
Map<String, Object> columns = new HashMap<>();
List<String> fields = new ArrayList<>();
List<String> groups = new ArrayList<>();
List<String> orders = new ArrayList<>();
Set<String> excludeColumns = new HashSet<>();
Function<String, String> rowMapColumnMapper;
Object defaultPrimaryValue;
boolean useLogic = false;
boolean withBlank = false;
List<NamedTableInterceptor> namedTableInterceptors;
Where where = new Where(this);
public NamedTable(String tableName, SQLModule sqlModule, Function<String, String> rowMapColumnMapper, List<NamedTableInterceptor> namedTableInterceptors) {
this.tableName = tableName;
this.sqlModule = sqlModule;
this.rowMapColumnMapper = rowMapColumnMapper;
this.namedTableInterceptors = namedTableInterceptors;
this.logicDeleteColumn = sqlModule.getLogicDeleteColumn();
String deleteValue = sqlModule.getLogicDeleteValue();
this.logicDeleteValue = deleteValue;
if (deleteValue != null) {
boolean isString = deleteValue.startsWith("'") || deleteValue.startsWith("\"");
if (isString && deleteValue.length() > 2) {
this.logicDeleteValue = deleteValue.substring(1, deleteValue.length() - 1);
} else {
try {
this.logicDeleteValue = Integer.parseInt(deleteValue);
} catch (NumberFormatException e) {
this.logicDeleteValue = deleteValue;
}
}
}
}
private NamedTable() {
}
@Override
@Comment("克隆")
public NamedTable clone() {
NamedTable namedTable = new NamedTable();
namedTable.tableName = this.tableName;
namedTable.sqlModule = this.sqlModule;
namedTable.primary = this.primary;
namedTable.logicDeleteValue = this.logicDeleteValue;
namedTable.logicDeleteColumn = this.logicDeleteColumn;
namedTable.columns = new HashMap<>(this.columns);
namedTable.fields = new ArrayList<>(fields);
namedTable.groups = new ArrayList<>(groups);
namedTable.orders = new ArrayList<>(orders);
namedTable.excludeColumns = new HashSet<>(excludeColumns);
namedTable.rowMapColumnMapper = this.rowMapColumnMapper;
namedTable.defaultPrimaryValue = this.defaultPrimaryValue;
namedTable.useLogic = this.useLogic;
namedTable.withBlank = this.withBlank;
namedTable.where = this.where == null ? null : this.where.clone();
namedTable.namedTableInterceptors = this.namedTableInterceptors;
namedTable.properties = this.properties;
return namedTable;
}
@Comment("使用逻辑删除")
public NamedTable logic() {
this.useLogic = true;
return this;
}
@Comment("更新空值")
public NamedTable withBlank() {
this.withBlank = true;
return this;
}
@Comment("设置主键名,update时使用")
public NamedTable primary(@Comment(name = "primary", value = "主键列") String primary) {
this.primary = rowMapColumnMapper.apply(primary);
return this;
}
@Comment("设置主键名,并设置默认主键值(主要用于insert)")
public NamedTable primary(@Comment(name = "primary", value = "主键列") String primary,
@Comment(name = "defaultPrimaryValue", value = "默认值") Serializable defaultPrimaryValue) {
this.primary = rowMapColumnMapper.apply(primary);
this.defaultPrimaryValue = defaultPrimaryValue;
return this;
}
@Comment("设置主键名,并设置默认主键值(主要用于insert)")
public NamedTable primary(@Comment(name = "primary", value = "主键列") String primary,
@Comment(name = "defaultPrimaryValue", value = "默认值") Supplier<Object> defaultPrimaryValue) {
this.primary = rowMapColumnMapper.apply(primary);
this.defaultPrimaryValue = defaultPrimaryValue;
return this;
}
@Comment("拼接where")
public Where where() {
return where;
}
@Comment("设置单列的值")
public NamedTable column(@Comment(name = "property", value = "列名") String property,
@Comment(name = "value", value = "值") Object value) {
this.columns.put(rowMapColumnMapper.apply(property), value);
return this;
}
@Comment("设置查询的列,如`columns('a','b','c')`")
public NamedTable columns(@Comment(name = "properties", value = "各项列") String... properties) {
if (properties != null) {
for (String property : properties) {
column(property);
}
}
return this;
}
@Comment("设置要排除的列")
public NamedTable exclude(@Comment(name = "property", value = "排除的列") String property) {
if (property != null) {
excludeColumns.add(property);
}
return this;
}
@Comment("设置要排除的列")
public NamedTable excludes(@Comment(name = "properties", value = "排除的列") String... properties) {
if (columns != null) {
excludeColumns.addAll(Arrays.asList(properties));
}
return this;
}
@Comment("设置要排除的列")
public NamedTable excludes(@Comment(name = "properties", value = "排除的列") List<String> properties) {
if (columns != null) {
excludeColumns.addAll(properties);
}
return this;
}
@Comment("设置查询的列,如`columns(['a','b','c'])`")
public NamedTable columns(@Comment(name = "properties", value = "查询的列") Collection<String> properties) {
if (properties != null) {
properties.stream().filter(StringUtils::isNotBlank).map(rowMapColumnMapper).forEach(this.fields::add);
}
return this;
}
@Comment("设置查询的列,如`column('a')`")
public NamedTable column(@Comment(name = "property", value = "查询的列") String property) {
if (StringUtils.isNotBlank(property)) {
this.fields.add(this.rowMapColumnMapper.apply(property));
}
return this;
}
@Comment("拼接`order by xxx asc/desc`")
public NamedTable orderBy(@Comment(name = "property", value = "要排序的列") String property,
@Comment(name = "sort", value = "`asc`或`desc`") String sort) {
this.orders.add(rowMapColumnMapper.apply(property) + " " + sort);
return this;
}
@Comment("拼接`order by xxx asc`")
public NamedTable orderBy(@Comment(name = "property", value = "要排序的列") String property) {
return orderBy(property, "asc");
}
@Comment("拼接`order by xxx desc`")
public NamedTable orderByDesc(@Comment(name = "property", value = "要排序的列") String property) {
return orderBy(property, "desc");
}
@Comment("拼接`group by`")
public NamedTable groupBy(@Comment(name = "properties", value = "要分组的列") String... properties) {
this.groups.addAll(Arrays.stream(properties).map(rowMapColumnMapper).collect(Collectors.toList()));
return this;
}
@Comment("执行插入,返回主键")
public Object insert(RuntimeContext runtimeContext) {
return insert(runtimeContext, null);
}
@Comment("执行插入,返回主键")
public Object insert(RuntimeContext runtimeContext,
@Comment(name = "data", value = "各项列和值") Map<String, Object> data) {
if (data != null) {
data.forEach((key, value) -> this.columns.put(rowMapColumnMapper.apply(key), value));
}
if (this.defaultPrimaryValue != null && StringUtils.isBlank(Objects.toString(this.columns.getOrDefault(this.primary, "")))) {
if (this.defaultPrimaryValue instanceof Supplier) {
this.columns.put(this.primary, ((Supplier<?>) this.defaultPrimaryValue).get());
} else {
this.columns.put(this.primary, this.defaultPrimaryValue);
}
}
preHandle(SqlMode.INSERT);
Collection<Map.Entry<String, Object>> entries = filterNotBlanks();
if (entries.isEmpty()) {
throw new MagicAPIException("参数不能为空");
}
StringBuilder builder = new StringBuilder();
builder.append("insert into ");
builder.append(tableName);
builder.append("(");
builder.append(StringUtils.join(entries.stream().map(Map.Entry::getKey).toArray(), ","));
builder.append(") values (");
builder.append(StringUtils.join(Collections.nCopies(entries.size(), "?"), ","));
builder.append(")");
Object value = sqlModule.insert(new BoundSql(runtimeContext, builder.toString(), entries.stream().map(Map.Entry::getValue).collect(Collectors.toList()), sqlModule), this.primary);
if(value == null && StringUtils.isNotBlank(this.primary)){
return this.columns.get(this.primary);
}
return value;
}
@Comment("执行delete语句")
public int delete(RuntimeContext runtimeContext) {
preHandle(SqlMode.DELETE);
if (useLogic) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put(logicDeleteColumn, logicDeleteValue);
return update(runtimeContext, dataMap);
}
if (where.isEmpty()) {
throw new MagicAPIException("delete语句不能没有条件");
}
StringBuilder builder = new StringBuilder();
builder.append("delete from ");
builder.append(tableName);
builder.append(where.getSql());
return sqlModule.update(new BoundSql(runtimeContext, builder.toString(), where.getParams(), sqlModule));
}
@Comment("保存到表中,当主键有值时则修改,否则插入")
public Object save(RuntimeContext runtimeContext) {
return this.save(runtimeContext, null, false);
}
@Comment("保存到表中,当主键有值时则修改,否则插入")
public Object save(RuntimeContext runtimeContext,
@Comment(name = "data", value = "各项列和值") Map<String, Object> data,
@Comment(name = "beforeQuery", value = "是否根据id查询有没有数据") boolean beforeQuery) {
if (StringUtils.isBlank(this.primary)) {
throw new MagicAPIException("请设置主键");
}
if (data != null) {
data.forEach((key, value) -> this.columns.put(rowMapColumnMapper.apply(key), value));
}
String primaryValue = Objects.toString(this.columns.get(this.primary), "");
if (StringUtils.isBlank(primaryValue) && data != null) {
primaryValue = Objects.toString(data.get(this.primary), "");
}
if (beforeQuery) {
if (StringUtils.isNotBlank(primaryValue)) {
List<Object> params = new ArrayList<>();
params.add(primaryValue);
Integer count = sqlModule.selectInt(new BoundSql(runtimeContext, "select count(*) count from " + this.tableName + " where " + this.primary + " = ?", params, sqlModule));
if (count == 0) {
return insert(runtimeContext, data);
}
return update(runtimeContext, data);
} else {
return insert(runtimeContext, data);
}
}
if (StringUtils.isNotBlank(primaryValue)) {
return update(runtimeContext, data);
}
return insert(runtimeContext, data);
}
@Comment("保存到表中,当主键有值时则修改,否则插入")
public Object save(RuntimeContext runtimeContext,
@Comment(name = "beforeQuery", value = "是否根据id查询有没有数据") boolean beforeQuery) {
return this.save(runtimeContext, null, beforeQuery);
}
@Comment("保存到表中,当主键有值时则修改,否则插入")
public Object save(RuntimeContext runtimeContext,
@Comment(name = "data", value = "各项列和值") Map<String, Object> data) {
return this.save(runtimeContext, data, false);
}
@Comment("批量插入")
public int batchInsert(@Comment(name = "collection", value = "各项列和值") Collection<Map<String, Object>> collection, @Comment("batchSize") int batchSize) {
Set<String> keys = collection.stream().flatMap(it -> it.keySet().stream()).collect(Collectors.toSet());
if (keys.isEmpty()) {
throw new MagicAPIException("要插入的列不能为空");
}
StringBuilder builder = new StringBuilder();
builder.append("insert into ");
builder.append(tableName);
builder.append("(");
builder.append(StringUtils.join(keys.stream().map(rowMapColumnMapper).collect(Collectors.toList()), ","));
builder.append(") values (");
builder.append(StringUtils.join(Collections.nCopies(keys.size(), "?"), ","));
builder.append(")");
return this.sqlModule.batchUpdate(builder.toString(), batchSize, collection.stream()
.map(it -> keys.stream().map(it::get).toArray())
.collect(Collectors.toList()));
}
@Comment("批量插入")
public int batchInsert(@Comment(name = "collection", value = "各项列和值") Collection<Map<String, Object>> collection) {
return batchInsert(collection, 100);
}
@Comment("执行`select`查询")
public List<Map<String, Object>> select(RuntimeContext runtimeContext) {
preHandle(SqlMode.SELECT);
return sqlModule.select(buildSelect(runtimeContext));
}
@Comment("执行`selectOne`查询")
public Map<String, Object> selectOne(RuntimeContext runtimeContext) {
preHandle(SqlMode.SELECT_ONE);
return sqlModule.selectOne(buildSelect(runtimeContext));
}
@Comment("执行分页查询")
public Object page(RuntimeContext runtimeContext) {
preHandle(SqlMode.PAGE);
return sqlModule.page(buildSelect(runtimeContext));
}
@Comment("执行分页查询,分页条件手动传入")
public Object page(RuntimeContext runtimeContext,
@Comment(name = "limit", value = "限制条数") long limit,
@Comment(name = "offset", value = "跳过条数") long offset) {
preHandle(SqlMode.PAGE);
return sqlModule.page(buildSelect(runtimeContext), new Page(limit, offset));
}
@Comment("执行update语句")
public int update(RuntimeContext runtimeContext) {
return update(runtimeContext, null);
}
@Comment("执行update语句")
public int update(RuntimeContext runtimeContext,
@Comment(name = "data", value = "各项列和值") Map<String, Object> data,
@Comment(name = "isUpdateBlank", value = "是否更新空值字段") boolean isUpdateBlank) {
if (null != data) {
data.forEach((key, value) -> this.columns.put(rowMapColumnMapper.apply(key), value));
}
preHandle(SqlMode.UPDATE);
Object primaryValue = null;
if (StringUtils.isNotBlank(this.primary)) {
primaryValue = this.columns.remove(this.primary);
}
this.withBlank = isUpdateBlank;
List<Map.Entry<String, Object>> entries = new ArrayList<>(filterNotBlanks());
if (entries.isEmpty()) {
throw new MagicAPIException("要修改的列不能为空");
}
StringBuilder builder = new StringBuilder();
builder.append("update ");
builder.append(tableName);
builder.append(" set ");
List<Object> params = new ArrayList<>();
for (int i = 0, size = entries.size(); i < size; i++) {
Map.Entry<String, Object> entry = entries.get(i);
builder.append(entry.getKey()).append(" = ?");
params.add(entry.getValue());
if (i + 1 < size) {
builder.append(",");
}
}
if (!where.isEmpty()) {
builder.append(where.getSql());
params.addAll(where.getParams());
} else if (primaryValue != null) {
builder.append(" where ").append(this.primary).append(" = ?");
params.add(primaryValue);
} else {
throw new MagicAPIException("主键值不能为空");
}
return sqlModule.update(new BoundSql(runtimeContext, builder.toString(), params, sqlModule));
}
@Comment("执行update语句")
public int update(RuntimeContext runtimeContext,
@Comment(name = "data", value = "各项列和值") Map<String, Object> data) {
return update(runtimeContext, data, this.withBlank);
}
@Comment("查询条数")
public int count(RuntimeContext runtimeContext) {
preHandle(SqlMode.COUNT);
StringBuilder builder = new StringBuilder();
builder.append("select count(1) from ").append(tableName);
List<Object> params = buildWhere(builder);
return sqlModule.selectInt(new BoundSql(runtimeContext, builder.toString(), params, sqlModule));
}
@Comment("判断是否存在")
public boolean exists(RuntimeContext runtimeContext) {
return count(runtimeContext) > 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(RuntimeContext runtimeContext) {
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 (!groups.isEmpty()) {
builder.append(" group by ");
builder.append(String.join(",", groups));
}
if (!orders.isEmpty()) {
builder.append(" order by ");
builder.append(String.join(",", orders));
}
BoundSql boundSql = new BoundSql(runtimeContext, 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 表名
*/
@Transient
public String getTableName() {
return tableName;
}
/**
* 设置表名
*
* @param tableName 表名
*/
@Transient
public void setTableName(String tableName) {
this.tableName = tableName;
}
/**
* 获取SQL模块
*/
@Transient
public SQLModule getSqlModule() {
return sqlModule;
}
/**
* 获取主键列
*/
@Transient
public String getPrimary() {
return primary;
}
/**
* 获取逻辑删除列
*/
@Transient
public String getLogicDeleteColumn() {
return logicDeleteColumn;
}
/**
* 获取逻辑删除值
*/
@Transient
public Object getLogicDeleteValue() {
return logicDeleteValue;
}
/**
* 获取设置的columns
*/
@Transient
public Map<String, Object> getColumns() {
return columns;
}
/**
* 设置columns
*/
@Transient
public void setColumns(Map<String, Object> columns) {
this.columns = columns;
}
/**
* 获取设置的fields
*/
@Transient
public List<String> getFields() {
return fields;
}
/**
* 设置 fields
*/
@Transient
public void setFields(List<String> fields) {
this.fields = fields;
}
/**
* 获取设置的group
*/
@Transient
public List<String> getGroups() {
return groups;
}
/**
* 设置 group
*/
@Transient
public void setGroups(List<String> groups) {
this.groups = groups;
}
/**
* 获取设置的order
*/
@Transient
public List<String> getOrders() {
return orders;
}
/**
* 设置 order
*/
@Transient
public void setOrders(List<String> orders) {
this.orders = orders;
}
/**
* 获取设置的排除的列
*/
@Transient
public Set<String> getExcludeColumns() {
return excludeColumns;
}
/**
* 设置排除的列
*/
@Transient
public void setExcludeColumns(Set<String> excludeColumns) {
this.excludeColumns = excludeColumns;
}
/**
* 主键默认值
*
* @return
*/
@Transient
public Object getDefaultPrimaryValue() {
return defaultPrimaryValue;
}
/**
* 是否设逻辑了逻辑删除
*/
@Transient
public boolean isUseLogic() {
return useLogic;
}
/**
* 设置是否使用逻辑删除
*/
@Transient
public void setUseLogic(boolean useLogic) {
this.useLogic = useLogic;
}
/**
* 获取是否不过滤空参数
*/
@Transient
public boolean isWithBlank() {
return withBlank;
}
/**
* 设置是否不过滤空参数
*/
@Transient
public void setWithBlank(boolean withBlank) {
this.withBlank = withBlank;
}
/**
* 获取where
*/
@Transient
public Where getWhere() {
return where;
}
/**
* 获取RequestEntity
*/
@Transient
public RequestEntity getRequestEntity() {
return RequestContext.getRequestEntity();
}
}
package org.ssssssss.magicapi.modules.db.table;
import org.apache.commons.lang3.StringUtils;
import org.ssssssss.script.annotation.Comment;
import org.ssssssss.script.functions.StreamExtension;
import org.ssssssss.script.runtime.RuntimeContext;
import java.beans.Transient;
import java.util.*;
import java.util.function.Function;
/**
* 单表API的Where
*
* @author mxd
*/
public class Where {
private final List<String> tokens = new ArrayList<>();
private final List<Object> params = new ArrayList<>();
private final NamedTable namedTable;
private final boolean needWhere;
private boolean notNull = false;
private boolean notBlank = false;
public Where(NamedTable namedTable) {
this(namedTable, true);
}
public Where(NamedTable namedTable, boolean needWhere) {
this.namedTable = namedTable;
this.needWhere = needWhere;
}
@Override
@Comment("克隆")
public Where clone() {
Where where = new Where(this.namedTable, this.needWhere);
where.tokens.addAll(this.tokens);
where.params.addAll(this.params);
where.notNull = this.notNull;
where.notBlank = this.notBlank;
return where;
}
@Comment("过滤`null`的参数")
public Where notNull() {
return notNull(true);
}
@Comment("过滤`blank`的参数")
public Where notBlank() {
return notBlank(true);
}
@Comment("是否过滤`null`的参数")
public Where notNull(boolean flag) {
this.notNull = flag;
return this;
}
@Comment("是否过滤`blank`的参数")
public Where notBlank(boolean flag) {
this.notBlank = flag;
return this;
}
@Comment("等于`=`,如:`eq('name', '老王') ---> name = '老王'`")
public Where eq(@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return eq(true, column, value);
}
@Comment("等于`=`,如:`eq('name', '老王') ---> name = '老王'`")
public Where eq(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
if (condition && filterNullAndBlank(value)) {
tokens.add(namedTable.rowMapColumnMapper.apply(column));
if (value == null) {
append(" is null");
} else {
params.add(value);
append(" = ?");
}
appendAnd();
}
return this;
}
@Comment("不等于`<>`,如:`ne('name', '老王') ---> name <> '老王'`")
public Where ne(@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return ne(true, column, value);
}
@Comment("不等于`<>`,如:`ne('name', '老王') ---> name <> '老王'`")
public Where ne(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
if (condition && filterNullAndBlank(value)) {
append(namedTable.rowMapColumnMapper.apply(column));
if (value == null) {
append("is not null");
} else {
params.add(value);
append("<> ?");
}
appendAnd();
}
return this;
}
@Comment("小于`<`,如:`lt('age', 18) ---> age < 18")
public Where lt(@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return lt(true, column, value);
}
@Comment("小于`<`,如:`lt('age', 18) ---> age < 18")
public Where lt(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return append(condition, column, " < ?", value);
}
@Comment("小于等于`<=`,如:`lte('age', 18) ---> age <= 18")
public Where lte(@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return lte(true, column, value);
}
@Comment("小于等于`<=`,如:`lte('age', 18) ---> age <= 18")
public Where lte(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return append(condition, column, " <= ?", value);
}
@Comment("大于`>`,如:`get('age', 18) ---> age > 18")
public Where gt(@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return gt(true, column, value);
}
@Comment("大于`>`,如:`get('age', 18) ---> age > 18")
public Where gt(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return append(condition, column, " > ?", value);
}
@Comment("大于等于`>=`,如:`get('age', 18) ---> age >= 18")
public Where gte(@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return gte(true, column, value);
}
@Comment("大于等于`>=`,如:`get('age', 18) ---> age >= 18")
public Where gte(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return append(condition, column, " >= ?", value);
}
@Comment("`in`,如:`in('age', [1,2,3]) ---> age in (1,2,3)")
public Where in(@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return in(true, column, value);
}
@Comment("`in`,如:`in('age', [1,2,3]) ---> age in (1,2,3)")
public Where in(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
if (condition && value != null) {
List<Object> objects = StreamExtension.arrayLikeToList(value);
if (objects.size() > 0) {
append(namedTable.rowMapColumnMapper.apply(column));
append(" in (");
append(String.join(",", Collections.nCopies(objects.size(), "?")));
append(")");
appendAnd();
params.addAll(objects);
}
}
return this;
}
@Comment("`not in`,如:`notIn('age', [1,2,3]) ---> age not in (1,2,3)")
public Where notIn(@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return notIn(true, column, value);
}
@Comment("`not in`,如:`notIn('age', [1,2,3]) ---> age not in (1,2,3)")
public Where notIn(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
if (condition && value != null) {
List<Object> objects = StreamExtension.arrayLikeToList(value);
if (objects.size() > 0) {
append(namedTable.rowMapColumnMapper.apply(column));
append("not in (");
append(String.join(",", Collections.nCopies(objects.size(), "?")));
append(")");
appendAnd();
params.addAll(objects);
}
}
return this;
}
@Comment("`like`,如:`like('name', '%王%') ---> name like '%王%'")
public Where like(@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return like(true, column, value);
}
@Comment("`like`,如:`like('name', '%王%') ---> name like '%王%'")
public Where like(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return append(condition, column, "like ?", value);
}
@Comment("`not like`,如:`notLike('name', '%王%') ---> name not like '%王%'")
public Where notLike(@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return notLike(true, column, value);
}
@Comment("`not like` ,如:`notLike('name', '%王%') ---> name not like '%王%'")
public Where notLike(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "column", value = "数据库中的列名") String column,
@Comment(name = "value", value = "值") Object value) {
return append(condition, column, "not like ?", value);
}
@Comment("`is null`,如:`isNull('name') ---> name is null")
public Where isNull(@Comment(name = "column", value = "数据库中的列名") String column) {
return isNull(true, column);
}
@Comment("`is null`,如:`isNull('name') ---> name is null")
public Where isNull(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "column", value = "数据库中的列名") String column) {
if (condition) {
append(namedTable.rowMapColumnMapper.apply(column));
append("is null");
appendAnd();
}
return this;
}
@Comment("`is not null`,如:`isNotNull('name') ---> name is not null")
public Where isNotNull(@Comment(name = "column", value = "数据库中的列名") String column) {
return isNotNull(true, column);
}
@Comment("`is not null`,如:`isNotNull('name') ---> name is not null")
public Where isNotNull(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "column", value = "数据库中的列名") String column) {
if (condition) {
append(namedTable.rowMapColumnMapper.apply(column));
append("is not null");
appendAnd();
}
return this;
}
@Comment("拼接`or`")
public Where or() {
appendOr();
return this;
}
@Comment("拼接`and`")
public Where and() {
appendAnd();
return this;
}
@Comment("`and`嵌套,如and(it => it.eq('name','李白').ne('status','正常') --> and (name = '李白' and status <> '正常')")
public Where and(@Comment(name = "function", value = "回调函数") Function<Object[], Where> function) {
return and(true, function);
}
@Comment("`and`嵌套,如and(it => it.eq('name','李白').ne('status','正常') --> and (name = '李白' and status <> '正常')")
public Where and(@Comment(name = "condition", value = "判断表达式,当为true时拼接条件") boolean condition,
@Comment(name = "function", value = "回调函数") Function<Object[], Where> function) {
if (condition) {
Where expr = function.apply(new Object[]{new Where(this.namedTable, false)});
this.params.addAll(expr.params);
append("(");
append(expr.getSql());
append(")");
appendAnd();
}
return this;
}
@Comment("拼接`order by xxx asc/desc`")
public Where orderBy(@Comment(name = "column", value = "要排序的列") String column,
@Comment(name = "sort", value = "`asc`或`desc`") String sort) {
this.namedTable.orderBy(column, sort);
return this;
}
@Comment("拼接`order by xxx asc`")
public Where orderBy(@Comment(name = "column", value = "要排序的列") String column) {
return orderBy(column, "asc");
}
@Comment("拼接`order by xxx desc`")
public Where orderByDesc(@Comment(name = "column", value = "要排序的列") String column) {
return orderBy(column, "desc");
}
@Comment("拼接`group by`")
public Where groupBy(@Comment("要分组的列") String... columns) {
this.namedTable.groupBy(columns);
return this;
}
@Comment("保存到表中,当主键有值时则修改,否则插入")
public Object save(RuntimeContext runtimeContext) {
return namedTable.save(runtimeContext);
}
@Comment("保存到表中,当主键有值时则修改,否则插入")
public Object save(RuntimeContext runtimeContext,
@Comment(name = "beforeQuery", value = "是否根据id查询有没有数据") boolean beforeQuery) {
return namedTable.save(runtimeContext, beforeQuery);
}
@Comment("保存到表中,当主键有值时则修改,否则插入")
public Object save(RuntimeContext runtimeContext,
@Comment(name = "data", value = "各项列和值") Map<String, Object> data) {
return namedTable.save(runtimeContext, data);
}
@Comment("保存到表中,当主键有值时则修改,否则插入")
public Object save(RuntimeContext runtimeContext,
@Comment(name = "data", value = "各项列和值") Map<String, Object> data,
@Comment(name = "beforeQuery", value = "是否根据id查询有没有数据") boolean beforeQuery) {
return namedTable.save(runtimeContext, data, beforeQuery);
}
@Comment("执行插入语句,返回主键")
public Object insert(RuntimeContext runtimeContext) {
return namedTable.insert(runtimeContext);
}
@Comment("执行插入语句,返回主键")
public Object insert(RuntimeContext runtimeContext,
@Comment(name = "data", value = "各项列和值") Map<String, Object> data) {
return namedTable.insert(runtimeContext, data);
}
@Comment("执行update语句")
public int update(RuntimeContext runtimeContext) {
return namedTable.update(runtimeContext);
}
@Comment("执行delete语句")
public int delete(RuntimeContext runtimeContext) {
return namedTable.delete(runtimeContext);
}
@Comment("执行update语句")
public int update(RuntimeContext runtimeContext,
@Comment(name = "data", value = "各项列和值") Map<String, Object> data) {
return namedTable.update(runtimeContext, data);
}
@Comment("执行update语句")
public int update(RuntimeContext runtimeContext,
@Comment(name = "data", value = "各项列和值") Map<String, Object> data,
@Comment(name = "isUpdateBlank", value = "是否更新空值字段") boolean isUpdateBlank) {
return namedTable.update(runtimeContext, data, isUpdateBlank);
}
@Comment("执行分页查询")
public Object page(RuntimeContext runtimeContext) {
return namedTable.page(runtimeContext);
}
@Comment("执行分页查询,分页条件手动传入")
public Object page(RuntimeContext runtimeContext,
@Comment(name = "limit", value = "限制条数") long limit,
@Comment(name = "offset", value = "跳过条数") long offset) {
return namedTable.page(runtimeContext, limit, offset);
}
@Comment("执行select查询")
public List<Map<String, Object>> select(RuntimeContext runtimeContext) {
return namedTable.select(runtimeContext);
}
@Comment("执行selectOne查询")
public Map<String, Object> selectOne(RuntimeContext runtimeContext) {
return namedTable.selectOne(runtimeContext);
}
@Comment("查询条数")
public int count(RuntimeContext runtimeContext) {
return namedTable.count(runtimeContext);
}
@Comment("查询是否存在")
public boolean exists(RuntimeContext runtimeContext) {
return namedTable.exists(runtimeContext);
}
@Transient
public void appendAnd() {
remove();
tokens.add("and");
}
@Transient
public void appendOr() {
remove();
tokens.add("or");
}
List<Object> getParams() {
return params;
}
void remove() {
int size = tokens.size();
while (size > 0) {
String token = tokens.get(size - 1);
if ("and".equalsIgnoreCase(token) || "or".equalsIgnoreCase(token)) {
tokens.remove(size - 1);
size--;
} else {
break;
}
}
while (size > 0) {
String token = tokens.get(0);
if ("and".equalsIgnoreCase(token) || "or".equalsIgnoreCase(token)) {
tokens.remove(0);
size--;
} else {
break;
}
}
}
boolean isEmpty() {
return tokens.isEmpty();
}
@Transient
public void append(String value) {
tokens.add(value);
}
@Transient
public void append(String sql, Object value) {
tokens.add(sql);
params.add(value);
}
String getSql() {
remove();
if (isEmpty()) {
return "";
}
return (needWhere ? " where " : "") + String.join(" ", tokens);
}
boolean filterNullAndBlank(Object value) {
if (notNull && value == null) {
return false;
}
return !notBlank || !StringUtils.isEmpty(Objects.toString(value, ""));
}
private Where append(boolean append, String column, String condition, Object value) {
if (append && filterNullAndBlank(value)) {
append(namedTable.rowMapColumnMapper.apply(column));
append(condition);
appendAnd();
params.add(value);
}
return this;
}
}
package org.ssssssss.magicapi.modules.http;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.ssssssss.magicapi.core.annotation.MagicModule;
import org.ssssssss.script.annotation.Comment;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* http 模块
*
* @author mxd
* @since 1.1.0
*/
@MagicModule("http")
public class HttpModule {
private final RestTemplate template;
private final HttpHeaders httpHeaders = new HttpHeaders();
private Class<?> responseType = Object.class;
private final MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
private final MultiValueMap<String, Object> data = new LinkedMultiValueMap<>();
private final Map<String, ?> variables = new HashMap<>();
private String url;
private HttpMethod method = HttpMethod.GET;
private HttpEntity<Object> entity = null;
private Object requestBody;
public HttpModule(RestTemplate template) {
this.template = template;
}
public HttpModule(RestTemplate template, String url) {
this.template = template;
this.url = url;
}
@Comment("创建连接")
public HttpModule connect(@Comment(name = "url", value = "目标URL") String url) {
return new HttpModule(template, url);
}
@Comment("设置URL参数")
public HttpModule param(@Comment(name = "key", value = "参数名") String key,
@Comment(name = "values", value = "参数值") Object... values) {
if (values != null) {
for (Object value : values) {
this.params.add(key, value);
}
}
return this;
}
@Comment("批量设置URL参数")
public HttpModule param(@Comment(name = "values", value = "参数值") Map<String, Object> values) {
values.forEach((key, value) -> param(key, Objects.toString(value, "")));
return this;
}
@Comment("设置form参数")
public HttpModule data(@Comment(name = "key", value = "参数名") String key,
@Comment(name = "values", value = "参数值") Object... values) {
if (values != null) {
for (Object value : values) {
this.data.add(key, value);
}
}
return this;
}
@Comment("批量设置form参数")
public HttpModule data(@Comment(name = "values", value = "参数值") Map<String, Object> values) {
values.forEach((key, value) -> data(key, Objects.toString(value, "")));
return this;
}
@Comment("设置header")
public HttpModule header(@Comment(name = "key", value = "header名") String key,
@Comment(name = "value", value = "header值") String value) {
httpHeaders.add(key, value);
return this;
}
@Comment("批量设置header")
public HttpModule header(@Comment(name = "values", value = "header值") Map<String, Object> values) {
values.entrySet()
.stream()
.filter(it -> it.getValue() != null)
.forEach(entry -> header(entry.getKey(), entry.getValue().toString()));
return this;
}
@Comment("设置请求方法,默认GET")
public HttpModule method(@Comment(name = "method", value = "请求方法") HttpMethod method) {
this.method = method;
return this;
}
@Comment("设置`RequestBody`")
public HttpModule body(@Comment(name = "requestBody", value = "`RequestBody`") Object requestBody) {
this.requestBody = requestBody;
this.contentType(MediaType.APPLICATION_JSON);
return this;
}
@Comment("自定义`HttpEntity`")
public HttpModule entity(@Comment(name = "entity", value = "`HttpEntity`") HttpEntity<Object> entity) {
this.entity = entity;
return this;
}
@Comment("设置`ContentType`")
public HttpModule contentType(@Comment(name = "contentType", value = "Content-Type值") String contentType) {
return contentType(MediaType.parseMediaType(contentType));
}
@Comment("设置`ContentType`")
public HttpModule contentType(@Comment(name = "mediaType", value = "Content-Type值") MediaType mediaType) {
this.httpHeaders.setContentType(mediaType);
return this;
}
@Comment("设置返回值为`byte[]`")
public HttpModule expectBytes() {
this.responseType = byte[].class;
return this;
}
@Comment("发送`POST`请求")
public ResponseEntity<?> post() {
this.method(HttpMethod.POST);
return this.execute();
}
@Comment("发送`GET`请求")
public ResponseEntity<?> get() {
this.method(HttpMethod.GET);
return this.execute();
}
@Comment("发送`PUT`请求")
public ResponseEntity<?> put() {
this.method(HttpMethod.PUT);
return this.execute();
}
@Comment("发送`DELETE`请求")
public ResponseEntity<?> delete() {
this.method(HttpMethod.DELETE);
return this.execute();
}
@Comment("发送`HEAD`请求")
public ResponseEntity<?> head() {
this.method(HttpMethod.HEAD);
return this.execute();
}
@Comment("发送`OPTIONS`请求")
public ResponseEntity<?> options() {
this.method(HttpMethod.OPTIONS);
return this.execute();
}
@Comment("发送`TRACE`请求")
public ResponseEntity<?> trace() {
this.method(HttpMethod.TRACE);
return this.execute();
}
@Comment("发送`PATCH`请求")
public ResponseEntity<?> patch() {
this.method(HttpMethod.PATCH);
return this.execute();
}
@Comment("执行请求")
public ResponseEntity<?> execute() {
if (!this.params.isEmpty()) {
String queryString = this.params.entrySet().stream()
.map(it -> it.getValue().stream()
.map(value -> it.getKey() + "=" + value)
.collect(Collectors.joining("&"))
).collect(Collectors.joining("&"));
if (StringUtils.isNotBlank(queryString)) {
this.url += (this.url.contains("?") ? "&" : "?") + queryString;
}
}
if (!this.data.isEmpty()) {
this.entity = new HttpEntity<>(this.data, this.httpHeaders);
} else if (this.entity == null && this.requestBody != null) {
this.entity = new HttpEntity<>(this.requestBody, this.httpHeaders);
} else {
this.entity = new HttpEntity<>(null, this.httpHeaders);
}
return template.exchange(url, this.method, entity, responseType, variables);
}
}
package org.ssssssss.magicapi.modules.servlet;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;
import org.ssssssss.magicapi.core.annotation.MagicModule;
import org.ssssssss.magicapi.core.servlet.MagicHttpServletRequest;
import org.ssssssss.magicapi.core.servlet.MagicRequestContextHolder;
import org.ssssssss.magicapi.utils.IpUtils;
import org.ssssssss.script.annotation.Comment;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.stream.Collectors;
/**
* request 模块
*
* @author mxd
*/
@MagicModule("request")
public class RequestModule {
private static MagicRequestContextHolder magicRequestContextHolder;
public RequestModule(MagicRequestContextHolder magicRequestContextHolder) {
RequestModule.magicRequestContextHolder = magicRequestContextHolder;
}
/**
* 获取文件信息
*
* @param name 参数名
*/
@Comment("获取文件")
public static MultipartFile getFile(@Comment(name = "name", value = "参数名") String name) {
MultipartRequest request = getMultipartHttpServletRequest();
if (request == null) {
return null;
}
MultipartFile file = request.getFile(name);
return file == null || file.isEmpty() ? null : file;
}
/**
* 获取文件信息
*
* @param name 参数名
*/
@Comment("获取多个文件")
public static List<MultipartFile> getFiles(@Comment(name = "name", value = "参数名") String name) {
MultipartRequest request = getMultipartHttpServletRequest();
if (request == null) {
return null;
}
return request.getFiles(name).stream().filter(it -> !it.isEmpty()).collect(Collectors.toList());
}
/**
* 获取原生HttpServletRequest对象
*/
@Comment("获取原生HttpServletRequest对象")
public static MagicHttpServletRequest get() {
return magicRequestContextHolder.getRequest();
}
private static MultipartRequest getMultipartHttpServletRequest() {
MagicHttpServletRequest request = get();
if (request != null && request.isMultipart()) {
return request.resolveMultipart();
}
return null;
}
/**
* 根据参数名获取参数值集合
*
* @param name 参数名
*/
@Comment("根据请求参数名获取值")
public List<String> getValues(@Comment(name = "name", value = "参数名") String name) {
MagicHttpServletRequest request = get();
if (request != null) {
String[] values = request.getParameterValues(name);
return values == null ? null : Arrays.asList(values);
}
return null;
}
/**
* 根据header名获取header集合
*
* @param name 参数名
*/
@Comment("根据header名获取值")
public List<String> getHeaders(@Comment(name = "name", value = "header名") String name) {
MagicHttpServletRequest request = get();
if (request != null) {
Enumeration<String> headers = request.getHeaders(name);
return headers == null ? null : Collections.list(headers);
}
return null;
}
@Comment("获取客户端IP")
public String getClientIP(String... otherHeaderNames) {
MagicHttpServletRequest request = get();
if (request == null) {
return null;
}
return IpUtils.getRealIP(request.getRemoteAddr(), request::getHeader, otherHeaderNames);
}
}
package org.ssssssss.magicapi.modules.servlet;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.ssssssss.magicapi.core.annotation.MagicModule;
import org.ssssssss.magicapi.core.context.RequestContext;
import org.ssssssss.magicapi.core.interceptor.ResultProvider;
import org.ssssssss.magicapi.core.servlet.MagicHttpServletResponse;
import org.ssssssss.script.annotation.Comment;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
/**
* response模块
*
* @author mxd
*/
@MagicModule("response")
public class ResponseModule {
private final ResultProvider resultProvider;
public ResponseModule(ResultProvider resultProvider) {
this.resultProvider = resultProvider;
}
/**
* 文件下载
*
* @param value 文件内容
* @param filename 文件名
*/
@Comment("文件下载")
public static ResponseEntity<?> download(@Comment(name = "value", value = "文件内容,如`byte[]`") Object value,
@Comment(name = "filename", value = "文件名") String filename) throws UnsupportedEncodingException {
return ResponseEntity.ok().contentType(MediaType.APPLICATION_OCTET_STREAM)
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + URLEncoder.encode(filename, "UTF-8"))
.body(value);
}
/**
* 自行构建分页结果
*
* @param total 条数
* @param values 数据内容
*/
@Comment("返回自定义分页结果")
public Object page(@Comment(name = "total", value = "总条数") long total,
@Comment(name = "values", value = "当前结果集") List<Map<String, Object>> values) {
return resultProvider.buildPageResult(RequestContext.getRequestEntity(), null, total, values);
}
/**
* 自定义json结果
*
* @param value json内容
*/
@Comment("自定义返回json内容")
public ResponseEntity<Object> json(@Comment(name = "value", value = "返回对象") Object value) {
return ResponseEntity.ok(value);
}
/**
* 添加Header
*/
@Comment("添加response header")
public ResponseModule addHeader(@Comment(name = "key", value = "header名") String key,
@Comment(name = "value", value = "header值") String value) {
if (StringUtils.isNotBlank(key)) {
MagicHttpServletResponse response = getResponse();
if (response != null) {
response.addHeader(key, value);
}
}
return this;
}
/**
* 设置header
*/
@Comment("设置response header")
public ResponseModule setHeader(@Comment(name = "key", value = "header名") String key,
@Comment(name = "value", value = "header值") String value) {
if (StringUtils.isNotBlank(key)) {
MagicHttpServletResponse response = getResponse();
if (response != null) {
response.setHeader(key, value);
}
}
return this;
}
/**
* 获取OutputStream
*
* @since 1.2.3
*/
@Comment("获取OutputStream")
public OutputStream getOutputStream() throws IOException {
MagicHttpServletResponse response = getResponse();
return response.getOutputStream();
}
@Comment("终止输出,执行此方法后不会对结果进行任何输出及处理")
public NullValue end() {
return NullValue.INSTANCE;
}
private MagicHttpServletResponse getResponse() {
return RequestContext.getHttpServletResponse();
}
/**
* 展示图片
*
* @param value 图片内容
* @param mime 图片类型,image/png,image/jpeg,image/gif
*/
@Comment("输出图片")
public ResponseEntity image(@Comment(name = "value", value = "图片内容,如`byte[]`") Object value,
@Comment(name = "mime", value = "图片类型,如`image/png`、`image/jpeg`、`image/gif`") String mime) {
return ResponseEntity.ok().header(HttpHeaders.CONTENT_TYPE, mime).body(value);
}
/**
* 输出文本
*
* @param text 文本内容
*/
@Comment("输出文本")
public ResponseEntity text(@Comment(name = "text", value = "文本内容") String text) {
return ResponseEntity.ok().header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE).body(text);
}
/**
* 重定向
*
* @param url 目标网址
*/
@Comment("重定向")
public NullValue redirect(@Comment(name = "url", value = "目标网址") String url) throws IOException {
getResponse().sendRedirect(url);
return NullValue.INSTANCE;
}
public static class NullValue {
static final NullValue INSTANCE = new NullValue();
}
}
package org.ssssssss.magicapi.modules.spring;
import org.springframework.core.env.Environment;
import org.ssssssss.magicapi.core.annotation.MagicModule;
import org.ssssssss.script.annotation.Comment;
/**
* env模块
*
* @author mxd
*/
@MagicModule("env")
public class EnvModule {
private final Environment environment;
@Comment("获取配置")
public String get(@Comment(name = "key", value = "配置项") String key) {
return environment.getProperty(key);
}
public EnvModule(Environment environment) {
this.environment = environment;
}
@Comment("获取配置")
public String get(@Comment(name = "key", value = "配置项") String key,
@Comment(name = "defaultValue", value = "未配置时的默认值") String defaultValue) {
return environment.getProperty(key, defaultValue);
}
}
package org.ssssssss.magicapi.utils;
import org.apache.commons.lang3.StringUtils;
import org.ssssssss.magicapi.core.exception.MagicAPIException;
/**
* 断言辅助类
*
* @author mxd
*/
public class Assert {
/**
* 断言值不能为空
*/
public static void isNotNull(Object value, String message) {
if (value == null) {
throw new MagicAPIException(message);
}
}
/**
* 验证值必须是true
*/
public static void isTrue(boolean value, String message) {
if (!value) {
throw new MagicAPIException(message);
}
}
/**
* 断言值不能为空字符串
*/
public static void isNotBlank(String value, String message) {
if (StringUtils.isBlank(value)) {
throw new MagicAPIException(message);
}
}
/**
* 断言值不能为空字符串
*/
public static void isNotBlanks(String message, String... values) {
if (values != null) {
for (String value : values) {
isNotBlank(value, message);
}
}
}
}
package org.ssssssss.magicapi.utils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.ssssssss.script.asm.ClassReader;
import org.ssssssss.script.functions.ObjectConvertExtension;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* class 扫描器
*
* @author mxd
*/
public class ClassScanner {
public static List<String> scan() throws URISyntaxException, IOException {
Set<String> classes = new HashSet<>();
if (Double.parseDouble(System.getProperty("java.specification.version")) >= 11) {
classes.addAll(latestJdkScan());
} else {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
do {
if (loader instanceof URLClassLoader) {
classes.addAll(scan(((URLClassLoader) loader).getURLs()));
}
} while ((loader = loader.getParent()) != null);
}
ClassLoader loader = Thread.currentThread().getContextClassLoader();
do {
if (loader instanceof URLClassLoader) {
classes.addAll(scan(((URLClassLoader) loader).getURLs()));
}
} while ((loader = loader.getParent()) != null);
classes.addAll(addJavaLibrary());
return new ArrayList<>(classes);
}
public static List<String> latestJdkScan() throws IOException {
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resourcePatternResolver.getResources("classpath*:**/**.class");
return Arrays.asList(resources).parallelStream().map(it -> {
try {
if (isClass(it.getURL().getPath())) {
if ("\"classes\"".contains(it.getURL().getPath())) {
return it.getURL().getPath().split("classes")[1].substring(1).replace(".class", "").replaceAll("\\/", ".");
} else if (it.getURL().getPath().split("!").length > 1) {
return it.getURL().getPath().split("!")[1].substring(1).replace(".class", "").replaceAll("\\/", ".");
} else {
try (InputStream stream = it.getInputStream()) {
return new ClassReader(stream).getClassName().replace("/", ".");
} catch (Exception e) {
return null;
}
}
}
} catch (Exception e) {
return null;
}
return null;
}).filter(Objects::nonNull).distinct().sorted(Comparator.comparing(Objects::toString)).collect(Collectors.toList());
}
public static String compress(List<String> classes) {
Collections.sort(classes);
String currentPackage = "";
StringBuffer buf = new StringBuffer();
int classCount = 0;
for (String fullName : classes) {
String packageName = "";
String className = fullName;
if (fullName.contains(".")) {
int index = fullName.lastIndexOf(".");
className = fullName.substring(index + 1);
packageName = fullName.substring(0, index);
}
if (className.equals("package-info")) {
continue;
}
if (currentPackage.equals(packageName)) {
if (classCount > 0) {
buf.append(",");
}
buf.append(className);
classCount++;
} else {
currentPackage = packageName;
if (buf.length() > 0) {
buf.append("\n");
}
buf.append(packageName);
buf.append(":");
buf.append(className);
classCount = 1;
}
}
return buf.toString();
}
private static Set<String> scan(URL[] urls) throws URISyntaxException {
Set<String> classes = new HashSet<>();
if (urls != null) {
for (URL url : urls) {
String protocol = url.getProtocol();
if ("file".equalsIgnoreCase(protocol)) {
String path = url.getPath();
if (path.toLowerCase().endsWith(".jar")) {
classes.addAll(scanJarFile(url));
} else {
classes.addAll(scanDirectory(new File(url.toURI()), null));
}
} else if ("jar".equalsIgnoreCase(protocol)) {
classes.addAll(scanJarFile(url));
}
}
}
return classes;
}
private static Set<String> addJavaLibrary() {
int version = checkJavaVersion();
if (version >= 9) {
return addJava9PlusLibrary();
}
return addJava8Library();
}
private static int checkJavaVersion() {
String version = System.getProperty("java.version");
int index = version.indexOf(".");
if (index > -1) {
String first = version.substring(0, index);
if (!"1".equals(first)) {
return ObjectConvertExtension.asInt(first, -1);
} else {
int endIndex = version.indexOf(".", index + 1);
return ObjectConvertExtension.asInt(version.substring(index + 1, endIndex), -1);
}
}
return -1;
}
/**
* jdk 8
*/
private static Set<String> addJava8Library() {
try {
// 直接反射调用..
Object classpath = Class.forName("sun.misc.Launcher").getMethod("getBootstrapClassPath").invoke(null);
return scan((URL[]) classpath.getClass().getMethod("getURLs").invoke(classpath));
} catch (Exception ignored) {
}
return Collections.emptySet();
}
/**
* jdk 9+
*/
private static Set<String> addJava9PlusLibrary() {
Set<String> classes = new HashSet<>();
try {
Class<?> moduleLayer = Class.forName("java.lang.ModuleLayer");
Object boot = moduleLayer.getMethod("boot").invoke(null);
Object configuration = moduleLayer.getMethod("configuration").invoke(boot);
//Set<ResolvedModule>
Set<?> modules = (Set<?>) Class.forName("java.lang.module.Configuration").getMethod("modules").invoke(configuration);
Method reference = Class.forName("java.lang.module.ResolvedModule").getMethod("reference");
Method open = Class.forName("java.lang.module.ModuleReference").getMethod("open");
Method list = Class.forName("java.lang.module.ModuleReader").getMethod("list");
modules.forEach(module -> {
});
for (Object module : modules) {
Object ref = reference.invoke(module);
try (Closeable reader = (Closeable) open.invoke(ref)) {
@SuppressWarnings("unchecked")
Stream<String> stream = (Stream<String>) list.invoke(reader);
stream.filter(ClassScanner::isClass).forEach(className -> classes.add(className.substring(0, className.length() - 6).replace("/", ".")));
} catch (IOException ignored) {
}
}
} catch (Exception ignored) {
}
return classes;
}
private static List<String> scanDirectory(File dir, String packageName) {
File[] files = dir.listFiles();
List<String> classes = new ArrayList<>();
if (files != null) {
for (File file : files) {
String name = file.getName();
if (file.isDirectory()) {
classes.addAll(scanDirectory(file, packageName == null ? name : packageName + "." + name));
} else if (name.endsWith(".class") && !name.contains("$")) {
classes.add(filterFullName(packageName + "." + name.substring(0, name.length() - 6)));
}
}
}
return classes;
}
private static String filterFullName(String fullName) {
if (fullName.startsWith("BOOT-INF.classes.")) {
fullName = fullName.substring(17);
}
return fullName;
}
private static List<String> scanJarFile(URL url) {
List<String> classes = new ArrayList<>();
try (ZipInputStream zis = new ZipInputStream(url.openStream())) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
if (!entry.getName().contains("META-INF")) {
String className = entry.getName();
if (isClass(className)) {
classes.add(filterFullName(className.substring(0, className.length() - 6).replace("/", ".")));
}
}
}
} catch (IOException ignored) {
}
return classes;
}
private static boolean isClass(String className) {
return className.endsWith(".class") && !className.contains("$") && !className.contains("module-info");
}
}
package org.ssssssss.magicapi.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sql.DataSource;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.nio.charset.StandardCharsets;
/**
* IO工具包
*
* @author mxd
*/
public class IoUtils {
private static final Logger logger = LoggerFactory.getLogger(IoUtils.class);
private static final Pattern FILE_NAME_PATTERN = Pattern.compile("^(?!\\.)[\\u4e00-\\u9fa5_a-zA-Z0-9.\\-()]+$");
public static boolean validateFileName(String name) {
return FILE_NAME_PATTERN.matcher(name).matches();
}
public static List<File> files(File file, String suffix) {
List<File> list = new ArrayList<>();
if (file.isDirectory()) {
File[] files = file.listFiles((path) -> path.isDirectory() || path.getName().endsWith(suffix));
if (files != null) {
for (int i = files.length - 1; i >= 0; i--) {
list.addAll(files(files[i], suffix));
}
}
} else if (file.exists()) {
list.add(file);
}
return list;
}
public static List<File> dirs(File file) {
return subDirs(true, file);
}
private static List<File> subDirs(boolean isRoot, File file) {
List<File> list = new ArrayList<>();
if (file.isDirectory()) {
File[] files = file.listFiles(File::isDirectory);
if (files != null) {
for (int i = files.length - 1; i >= 0; i--) {
list.addAll(subDirs(false, files[i]));
}
}
if (!isRoot) {
list.add(file);
}
}
return list;
}
public static byte[] bytes(File file) {
try {
return Files.readAllBytes(file.toPath());
} catch (IOException e) {
logger.error("读取文件失败", e);
return new byte[0];
}
}
public static String string(File file) {
return new String(bytes(file), StandardCharsets.UTF_8);
}
public static byte[] bytes(InputStream inputStream) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[4096];
int len;
while ((len = inputStream.read(buf, 0, buf.length)) != -1) {
baos.write(buf, 0, len);
}
return baos.toByteArray();
} catch (IOException e) {
logger.error("读取InputStream失败", e);
return new byte[0];
}
}
public static String string(InputStream inputStream) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
StringBuilder result = new StringBuilder();
String line;
boolean flag = false;
while ((line = reader.readLine()) != null) {
if (flag) {
result.append("\r\n");
}
result.append(line);
flag = true;
}
return result.toString();
} catch (IOException e) {
logger.error("读取InputStream失败", e);
return "";
}
}
public static boolean write(File file, byte[] bytes) {
try {
Files.write(file.toPath(), bytes);
return true;
} catch (IOException e) {
logger.error("写文件失败", e);
return false;
}
}
public static boolean write(File file, String content) {
if (content == null) {
return false;
}
return write(file, content.getBytes(StandardCharsets.UTF_8));
}
public static boolean delete(File file) {
if (file == null) {
return true;
}
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null) {
for (int i = files.length - 1; i >= 0; i--) {
if (!delete(files[i])) {
return false;
}
}
}
}
if (!file.exists()) {
return true;
}
return file.delete();
}
public static void closeDataSource(DataSource dataSource) {
if (dataSource != null) {
if (dataSource instanceof Closeable) {
try {
((Closeable) dataSource).close();
} catch (Exception e) {
logger.warn("Close DataSource error", e);
}
} else {
logger.warn("DataSource can not close");
}
}
}
public static void close(Closeable closeable){
try {
if(closeable != null){
closeable.close();
}
} catch (IOException ignored) {
}
}
}
package org.ssssssss.magicapi.utils;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class IpUtils {
private static final String[] DEFAULT_IP_HEADER = new String[]{"X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};
public static String getRealIP(String remoteAddr, Function<String, String> getHeader, String... otherHeaderNames) {
String ip = null;
List<String> headers = Stream.concat(Stream.of(DEFAULT_IP_HEADER), Stream.of(otherHeaderNames == null ? new String[0] : otherHeaderNames)).collect(Collectors.toList());
for (String header : headers) {
if ((ip = processIp(getHeader.apply(header))) != null) {
break;
}
}
return ip == null ? processIp(remoteAddr) : ip;
}
private static String processIp(String ip) {
if (ip != null) {
ip = ip.trim();
if (isUnknown(ip)) {
return null;
}
if (ip.contains(",")) {
String[] ips = ip.split(",");
for (String subIp : ips) {
ip = processIp(subIp);
if (ip != null) {
return ip;
}
}
}
return ip;
}
return null;
}
private static boolean isUnknown(String ip) {
return StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip.trim());
}
}
package org.ssssssss.magicapi.utils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.ssssssss.magicapi.core.exception.MagicAPIException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JdbcUtils {
private static final Logger logger = LoggerFactory.getLogger(JdbcUtils.class);
public static Connection getConnection(String driver, String url, String username, String password) {
try {
if (StringUtils.isBlank(driver)) {
driver = DatabaseDriver.fromJdbcUrl(url).getDriverClassName();
if (StringUtils.isBlank(driver)) {
throw new MagicAPIException("无法从url中获得驱动类");
}
}
Class.forName(driver);
} catch (ClassNotFoundException e) {
throw new MagicAPIException("找不到驱动:" + driver);
}
try {
return DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
logger.error("获取Jdbc链接失败", e);
throw new MagicAPIException("获取Jdbc链接失败:" + e.getMessage());
}
}
public static void close(Connection connection) {
try {
connection.close();
} catch (Exception ignored) {
}
}
}
package org.ssssssss.magicapi.utils;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* JSON工具包
*
* @author mxd
*/
public class JsonUtils {
private static final ObjectMapper MAPPER = new ObjectMapper();
private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);
static {
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Logger.class, new JsonSerializer<Logger>() {
@Override
public void serialize(Logger value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(value.toString());
}
});
MAPPER.registerModule(simpleModule);
}
public static String toJsonString(Object target) {
try {
return MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(target);
} catch (JsonProcessingException e) {
logger.error("json序列化失败", e);
return null;
}
}
public static String toJsonStringWithoutPretty(Object target) {
try {
return MAPPER.writeValueAsString(target);
} catch (JsonProcessingException e) {
logger.error("json序列化失败", e);
return null;
}
}
public static String toJsonStringWithoutLog(Object target) {
try {
return MAPPER.writeValueAsString(target);
} catch (Exception e) {
return target == null ? null : target.toString();
}
}
public static <T> T readValue(String json, TypeReference<T> typeReference) {
try {
return MAPPER.readValue(json, typeReference);
} catch (IOException e) {
logger.error("读取json失败,json:{}", json, e);
return null;
}
}
public static <T> T readValue(String json, Class<T> clazz) {
try {
return MAPPER.readValue(json, clazz);
} catch (IOException e) {
logger.error("读取json失败,json:{}", json, e);
return null;
}
}
public static <T> T readValue(byte[] bytes, Class<T> clazz) {
try {
return MAPPER.readValue(bytes, clazz);
} catch (IOException e) {
logger.error("读取json失败,json:{}", new String(bytes), e);
return null;
}
}
public static <T> T readValue(byte[] bytes, JavaType javaType) {
try {
return MAPPER.readValue(bytes, javaType);
} catch (IOException e) {
logger.error("读取json失败,json:{}", new String(bytes), e);
return null;
}
}
public static byte[] toJsonBytes(Object target) {
String json = toJsonString(target);
return json == null ? new byte[0] : json.getBytes(StandardCharsets.UTF_8);
}
}
package org.ssssssss.magicapi.utils;
import org.ssssssss.magicapi.core.exception.MagicAPIException;
import java.security.MessageDigest;
/**
* MD5加密类
*
* @author mxd
*/
public class MD5Utils {
private static final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
/**
* MD5加密
*/
public static String encrypt(String value) {
return encrypt(value.getBytes());
}
/**
* MD5加密
*/
public static String encrypt(byte[] value) {
try {
byte[] bytes = MessageDigest.getInstance("MD5").digest(value);
char[] chars = new char[32];
for (int i = 0; i < chars.length; i = i + 2) {
byte b = bytes[i / 2];
chars[i] = HEX_CHARS[(b >>> 0x4) & 0xf];
chars[i + 1] = HEX_CHARS[b & 0xf];
}
return new String(chars);
} catch (Exception e) {
throw new MagicAPIException("md5 encrypt error", e);
}
}
}
package org.ssssssss.magicapi.utils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.ssssssss.script.reflection.JavaReflection;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public class Mapping {
private final AbstractHandlerMethodMapping<RequestMappingInfo> methodMapping;
private final String base;
private final RequestMappingInfo.BuilderConfiguration config;
private static final boolean HAS_GET_PATTERN_PARSER = JavaReflection.getMethod(RequestMappingHandlerMapping.class, "getPatternParser") != null;
private Mapping(AbstractHandlerMethodMapping<RequestMappingInfo> methodMapping, RequestMappingInfo.BuilderConfiguration config, String base) {
this.methodMapping = methodMapping;
this.config = config;
this.base = StringUtils.defaultIfBlank(base, "");
}
public static Mapping create(RequestMappingHandlerMapping mapping) {
return create(mapping, null);
}
public static Mapping create(RequestMappingHandlerMapping mapping, String base) {
if (HAS_GET_PATTERN_PARSER) {
RequestMappingInfo.BuilderConfiguration config = new RequestMappingInfo.BuilderConfiguration();
config.setTrailingSlashMatch(mapping.useTrailingSlashMatch());
config.setContentNegotiationManager(mapping.getContentNegotiationManager());
if (mapping.getPatternParser() != null) {
config.setPatternParser(mapping.getPatternParser());
} else {
config.setPathMatcher(mapping.getPathMatcher());
}
return new Mapping(mapping, config, base);
}
return new Mapping(mapping, null, base);
}
public RequestMappingInfo.Builder paths(String ... paths){
RequestMappingInfo.Builder builder = RequestMappingInfo.paths(paths);
if(this.config != null){
return builder.options(this.config);
}
return builder;
}
public Mapping register(RequestMappingInfo requestMappingInfo, Object handler, Method method) {
this.methodMapping.registerMapping(requestMappingInfo, handler, method);
return this;
}
public RequestMappingInfo register(String requestMethod, String path, Object handler, Method method) {
RequestMappingInfo info = paths(path).methods(RequestMethod.valueOf(requestMethod.toUpperCase())).build();
register(info, handler, method);
return info;
}
public Map<RequestMappingInfo, HandlerMethod> getHandlerMethods() {
return this.methodMapping.getHandlerMethods();
}
public Mapping unregister(RequestMappingInfo info) {
this.methodMapping.unregisterMapping(info);
return this;
}
public Mapping registerController(Object target) {
Method[] methods = target.getClass().getDeclaredMethods();
for (Method method : methods) {
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
if (requestMapping != null) {
String[] paths = Stream.of(requestMapping.value()).map(value -> PathUtils.replaceSlash(base + value)).toArray(String[]::new);
this.register(paths(paths).build(), target, method);
}
}
return this;
}
}
package org.ssssssss.magicapi.utils;
import java.util.regex.Pattern;
/**
* 路径处理工具包
*
* @author mxd
*/
public class PathUtils {
private static final Pattern REPLACE_SLASH_REGX = Pattern.compile("/+");
/**
* 将多个/替换为一个/
*/
public static String replaceSlash(String path) {
return REPLACE_SLASH_REGX.matcher(path).replaceAll("/");
}
}
package org.ssssssss.magicapi.utils;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
/**
* 正则相关工具包
*
* @author mxd
*/
public class PatternUtils {
private static final Map<String, Pattern> CACHED_PATTERNS = new ConcurrentHashMap<>();
public static boolean match(String content, String regex) {
Pattern pattern = CACHED_PATTERNS.get(regex);
if (pattern == null) {
pattern = Pattern.compile(regex);
CACHED_PATTERNS.put(regex, pattern);
}
return pattern.matcher(content).find();
}
}
package org.ssssssss.magicapi.utils;
import org.ssssssss.script.MagicScript;
import org.ssssssss.script.MagicScriptContext;
import org.ssssssss.script.MagicScriptDebugContext;
import java.util.Map;
/**
* 脚本管理
*
* @author mxd
*/
public class ScriptManager {
private static final String EXPRESSION_PREFIX = "/* generated by execute expression */ return ";
/**
* 执行脚本
*/
public static Object executeScript(String script, MagicScriptContext context) {
script = (context instanceof MagicScriptDebugContext ? MagicScript.DEBUG_MARK : "") + script;
MagicScript magicScript = MagicScript.create(script, null);
// 执行脚本
return magicScript.execute(context);
}
/**
* 执行脚本
*/
public static Object executeExpression(String script, MagicScriptContext context) {
return executeScript(EXPRESSION_PREFIX + script, context);
}
/**
* 执行脚本
*/
public static Object executeExpression(String script, Map<String, Object> paramMap) {
return executeExpression(script, new MagicScriptContext(paramMap));
}
}
package org.ssssssss.magicapi.utils;
/**
* 签名工具类
*
* @author mxd
*/
public class SignUtils {
public static String sign(Long timestamp, String secretKey, String mode, byte[] bytes) {
return MD5Utils.encrypt(String.format("%s|%s|%s|%s", timestamp, mode, MD5Utils.encrypt(bytes), secretKey));
}
}
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