magic-api

一個基于 Java 的接口快速開發框架,通過 magic-api 提供的 UI 界面完成編寫接口,無需定義 ControllerServiceDaoMapperXMLVO 等 Java 對象即可完成常見的 HTTP API 接口開發。

特性

使用示例

添加依賴

新建 SpringBoot 項目,添加相關依賴:

<properties>
<java.version>1.8</java.version>
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>2.7.15</spring-boot.version>

<magic-api.version>2.1.1</magic-api.version>
<druid-spring-boot.varsion>1.2.6</druid-spring-boot.varsion>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-spring-boot-starter</artifactId>
<version>${magic-api.version}</version>
</dependency>

<dependency>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-plugin-task</artifactId>
<version>${magic-api.version}</version>
</dependency>

<dependency>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-plugin-component</artifactId>
<version>${magic-api.version}</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid-spring-boot.varsion}</version>
</dependency>
</dependencies>

配置文件

server:
port: 8080

spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mvc:
pathmatch:
matching-strategy: ant_path_matcher
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/demo?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&autoReconnect=true
username: root
password: 123456
initialSize: 10
minIdle: 10
maxActive: 100
maxWait: 60000
timeBetweenEvictionRunsMillis: 300000
minEvictableIdleTimeMillis: 3600000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20

magic-api:
web: /api/web
show-sql: true #配置打印SQL
sql-column-case: camel
security:
username: admin # 登錄用的用戶名
password: admin@123 # 登錄用的密碼
support-cross-domain: true # 跨域支持,默認開啟
resource:
type: database # 配置接口存儲方式,這里選擇存在數據庫中
table-name: magic_api_file # 數據庫中的表名
prefix: / # 前綴
# location: data/magic-api
page:
page: current
size: size
cache:
enable: true #開啟緩存,默認是不開啟的
ttl: 3600000 #有效期1小時,默認-1 即永不過期
response-code:
success: 200 #執行成功的code值
invalid: 400 #參數驗證未通過的code值
exception: 500 #執行出現異常的code值

詳細配置見文檔:https://www.ssssssss.org/magic-api/pages/config/spring-boot/#%E5%AE%8C%E6%95%B4%E9%85%8D%E7%BD%AE%E7%A4%BA%E4%BE%8B

統一請求響應配置

package com.demo.config;

import com.demo.base.WrapMapper;
import org.springframework.stereotype.Component;
import org.ssssssss.magicapi.core.context.RequestEntity;
import org.ssssssss.magicapi.core.interceptor.ResultProvider;
import org.ssssssss.magicapi.modules.db.model.Page;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @ClassName: MagicAPIJsonConfig.java
* @Description: 統一請求響應配置
* @Author: tanyp
**/
@Component
public class MagicAPIJsonConfig implements ResultProvider {

/**
* @MonthName: buildResult
* @Description: 定義返回結果,默認返回JsonBean
* @Author: tanyp
* @Param: [requestEntity, i, s, o]
* @return: java.lang.Object
**/
@Override
public Object buildResult(RequestEntity requestEntity, int code, String message, Object data) {
return WrapMapper.wrap(code, message, data);
}

/**
* @MonthName: buildPageResult
* @Description: 定義分頁返回結果
* @Author: tanyp
* @Param: [requestEntity, page, total, data]
* @return: java.lang.Object
**/
@Override
public Object buildPageResult(RequestEntity requestEntity, Page page, long total, List<Map<String, Object>> data) {
return new HashMap<String, Object>() {
{
put("total", total);
put("pages", page.getOffset());
put("size", page.getLimit());
put("records", data);
}
};
}
}

定義返回結果實體類

package com.demo.base;

import java.util.Objects;

/**
* @ClassName: WrapMapper.java
* @Description: 返回包裝類
* @Author: tanyp
**/
public class WrapMapper {

private WrapMapper() {
}

public static <E> Wrapper<E> wrap(int code, String message, E o) {
return new Wrapper<E>(code, message, o);
}

public static <E> Wrapper<E> wrap(int code, String message) {
return new Wrapper<E>(code, message);
}

public static <E> Wrapper<E> wrap(int code) {
return wrap(code, null);
}

public static <E> Wrapper<E> wrap(Exception e) {
return new Wrapper<E>(Wrapper.ERROR_CODE, e.getMessage());
}

public static <E> E unWrap(Wrapper<E> wrapper) {
return wrapper.getResult();
}

public static <E> Wrapper<E> illegalArgument() {
return wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, Wrapper.ILLEGAL_ARGUMENT_MESSAGE);
}

public static <E> Wrapper<E> error() {
return wrap(Wrapper.ERROR_CODE, Wrapper.ERROR_MESSAGE);
}

public static <E> Wrapper<E> error(String message) {
return wrap(Wrapper.ERROR_CODE, Objects.isNull(message) ? Wrapper.ERROR_MESSAGE : message);
}

public static <E> Wrapper<E> error(int code, String message) {
return wrap(code, Objects.isNull(message) ? Wrapper.ERROR_MESSAGE : message);
}

public static <E> Wrapper<E> ok() {
return new Wrapper<E>();
}

public static <E> Wrapper<E> wrap(E o) {
return new Wrapper<>(Wrapper.SUCCESS_CODE, Wrapper.SUCCESS_MESSAGE, o);
}

public static <E> Wrapper<E> ok(E o) {
return new Wrapper<>(Wrapper.SUCCESS_CODE, Wrapper.SUCCESS_MESSAGE, o);
}

public static <E> Wrapper<E> success() {
return new Wrapper<>(Wrapper.SUCCESS_CODE, Wrapper.SUCCESS_MESSAGE);
}
}
package com.demo.base;

import java.io.Serializable;

