百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

一款接口快速开发框架

mhr18 2024-12-24 12:24 22 浏览 0 评论

在日常开发过程中我们总是需要写很多的CRUD接口,乏味且无聊。太多重复性的工作,会降低我们的工作热情!现在有这么一款框架,可以快速的帮助你编写这些接口,甚至包括一些复杂的逻辑处理,那么它就是magic-api。

magic-api 是一个基于Java的接口快速开发框架,编写接口将通过magic-api提供的UI界面完成,自动映射为HTTP接口,无需定义Controller、Service、Dao、Mapper、XML、VO等Java对象即可完成常见的HTTP API接口开发

【已有上千家中小型公司使用,上万名开发者用于接口配置开发。上百名开发者参与提交了功能建议,接近20多名贡献者参与。已被gitee长期推荐。从首个版本开始不断优化升级,目前版本稳定,开发者交流群活跃。】

开源地址:https://gitee.com/ssssssss-team/magic-api

特性

  • 支持MySQL、MariaDB、Oracle、DB2、PostgreSQL、SQLServer 等支持jdbc规范的数据库
  • 支持非关系型数据库Redis、Mongodb
  • 支持集群部署、接口自动同步。
  • 支持分页查询以及自定义分页查询
  • 支持多数据源配置,支持在线配置数据源
  • 支持SQL缓存,以及自定义SQL缓存
  • 支持自定义JSON结果、自定义分页结果
  • 支持对接口权限配置、拦截器等功能
  • 支持运行时动态修改数据源
  • 支持Swagger接口文档生成
  • 基于magic-script脚本引擎,动态编译,无需重启,实时发布
  • 支持Linq式查询,关联、转换更简单
  • 支持数据库事务、SQL支持拼接,占位符,判断等语法
  • 支持文件上传、下载、输出图片
  • 支持脚本历史版本对比与恢复
  • 支持脚本代码自动提示、参数提示、悬浮提示、错误提示
  • 支持导入Spring中的Bean、Java中的类
  • 支持在线调试
  • 支持自定义工具类、自定义模块包、自定义类型扩展、自定义方言、自定义列名转换等自定义操作

快速开始

首先我们新建一个springboot工程,这里就不过多赘述,接下来引入magic-api依赖

<!-- 以spring-boot-starter的方式引用 -->
<dependency>
	<groupId>org.ssssssss</groupId>
    <artifactId>magic-api-spring-boot-starter</artifactId>
    <version>2.0.1</version>
</dependency>

修改application.properties

magic-api:
  web: /magic/web # UI请求的界面以及UI服务地址
  resource: #配置存储方式
    type: database # 配置存储在数据库中
    tableName: magic_api_file_v2 # 数据库中的表名
    #datasource: magic #指定数据源(单数据源时无需配置,多数据源时默认使用主数据源,如果存在其他数据源中需要指定。)
    prefix: /magic-api # key前缀
    readonly: false # 是否是只读模式
  prefix: / # 接口前缀,可以不配置
  auto-import-module: db  # 自动导入的模块
  auto-import-package: java.lang.*,java.util.* #自动导包
  allow-override: false #禁止覆盖应用接口
  sql-column-case: camel #启用驼峰命名转换
  editor-config: classpath:./magic-editor.js #编辑器配置
  support-cross-domain: true # 跨域支持,默认开启
  #secret-key: 123456789 # 远程推送时的秘钥,未配置则不开启推送
  #push-path: /_magic-api-sync #远程推送的路径,默认为/_magic-api-sync
  show-sql: true #配置打印SQL
  compile-cache-size: 500 #配置编译缓存容量
  persistence-response-body: true #是否持久化保存ResponseBody
  date-pattern: # 配置请求参数支持的日期格式
    - yyyy-MM-dd
    - yyyy-MM-dd HH:mm:ss
    - yyyyMMddHHmmss
    - yyyyMMdd
  response: |- #配置JSON格式,格式为magic-script中的表达式
    {
      state: code == 1 ? 'success' : 'fail',
      msg: message,
      data,
      timestamp,
      requestTime,
      executeTime,
    }
  response-code:
    success: 1 #执行成功的code值
    invalid: 0 #参数验证未通过的code值
    exception: -1 #执行出现异常的code值
  banner: true # 打印banner
  thread-pool-executor-size: 8 # async语句的线程池大小
  throw-exception: false #执行出错时是否抛出异常
  backup: #备份相关配置
    enable: true #是否启用
    max-history: -1 #备份保留天数,-1为永久保留
    #datasource: magic  #指定数据源(单数据源时无需配置,多数据源时默认使用主数据源,如果存在其他数据源中需要指定。)
    table-name: magic_backup_record_v2 #使用数据库存储备份时的表名
  crud: # CRUD相关配置
    logic-delete-column: deleted #逻辑删除列
    logic-delete-value: 1 #逻辑删除值
  cache: # 缓存相关配置
    capacity: 10000 #缓存容量
    ttl: -1 # 永不过期
    enable: true # 启用缓存
  page:
    size: pageSize # 页大小的参数名称
    page: page # 页码的参数名称
    default-page: 1 # 未传页码时的默认首页
    default-size: 10 # 未传页大小时的默认页大小
  security:  # 安全配置
    username: admin # 登录用的用户名
    password: 123456 # 登录用的密码
  swagger:
    version: 1.0
    description: MagicAPI 接口信息
    title: MagicAPI Swagger Docs
    name: MagicAPI 接口
    location: /v2/api-docs/magic-api/swagger2.json
  debug:
    timeout: 60 # 断点超时时间,默认60s

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.1.197:3306/magic-api-test?allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
    username: root
    password: 123

