
node.js + express + docker + mysql + jwt 實現用戶管理restful api
一個基于 Java 的接口快速開發框架,通過 magic-api
提供的 UI 界面完成編寫接口,無需定義 Controller
、Service
、Dao
、Mapper
、XML
、VO
等 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值
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
本文章轉載微信公眾號@全棧客
node.js + express + docker + mysql + jwt 實現用戶管理restful api
nodejs + mongodb 編寫 restful 風格博客 api
表格插件wpDataTables-將 WordPress 表與 Google Sheets API 連接
手把手教你用Python和Flask創建REST API
使用 Django 和 Django REST 框架構建 RESTful API:實現 CRUD 操作
ASP.NET Web API快速入門介紹
2024年在線市場平臺的11大最佳支付解決方案
完整指南:如何在應用程序中集成和使用ChatGPT API
選擇AI API的指南:ChatGPT、Gemini或Claude,哪一個最適合你?