/**
* @ClassName: Wrapper.java
* @Description: 包裝類
* @Author: tanyp
**/
public class Wrapper<T> implements Serializable {

/**
* 成功碼.
*/
public static final int SUCCESS_CODE = 200;

/**
* 成功信息.
*/
public static final String SUCCESS_MESSAGE = "操作成功";

/**
* 錯誤碼.
*/
public static final int ERROR_CODE = 500;

/**
* 錯誤信息.
*/
public static final String ERROR_MESSAGE = "系統異常,請稍后重試!";

/**
* 錯誤碼:參數非法
*/
public static final int ILLEGAL_ARGUMENT_CODE_ = 400;

/**
* 錯誤信息:參數非法
*/
public static final String ILLEGAL_ARGUMENT_MESSAGE = "請求參數非法,請核查!";

/**
* 錯誤碼:參數非法
*/
public static final int AUTHORIZATION_CODE = 402;

/**
* 錯誤信息:參數非法
*/
public static final String AUTHORIZATION_MESSAGE = "Token has expired";

/**
* 編號.
*/
private int code;

/**
* 信息.
*/
private String message;

/**
* 結果數據
*/
private T result;

public Wrapper() {
this(SUCCESS_CODE, SUCCESS_MESSAGE);
}

public Wrapper(int code, String message) {
this.code(code).message(message);
}

public Wrapper(int code, String message, T result) {
super();
this.code(code).message(message).result(result);
}

public int getCode() {
return code;
}

public void setCode(int code) {
this.code = code;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public T getResult() {
return result;
}

public void setResult(T result) {
this.result = result;
}

public Wrapper<T> code(int code) {
this.setCode(code);
return this;
}

public Wrapper<T> message(String message) {
this.setMessage(message);
return this;
}

public Wrapper<T> result(T result) {
this.setResult(result);
return this;
}

@Override
public String toString() {
return "Wrapper{" +
"code=" + code +
", message='" + message + '\'' +
", result=" + result +
'}';
}

public boolean isSuccess() {
return this.getCode() == Wrapper.SUCCESS_CODE;
}

public boolean isFail() {
return !isSuccess();
}
}

全局異常攔截

package com.demo.extension;

import com.demo.base.WrapMapper;
import com.demo.base.Wrapper;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
* @ClassName: GlobalException.java
* @Description: 全局異常攔截
* @Author: tanyp
**/
@RestControllerAdvice
public class GlobalException {

@ExceptionHandler(value = Exception.class)
public Wrapper handleException(Exception e) {
if (e instanceof MethodArgumentNotValidException) {
MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
// 參數校驗異常
return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, "參數有誤:" + ex.getBindingResult().getFieldError().getDefaultMessage(), null);
} else {
// 統一系統異常
return WrapMapper.wrap(Wrapper.ERROR_CODE, e.getMessage(), null);
}
}
}

初始化數據庫

CREATE TABLE magic_api_file (
  file_path varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  file_content mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
  PRIMARY KEY (file_path) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='API 表';

CREATE TABLE magic_backup_record (
  id varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '原對象ID',
  create_date bigint NOT NULL COMMENT '備份時間',
  tag varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '標簽',
  type varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '類型',
  name varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '原名稱',
  content blob COMMENT '備份內容',
  create_by varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '操作人',
  PRIMARY KEY (id,create_date) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='api 備份';

啟動項目

啟動成功,日志如下:

2024-01-03 09:44:24.290  INFO 4324 --- [           main] o.s.m.s.b.s.MagicAPIAutoConfiguration    : 注冊擴展:class org.ssssssss.magicapi.modules.servlet.ResponseModule -> class org.ssssssss.magicapi.servlet.javaee.MagicJavaEEResponseExtension
__ __ _ _ ____ ___
| \/ | __ _ __ _ (_) ___ / \ | _ \|_ _|
| |\/| | / _ | / _ || | / __| / _ \ | |_) || | | | | || (_| || (_| || || (__ / ___ \ | __/ | | |_| |_| \__,_| \__, ||_| \___|/_/ \_\|_| |___| |___/ 2.1.1 集成插件: - 組件 - 定時任務 2024-01-03 09:44:24.308 ERROR 4324 --- [ main] o.s.m.s.b.s.MagicAPIAutoConfiguration : 當前備份設置未配置,強烈建議配置備份設置,以免代碼丟失。 2024-01-03 09:44:24.338 INFO 4324 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '/' 2024-01-03 09:44:24.343 INFO 4324 --- [ main] com.ufan.admin.UfanAdminApplication : Started UfanAdminApplication in 2.158 seconds (JVM running for 2.62) ********************************************當前服務相關地址******************************************** 服務啟動成功,magic-api已內置啟動! Access URLs: 接口本地地址: http://localhost:8080/ 接口外部地址: http://172.16.80.253:8080/ 接口配置平臺: http://172.16.80.253:8080/api/web/index.html 可通過配置關閉輸出: magic-api.show-url=false ********************************************當前服務相關地址******************************************** 2024-01-03 09:44:26.206 INFO 4324 --- [nio-7001-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2024-01-03 09:44:26.206 INFO 4324 --- [nio-7001-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2024-01-03 09:44:26.206 INFO 4324 --- [nio-7001-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 0 ms

訪問:http://localhost:8080/api/web/index.html

如圖所示:

magic-api 總體來說還是非常方便的,在做一些中小型項目的時候可以輕易的解決問題。

了解更多請看官方文檔:https://www.ssssssss.org/magic-api

本文章轉載微信公眾號@全棧客

上一篇:

Ocelot:.NET開源API網關提供路由管理、服務發現、鑒權限流等功能

下一篇:

API生成完整指南
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費