从上面的配置文件我们可以看出magic-api支持配置存储方式数据库/磁盘,可以更好的迁移与备份;支持开始是否跨域,无需我们另外手写跨域配置;支持请求参数配置日期格式;支持配置统一的返回格式;支持在线编辑页面的登录管理;支持缓存配置;支持自定义插件引入;

启动项目

********************************************当前服务相关地址********************************************
服务启动成功,magic-api已内置启动! Access URLs:
接口本地地址: http://localhost:9999/
接口外部地址: http://192.168.57.1:9999/
接口配置平台: http://192.168.57.1:9999/magic/web/index.html
可通过配置关闭输出: magic-api.show-url=false
********************************************当前服务相关地址********************************************

项目启动成功我们可以看到输出的接口根目录与在线编辑的web地址

登录

访问http://localhost:9999/magic/web或者http://192.168.57.1:9999/magic/web/index.html进行操作


由于我们开启了登录验证,所以需要我们登录一下才能进入管理页面。magic-api也提供了登录方法的拦截器让我们自定义校验,通过这个拦截器我们可以实现和数据库的账号密码接入,实现员工一人一账号,下面是拦截器代码

#配置用户名密码
默认情况下是不配置用户名密码的。

如果需要可以通过以下配置开启用户名密码验证登录。

magic-api:
  security:
    username: admin # 登录用的用户名
    password: 123456 # 登录用的密码
#多用户登录
如果需要配置多用户登录,则需要使用自定义鉴权的方式。

/**
 * 自定义用户名密码登录
 */
@Component  //注入到Spring容器中
public class CustomAuthorizationInterceptor implements AuthorizationInterceptor {

	/**
     * 配置是否需要登录
	 */
	@Override
	public boolean requireLogin() {
		return true;
	}

	/**
     * 根据Token获取User
	 */
	@Override
	public MagicUser getUserByToken(String token) throws MagicLoginException {
		if (判断token是否有效) {
			return magicUser;   // 从token中获取MagicUser对象
		}
		throw new MagicLoginException("token无效");
	}

	@Override
	public MagicUser login(String username, String password) throws MagicLoginException {
		// 根据实际情况进行修改,如查询数据库。。
		if("admin".equals(username) && "admin".equals(password)){
			// 登录成功后 构造MagicUser对象。
			return new MagicUser("1","admin","tokenvalue......");
        }
		throw new MagicLoginException("用户名或密码不正确");
	}

}

管理页面

接下来我们输入配置的账号密码登录,进入管理页面


界面简介

整体说明

接口信息

RequestBody

ResponseBody

DEBUG


创建接口

1. 创建分组

点击创建分组按钮后,输入分组信息,点击创建。

2. 新建接口

右键分组,点击新建接口。

在编辑器输入内容后,填写接口名称和及其路径。

var sql = """
select * from test_data
"""

return db.select(sql)

ctrl+s保存后,即可访问接口。

3.访问接口

> curl http://localhost:9999/test/test

{
    "code": 1,
    "message": "success",
    "data": [
        {
            "id": 1,
            "name": "magicApi"
        },
        {
            "id": 2,
            "name": "xiaoDong"
        }
    ],
    "timestamp": 1638192442535,
    "executeTime": 9
}

? 也可以通过web界面执行。

