diff --git a/.gitignore b/.gitignore
index 3aa6fbd5..056a5348 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@ APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/resources/static/cv/js/
APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/resources/static/cv/js/package.json
APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/resources/static/cv/package-lock.json
APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/resources/static/api/package-lock.json
+/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/.mvn
diff --git a/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/.gitignore b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/.gitignore
new file mode 100644
index 00000000..549e00a2
--- /dev/null
+++ b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/pom.xml b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/pom.xml
new file mode 100644
index 00000000..1da2e809
--- /dev/null
+++ b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/pom.xml
@@ -0,0 +1,74 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 4.1.1
+
+
+ apijson.demo
+ apijson-demo
+ apijson-demo
+ Demo project for Spring Boot
+ 7.9.0
+
+ 17
+
+
+
+
+ com.alibaba
+ fastjson
+ 1.2.84
+
+
+
+
+ com.github.Tencent
+ APIJSON
+ 7.9.0
+
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.29
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ 4.1.1
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ 4.1.1
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 4.1.1
+
+
+
+
+
+
+
+ jitpack.io
+ https://jitpack.io
+
+
+
+
diff --git a/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoApplication.java b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoApplication.java
new file mode 100755
index 00000000..f33713cd
--- /dev/null
+++ b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoApplication.java
@@ -0,0 +1,72 @@
+/*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.*/
+
+package apijson.demo;
+
+import apijson.Log;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.Map;
+
+
+/**
+ * Demo SpringBoot Application 主应用程序启动类
+ * 右键这个类 > Run As > Java Application
+ * 具体见 SpringBoot 文档
+ * https://www.springcloud.cc/spring-boot.html#using-boot-locating-the-main-class
+ *
+ * @author Lemon
+ */
+@Configuration
+@SpringBootApplication
+@EnableConfigurationProperties
+public class DemoApplication {
+
+ public static void main(String[] args) throws Exception {
+ SpringApplication app = new SpringApplication(DemoApplication.class);
+ app.setDefaultProperties(Map.of("server.port", 8080));
+ app.run(args);
+
+ Log.DEBUG = true; // TODO 上线前改为 false
+ System.out.println("官方网站: http://apijson.cn");
+ System.out.println("设计规范: https://github.com/Tencent/APIJSON/blob/master/Document.md#3");
+ System.out.println("测试链接: http://apijson.cn/api?type=JSON&url=http://localhost:8080/get");
+ System.out.println("\n\n<<<<<<<<<<<<<<<<<<<<<<<<< APIJSON 启动完成,试试调用零代码万能通用 API 吧 ^_^ >>>>>>>>>>>>>>>>>>>>>>>>\n");
+ }
+
+
+ // 支持 APIAuto 中 JavaScript 代码跨域请求
+ @Bean
+ public WebMvcConfigurer corsConfig() {
+ return new WebMvcConfigurer() {
+ @Override
+ public void addCorsMappings(CorsRegistry registry) {
+ registry.addMapping("/**")
+ .allowedOriginPatterns("*")
+ .allowedMethods("*")
+ .allowCredentials(true)
+ .maxAge(3600);
+ }
+ };
+ }
+
+
+}
diff --git a/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoController.java b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoController.java
new file mode 100644
index 00000000..48f5f531
--- /dev/null
+++ b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoController.java
@@ -0,0 +1,89 @@
+/*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.*/
+
+package apijson.demo;
+
+import apijson.RequestMethod;
+import apijson.StringUtil;
+import jakarta.servlet.http.HttpSession;
+import org.springframework.web.bind.annotation.*;
+
+import java.net.URLDecoder;
+
+
+/**请求路由入口控制器,包括通用增删改查接口等,转交给 APIJSON 的 Parser 来处理
+ * 具体见 SpringBoot 文档
+ * https://www.springcloud.cc/spring-boot.html#boot-features-spring-mvc
+ * 以及 APIJSON 通用文档 3.设计规范 3.1 操作方法
+ * https://github.com/Tencent/APIJSON/blob/master/Document.md#3.1
+ *
建议全通过HTTP POST来请求:
+ *
1.减少代码 - 客户端无需写HTTP GET,PUT等各种方式的请求代码
+ *
2.提高性能 - 无需URL encode和decode
+ *
3.调试方便 - 建议使用 APIAuto(http://apijson.cn/api) 或 Postman
+ * @author Lemon
+ */
+@RestController
+@RequestMapping("")
+public class DemoController { // extends APIJSONController {
+
+ public String parse(RequestMethod method, String request, HttpSession session) {
+ // TODO 这里关闭校验,方便新手快速测试,实际线上项目建议开启
+ return new DemoParser(method).setSession(session).setNeedVerify(false).parse(request);
+ }
+
+
+ //通用接口,非事务型操作 和 简单事务型操作 都可通过这些接口自动化实现<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+ /**获取
+ * @param request 只用String,避免encode后未decode
+ * @param session
+ * @return
+ * @see {@link RequestMethod#GET}
+ */
+ @PostMapping(value = "get")
+ public String get(@RequestBody String request, HttpSession session) {
+ return parse(RequestMethod.GET, request, session);
+ }
+
+
+ /**增删改查统一接口,这个一个接口可替代 7 个万能通用接口,牺牲一些路由解析性能来提升一点开发效率
+ * @param method
+ * @param request
+ * @param session
+ * @return
+ */
+ @PostMapping(value = "{method}") // 如果和其它的接口 URL 冲突,可以加前缀,例如改为 crud/{method} 或 Controller 注解 @RequestMapping("crud")
+// @Override
+ public String crud(@PathVariable String method, @RequestBody String request, HttpSession session) {
+ return parse(RequestMethod.valueOf(StringUtil.toUpperCase(method)), request, session);
+ }
+
+ /**获取
+ * 只为兼容HTTP GET请求,推荐用HTTP POST,可删除
+ * @param request 只用String,避免encode后未decode
+ * @param session
+ * @return
+ * @see {@link RequestMethod#GET}
+ */
+ @GetMapping("get/{request}")
+ public String openGet(@PathVariable String request, HttpSession session) {
+ try {
+ request = URLDecoder.decode(request, StringUtil.UTF_8);
+ } catch (Exception e) {
+ // Parser 会报错
+ }
+ return get(request, session);
+ }
+
+}
\ No newline at end of file
diff --git a/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoFunctionParser.java b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoFunctionParser.java
new file mode 100644
index 00000000..ef800088
--- /dev/null
+++ b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoFunctionParser.java
@@ -0,0 +1,39 @@
+/*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.*/
+
+package apijson.demo;
+
+import apijson.orm.AbstractFunctionParser;
+import com.alibaba.fastjson.JSONObject;
+
+import apijson.RequestMethod;
+
+
+/**可远程调用的函数类,用于自定义业务逻辑处理
+ * 具体见 https://github.com/Tencent/APIJSON/issues/101
+ * @author Lemon
+ */
+public class DemoFunctionParser extends AbstractFunctionParser {
+ public static final String TAG = "DemoFunctionParser";
+
+
+ public DemoFunctionParser() {
+ this(null, null, 0, null);
+ }
+ public DemoFunctionParser(RequestMethod method, String tag, int version, JSONObject request) {
+ super(method, tag, version, request);
+ }
+
+
+}
\ No newline at end of file
diff --git a/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoObjectParser.java b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoObjectParser.java
new file mode 100644
index 00000000..8c511ec9
--- /dev/null
+++ b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoObjectParser.java
@@ -0,0 +1,46 @@
+/*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.*/
+
+package apijson.demo;
+
+import apijson.orm.AbstractObjectParser;
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.List;
+
+
+import apijson.NotNull;
+import apijson.RequestMethod;
+import apijson.orm.Join;
+import apijson.orm.SQLConfig;
+import jakarta.servlet.http.HttpSession;
+
+
+/**对象解析器,用来简化 Parser
+ * @author Lemon
+ */
+public class DemoObjectParser extends AbstractObjectParser {
+
+ public DemoObjectParser(HttpSession session, @NotNull JSONObject request, String parentPath, SQLConfig arrayConfig
+ , boolean isSubquery, boolean isTable, boolean isArrayMainTable) throws Exception {
+ super(request, parentPath, arrayConfig, isSubquery, isTable, isArrayMainTable);
+ }
+
+ @Override
+ public SQLConfig newSQLConfig(RequestMethod method, String table, String alias, JSONObject request, List joinList, boolean isProcedure) throws Exception {
+ return DemoSQLConfig.newSQLConfig(method, table, alias, request, joinList, isProcedure);
+ }
+
+
+}
diff --git a/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoParser.java b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoParser.java
new file mode 100644
index 00000000..268fb164
--- /dev/null
+++ b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoParser.java
@@ -0,0 +1,139 @@
+/*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.*/
+
+package apijson.demo;
+
+import apijson.orm.*;
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import jakarta.servlet.http.HttpSession;
+
+import apijson.RequestMethod;
+
+
+/**请求解析器
+ * 具体见 https://github.com/Tencent/APIJSON/issues/38
+ * @author Lemon
+ */
+public class DemoParser extends AbstractParser {
+
+ public static final Map KEY_MAP;
+ static {
+ KEY_MAP = new HashMap<>();
+ }
+
+ public DemoParser() {
+ super();
+ }
+ public DemoParser(RequestMethod method) {
+ super(method);
+ }
+ public DemoParser(RequestMethod method, boolean needVerify) {
+ super(method, needVerify);
+ }
+
+ private int maxQueryCount = 2000;
+// // 可重写来设置最大查询数量
+// @Override
+// public int getMaxQueryCount() {
+// return maxQueryCount;
+// }
+//
+// @Override
+// public int getMaxUpdateCount() {
+// return 2000;
+// }
+//
+// @Override
+// public int getMaxObjectCount() {
+// return getMaxUpdateCount();
+// }
+//
+// @Override
+// public int getMaxSQLCount() {
+// return getMaxUpdateCount();
+// }
+
+
+ private HttpSession session;
+ public Parser setSession(HttpSession session) {
+ this.session = session;
+ return this;
+ }
+ public HttpSession getSession() {
+ return session;
+ }
+
+
+ @Override
+ public Parser createParser() {
+ return new DemoParser();
+ }
+
+ @Override
+ public ObjectParser createObjectParser(JSONObject request, String parentPath, SQLConfig arrayConfig
+ , boolean isSubquery, boolean isTable, boolean isArrayMainTable) throws Exception {
+ return new DemoObjectParser(getSession(), request, parentPath, arrayConfig
+ , isSubquery, isTable, isArrayMainTable).setMethod(getMethod()).setParser(this);
+ }
+
+ @Override
+ public FunctionParser createFunctionParser() {
+ return new DemoFunctionParser();
+ }
+
+ @Override
+ public SQLConfig createSQLConfig() {
+ return new DemoSQLConfig();
+ }
+
+ @Override
+ public SQLExecutor createSQLExecutor() {
+ return new DemoSQLExecutor();
+ }
+
+ @Override
+ public Verifier createVerifier() {
+ return new DemoVerifier();
+ }
+
+ private FunctionParser functionParser;
+ public FunctionParser getFunctionParser() {
+ return functionParser;
+ }
+
+ public Object onFunctionParse(String key, String function, String parentPath, String currentName
+ , JSONObject currentObject, boolean containRaw) throws Exception {
+ if (functionParser == null) {
+ functionParser = createFunctionParser();
+ functionParser.setMethod(getMethod());
+ functionParser.setTag(getTag());
+ functionParser.setVersion(getVersion());
+ functionParser.setRequest(requestObject);
+ }
+ functionParser.setKey(key);
+ functionParser.setParentPath(parentPath);
+ functionParser.setCurrentName(currentName);
+ functionParser.setCurrentObject(currentObject);
+
+ return functionParser.invoke(function, currentObject, containRaw);
+ }
+
+
+ // 实现应用层与数据库共用账号密码,可用于多租户、SQLAuto 等 >>>>>>>>>>>>>>>
+
+}
diff --git a/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoSQLConfig.java b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoSQLConfig.java
new file mode 100755
index 00000000..72b79a41
--- /dev/null
+++ b/APIJSON-Java-Server/APIJSONDemo-SpringBoot4/src/main/java/apijson/demo/DemoSQLConfig.java
@@ -0,0 +1,118 @@
+/*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.*/
+
+package apijson.demo;
+
+import java.util.*;
+
+import apijson.orm.AbstractSQLConfig;
+
+import apijson.RequestMethod;
+import apijson.orm.Join;
+import apijson.orm.Join.On;
+import apijson.orm.SQLConfig;
+
+
+/**SQL配置
+ * TiDB 用法和 MySQL 一致
+ * 具体见详细的说明文档 C.开发说明 C-1-1.修改数据库链接
+ * https://github.com/Tencent/APIJSON/blob/master/%E8%AF%A6%E7%BB%86%E7%9A%84%E8%AF%B4%E6%98%8E%E6%96%87%E6%A1%A3.md#c-1-1%E4%BF%AE%E6%94%B9%E6%95%B0%E6%8D%AE%E5%BA%93%E9%93%BE%E6%8E%A5
+ * @author Lemon
+ */
+public class DemoSQLConfig extends AbstractSQLConfig {
+
+ public DemoSQLConfig() {
+ super(RequestMethod.GET);
+ }
+ public DemoSQLConfig(RequestMethod method) {
+ super(method);
+ }
+ public DemoSQLConfig(RequestMethod method, String table) {
+ super(method, table);
+ }
+
+ static {
+ DEFAULT_DATABASE = DATABASE_MYSQL; //TODO 默认数据库类型,改成你自己的。TiDB, MariaDB, OceanBase 这类兼容 MySQL 的可当做 MySQL 使用
+ DEFAULT_SCHEMA = "sys"; //TODO 默认数据库名/模式,改成你自己的,默认情况是 MySQL: sys, PostgreSQL: sys, SQL Server: dbo, Oracle:
+
+ // 表名和数据库不一致的,需要配置映射关系。只使用 APIJSONORM 时才需要;
+ // 这个 Demo 用了 apijson-framework 且调用了 APIJSONApplication.init 则不需要
+ // (间接调用 DemoVerifier.init 方法读取数据库 Access 表来替代手动输入配置)。
+ // 但如果 Access 这张表的对外表名与数据库实际表名不一致,仍然需要这里注册。例如
+ // TABLE_KEY_MAP.put(Access.class.getSimpleName(), "access");
+
+ // 表名映射,隐藏真实表名,对安全要求很高的表可以这么做
+ TABLE_KEY_MAP.put("User", "apijson_user");
+ TABLE_KEY_MAP.put("Privacy", "apijson_privacy");
+
+ }
+
+
+ @Override
+ public String getDBVersion() {
+ return "8.0.11"; //TODO 改成你自己的 MySQL 或 PostgreSQL 数据库版本号 //MYSQL 8 和 7 使用的 JDBC 配置不一样
+ }
+ @Override
+ public String getDBUri() {
+ // 这个是 MySQL 8.0 及以上,要加 userSSL=false
+ return "jdbc:mysql://localhost:3306?userSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8";
+ // 以下是 MySQL 5.7 及以下
+ // return "jdbc:mysql://localhost:3306?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8"; //TODO 改成你自己的,TiDB 可以当成 MySQL 使用,默认端口为 4000
+ }
+ @Override
+ public String getDBAccount() {
+ return "root"; //TODO 改成你自己的
+ }
+ @Override
+ public String getDBPassword() {
+ return "apijson"; //TODO 改成你自己的,TiDB 可以当成 MySQL 使用, 默认密码为空字符串 ""
+ }
+
+ public static SQLConfig newSQLConfig(RequestMethod method, String table, String alias, com.alibaba.fastjson.JSONObject request, List joinList, boolean isProcedure) throws Exception {
+ return AbstractSQLConfig.newSQLConfig(method, table, alias, request, joinList, isProcedure, new SimpleCallback