1.概述
magic-api
是一个基于Java的接口快速开发框架,编写接口将通过magic-api
提供的UI界面完成,自动映射为HTTP接口,无需定义Controller、Service、Dao、Mapper、XML、VO等Java对象。
只不过这种方式虽然简单,但无法处理复制的业务逻辑。对于复杂的业务逻辑,还是使用java代码进行实现。注意要保证二者的接口路径不重复。
2.实战演练
源码:https://github.com/zhongyushi-git/springboot-magic-demo。数据库的备份在项目根目录下打包db2020.nb3。
2.1项目准备
1)新建一个SpringBoot的项目,导入数据库需要的依赖:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.9</version> </dependency>
2)新建数据库和表
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) COLLATE utf8_bin DEFAULT NULL, `password` varchar(255) COLLATE utf8_bin DEFAULT NULL, `addr` varchar(500) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
3)在配置文件配置数据源
spring: datasource: type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://localhost:3306/db2020?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: zys123456
2.2 加入magic-api
1)在pom.xml
中添加magic-api
相关依赖:
<dependency>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-spring-boot-starter</artifactId>
<version>1.2.1</version>
</dependency>
2)在配置文件配置magic-api相关信息
magic-api: # 配置api管理页面入口 web: /magic/web # 配置存储方式 resource: # 配置接口资源存储位置,可选file、database、redis type: database # 存储表名 tableName: magic_api_file # 使用database、redis存储时的key前缀 prefix: /db2020 # 是否是只读模式 readonly: false # 启用驼峰命名转换 sql-column-case: camel # 分页配置 page-config: # 页大小的请求参数名称 size: size # 页码的请求参数名称 page: page # 未传页码时的默认页码 default-page: 1 # 未传页大小时的默认页大小 default-size: 10
3)创建表magic_api_file,用来存储接口的配置信息
CREATE TABLE `magic_api_file` ( `id` bigint(255) NOT NULL AUTO_INCREMENT, `file_path` varchar(255) DEFAULT NULL, `file_content` text, PRIMARY KEY (`id`) )
4)启动项目,访问http://localhost:8080/magic/web,即可进入magic的管理页面,如下图:
默认是白色,可点击皮肤设置黑色。
4.基本用法
4.1添加操作
1)在接口列表中添加添加按钮,添加一个分组并设置分组前缀
2)在创建的分组中选择右键,新建一个接口,填写接口的相关信息和执行脚本,如下图:
右侧区域是编辑框,里面主要编写magic的执行脚本,添加如下脚本:
return db.table(\'user\').insert(body);
在底部的接口信息
中进行如下配置,POST
请求,请求路径为/create
,请求参数放在请求body
中,是json字符串:
{ "username":"zhangsan", "password":"123", "addr":"湖北武汉" }
点击右上角的执行按钮,在执行结果中看到返回了success,说明添加成功。在数据库中查询,数据已经添加进来。
在浏览器中查看请求的路径:此路径的组成:http://localhost:8080+"分组前缀"+接口路径。后续可直接根据此路径执行用户的添加操作,其他类同。
4.2修改操作
1)添加修改的接口,输入执行脚本
return db.table(\'user\').primary(\'id\',body.id).update(body);
2)在接口信息
中进行如下配置,POST
请求,请求路径为/update
,请求参数放在请求body
中:
修改id等于3的用户的密码和地址。
4.3删除操作
1)添加删除的接口,输入执行脚本
return db.update(\'delete from user where id=#{id}\');
2)在接口信息
中进行如下配置,POST
请求,请求路径为/del/{id}
,请求参数放在路径变量
中:
3)点击执行按钮,会把数据删除,返回执行的结果。
4.4查询操作
4.4.1根据id查询
1)新建一个接口,添加执行脚本:
// 路径变量从path对象中获取 return db.table(\'user\') .where() .eq(\'id\',path.id) .selectOne();
2)在接口信息
中进行如下配置,GET
请求,请求路径为/one/{id}
,请求参数放在路径变量
中:
3)点击执行按钮,若有数据,则会返回数据,没有数据则data的值是null
4.4.2 分页查询
由于已在配置文件中配置了分页的参数信息,故这里直接使用。
1)新建一个接口,添加执行脚本:
return db.table(\'user\').page();
2)在接口信息
中进行如下配置,GET
请求,请求路径为/page
,请求参数放在请求参数
中:
3)点击执行按钮,若有数据,则会返回数据,没有数据则data的值是null。
5.magic语法详解
5.1db模块
(1)db是默认引入的模块,使用此模块操作数据库,需要使用return把结果返回。
(2)db.table()就指定了表名,可以使用期自带的方法进行查询等操作,但其只能对单表进行操作,多表无法使用。
(3)除了使用自带的方法外,还可以自定义sql进行操作。具体见后面的章节
5.2自定义查询
1)select()
根据sql查询结果,返回的是list集合。
return db.select(\'select * from user\')
若需要携带参数,可以使用#{}进行占位,其他查询类似:
return db.select(\'select * from user where id = #{id} \')
2)selectInt()
根据sql查询结果,返回的是int值。
return db.selectInt(\'select count(*) from user\')
3)selectOne()
查询单个对象,其返回值必须是小于等于一条数据,不能超过一条。
return db.selectOne(\'select * from user where id = #{id} \')
使用db.tableI()方式进行对比:
return db.table(\'user\') .where() .eq(\'id\',path.id) .selectOne();
两种方式的效果一样,只不过使用的模式不一样。
4)selectValue()
查询单个列的值。若查询结果是多条,则只会返回第一条数据的对应字段信息。
return db.selectValue(\'select username from user where id = #{id}\');
5)page()
分页查询。要传递分页的条件(当前页码page,每页条数size),会返回数据总条数和数据集合。
return db.page(\'select * from user\')
使用db.tableI()方式进行对比:
return db.table(\'user\').page()
两种方式的效果是一样的,可*选择。
6)update()
对于增删改操作,都可以使用此方法,不过一般删除会使用此方法,添加和修改均使用db.table()方式。原因是此方法必须使用get请求传递参数,不安全。
return db.update(\'delete from user where id=#{id}\');
如根据id进行修改:使用post请求,把需要修改的字段和值使用json字符串方式传递即可,可参考4.2小节的说明。
return db.table(\'user\').primary(\'id\',body.id).update(body);
6.集成Swagger
当接口很多时,想查询接口及路径,Swagger是一个不错的选择。而magic也可以和Swagger进行无缝整合。
1)导入Swagger相关依赖
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
2)在配置文件application.yml
中添加Swagger相关配置。
magic-api: # 集成Swagger配置 swagger-config: # 文档名称 name: MagicAPI # 文档标题 title: MagicAPI Swagger Docs # 文档描述 description: MagicAPI # 文档版本号 version: 1.0 # 文档资源位置 location: /v2/api-docs/magic-api/swagger2.json
3)重启项目,访问Swagger界面http://localhost:8080/swagger-ui.html,即可查看我们在magic-api
中写的接口
7.拦截器配置
在开发环境,可以使用magic进行接口的开发,但是在正式环境中,其页面是不能暴露出来的,同时swagger在正式环境也不能暴露。故需要拦截器进行拦截,同时其自带SQL的拦截器,可以打印SQL的日志信息。
新建一个类,进行配置,具体见源码:
/** * 拦截器配置 */ @Component public class MyInterceptor implements SQLInterceptor, HandlerInterceptor { Logger logger = LoggerFactory.getLogger(this.getClass()); @Value("${isAllowed}") private Boolean isAllowed; /*** * 自定义SQL拦截器,打印sql及参数 * @param boundSql * @param requestEntity */ @Override public void preHandle(BoundSql boundSql, RequestEntity requestEntity) { logger.warn("执行的SQL===> " + boundSql.getSql()); logger.warn("执行的SQL参数===> " + Arrays.toString(boundSql.getParameters())); } /** * 配置资源拦截器,开发页面只能在开发中使用,在正式环境拦截 * * @param request * @param response * @param handler * @return */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { if (!isAllowed) { Map<String, Object> result = new HashMap<>(); result.put("msg", "抱歉,未找到可访问资源!"); result.put("status", false); response.setCharacterEncoding("utf-8"); response.setHeader("Content-type", "text/html;charset=UTF-8"); response.getWriter().write(JSON.toJSONString(result)); return false; } return true; } }
另外还需要一个MVC的配置其注入拦截器和要拦截的资源:
/** * mvc配置,注入拦截器 */ @Configuration public class MyWebMvcConfigurer implements WebMvcConfigurer { @Autowired private MyInterceptor myInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { //addPathPatterns表示拦截所有请求,excludePathPatterns表示不拦截的请求 registry.addInterceptor(myInterceptor).addPathPatterns("/swagger-ui.html").addPathPatterns("/magic/**"); } }
这样一来,就可以通过修改isAllowed的值选择是否可访问。到这里,基本的接口开发已经完成,只需前端进行整合即可。