通过以上几个步骤,我们就实现了一个简单的查询功能。省去了ControllerServiceDaoMapperXMLVO等模板代码的工作量。

脚本语法

#关键字

关键字

含义

var

定义变量

if

条件语句的引导词

else

用在条件语句中,表明当条件不成立时的分支

for

for循环语句

in

与for配合使用

while

while循环语句

continue

执行下一次循环

break

跳出循环

return

终止当前过程的执行并正常退出到上一个执行过程中

exit

终止当前脚本,并退出返回,如exit 200,'执行成功',[1,2,3]; v0.5.0中新增

assert

断言 v1.3.4中新增

instanceof

判断一个对象是否为一个类的实例 v2.0.0中新增

try

用于捕获可能发生异常的代码块

catch

与try关键字配合使用,当发生异常时执行

finally

与try关键字配合使用,finally块无论发生异常都会执行

import

导入Java类或导入已定义好的模块

as

与 import 关键字配合使用,用作将导入的 Java类或模块 命名为一个本地变量名

new

创建对象

true

基础类型之一,表示 Boolean 的:真值

false

基础类型之一,表示 Boolean 的:假值

null

基础类型之一,表示 NULL 值

async

异步调用

#运算符

数学运算

比较运算

逻辑运算

位运算

+

加法

<

小于

&&

并且

&、&=

-

减法

<=

小于等于

||

或者

|、|=

*

乘法

>

大于



^、^=

异或

/

除法

>=

大于等于



~、~=

取反

%

取模

==

等于



<<、<<=

左移

++

自增

!=

不等于



>>、>>=

右移

--

自减

===

等于



>>>、>>>=

无符号右移



!==

不等于





#类型

类型

写法

byte

123b、123B

short

123s、123S

int

123

long

123l、123L

float

123f、123F

double

123d、123D

BigDecimal

123m、123M

boolean

true、false

string

'hello'

string

"hello"

string

"""多行文本块,主要用于编写SQL"""

Pattern

/\d+/g,/pattern/gimuy 用于定义正则

lambda

()=>expr、(param1,param2....)=>{...}
()->expr、(param1,param2....)->{...}

list

[1,2,3,4,5]

map

{key : value,key1 : value}

{[key] : "value"} [key]表示动态从变量中获取key值

#一元运算符

您可以通过一元运算-符将数字取反,例如-234。要取反布尔表达式,可以使用!运算符,例如!true。 自增/自减 i++ 、 ++i、i--、--i

#算术运算符

支持常见的算术运算符,例如1 + 2 * 3 / 4 % 2,同样也支持+=、-=、*=、/=、%=

#比较运算符

23 < 34,23 <= 34,23 > 34,23 >= 34,true != false,23 == 34

比较运算符结果为boolean类型

#逻辑运算符

除了一元运算!符,您还可以使用&&和||。就像Java中一样,运算符也是一种短路运算符。如果&&左边计算为false,则不会计算右边。如果||左侧为true,则不会计算右边 在0.4.6+版本中增强了&& || 不再强制两边必须是布尔类型。作用与JS一样

#三元运算符

三元运算符是if语句的简写形式,其工作方式类似于Java中,例如true ? "yes" : "no" 在0.4.3+版本中,增强了if 和三元运算符,不再强制值必须是布尔类型,可以写if(xxx)的形式当xxx为以下情况时为fasle、其它情况为true

  • null
  • 空集合
  • 空Map
  • 空数组
  • 数值==0
  • 非空字符串
  • false

#类型转换

可使用::type(defaultValue) 的方式进行类型转换,如

var a = "123"::int; // 123
var b = "abc"::int(111); // 111
var c = "2020-01-01"::date('yyyy-MM-dd'); // 转换为date

#可选链操作符

可选链操作符(?.)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?.操作符的功能类似于.链式操作符,不同之处在于,在引用为空 的情况下不会引起错误,该表达式短路返回值是 null。

当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链操作符也是很有帮助的。

obj?.prop
obj?.method(args)

示例:

var a = null;
var b = a?.name;    // b = null;
var c = a?.getName();   // c = null;

#扩展运算符

扩展运算符,又叫展开语法(Spread syntax), 是用于将list或map在语法层面展开;

语法:

lambda 调用

var sum = (a,b,c) => a + b + c;
System.out.println(sum(...[1,2,3]))
/*
结果:6
*/

list 展开

var arr = [3,4,5];
System.out.println([1,2,...arr,6,7])
/*
结果:[1, 2, 3, 4, 5, 6, 7]
*/

