diff --git a/.gitignore b/.gitignore index 979b4ad5..44013869 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.class data.db* .neutrino-proxy.license +.neutrino-proxy-client.json* lib/* diff --git a/README.md b/README.md index f9e663ed..8a389016 100644 --- a/README.md +++ b/README.md @@ -99,20 +99,25 @@ proxy: 默认情况下,客户端会加载当前目录下的.neutrino-proxy.license里的license,可通过命令行参数指定,如:java -jar neutrino-proxy-client.jar license=xxx 若启动参数未指定license,且是首次启动(当前目录下未缓存license),则需要根据命令行提示输入正确的license, 输入完成后完成连接,可在服务端管理页面控制端口转发,参见[2、运行示例](#2) -# 6、未来迭代方向 +# 6、演示环境 +> 可适用分配好的游客license试用。服务器带宽较低,仅供学习使用,大家手下留情! +- 管理后台地址:http://103.163.47.16:8888 +- 游客账号:visitor/123456 + +# 7、未来迭代方向 - 优化代码、增强稳定性 - 服务端增加管理页面,提供报表、授权、限流等功能 - 从项目中分离、孵化出另一个开源项目(neutrino-framework) -# 7、技术文档 +# 8、技术文档 - [Aop](./docs/Aop.MD) +- [Channel](./docs/Channel.MD) -# 8、联系我们 +# 9、联系我们 - 微信: yuyunshize -- Gitee(主更): https://gitee.com/asgc/neutrino-proxy -- Github: https://github.com/aoshiguchen/neutrino-proxy +- Gitee: https://gitee.com/asgc/neutrino-proxy -# 9、特别鸣谢 +# 10、特别鸣谢 * [JetBrains](https://www.jetbrains.com?from=RedisFront) ![JenBrains logo](assets/jetbrains.svg) \ No newline at end of file diff --git a/docs/Channel.MD b/docs/Channel.MD new file mode 100644 index 00000000..5c31b33e --- /dev/null +++ b/docs/Channel.MD @@ -0,0 +1,54 @@ +# 代理实现中涉及的几类Channel + +## 指令通道(CmdChannel) +- 该channel负责维护客户端与服务端之间的指令通讯,由客户端启动后向服务端发起连接请求,服务端验证license成功后连接建立。 +- 服务端维护第一个CmdChannel的映射表,key为licenseId。服务端可以根据licenseId,向指定的客户端指令通道发布指令。 +- 该通道建立完成后,服务端会将该license授权的外网映射端口打开,等待用户访问。正常情况下,只要客户端不下线,该通道一直可用。 +- 然后服务端维护第二个CmdChannel的映射表,key为服务端外网端口。服务端可以根据指定的外网端口,向指定的客户端指令通道发布指令。 + +## 用户访问通道(VisitorChannel) +- 该channel负责维护访问者与服务端端口之间的通讯,由访问者向服务端映射的外网端口发起请求开始建立,具体断开时机由实际的被代理的 +协议决定。 +- 如HTTP/1.0下,用户向该端口发起请求,响应结束后,该通道随之关闭,下一次发起请求后,重新建立新的连接。 +- 该连接建立后,服务端会向该外网端口映射的指令通道发送`Connect`指令,传输该外网端口需要代理的内网信息, +如:`127.0.0.1:3306`。 + +## 被代理服务的实际通道(RealServerChannel) +- 该channel负责维护客户端与实际被代理服务之间的通讯,当客户端接收到服务端的`Connect`指令后,客户端便会建立该通道。 + +## 代理数据传输的通道(ProxyChannel) +- 该channel负责完成内网被代理服务与代理服务端之间的数据转发任务。 +- 每个客户端维护一个`ProxyChannel`的缓存队列,需要时从该队列中取,当取不到时,直接新建一个`ProxyChannel`返回。 +当一个`ProxyChannel`实例用完后,需要归还到缓存队列中(`ProxyChannel`收到`DisConnect`指令时)。 +- 当`RealServerChannel`建立完成后,就会获取相关联的`ProxyChannel`,并与其绑定。设置`RealServerChannel`为 +可读状态。然后通过`ProxyChannel`向服务端发送`Connect`指令。 + + +# 代理实现流程 +## 1、服务连接阶段 +- 1.1、客户端根据是否需要使用SSL,选择对应的服务端端口发起连接,建立`CmdChannel`。 +- 1.2、客户端根据用户输入或配置文件获取`license`,并携带`license`通过`CmdChannel`向服务端发送`Auth`指令。 +- 1.3、服务端通过`CmdChannel`接收到来自客户端的`Auth`指令。若验证`license`有效,则建立`licenseId`与`CmdChannel`的映射缓存、 +外网端口与`CmdChannel`的映射缓存。并启动服务端代理端口,等待用户连接。 +## 2、用户连接阶段 +- 2.1、用户访向服务端代理的外网端口发起请求,服务端建立`VisitorChannel`。 +- 2.2、根据外网端口查找`CmdChannel`,若不存在有效的`CmdChannel`,则关闭该`VisitorChannel`。否则, +设置`VisitorChannel`为不可读,并携带内网映射信息(如:`127.0.0.1:3306`)通过`CmdChannel`向客户端发送`Connect`指令。 +## 3、实际被代理服务连接阶段 +- 3.1、客户端通过`CmdChannel`接收到服务端的`Connect`指令。拿到需要代理的内网IP、端口号,向实际被 +代理服务发起连接请求,若连接失败,则通过`CmdChannel`向服务端发送`DisConnect`指令。建立`RealServerChannel`成功,设置`RealServerChannel`为不可读 +状态,并进入4.1阶段 +## 4、代理通道连接阶段 +- 4.1、客户端通过`ProxyChannelQueue`获取或新建一个`ProxyChannel`,并将`RealServerChannel`与`ProxyChannel`进行绑定。 +- 4.2、客户端通过`ProxyChannel`向服务端发送`Connect`指令。 +- 4.3、服务端通过`ProxyChannel`通道收到来自客户端的`Connect`指令后,将`ProxyChannel`与对应的`VisitorChannel`进行绑定,并 +设置`VisitorChannel`为可读状态。 +## 5、数据传输阶段 +- 5.1、服务端通过`VisitorChannel`收到来自用户的请求数据,然后找到`VisitorChannel`绑定的`ProxyChannel`, +通过`ProxyChannel`发送`Transfer`指令,并携带用户请求数据。 +- 5.2、客户端通过`ProxyChannel`收到来自服务端的`Transfer`指令,取出用户请求数据。找到`ProxyChannel`绑定的`RealServerChannel`, +通过`RealServerChannel`向被代理服务写入用户请求数据。 +- 5.3、客户端通过`RealServerChannel`收到被代理服务响应的数据,找到`RealServerChannel`绑定的`ProxyChannel`, +通过`ProxyChannel`向服务端发送`Transfer`指令,并携带响应数据。 +- 5.4、服务端通过`ProxyChannel`收到来自客户端的`Transfer`指令,找到`ProxyChannel`绑定的`VisitorChannel`, +通过`VisitorChannel`向用户端写入响应数据。 diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/AsgcProxyFactory.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/AsgcProxyFactory.java index aa0acdc1..4df457f3 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/AsgcProxyFactory.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/AsgcProxyFactory.java @@ -40,7 +40,6 @@ public class AsgcProxyFactory implements ProxyFactory { private static final String classNameTemplate = "%s" + SYMBOLIC + "%s"; private static AtomicLong proxyClassCounter = new AtomicLong(); private AsgcCompiler compiler = new AsgcCompiler(); - private ProxyClassLoader classLoader = new ProxyClassLoader(); @Override public T get(Class targetType) throws Exception { diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/ProxyClassLoader.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/ProxyClassLoader.java deleted file mode 100644 index 016ee66b..00000000 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/aop/proxy/ProxyClassLoader.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Copyright (c) 2022 aoshiguchen - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fun.asgc.neutrino.core.aop.proxy; - -import fun.asgc.neutrino.core.base.GlobalConfig; -import fun.asgc.neutrino.core.util.FileUtil; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 代理类加载器 - * @author: aoshiguchen - * @date: 2022/6/24 - */ -public class ProxyClassLoader extends ClassLoader { - - protected Map byteCodeMap = new ConcurrentHashMap<>(); - - static { - registerAsParallelCapable(); - } - - public ProxyClassLoader() { - super(getParentClassLoader()); - } - - protected static ClassLoader getParentClassLoader() { - ClassLoader ret = Thread.currentThread().getContextClassLoader(); - return ret != null ? ret : ProxyClassLoader.class.getClassLoader(); - } - - public Class loadProxyClass(ProxyClass proxyClass) { - if (null != proxyClass.getByteCode()) { - for (Map.Entry e : proxyClass.getByteCode().entrySet()) { - byteCodeMap.putIfAbsent(e.getKey(), e.getValue()); - } - } - - try { - return loadClass(proxyClass.getPkg() + "." + proxyClass.getName()); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - byte[] bytes = byteCodeMap.get(name); - if (null == bytes) { - bytes = FileUtil.readBytes( GlobalConfig.getGeneratorCodeSavePath() + name.replaceAll("\\.", "/") + ".class"); - } - if (bytes != null) { - Class ret = defineClass(name, bytes, 0, bytes.length); - byteCodeMap.remove(name); - return ret; - } - - return super.findClass(name); - } -} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/CrispDbKit.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/CrispDbKit.java new file mode 100644 index 00000000..b189ea9c --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/CrispDbKit.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp; + +/** + * 清爽的数据库工具 + * @author: aoshiguchen + * @date: 2022/11/3 + */ +public class CrispDbKit { + private static final JdbcManager manager = new JdbcManager(); + + +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/DbConfig.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/DbConfig.java new file mode 100644 index 00000000..9ee65ced --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/DbConfig.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp; + +import fun.asgc.neutrino.core.db.crisp.ds.DefaultDataSourceProvider; +import fun.asgc.neutrino.core.db.crisp.ds.IDataSourceProvider; + +import javax.sql.DataSource; + +/** + * @author: aoshiguchen + * @date: 2022/11/3 + */ +public class DbConfig { + /** + * 数据库名称 + */ + private String name; + /** + * 数据源提供者 + */ + private IDataSourceProvider dataSourceProvider; + /** + * 是否显示sql + */ + private Boolean showSql; + /** + * 是否开启调试模式 + */ + private Boolean debugMode; + /** + * 上下文 + */ + private DbContext context; + /** + * 数据库执行器 + */ + private DbExecutor dbExecutor; + + public DbConfig(String name, IDataSourceProvider dataSourceProvider) { + this.name = name; + this.dataSourceProvider = dataSourceProvider; + this.showSql = Boolean.FALSE; + this.debugMode = Boolean.FALSE; + this.context = new DbContext(this); + this.dbExecutor = new DbExecutor(this); + } + + public DbConfig(String name, DataSource dataSource) { + this(name, new DefaultDataSourceProvider(dataSource)); + } + + public DbConfig(IDataSourceProvider dataSourceProvider) { + this("unknown", dataSourceProvider); + } + + public DbConfig(DataSource dataSource) { + this(new DefaultDataSourceProvider(dataSource)); + } + + /** + * 获取数据库操作实例 + * @return 数据库操作实例 + */ + public DbExecutor getDbExecutor() { + return dbExecutor; + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/DbContext.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/DbContext.java new file mode 100644 index 00000000..78f9ef4b --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/DbContext.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp; + +import fun.asgc.neutrino.core.db.crisp.session.SqlSessionFactory; + +import java.sql.Connection; + +/** + * @author: aoshiguchen + * @date: 2022/11/3 + */ +public class DbContext { + private DbConfig dbConfig; + private final ThreadLocal connectionHolder = new ThreadLocal<>(); + + public DbContext(DbConfig dbConfig) { + this.dbConfig = dbConfig; + } + public SqlSessionFactory getSqlSessionFactory() { + // TODO + return null; + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/DbExecutor.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/DbExecutor.java new file mode 100644 index 00000000..8851b75a --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/DbExecutor.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp; + +import fun.asgc.neutrino.core.db.crisp.base.DbUpdateResult; +import fun.asgc.neutrino.core.db.crisp.ds.IDataSourceProvider; + +import javax.sql.DataSource; +import java.util.List; + +/** + * @author: aoshiguchen + * @date: 2022/11/3 + */ +class DbExecutor implements DbOperator { + /** + * 配置 + */ + private DbConfig config; + + + public DbExecutor(DbConfig config) { + this.config = config; + } + + public DbExecutor(IDataSourceProvider dataSourceProvider) { + this(new DbConfig(dataSourceProvider)); + } + + public DbExecutor(String name, IDataSourceProvider dataSourceProvider) { + this(new DbConfig(name, dataSourceProvider)); + } + + public DbExecutor(DataSource dataSource) { + this(new DbConfig(dataSource)); + } + + public DbExecutor(String name, DataSource dataSource) { + this(new DbConfig(name, dataSource)); + } + + @Override + public List queryList(Class resultType, String sql, Object... params) { + return null; + } + + @Override + public T query(Class resultType, String sql, Object... params) { + return null; + } + + @Override + public DbUpdateResult update(String sql, Object... params) { + return null; + } + + @Override + public DbUpdateResult insert(String sql, Object... params) { + return null; + } + + @Override + public DbUpdateResult delete(String sql, Object... params) { + return null; + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/DbOperator.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/DbOperator.java new file mode 100644 index 00000000..1e114cf7 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/DbOperator.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp; + +import fun.asgc.neutrino.core.db.crisp.base.DbUpdateResult; + +import java.util.List; + +/** + * @author: aoshiguchen + * @date: 2022/11/3 + */ +public interface DbOperator { + /** + * 查询数据列表 + * @param resultType 结果类型 + * @param sql sql + * @param params 参数列表 + * @return 查询结果列表 + * @param + */ + List queryList(Class resultType, String sql, Object... params); + + /** + * 查询单条记录 + * @param resultType 结果类型 + * @param sql sql + * @param params 参数列表 + * @return 查询结果 + * @param + */ + T query(Class resultType, String sql, Object... params); + + /** + * 更新 + * @param sql sql + * @param params 参数列表 + * @return 更新结果 + */ + DbUpdateResult update(String sql, Object... params); + + /** + * 新增 + * @param sql sql + * @param params 参数列表 + * @return 新增结果 + */ + DbUpdateResult insert(String sql, Object... params); + + /** + * 删除 + * @param sql sql + * @param params 参数列表 + * @return 删除结果 + */ + DbUpdateResult delete(String sql, Object... params); +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/JdbcException.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/JdbcException.java new file mode 100644 index 00000000..664e9b98 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/JdbcException.java @@ -0,0 +1,18 @@ +package fun.asgc.neutrino.core.db.crisp; + +import fun.asgc.neutrino.core.exception.InternalException; + +/** + * @author: aoshiguchen + * @date: 2022/11/7 + */ +public class JdbcException extends InternalException { + + public JdbcException(String message) { + super(message); + } + + public JdbcException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/JdbcManager.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/JdbcManager.java new file mode 100644 index 00000000..c29cb768 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/JdbcManager.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author: aoshiguchen + * @date: 2022/11/4 + */ +public class JdbcManager { + /** + * 数据源缓存 + */ + private Map dbConfigMap = new HashMap<>(); + /** + * 默认数据库的key + */ + private final String DEFAULT_KEY = "default"; + + /** + * 设置默认数据库配置 + * @param config 数据库配置 + */ + public void setConfig(DbConfig config) { + setConfig(DEFAULT_KEY, config); + } + + /** + * 设置数据库配置 + * @param key 键 + * @param config 数据库配置 + */ + public void setConfig(String key, DbConfig config) { + dbConfigMap.put(key, config); + } + + /** + * 根据名称获取数据库配置 + * @param key 键 + * @return 数据库配置 + */ + public DbConfig getConfig(String key) { + return dbConfigMap.get(key); + } + + /** + * 获取默认数据库配置 + * @return 数据库配置 + */ + public DbConfig getConfig() { + return getConfig(DEFAULT_KEY); + } + + /** + * 获取默认数据库操作实例 + * @return + */ + private DbExecutor getDbExecutor(String key) { + DbConfig dbConfig = getConfig(key); + return null == dbConfig ? null : dbConfig.getDbExecutor(); + } + + /** + * 切换数据源 + * @param name 数据源名称 + * @return 数据库操作实例 + */ + public DbExecutor use(String name) { + return getDbExecutor(name); + } + + /** + * 切换为默认数据源 + * @return 默认数据库操作实例 + */ + public DbExecutor useDefault() { + return getDbExecutor(DEFAULT_KEY); + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/BatchResult.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/BatchResult.java new file mode 100644 index 00000000..982b3198 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/BatchResult.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.base; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author: aoshiguchen + * @date: 2022/11/4 + */ +public class BatchResult { + + private final MappedStatement mappedStatement; + private final String sql; + private final List parameterObjects; + + private int[] updateCounts; + + public BatchResult(MappedStatement mappedStatement, String sql) { + super(); + this.mappedStatement = mappedStatement; + this.sql = sql; + this.parameterObjects = new ArrayList<>(); + } + + public BatchResult(MappedStatement mappedStatement, String sql, Object parameterObject) { + this(mappedStatement, sql); + addParameterObject(parameterObject); + } + + public MappedStatement getMappedStatement() { + return mappedStatement; + } + + public String getSql() { + return sql; + } + + @Deprecated + public Object getParameterObject() { + return parameterObjects.get(0); + } + + public List getParameterObjects() { + return parameterObjects; + } + + public int[] getUpdateCounts() { + return updateCounts; + } + + public void setUpdateCounts(int[] updateCounts) { + this.updateCounts = updateCounts; + } + + public void addParameterObject(Object parameterObject) { + this.parameterObjects.add(parameterObject); + } + +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/DbUpdateResult.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/DbUpdateResult.java new file mode 100644 index 00000000..91e7a423 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/DbUpdateResult.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.base; + +/** + * @author: aoshiguchen + * @date: 2022/11/3 + */ +public class DbUpdateResult { + +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/MappedStatement.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/MappedStatement.java new file mode 100644 index 00000000..c2459d9b --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/MappedStatement.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.base; + +/** + * @author: aoshiguchen + * @date: 2022/11/4 + */ +public class MappedStatement { + // TODO +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/RowBounds.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/RowBounds.java new file mode 100644 index 00000000..461c1e79 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/RowBounds.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.base; + +/** + * @author: aoshiguchen + * @date: 2022/11/4 + */ +public class RowBounds { + + public static final int NO_ROW_OFFSET = 0; + public static final int NO_ROW_LIMIT = Integer.MAX_VALUE; + public static final RowBounds DEFAULT = new RowBounds(); + + private final int offset; + private final int limit; + + public RowBounds() { + this.offset = NO_ROW_OFFSET; + this.limit = NO_ROW_LIMIT; + } + + public RowBounds(int offset, int limit) { + this.offset = offset; + this.limit = limit; + } + + public int getOffset() { + return offset; + } + + public int getLimit() { + return limit; + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/SqlExecutorType.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/SqlExecutorType.java new file mode 100644 index 00000000..802e513a --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/base/SqlExecutorType.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.base; + +/** + * @author: aoshiguchen + * @date: 2022/11/4 + */ +public enum SqlExecutorType { + SIMPLE, REUSE, BATCH +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/ds/DefaultDataSourceProvider.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/ds/DefaultDataSourceProvider.java new file mode 100644 index 00000000..4d49288c --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/ds/DefaultDataSourceProvider.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.ds; + +import javax.sql.DataSource; + +/** + * @author: aoshiguchen + * @date: 2022/11/3 + */ +public class DefaultDataSourceProvider implements IDataSourceProvider { + /** + * 数据源 + */ + private DataSource dataSource; + + public DefaultDataSourceProvider(DataSource dataSource) { + this.dataSource = dataSource; + } + + @Override + public DataSource getDataSource() { + return dataSource; + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/ds/IDataSourceProvider.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/ds/IDataSourceProvider.java new file mode 100644 index 00000000..fa748d58 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/ds/IDataSourceProvider.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.ds; + +import javax.sql.DataSource; + +/** + * 数据源提供商 + * @author: aoshiguchen + * @date: 2022/11/3 + */ +public interface IDataSourceProvider { + /** + * 获取数据源 + * @return + */ + DataSource getDataSource(); +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/DefaultSqlSessionFactory.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/DefaultSqlSessionFactory.java new file mode 100644 index 00000000..fa613d44 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/DefaultSqlSessionFactory.java @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.session; + +import fun.asgc.neutrino.core.db.crisp.DbConfig; +import fun.asgc.neutrino.core.db.crisp.base.SqlExecutorType; +import fun.asgc.neutrino.core.db.crisp.tx.TransactionIsolationLevel; + +import java.sql.Connection; + +/** + * @author: aoshiguchen + * @date: 2022/11/4 + */ +public class DefaultSqlSessionFactory implements SqlSessionFactory { + + private final DbConfig config; + + public DefaultSqlSessionFactory(DbConfig config) { + this.config = config; + } + + @Override + public SqlSession openSession() { + // TODO + return null; + } + + @Override + public SqlSession openSession(boolean autoCommit) { + // TODO + return null; + } + + @Override + public SqlSession openSession(Connection connection) { + // TODO + return null; + } + + @Override + public SqlSession openSession(TransactionIsolationLevel level) { + // TODO + return null; + } + + @Override + public SqlSession openSession(SqlExecutorType execType) { + // TODO + return null; + } + + @Override + public SqlSession openSession(SqlExecutorType execType, boolean autoCommit) { + // TODO + return null; + } + + @Override + public SqlSession openSession(SqlExecutorType execType, TransactionIsolationLevel level) { + // TODO + return null; + } + + @Override + public SqlSession openSession(SqlExecutorType execType, Connection connection) { + // TODO + return null; + } + + @Override + public DbConfig getDbConfig() { + // TODO + return null; + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/ResultContext.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/ResultContext.java new file mode 100644 index 00000000..4448e05d --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/ResultContext.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.session; + +/** + * @author: aoshiguchen + * @date: 2022/11/23 + */ +public interface ResultContext { + T getResultObject(); + + int getResultCount(); + + boolean isStopped(); + + void stop(); +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/ResultHandler.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/ResultHandler.java new file mode 100644 index 00000000..027c9108 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/ResultHandler.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.session; + +/** + * @author: aoshiguchen + * @date: 2022/11/23 + */ +public interface ResultHandler { + void handleResult(ResultContext resultContext); +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/SqlSession.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/SqlSession.java new file mode 100644 index 00000000..6633f51c --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/SqlSession.java @@ -0,0 +1,264 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.session; + +import fun.asgc.neutrino.core.db.crisp.DbConfig; +import fun.asgc.neutrino.core.db.crisp.base.BatchResult; +import fun.asgc.neutrino.core.db.crisp.base.RowBounds; + +import java.io.Closeable; +import java.sql.Connection; +import java.util.List; +import java.util.Map; + +/** + * @author: aoshiguchen + * @date: 2022/11/4 + */ +public interface SqlSession extends Closeable { + + /** + * Retrieve a single row mapped from the statement key. + * @param the returned object type + * @param statement + * @return Mapped object + */ + T selectOne(String statement); + + /** + * Retrieve a single row mapped from the statement key and parameter. + * @param the returned object type + * @param statement Unique identifier matching the statement to use. + * @param parameter A parameter object to pass to the statement. + * @return Mapped object + */ + T selectOne(String statement, Object parameter); + + /** + * Retrieve a list of mapped objects from the statement key and parameter. + * @param the returned list element type + * @param statement Unique identifier matching the statement to use. + * @return List of mapped object + */ + List selectList(String statement); + + /** + * Retrieve a list of mapped objects from the statement key and parameter. + * @param the returned list element type + * @param statement Unique identifier matching the statement to use. + * @param parameter A parameter object to pass to the statement. + * @return List of mapped object + */ + List selectList(String statement, Object parameter); + + /** + * Retrieve a list of mapped objects from the statement key and parameter, + * within the specified row bounds. + * @param the returned list element type + * @param statement Unique identifier matching the statement to use. + * @param parameter A parameter object to pass to the statement. + * @param rowBounds Bounds to limit object retrieval + * @return List of mapped object + */ + List selectList(String statement, Object parameter, RowBounds rowBounds); + + /** + * The selectMap is a special case in that it is designed to convert a list + * of results into a Map based on one of the properties in the resulting + * objects. + * Eg. Return a of Map[Integer,Author] for selectMap("selectAuthors","id") + * @param the returned Map keys type + * @param the returned Map values type + * @param statement Unique identifier matching the statement to use. + * @param mapKey The property to use as key for each value in the list. + * @return Map containing key pair data. + */ + Map selectMap(String statement, String mapKey); + + /** + * The selectMap is a special case in that it is designed to convert a list + * of results into a Map based on one of the properties in the resulting + * objects. + * @param the returned Map keys type + * @param the returned Map values type + * @param statement Unique identifier matching the statement to use. + * @param parameter A parameter object to pass to the statement. + * @param mapKey The property to use as key for each value in the list. + * @return Map containing key pair data. + */ + Map selectMap(String statement, Object parameter, String mapKey); + + /** + * The selectMap is a special case in that it is designed to convert a list + * of results into a Map based on one of the properties in the resulting + * objects. + * @param the returned Map keys type + * @param the returned Map values type + * @param statement Unique identifier matching the statement to use. + * @param parameter A parameter object to pass to the statement. + * @param mapKey The property to use as key for each value in the list. + * @param rowBounds Bounds to limit object retrieval + * @return Map containing key pair data. + */ + Map selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds); + + /** + * Retrieve a single row mapped from the statement key and parameter + * using a {@code ResultHandler}. + * + * @param statement Unique identifier matching the statement to use. + * @param parameter A parameter object to pass to the statement. + * @param handler ResultHandler that will handle each retrieved row + */ + default void select(String statement, Object parameter, ResultHandler handler) { + + } + + /** + * Retrieve a single row mapped from the statement + * using a {@code ResultHandler}. + * @param statement Unique identifier matching the statement to use. + * @param handler ResultHandler that will handle each retrieved row + */ + void select(String statement, ResultHandler handler); + + /** + * Retrieve a single row mapped from the statement key and parameter + * using a {@code ResultHandler} and {@code RowBounds}. + * @param statement Unique identifier matching the statement to use. + * @param rowBounds RowBound instance to limit the query results + * @param handler ResultHandler that will handle each retrieved row + */ + void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler); + + /** + * Execute an insert statement. + * @param statement Unique identifier matching the statement to execute. + * @return int The number of rows affected by the insert. + */ + int insert(String statement); + + /** + * Execute an insert statement with the given parameter object. Any generated + * autoincrement values or selectKey entries will modify the given parameter + * object properties. Only the number of rows affected will be returned. + * @param statement Unique identifier matching the statement to execute. + * @param parameter A parameter object to pass to the statement. + * @return int The number of rows affected by the insert. + */ + int insert(String statement, Object parameter); + + /** + * Execute an update statement. The number of rows affected will be returned. + * @param statement Unique identifier matching the statement to execute. + * @return int The number of rows affected by the update. + */ + int update(String statement); + + /** + * Execute an update statement. The number of rows affected will be returned. + * @param statement Unique identifier matching the statement to execute. + * @param parameter A parameter object to pass to the statement. + * @return int The number of rows affected by the update. + */ + int update(String statement, Object parameter); + + /** + * Execute a delete statement. The number of rows affected will be returned. + * @param statement Unique identifier matching the statement to execute. + * @return int The number of rows affected by the delete. + */ + int delete(String statement); + + /** + * Execute a delete statement. The number of rows affected will be returned. + * @param statement Unique identifier matching the statement to execute. + * @param parameter A parameter object to pass to the statement. + * @return int The number of rows affected by the delete. + */ + int delete(String statement, Object parameter); + + /** + * Flushes batch statements and commits database connection. + * Note that database connection will not be committed if no updates/deletes/inserts were called. + * To force the commit call {@link SqlSession#commit(boolean)} + */ + void commit(); + + /** + * Flushes batch statements and commits database connection. + * @param force forces connection commit + */ + void commit(boolean force); + + /** + * Discards pending batch statements and rolls database connection back. + * Note that database connection will not be rolled back if no updates/deletes/inserts were called. + * To force the rollback call {@link SqlSession#rollback(boolean)} + */ + void rollback(); + + /** + * Discards pending batch statements and rolls database connection back. + * Note that database connection will not be rolled back if no updates/deletes/inserts were called. + * @param force forces connection rollback + */ + void rollback(boolean force); + + /** + * Flushes batch statements. + * @return BatchResult list of updated records + * @since 3.0.6 + */ + List flushStatements(); + + /** + * Closes the session. + */ + @Override + void close(); + + /** + * Clears local session cache. + */ + void clearCache(); + + /** + * Retrieves current configuration. + * @return DbConfig + */ + DbConfig getDbConfig(); + + /** + * Retrieves a mapper. + * @param the mapper type + * @param type Mapper interface class + * @return a mapper bound to this SqlSession + */ + T getMapper(Class type); + + /** + * Retrieves inner database connection. + * @return Connection + */ + Connection getConnection(); +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/SqlSessionFactory.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/SqlSessionFactory.java new file mode 100644 index 00000000..ebd82cc0 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/SqlSessionFactory.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.session; + +import fun.asgc.neutrino.core.db.crisp.DbConfig; +import fun.asgc.neutrino.core.db.crisp.base.SqlExecutorType; +import fun.asgc.neutrino.core.db.crisp.tx.TransactionIsolationLevel; + +import java.sql.Connection; + +/** + * @author: aoshiguchen + * @date: 2022/11/4 + */ +public interface SqlSessionFactory { + + SqlSession openSession(); + + SqlSession openSession(boolean autoCommit); + + SqlSession openSession(Connection connection); + + SqlSession openSession(TransactionIsolationLevel level); + + SqlSession openSession(SqlExecutorType execType); + + SqlSession openSession(SqlExecutorType execType, boolean autoCommit); + + SqlSession openSession(SqlExecutorType execType, TransactionIsolationLevel level); + + SqlSession openSession(SqlExecutorType execType, Connection connection); + + DbConfig getDbConfig(); +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/SqlSessionFactoryBuilder.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/SqlSessionFactoryBuilder.java new file mode 100644 index 00000000..ff77cc3f --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/session/SqlSessionFactoryBuilder.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.session; + +import fun.asgc.neutrino.core.db.crisp.DbConfig; + +/** + * @author: aoshiguchen + * @date: 2022/11/7 + */ +public class SqlSessionFactoryBuilder { + public SqlSessionFactory build(DbConfig config) { + return new DefaultSqlSessionFactory(config); + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/tx/JdbcTransaction.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/tx/JdbcTransaction.java new file mode 100644 index 00000000..9e971f94 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/tx/JdbcTransaction.java @@ -0,0 +1,123 @@ +package fun.asgc.neutrino.core.db.crisp.tx; + +import lombok.extern.slf4j.Slf4j; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author: aoshiguchen + * @date: 2022/11/7 + */ +@Slf4j +public class JdbcTransaction implements Transaction { + + protected Connection connection; + protected DataSource dataSource; + protected TransactionIsolationLevel level; + protected boolean autoCommit; + + public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) { + dataSource = ds; + level = desiredLevel; + autoCommit = desiredAutoCommit; + } + + public JdbcTransaction(Connection connection) { + this.connection = connection; + } + + @Override + public Connection getConnection() throws SQLException { + if (connection == null) { + openConnection(); + } + return connection; + } + + @Override + public void commit() throws SQLException { + if (connection != null && !connection.getAutoCommit()) { + if (log.isDebugEnabled()) { + log.debug("Committing JDBC Connection [" + connection + "]"); + } + connection.commit(); + } + } + + @Override + public void rollback() throws SQLException { + if (connection != null && !connection.getAutoCommit()) { + if (log.isDebugEnabled()) { + log.debug("Rolling back JDBC Connection [" + connection + "]"); + } + connection.rollback(); + } + } + + @Override + public void close() throws SQLException { + if (connection != null) { + resetAutoCommit(); + if (log.isDebugEnabled()) { + log.debug("Closing JDBC Connection [" + connection + "]"); + } + connection.close(); + } + } + + @Override + public Integer getTimeout() throws SQLException { + return null; + } + + protected void openConnection() throws SQLException { + if (log.isDebugEnabled()) { + log.debug("Opening JDBC Connection"); + } + connection = dataSource.getConnection(); + if (level != null) { + connection.setTransactionIsolation(level.getLevel()); + } + setDesiredAutoCommit(autoCommit); + } + + protected void setDesiredAutoCommit(boolean desiredAutoCommit) { + try { + if (connection.getAutoCommit() != desiredAutoCommit) { + if (log.isDebugEnabled()) { + log.debug("Setting autocommit to " + desiredAutoCommit + " on JDBC Connection [" + connection + "]"); + } + connection.setAutoCommit(desiredAutoCommit); + } + } catch (SQLException e) { + // Only a very poorly implemented driver would fail here, + // and there's not much we can do about that. + throw new TransactionException("Error configuring AutoCommit. " + + "Your driver may not support getAutoCommit() or setAutoCommit(). " + + "Requested setting: " + desiredAutoCommit + ". Cause: " + e, e); + } + } + + protected void resetAutoCommit() { + try { + if (!connection.getAutoCommit()) { + // MyBatis does not call commit/rollback on a connection if just selects were performed. + // Some databases start transactions with select statements + // and they mandate a commit/rollback before closing the connection. + // A workaround is setting the autocommit to true before closing the connection. + // Sybase throws an exception here. + if (log.isDebugEnabled()) { + log.debug("Resetting autocommit to true on JDBC Connection [" + connection + "]"); + } + connection.setAutoCommit(true); + } + } catch (SQLException e) { + if (log.isDebugEnabled()) { + log.debug("Error resetting autocommit to true " + + "before closing the connection. Cause: " + e); + } + } + } +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/tx/Transaction.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/tx/Transaction.java new file mode 100644 index 00000000..65baaf8e --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/tx/Transaction.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.tx; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author: aoshiguchen + * @date: 2022/11/7 + */ +public interface Transaction { + + /** + * Retrieve inner database connection. + * @return DataBase connection + * @throws SQLException + */ + Connection getConnection() throws SQLException; + + /** + * Commit inner database connection. + * @throws SQLException + */ + void commit() throws SQLException; + + /** + * Rollback inner database connection. + * @throws SQLException + */ + void rollback() throws SQLException; + + /** + * Close inner database connection. + * @throws SQLException + */ + void close() throws SQLException; + + /** + * Get transaction timeout if set. + * @throws SQLException + */ + Integer getTimeout() throws SQLException; +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/tx/TransactionException.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/tx/TransactionException.java new file mode 100644 index 00000000..853fc704 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/tx/TransactionException.java @@ -0,0 +1,19 @@ +package fun.asgc.neutrino.core.db.crisp.tx; + +import fun.asgc.neutrino.core.db.crisp.JdbcException; + +/** + * @author: aoshiguchen + * @date: 2022/11/7 + */ +public class TransactionException extends JdbcException { + + public TransactionException(String message) { + super(message); + } + + public TransactionException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/tx/TransactionIsolationLevel.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/tx/TransactionIsolationLevel.java new file mode 100644 index 00000000..78afa711 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/crisp/tx/TransactionIsolationLevel.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2022 aoshiguchen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package fun.asgc.neutrino.core.db.crisp.tx; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.sql.Connection; + +/** + * @author: aoshiguchen + * @date: 2022/11/4 + */ +@Getter +@AllArgsConstructor +public enum TransactionIsolationLevel { + NONE(Connection.TRANSACTION_NONE), + READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED), + READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED), + REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ), + SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE); + + private final int level; +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/DateUtil.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/DateUtil.java index e24da60f..377909b5 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/DateUtil.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/util/DateUtil.java @@ -36,6 +36,10 @@ import java.util.function.Consumer; * @date: 2022/6/28 */ public class DateUtil { + public static final long SECOND_LONG = 1000L; + public static final long MINUTE_LONG = 60 * SECOND_LONG; + public static final long HOUR_LONG = 60 * MINUTE_LONG; + private static final Cache sdfCache = new MemoryCache<>(); private static SimpleDateFormat getSimpleDateFormat(String format) { try { @@ -284,6 +288,30 @@ public class DateUtil { return calendar.getTime(); } + /** + * 获取指定小时开始时间 + * @param date 日期 + * @return 指定小时开始时间 + */ + public static Date getHourBegin(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + setCalender(calendar, calendar.get(Calendar.HOUR), 0, 0, 0); + return calendar.getTime(); + } + + /** + * 获取指定小时结束时间 + * @param date 日期 + * @return 指定小时结束时间 + */ + public static Date getHourEnd(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + setCalender(calendar, calendar.get(Calendar.HOUR), 59, 59, 999); + return calendar.getTime(); + } + /** * 获取当天开始时间 * diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/HttpRequestHandler.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/HttpRequestHandler.java index 65017509..a158b244 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/HttpRequestHandler.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/web/HttpRequestHandler.java @@ -40,9 +40,10 @@ import fun.asgc.neutrino.core.web.router.HttpRouteParam; import fun.asgc.neutrino.core.web.router.HttpRouteResult; import fun.asgc.neutrino.core.web.router.HttpRouterType; import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.*; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaderNames; +import io.netty.handler.codec.http.HttpResponseStatus; import lombok.extern.slf4j.Slf4j; import java.lang.reflect.Field; @@ -113,13 +114,14 @@ public class HttpRequestHandler { HttpResponseWrapper httpResponseWrapper = HttpContextHolder.getHttpResponseWrapper(); httpResponseWrapper.setContent(Unpooled.wrappedBuffer(res.getBytes())); - httpResponseWrapper.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON); + httpResponseWrapper.headers().add(HttpHeaderNames.CONTENT_TYPE, "application/json;charset=UTF-8"); httpResponseWrapper.writeAndFlush(); return; } else if(HttpRouterType.PAGE == httpRouteResult.getType()) { - if (!preHandle(httpRouteResult.getPageRoute(), null)) { - return; - } + // 静态页面无需前置拦截 +// if (!preHandle(httpRouteResult.getPageRoute(), null)) { +// return; +// } // 前端页面 String mimeType = MimeType.getMimeType(MimeType.parseSuffix(httpRouteResult.getPageLocation())); diff --git a/neutrino-proxy-admin/config/dev.env.js b/neutrino-proxy-admin/config/dev.env.js index e89dfbb0..f5ee615e 100644 --- a/neutrino-proxy-admin/config/dev.env.js +++ b/neutrino-proxy-admin/config/dev.env.js @@ -1,5 +1,5 @@ module.exports = { NODE_ENV: '"development"', ENV_CONFIG: '"dev"', - BASE_API: '"http://localhost:8080"' + BASE_API: '"http://localhost:8888"' } diff --git a/neutrino-proxy-admin/src/api/loginLog.js b/neutrino-proxy-admin/src/api/loginLog.js new file mode 100644 index 00000000..df20fede --- /dev/null +++ b/neutrino-proxy-admin/src/api/loginLog.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function fetchList(query) { + return request({ + url: '/user-login-record/page', + method: 'get', + params: query + }) +} diff --git a/neutrino-proxy-admin/src/lang/zh.js b/neutrino-proxy-admin/src/lang/zh.js index 63096fa8..fac13f8b 100644 --- a/neutrino-proxy-admin/src/lang/zh.js +++ b/neutrino-proxy-admin/src/lang/zh.js @@ -52,7 +52,9 @@ export default { license: 'License管理', portMapping: '端口映射', jobManager: '调度管理', - jobLog: '调度日志' + jobLog: '调度日志', + log: '日志管理', + loginLog: '登录日志' }, navbar: { logOut: '退出登录', @@ -135,7 +137,9 @@ export default { alarmDing: '任务报警钉钉', jobLogCode: '执行结果', jobLogMsg: '执行日志', - alarmStatus: '报警状态' + alarmStatus: '报警状态', + ip: 'IP', + happendTime: '发生时间' }, errorLog: { tips: '请点击右上角bug小图标', diff --git a/neutrino-proxy-admin/src/router/index.js b/neutrino-proxy-admin/src/router/index.js index fd920bdd..50d272b5 100644 --- a/neutrino-proxy-admin/src/router/index.js +++ b/neutrino-proxy-admin/src/router/index.js @@ -277,8 +277,21 @@ export const asyncRouterMap = [ children: [ { path: 'user', component: _import('system/user'), name: 'user', meta: { title: 'user' }}, { path: 'portPool', component: _import('system/portPool'), name: 'portPool', meta: { title: 'portPool' }}, - { path: 'jobManager', component: _import('system/jobManager'), name: 'jobManager', meta: { title: 'jobManager' }}, - { path: 'jobLog', component: _import('system/jobLog'), name: 'jobLog', meta: { title: 'jobLog' }} + { path: 'jobManager', component: _import('system/jobManager'), name: 'jobManager', meta: { title: 'jobManager' }} + ] + }, + { + path: '/log', + component: Layout, + redirect: 'noredirect', + name: 'log', + meta: { + title: 'log', + icon: 'component' + }, + children: [ + { path: 'jobLog', component: _import('log/jobLog'), name: 'jobLog', meta: { title: 'jobLog' }}, + { path: 'loginLog', component: _import('log/loginLog'), name: 'loginLog', meta: { title: 'loginLog' }} ] } ] diff --git a/neutrino-proxy-admin/src/views/system/jobLog.vue b/neutrino-proxy-admin/src/views/log/jobLog.vue similarity index 99% rename from neutrino-proxy-admin/src/views/system/jobLog.vue rename to neutrino-proxy-admin/src/views/log/jobLog.vue index 94340f77..ffffebd4 100644 --- a/neutrino-proxy-admin/src/views/system/jobLog.vue +++ b/neutrino-proxy-admin/src/views/log/jobLog.vue @@ -71,7 +71,7 @@ export default { listLoading: false, listQuery: { currentPage: 1, - pageSize: 20, + pageSize: 10, jobId: undefined }, jobList: [] diff --git a/neutrino-proxy-admin/src/views/log/loginLog.vue b/neutrino-proxy-admin/src/views/log/loginLog.vue new file mode 100644 index 00000000..c4c9ad04 --- /dev/null +++ b/neutrino-proxy-admin/src/views/log/loginLog.vue @@ -0,0 +1,135 @@ + + + diff --git a/neutrino-proxy-admin/src/views/proxy/license.vue b/neutrino-proxy-admin/src/views/proxy/license.vue index a116799f..64c0bb39 100644 --- a/neutrino-proxy-admin/src/views/proxy/license.vue +++ b/neutrino-proxy-admin/src/views/proxy/license.vue @@ -133,7 +133,7 @@ listLoading: true, listQuery: { currentPage: 1, - pageSize: 20, + pageSize: 10, importance: undefined, title: undefined, type: undefined diff --git a/neutrino-proxy-admin/src/views/proxy/portMapping.vue b/neutrino-proxy-admin/src/views/proxy/portMapping.vue index 3730df9a..ad46866a 100644 --- a/neutrino-proxy-admin/src/views/proxy/portMapping.vue +++ b/neutrino-proxy-admin/src/views/proxy/portMapping.vue @@ -172,7 +172,7 @@ listLoading: true, listQuery: { currentPage: 1, - pageSize: 20, + pageSize: 10, importance: undefined, title: undefined, type: undefined diff --git a/neutrino-proxy-admin/src/views/system/jobManager.vue b/neutrino-proxy-admin/src/views/system/jobManager.vue index 1521f03d..7370812c 100644 --- a/neutrino-proxy-admin/src/views/system/jobManager.vue +++ b/neutrino-proxy-admin/src/views/system/jobManager.vue @@ -41,7 +41,7 @@ 查看 - + - + - + - + - +