list 展开到 map 中

var arr = [3,4,5];
System.out.println({key1:1,...arr})
/*
结果:{key1=1, 0=3, 1=4, 2=5}

虽然这些key看起来像数值,但其实是String类型的key,如果把它们转为JSON看起来是这样的:

{"key1":1, "0":3, "1":4, "2":5}

*/

map 展开

var map = {key2:2}
System.out.println({key1:1,...map,key3:3})
/*
结果:{key1=1, key2=2, key3=3}
*/

#for循环

当前for循环只支持两种,循环集合或Map

#循环集合

import 'java.lang.System' as System;
var list = [1,2,3];
for(index,item in list){    //如果不需要index,也可以写成for(item in list)
    System.out.println(index + ":" + item);
}
/*
结果:
0:1
1:2
2:3
*/

#循环指定次数

var sum = 0;
for(value in range(0,100)){    //包括0包括100
    sum = sum + value; //不支持+= -= *= /= ++ -- 这种运算
}
return sum;
/*
结果:5050
*/

#while循环

var count = 100;
var sum = 0;
while(count){
    sum = sum + count;
    count = count - 1;
}
return sum; // 5050

#循环map

import 'java.lang.System' as System;
var map = {
    key1 : 123,
    key2 : 456
};
for(key,value in map){    //如果不需要key,也可以写成for(value in map)
    System.out.println(key + ":" + value);
}
/*
结果:
key1:123
key2:456
*/

#Import导入

#导入Java类

import 'java.lang.System' as System;//导入静态类并赋值给system作为变量
import 'javax.sql.DataSource' as ds;//从spring中获取DataSource并将值赋值给ds作为变量
import 'org.apache.commons.lang3.StringUtils' as string;//导入静态类并赋值给ds作为变量
import 'java.text.*'    //此写法跟Java一致,在1.3.4中新增
System.out.println('调用System打印');//调用静态方法
System.out.println(ds);
System.out.println(string.isBlank('')); //调用静态方法
System.out.println(new SimpleDateFormat('yyyy-MM-dd').format(new Date())); // 2020-01-01

#new创建对象

#创建对象

import 'java.util.Date' as Date;//创建之前先导包,不支持.*的操作
return new Date();

#导入已定义的模块

import log; //导入log模块,并定义一个与模块名相同的变量名
//import log as logger; //导入log模块,并赋值给变量 logger
log.info('Hello {}','Magic API!')

#异步调用

#异步调用方法

var val = async db.select('.....'); // 异步调用,返回Future类型
return val.get();   //调用Future的get方法

#异步调用lambda

var list = [];
for(index in range(1,10)){
    list.add(async (index)=>db.selectInt('select #{index}'));
}
return list.map(item=>item.get());  // 循环获取结果

#exit

语法格式为 exit expr[,expr][,expr][,expr][,expr][,expr][,expr]....

在magic-api中只取前三个值,分别对应code、message、data

如:exit 400,'参数填写有误'

#assert

语法格式为 assert expr : expr[,expr][,expr][,expr][,expr][,expr][,expr].... 如:assert a == 1 : 400, 'a的值应为1' 相当于

if(a != 1){
    exit 400, 'a的值应为1'
}

#类型转换

通过::进行类型转换,如xxx::int、xxx::double等, 当前支持转换类型有int、double、long、byte、short、float、date

var a = "1";
return {
    v1: a::int,
    v2: a::int(0),  //转换失败时,值为0
    v3: "2020-01-01"::date('yyyy-MM-dd') //转为Date
}

? ::sql支持将数据转换为对应的sql类型, 比如:

img::sql('blob')

? 可传入的参数请参考java.sql.Types中定义的常量,不区分大小写。

#嵌入其它脚本语言

var name = "hello";
var test = ```javascript
    name + ' ~ world'
```;
return test();

文档/演示

  • 文档地址:https://ssssssss.org
  • 在线演示:https://magic-api.ssssssss.org

最后

本文仅仅演示magic-api的一些简单功能,如果大家感兴趣的话可以自行到官方网站去学习!或者你有更好的开发框架或意见也可在评论区留言。

相关推荐

MySQL数据库中,数据量越来越大,有什么具体的优化方案么?

个人的观点,这种大表的优化,不一定上来就要分库分表,因为表一旦被拆分,开发、运维的复杂度会直线上升,而大多数公司和开发人员是欠缺这种能力的。所以MySQL中几百万甚至小几千万的表,先考虑做单表的优化。...

Redis的Bitmap(位图):签到打卡、用户在线状态,用它一目了然

你是不是每天打开APP,第一时间就是去“签到打卡”?或者在社交软件里,看到你的朋友头像旁边亮着“在线”的绿灯?这些看似简单的功能背后,都隐藏着一个有趣而高效的数据结构。如果让你来设计一个签到系统:用户...

想知道有多少人看了你的文章?Redis HyperLogLog几KB就搞定!

作为一名内容创作者,你每天最期待的,除了文章阅读量蹭蹭上涨,是不是还特别想知道,到底有多少个“独立用户”阅读了你的文章?这个数字,我们通常称为“UV”(UniqueVisitors),它比总阅读量更...

Redis的“HyperLogLog”:统计网站日活用户,省内存又高效的神器

你可能从未听过这个拗口的名字——“HyperLogLog”,它听起来就像是某个高深莫测的数学公式。但请相信我,理解它的核心思想并不难,而且一旦你掌握了它,你会发现它在处理大数据统计问题时,简直就是“救...

阿里云国际站:为什么我的云服务器运行缓慢?

本文由【云老大】TG@yunlaoda360撰写一、网络性能瓶颈带宽不足现象:上传/下载速度慢,远程连接卡顿。排查:通过阿里云控制台查看网络流量峰值是否接近带宽上限34。解决:升级带宽(如从1M提...

Java 近期新闻:Jakarta EE 11和Spring AI更新、WildFly 36.0 Beta、Infinispan

作者|MichaelRedlich译者|明知山策划|丁晓昀OpenJDKJEP503(移除32位x86移植版本)已从“ProposedtoTarget”状态进入到“T...

腾讯云国际站:怎样设置自动伸缩应对流量高峰?

云计算平台服务以阿里云为例:开通服务与创建伸缩组:登录阿里云控制台,找到弹性伸缩服务并开通。创建伸缩组时,选择地域与可用区,定义伸缩组内最小/最大实例数,绑定已有VPC虚拟交换机。实例模板需...

【案例分享】如何利用京东云建设高可用业务架构

本文以2022年一个实际项目为基础,来演示在京东云上构建高可用业务的整个过程。公有云及私有云客户可通过使用京东云的弹性IAAS、PAAS服务,创建高可用、高弹性、高可扩展、高安全的云上业务环境,提升业...

Spring Security在前后端分离项目中的使用

1文章导读SpringSecurity是Spring家族中的一个安全管理框架,可以和SpringBoot项目很方便的集成。SpringSecurity框架的两大核心功能:认证和授权认证:...

Redis与Java集成的最佳实践

Redis与Java集成的最佳实践在当今互联网飞速发展的时代,缓存技术的重要性毋庸置疑。Redis作为一款高性能的分布式缓存数据库,与Java语言的结合更是如虎添翼。今天,我们就来聊聊Redis与Ja...

Redis在Java项目中的应用与数据持久化

Redis在Java项目中的应用与数据持久化Redis简介:为什么我们需要它?在Java项目中,Redis就像一位不知疲倦的快跑选手,总能在关键时刻挺身而出。作为一个内存数据库,它在处理高并发请求时表...

Redis 集群最大节点个数是多少?

Redis集群最大节点个数取决于Redis的哈希槽数量,因为每个节点可以负责多个哈希槽。在Redis3.0之前,Redis集群最多支持16384个哈希槽,因此最大节点数为16384个。但是在Redi...

Java开发岗面试宝典:分布式相关问答详解

今天千锋广州Java小编就给大家分享一些就业面试宝典之分布式相关问题,一起来看看吧!1.Redis和Memcache的区别?1、存储方式Memecache把数据全部存在内存之中,断电后会挂掉,数据不...

当Redis内存不足时,除了加内存,还有哪些曲线救国的办法?

作为“速度之王”的Redis,其高性能的秘密武器之一就是将数据存储在内存中。然而,内存资源是有限且昂贵的。当你的Redis实例开始告警“内存不足”,或者写入请求被阻塞时,最直接的解决方案似乎就是“加内...

商品详情页那么多信息,Redis的“哈希”如何优雅存储?

你每天网购时,无论是打开淘宝、京东还是拼多多,看到的商品详情页都琳琅满目:商品名称、价格、库存、图片、描述、评价数量、销量。这些信息加起来,多的惊人。那么问题来了:这些海量的商品信息,程序是去哪里取出...

取消回复欢迎 发表评论: