├── docs ├── .nojekyll ├── CNAME ├── img │ ├── icon.png │ ├── logo.png │ ├── hserver.png │ ├── icon_2.png │ └── planning_map.jpg ├── _coverpage.md ├── zh-cn │ ├── plugin │ │ ├── web │ │ │ ├── reqresp.md │ │ │ ├── sse.md │ │ │ ├── exception.md │ │ │ ├── websocket.md │ │ │ ├── check.md │ │ │ ├── authentication.md │ │ │ ├── json.md │ │ │ ├── filter.md │ │ │ ├── limit.md │ │ │ └── prop.md │ │ ├── druid │ │ │ └── index.md │ │ ├── jar.md │ │ ├── forest.md │ │ └── rpc │ │ │ └── index.md │ ├── index.md │ ├── mqtt.md │ ├── log.md │ ├── unit.md │ ├── lifecycle.md │ ├── track.md │ ├── hum.md │ ├── prop.md │ ├── annotation.md │ ├── plugin.md │ ├── task.md │ ├── protocol.md │ └── optimization.md ├── _navbar.md ├── _sidebar.md └── index.html ├── doc ├── 23.png ├── 8.png ├── b.png ├── jm.png ├── w.png ├── file.png ├── icon.png ├── json.png ├── logo.png ├── logo1.png ├── logo3.png ├── 架构图2.jpg ├── 架构说明.png ├── 架构说明1.jpg ├── apidoc.png ├── hserver.png ├── LinuxFile.png ├── LinuxJson.png ├── LinuxTemp.png ├── template.png ├── planning_map.jpg └── maven ├── .gitignore ├── hserver-web ├── hserver-mvc │ └── src │ │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── services │ │ │ └── cn.hserver.core.plugin.handler.PluginAdapter │ │ └── java │ │ └── cn │ │ └── hserver │ │ └── mvc │ │ ├── constants │ │ ├── WsType.java │ │ └── HttpMethod.java │ │ ├── template │ │ ├── Template.java │ │ └── FreemarkerTemplate.java │ │ ├── annotation │ │ ├── WebSocket.java │ │ ├── Controller.java │ │ ├── router │ │ │ ├── CONNECT.java │ │ │ ├── GET.java │ │ │ ├── HEAD.java │ │ │ ├── POST.java │ │ │ ├── PUT.java │ │ │ ├── DELETE.java │ │ │ ├── OPTIONS.java │ │ │ ├── PATCH.java │ │ │ ├── TRACE.java │ │ │ └── RequestMapping.java │ │ └── validate │ │ │ ├── NotNull.java │ │ │ ├── Null.java │ │ │ ├── AssertTrue.java │ │ │ ├── AssertFalse.java │ │ │ ├── NotBlank.java │ │ │ ├── Max.java │ │ │ ├── Min.java │ │ │ ├── NotEmpty.java │ │ │ ├── Pattern.java │ │ │ ├── Length.java │ │ │ └── Size.java │ │ ├── exception │ │ ├── NotFoundException.java │ │ ├── MethodNotSupportException.java │ │ ├── QpsException.java │ │ ├── ValidateException.java │ │ ├── GlobalExceptionHandler.java │ │ └── WebException.java │ │ ├── router │ │ ├── Handler.java │ │ └── Route.java │ │ ├── filter │ │ ├── FilterAdapter.java │ │ └── GlobalFilterAdapter.java │ │ ├── server │ │ ├── StopServer.java │ │ ├── WebServer.java │ │ └── SslData.java │ │ ├── request │ │ ├── HeadMap.java │ │ └── Cookie.java │ │ ├── context │ │ ├── WebContext.java │ │ └── WebContextHolder.java │ │ ├── websoket │ │ ├── WebSocketHandler.java │ │ └── Ws.java │ │ ├── json │ │ └── JsonAdapter.java │ │ ├── util │ │ ├── SslUtil.java │ │ └── RequestIdGen.java │ │ ├── session │ │ └── HttpSession.java │ │ ├── sse │ │ ├── SSeStream.java │ │ └── SSeEvent.java │ │ └── common │ │ └── JsonResult.java ├── hserver-netty-web │ └── src │ │ └── main │ │ └── java │ │ └── cn │ │ └── hserver │ │ └── netty │ │ └── web │ │ ├── constants │ │ ├── IoMultiplexer.java │ │ └── NettyConfig.java │ │ ├── util │ │ ├── NettyIpUtil.java │ │ └── ByteBufUtil.java │ │ └── context │ │ └── HttpResponseFile.java ├── hserver-smart-web │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── cn │ │ │ └── hserver │ │ │ └── smart │ │ │ └── Main.java │ └── pom.xml ├── pom.xml └── hserver-web-starter │ └── pom.xml ├── hserver-plugin ├── hserver-plugin-mcp │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── cn.hserver.core.plugin.handler.PluginAdapter │ │ │ └── java │ │ │ └── cn │ │ │ └── hserver │ │ │ ├── mcp │ │ │ ├── type │ │ │ │ └── McpType.java │ │ │ ├── McpAnnotationHandler.java │ │ │ ├── McpFilter.java │ │ │ └── annotation │ │ │ │ ├── PromptMapping.java │ │ │ │ ├── ToolMapping.java │ │ │ │ ├── ResourcesMapping.java │ │ │ │ ├── McpServerEndpoint.java │ │ │ │ └── Param.java │ │ │ └── modelcontextprotocol │ │ │ └── spec │ │ │ ├── McpServerTransport.java │ │ │ ├── ClientMcpTransport.java │ │ │ ├── ServerMcpTransport.java │ │ │ ├── McpClientTransport.java │ │ │ └── McpError.java │ ├── pom.xml │ └── readme.md ├── hserver-plugin-druid │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── cn.hserver.core.plugin.handler.PluginAdapter │ │ │ └── java │ │ │ └── cn │ │ │ └── hserver │ │ │ └── plugin │ │ │ └── druid │ │ │ ├── DruidPlugin.java │ │ │ └── web │ │ │ ├── StatViewController.java │ │ │ └── config │ │ │ └── HtmlConst.java │ ├── readme.md │ └── pom.xml ├── hserver-plugin-beetlsql │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── cn.hserver.core.plugin.handler.PluginAdapter │ │ │ └── java │ │ │ └── cn │ │ │ └── hserver │ │ │ └── plugin │ │ │ └── beetlsql │ │ │ ├── annotation │ │ │ └── BeetlSQL.java │ │ │ ├── tx │ │ │ └── Tx.java │ │ │ └── handler │ │ │ └── BeetlSQLHandler.java │ ├── README.md │ └── pom.xml ├── hserver-plugin-forest │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── cn.hserver.core.plugin.handler.PluginAdapter │ │ │ └── java │ │ │ └── cn │ │ │ └── hserver │ │ │ └── plugin │ │ │ └── forest │ │ │ ├── config │ │ │ └── ForestClientConfig.java │ │ │ └── ForestPlugin.java │ ├── readme.md │ └── pom.xml ├── hserver-plugin-mybatisplus │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── cn.hserver.core.plugin.handler.PluginAdapter │ │ │ └── java │ │ │ └── cn │ │ │ └── hserver │ │ │ └── plugin │ │ │ └── mybatis │ │ │ └── annotation │ │ │ ├── Mybatis.java │ │ │ └── Tx.java │ └── pom.xml ├── hserver-plugin-satoken │ └── src │ │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── services │ │ │ └── cn.hserver.core.plugin.handler.PluginAdapter │ │ └── java │ │ └── cn │ │ └── hserver │ │ └── plugin │ │ └── satoken │ │ ├── mode │ │ ├── SaStorageForHServer.java │ │ └── SaResponseForHServer.java │ │ └── config │ │ ├── SaTokenContextForHServer.java │ │ └── SaAnnotationInterceptor.java ├── hserver-plugin-mybatis_flex │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── cn.hserver.core.plugin.handler.PluginAdapter │ │ │ └── java │ │ │ └── cn │ │ │ └── hserver │ │ │ └── plugin │ │ │ └── mybatis │ │ │ └── flex │ │ │ ├── annotation │ │ │ └── Mybatis.java │ │ │ ├── MybatisFlexPlugin.java │ │ │ └── bean │ │ │ └── MybatisConfig.java │ └── pom.xml └── pom.xml ├── hserver-cloud ├── hserver-cloud-register │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── cn.hserver.core.plugin.handler.PluginAdapter │ │ │ └── java │ │ │ └── cn │ │ │ └── hserver │ │ │ └── cloud │ │ │ └── register │ │ │ ├── RegisterService.java │ │ │ └── RegisterPlugin.java │ └── pom.xml ├── hserver-cloud-discovery │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── cn.hserver.core.plugin.handler.PluginAdapter │ │ │ └── java │ │ │ └── cn │ │ │ └── hserver │ │ │ └── cloud │ │ │ └── discovery │ │ │ ├── DiscoveryListener.java │ │ │ ├── DiscoveryPlugin.java │ │ │ └── DiscoveryService.java │ └── pom.xml ├── hserver-cloud-common │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── cn │ │ │ └── hserver │ │ │ └── cloud │ │ │ └── common │ │ │ ├── CloudAddress.java │ │ │ ├── ConstConfig.java │ │ │ └── RegisterConfig.java │ └── pom.xml ├── hserver-cloud-impl │ ├── pom.xml │ └── hserver-cloud-nacos │ │ └── src │ │ └── main │ │ └── java │ │ └── cn │ │ └── hserver │ │ └── cloud │ │ └── nacos │ │ ├── NamingConfig.java │ │ └── NacosRegisterService.java └── pom.xml ├── hserver-core └── src │ └── main │ ├── java │ └── cn │ │ └── hserver │ │ └── core │ │ ├── life │ │ ├── StartAdapter.java │ │ ├── CloseAdapter.java │ │ └── InitAdapter.java │ │ ├── scheduling │ │ ├── TaskJob.java │ │ ├── annotation │ │ │ └── Task.java │ │ ├── bean │ │ │ └── TaskDefinition.java │ │ └── CronExecutorService.java │ │ ├── boot │ │ └── annotation │ │ │ └── HServerBoot.java │ │ ├── queue │ │ ├── annotation │ │ │ ├── QueueHandler.java │ │ │ └── QueueListener.java │ │ ├── fqueue │ │ │ └── exception │ │ │ │ ├── FileFormatException.java │ │ │ │ └── FileEOFException.java │ │ ├── bean │ │ │ ├── QueueInfo.java │ │ │ ├── QueueData.java │ │ │ └── QueueHandleInfo.java │ │ ├── QueueEventHandler.java │ │ └── HServerQueue.java │ │ ├── config │ │ ├── annotation │ │ │ ├── ConfigurationProperties.java │ │ │ ├── Value.java │ │ │ └── Configuration.java │ │ ├── ConfigMap.java │ │ └── ConstConfig.java │ │ ├── ioc │ │ ├── annotation │ │ │ ├── PostConstruct.java │ │ │ ├── Order.java │ │ │ ├── Component.java │ │ │ ├── ScopeType.java │ │ │ ├── Autowired.java │ │ │ ├── Scope.java │ │ │ ├── Bean.java │ │ │ └── Qualifier.java │ │ └── handler │ │ │ ├── ConfigurationPropertiesHandler.java │ │ │ ├── ValueHandler.java │ │ │ └── AutowiredHandler.java │ │ ├── aop │ │ ├── annotation │ │ │ └── Hook.java │ │ ├── HookAdapter.java │ │ ├── RefreshMethodHandler.java │ │ └── bean │ │ │ └── HookBeanDefinition.java │ │ ├── logging │ │ ├── LogAdapter.java │ │ ├── ProcessIdClassicConverter.java │ │ ├── HServerDataDefinerFile.java │ │ ├── HServerLogAsyncAppender.java │ │ ├── HServerHighlightingCompositeConverter.java │ │ ├── HServerDataDefinerConsole.java │ │ └── HServerLogConfig.java │ │ ├── context │ │ └── handler │ │ │ ├── HookHandler.java │ │ │ ├── TestRunWithHandler.java │ │ │ ├── AnnotationHandler.java │ │ │ └── ComponentHandler.java │ │ ├── test │ │ └── HServerTest.java │ │ ├── util │ │ ├── NamedThreadFactory.java │ │ ├── JarInputStreamUtil.java │ │ └── ExceptionUtil.java │ │ └── plugin │ │ └── handler │ │ └── PluginAdapter.java │ └── resources │ └── app.properties.back └── hserver-build ├── hserver-runner ├── src │ └── main │ │ └── java │ │ └── cn │ │ └── hserver │ │ └── runner │ │ ├── RunnerConfig.java │ │ ├── JarURLStreamHandler.java │ │ ├── DataSafeUtil.java │ │ └── JarURLStreamHandlerFactory.java └── pom.xml ├── hserver-maven └── src │ └── main │ └── java │ └── cn │ └── hserver │ └── plugins │ └── maven │ └── AesUtil.java └── pom.xml /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | docs.hserver.cn 2 | -------------------------------------------------------------------------------- /doc/23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/23.png -------------------------------------------------------------------------------- /doc/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/8.png -------------------------------------------------------------------------------- /doc/b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/b.png -------------------------------------------------------------------------------- /doc/jm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/jm.png -------------------------------------------------------------------------------- /doc/w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/w.png -------------------------------------------------------------------------------- /doc/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/file.png -------------------------------------------------------------------------------- /doc/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/icon.png -------------------------------------------------------------------------------- /doc/json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/json.png -------------------------------------------------------------------------------- /doc/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/logo.png -------------------------------------------------------------------------------- /doc/logo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/logo1.png -------------------------------------------------------------------------------- /doc/logo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/logo3.png -------------------------------------------------------------------------------- /doc/架构图2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/架构图2.jpg -------------------------------------------------------------------------------- /doc/架构说明.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/架构说明.png -------------------------------------------------------------------------------- /doc/架构说明1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/架构说明1.jpg -------------------------------------------------------------------------------- /doc/apidoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/apidoc.png -------------------------------------------------------------------------------- /doc/hserver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/hserver.png -------------------------------------------------------------------------------- /doc/LinuxFile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/LinuxFile.png -------------------------------------------------------------------------------- /doc/LinuxJson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/LinuxJson.png -------------------------------------------------------------------------------- /doc/LinuxTemp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/LinuxTemp.png -------------------------------------------------------------------------------- /doc/template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/template.png -------------------------------------------------------------------------------- /docs/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/docs/img/icon.png -------------------------------------------------------------------------------- /docs/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/docs/img/logo.png -------------------------------------------------------------------------------- /doc/planning_map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/doc/planning_map.jpg -------------------------------------------------------------------------------- /docs/img/hserver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/docs/img/hserver.png -------------------------------------------------------------------------------- /docs/img/icon_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/docs/img/icon_2.png -------------------------------------------------------------------------------- /docs/img/planning_map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heixiaoma/HServer-For-JAVA/HEAD/docs/img/planning_map.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # idea ignore 2 | .idea/* 3 | .idea* 4 | \.idea* 5 | *.ipr 6 | *.iml 7 | *.iws 8 | /target 9 | /log 10 | /queue -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/resources/META-INF/services/cn.hserver.core.plugin.handler.PluginAdapter: -------------------------------------------------------------------------------- 1 | cn.hserver.mvc.MvcPlugin 2 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/resources/META-INF/services/cn.hserver.core.plugin.handler.PluginAdapter: -------------------------------------------------------------------------------- 1 | cn.hserver.mcp.McpPlugin -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-register/src/main/resources/META-INF/services/cn.hserver.core.plugin.handler.PluginAdapter: -------------------------------------------------------------------------------- 1 | cn.hserver.cloud.register.RegisterPlugin -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-druid/src/main/resources/META-INF/services/cn.hserver.core.plugin.handler.PluginAdapter: -------------------------------------------------------------------------------- 1 | cn.hserver.plugin.druid.DruidPlugin 2 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-discovery/src/main/resources/META-INF/services/cn.hserver.core.plugin.handler.PluginAdapter: -------------------------------------------------------------------------------- 1 | cn.hserver.cloud.discovery.DiscoveryPlugin -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-beetlsql/src/main/resources/META-INF/services/cn.hserver.core.plugin.handler.PluginAdapter: -------------------------------------------------------------------------------- 1 | cn.hserver.plugin.beetlsql.BeetLSqlPlugin -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-forest/src/main/resources/META-INF/services/cn.hserver.core.plugin.handler.PluginAdapter: -------------------------------------------------------------------------------- 1 | cn.hserver.plugin.forest.ForestPlugin 2 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mybatisplus/src/main/resources/META-INF/services/cn.hserver.core.plugin.handler.PluginAdapter: -------------------------------------------------------------------------------- 1 | cn.hserver.plugin.mybatis.MybatisPlugin -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-satoken/src/main/resources/META-INF/services/cn.hserver.core.plugin.handler.PluginAdapter: -------------------------------------------------------------------------------- 1 | cn.hserver.plugin.satoken.SaTokenPlugin 2 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mybatis_flex/src/main/resources/META-INF/services/cn.hserver.core.plugin.handler.PluginAdapter: -------------------------------------------------------------------------------- 1 | cn.hserver.plugin.mybatis.flex.MybatisFlexPlugin 2 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/mcp/type/McpType.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mcp.type; 2 | 3 | public enum McpType { 4 | string,number,object 5 | } 6 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/constants/WsType.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.constants; 2 | 3 | public enum WsType { 4 | TEXT,BINARY,CLOSE,INIT 5 | } 6 | -------------------------------------------------------------------------------- /hserver-web/hserver-netty-web/src/main/java/cn/hserver/netty/web/constants/IoMultiplexer.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.netty.web.constants; 2 | 3 | public enum IoMultiplexer { 4 | IO_URING,EPOLL, KQUEUE, NIO ,DEFAULT 5 | } -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/constants/HttpMethod.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.constants; 2 | 3 | public enum HttpMethod { 4 | OPTIONS,GET,HEAD,POST,PUT,PATCH,DELETE,TRACE,CONNECT; 5 | 6 | } 7 | -------------------------------------------------------------------------------- /docs/_coverpage.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ![logo](./img/icon_2.png) 4 | 5 | # HServer 6 | 7 | > 一个功能强大,资源丰富,开发灵活,轻量级,低入侵,高性能的网络开发框架 8 | 9 | [码云](https://gitee.com/HServer/HServer) 10 | [阅读文档](README.md) 11 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/life/StartAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.life; 2 | 3 | /** 4 | * @author hxm 5 | */ 6 | public interface StartAdapter { 7 | /** 8 | * 启动完成的回调 9 | */ 10 | void start(); 11 | } 12 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/life/CloseAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.life; 2 | 3 | /** 4 | * @author hxm 5 | */ 6 | public interface CloseAdapter { 7 | /** 8 | * 服务关闭回调执行 9 | */ 10 | void close(); 11 | } 12 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/template/Template.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.template; 2 | 3 | import java.util.Map; 4 | 5 | public interface Template { 6 | String getTemplate(String template, Map map) throws Exception; 7 | } 8 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin/web/reqresp.md: -------------------------------------------------------------------------------- 1 | 2 | ## 全局request,response获取 3 | ```text 4 | //全局获取 可以夸线程 5 | Webkit webKit = HServerContextHolder.getWebKit(); 6 | if (webKit != null) { 7 | return webKit.httpRequest.getRequestId(); 8 | } 9 | ``` 10 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/life/InitAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.life; 2 | 3 | /** 4 | * @author hxm 5 | */ 6 | public interface InitAdapter { 7 | /** 8 | * 启动中的回调 9 | * @param args 主函数的 args 10 | */ 11 | void init(String[] args); 12 | } 13 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/scheduling/TaskJob.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.scheduling; 2 | 3 | /** 4 | * @author hxm 5 | */ 6 | public interface TaskJob { 7 | 8 | /** 9 | * 定时任务 10 | * @param args 11 | */ 12 | void exec(Object... args); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/boot/annotation/HServerBoot.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.boot.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author hxm 7 | */ 8 | @Target(ElementType.TYPE) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface HServerBoot { 12 | } 13 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-forest/src/main/java/cn/hserver/plugin/forest/config/ForestClientConfig.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.forest.config; 2 | 3 | import com.dtflys.forest.config.ForestConfiguration; 4 | 5 | public abstract class ForestClientConfig { 6 | public abstract void config(ForestConfiguration forestConfiguration); 7 | 8 | } 9 | -------------------------------------------------------------------------------- /hserver-core/src/main/resources/app.properties.back: -------------------------------------------------------------------------------- 1 | #外置配置大于jar中包配置文件,配置文件大于代码默认设置 2 | #应用名字,默认HServer 3 | appName=HServer 4 | #动态环境配置文件 5 | env=dev 6 | #taskPool定时任务线程池子配置,默认大小是cpu核心数+1 7 | taskPool=5 8 | #日志级别 debug info error ... 9 | log=debug 10 | #自定义日志名字 11 | logbackName=logback-dev.xml 12 | #队列数据缓存位置 默认当前项目下 13 | persistPath=/user/mcl/data 14 | 15 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/WebSocket.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation; 2 | 3 | 4 | import java.lang.annotation.*; 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target(ElementType.TYPE) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface WebSocket { 13 | String value(); 14 | } 15 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/queue/annotation/QueueHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.queue.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 标记消费者的方法 7 | * 8 | * @author hxm 9 | */ 10 | @Documented 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.METHOD) 13 | public @interface QueueHandler { 14 | } 15 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-druid/readme.md: -------------------------------------------------------------------------------- 1 | 2 | ### 访问地址: 3 | http://127.0.0.1:端口/druid/index.html 4 | 5 | ```java 6 | DruidDataSource ds = new DruidDataSource (); 7 | ds.setUrl(mySqlUrl); 8 | ds.setUsername(mySqlUserName); 9 | ds.setPassword(mySqlPassword); 10 | ds.setDriverClassName(mySqlDriver); 11 | //接入时需要把拦截器打开,不然不能监控 12 | ds.setFilters("stat,wall"); 13 | ``` -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/Controller.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation; 2 | 3 | 4 | import java.lang.annotation.*; 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target(ElementType.TYPE) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface Controller { 13 | String value() default ""; 14 | } 15 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mybatis_flex/src/main/java/cn/hserver/plugin/mybatis/flex/annotation/Mybatis.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.mybatis.flex.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author hxm 7 | */ 8 | @Target({ElementType.TYPE}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface Mybatis { 12 | } 13 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/router/CONNECT.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.router; 2 | 3 | import java.lang.annotation.*; 4 | 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target({ElementType.METHOD}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface CONNECT { 13 | String value() default ""; 14 | } 15 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/router/GET.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.router; 2 | 3 | import java.lang.annotation.*; 4 | 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target({ElementType.METHOD}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface GET { 13 | String value() default ""; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/router/HEAD.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.router; 2 | 3 | import java.lang.annotation.*; 4 | 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target({ElementType.METHOD}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface HEAD { 13 | String value() default ""; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/router/POST.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.router; 2 | 3 | import java.lang.annotation.*; 4 | 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target({ElementType.METHOD}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface POST { 13 | String value() default ""; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/router/PUT.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.router; 2 | 3 | import java.lang.annotation.*; 4 | 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target({ElementType.METHOD}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface PUT { 13 | String value() default ""; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-discovery/src/main/java/cn/hserver/cloud/discovery/DiscoveryListener.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.cloud.discovery; 2 | 3 | import cn.hserver.cloud.common.ServerInstance; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public interface DiscoveryListener { 9 | void onChanged(String group, Map> newInstances); 10 | } -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/modelcontextprotocol/spec/McpServerTransport.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.modelcontextprotocol.spec; 2 | 3 | /** 4 | * Marker interface for the server-side MCP transport. 5 | * 6 | * @author Christian Tzolov 7 | * @author Dariusz Jędrzejczyk 8 | */ 9 | public interface McpServerTransport extends McpTransport { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/router/DELETE.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.router; 2 | 3 | import java.lang.annotation.*; 4 | 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target({ElementType.METHOD}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface DELETE { 13 | String value() default ""; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/router/OPTIONS.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.router; 2 | 3 | import java.lang.annotation.*; 4 | 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target({ElementType.METHOD}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface OPTIONS { 13 | String value() default ""; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/router/PATCH.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.router; 2 | 3 | import java.lang.annotation.*; 4 | 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target({ElementType.METHOD}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface PATCH { 13 | String value() default ""; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/router/TRACE.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.router; 2 | 3 | import java.lang.annotation.*; 4 | 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target({ElementType.METHOD}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface TRACE { 13 | String value() default ""; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/exception/NotFoundException.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.exception; 2 | 3 | /** 4 | * @author hxm 5 | */ 6 | public class NotFoundException extends Exception { 7 | 8 | public NotFoundException() { 9 | super(); 10 | } 11 | 12 | public NotFoundException(String s) { 13 | super(s); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/config/annotation/ConfigurationProperties.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.config.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author hxm 7 | */ 8 | @Target(ElementType.TYPE) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface ConfigurationProperties { 12 | String prefix() default ""; 13 | } 14 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/router/Handler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.router; 2 | 3 | import cn.hserver.mvc.context.WebContext; 4 | 5 | import java.lang.reflect.InvocationTargetException; 6 | 7 | 8 | /** 9 | * 路由处理器接口,使用函数式接口方便lambda表达式使用 10 | */ 11 | @FunctionalInterface 12 | public interface Handler { 13 | void handle(WebContext ctx) throws Throwable; 14 | } 15 | -------------------------------------------------------------------------------- /hserver-build/hserver-runner/src/main/java/cn/hserver/runner/RunnerConfig.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.runner; 2 | 3 | public interface RunnerConfig { 4 | String LIBS = "Libs"; 5 | String APP_MAIN_CLASS = "App-Main-Class"; 6 | String ENCRYPT = "Encrypt"; 7 | String CONSOLE= "Console"; 8 | String TYPE = "Type"; 9 | String IN_JAR="in-jar:"; 10 | String OUT_JAR="out-jar:"; 11 | } 12 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-beetlsql/src/main/java/cn/hserver/plugin/beetlsql/annotation/BeetlSQL.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.beetlsql.annotation; 2 | 3 | 4 | import java.lang.annotation.*; 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target({ElementType.TYPE}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface BeetlSQL { 13 | String value() default ""; 14 | } 15 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mybatisplus/src/main/java/cn/hserver/plugin/mybatis/annotation/Mybatis.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.mybatis.annotation; 2 | 3 | 4 | import java.lang.annotation.*; 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target({ElementType.TYPE}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface Mybatis { 13 | String value() default ""; 14 | } 15 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/scheduling/annotation/Task.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.scheduling.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | @Target({ElementType.TYPE, ElementType.METHOD}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface Task { 13 | String name(); 14 | 15 | String time(); 16 | } 17 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-common/src/main/java/cn/hserver/cloud/common/CloudAddress.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.cloud.common; 2 | 3 | 4 | public class CloudAddress { 5 | private String cloudAddress; 6 | 7 | public String getCloudAddress() { 8 | return cloudAddress; 9 | } 10 | public void setCloudAddress(String cloudAddress) { 11 | this.cloudAddress = cloudAddress; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/ioc/annotation/PostConstruct.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.ioc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface PostConstruct { 11 | } -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/exception/MethodNotSupportException.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.exception; 2 | 3 | /** 4 | * @author hxm 5 | */ 6 | public class MethodNotSupportException extends Exception { 7 | public MethodNotSupportException() { 8 | super("不支持当前请求方式"); 9 | } 10 | 11 | public MethodNotSupportException(String s) { 12 | super(s); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/aop/annotation/Hook.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.aop.annotation; 2 | 3 | import cn.hserver.core.ioc.annotation.Component; 4 | 5 | import java.lang.annotation.*; 6 | 7 | 8 | /** 9 | * @author hxm 10 | */ 11 | @Target(ElementType.TYPE) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Component 14 | @Documented 15 | public @interface Hook { 16 | Class[] value(); 17 | } 18 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/logging/LogAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.logging; 2 | 3 | import ch.qos.logback.classic.spi.LoggingEvent; 4 | 5 | /** 6 | * @author hxm 7 | */ 8 | public interface LogAdapter { 9 | 10 | /** 11 | * 当前被调用的的方法信息 12 | * @param loggingEvent 13 | * @throws Exception 14 | */ 15 | void log(LoggingEvent loggingEvent) throws Exception; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/ioc/annotation/Order.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.ioc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.TYPE) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface Order { 11 | int value(); 12 | } 13 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/validate/NotNull.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.validate; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 字段不能为Null 7 | * 8 | * @author hxm 9 | */ 10 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | public @interface NotNull { 14 | 15 | String message() default "字段不能为空"; 16 | } 17 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/validate/Null.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.validate; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 字段必须为Null 7 | * 8 | * @author hxm 9 | */ 10 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | public @interface Null { 14 | 15 | String message() default "字段必须为null"; 16 | } 17 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/validate/AssertTrue.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.validate; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 字段为必须为true 7 | * 8 | * @author hxm 9 | */ 10 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | public @interface AssertTrue { 14 | String message() default "字段不是:True"; 15 | } 16 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/filter/FilterAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.filter; 2 | 3 | 4 | import cn.hserver.mvc.context.WebContext; 5 | 6 | /** 7 | * 拦截器 8 | * @author hxm 9 | */ 10 | public interface FilterAdapter { 11 | 12 | /** 13 | * 所有拦截先走这里过滤一次 14 | * @param webContext 15 | * @throws Exception 16 | */ 17 | void doFilter(WebContext webContext) throws Exception; 18 | } 19 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/ioc/annotation/Component.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.ioc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.TYPE) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface Component { 11 | String value() default ""; 12 | } -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/ioc/annotation/ScopeType.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.ioc.annotation; 2 | 3 | public enum ScopeType { 4 | SINGLETON("singleton"), 5 | PROTOTYPE("prototype"), 6 | REFRESH("refresh"); 7 | 8 | private final String value; 9 | 10 | ScopeType(String value) { 11 | this.value = value; 12 | } 13 | 14 | public String getValue() { 15 | return value; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/validate/AssertFalse.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.validate; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 字段为必须为false 7 | * 8 | * @author hxm 9 | */ 10 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | public @interface AssertFalse { 14 | String message() default "字段不是:False"; 15 | } 16 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/validate/NotBlank.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.validate; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 字段不能为null同时不是 "" 7 | * 8 | * @author hxm 9 | */ 10 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | public @interface NotBlank { 14 | String message() default "字段不能为Null或者' '"; 15 | } 16 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/ioc/annotation/Autowired.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.ioc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface Autowired { 11 | } -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/filter/GlobalFilterAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.filter; 2 | 3 | 4 | import cn.hserver.mvc.context.WebContext; 5 | 6 | /** 7 | * 拦截器 8 | * @author hxm 9 | */ 10 | public interface GlobalFilterAdapter { 11 | 12 | /** 13 | * 所有拦截先走这里过滤一次 14 | * @param webContext 15 | * @throws Exception 16 | */ 17 | void doFilter(WebContext webContext) throws Exception; 18 | } 19 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin/web/sse.md: -------------------------------------------------------------------------------- 1 | # SSE 使用 2 | ```java 3 | @GET("/sse") 4 | public void res(HttpResponse response) throws Exception { 5 | SSeStream sSeStream = response.getSSeStream(); 6 | for (int i = 0; i < 100; i++) { 7 | sSeStream.sendSseEvent(new SSeEvent.Builder().id(String.valueOf(i)).event("a").data(String.valueOf(i)).build()); 8 | //模拟延迟 9 | Thread.sleep(1000); 10 | } 11 | } 12 | ``` -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/config/annotation/Value.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.config.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target({ElementType.FIELD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface Value { 11 | String value(); // 占位符表达式,如 "property.name" 12 | } -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-beetlsql/src/main/java/cn/hserver/plugin/beetlsql/tx/Tx.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.beetlsql.tx; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author hxm 7 | */ 8 | @Target({ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface Tx { 12 | 13 | int timeoutMillisecond() default -1; 14 | 15 | Class[] rollbackFor() default {}; 16 | } 17 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-register/src/main/java/cn/hserver/cloud/register/RegisterService.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.cloud.register; 2 | 3 | 4 | import cn.hserver.cloud.common.RegisterConfig; 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | public interface RegisterService { 10 | 11 | /** 12 | * 注册服务实例 13 | */ 14 | boolean register(RegisterConfig registerConfig); 15 | 16 | /** 17 | * 注销服务 18 | */ 19 | boolean deregister(); 20 | 21 | } -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/config/annotation/Configuration.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.config.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.TYPE) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface Configuration { 11 | String value() default ""; // Bean名称(可选) 12 | } -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/queue/fqueue/exception/FileFormatException.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.queue.fqueue.exception; 2 | 3 | public class FileFormatException extends Exception { 4 | 5 | private static final long serialVersionUID = -1L; 6 | 7 | public FileFormatException(String message) { 8 | super(message); 9 | } 10 | 11 | public FileFormatException(Throwable cause) { 12 | super(cause); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/queue/fqueue/exception/FileEOFException.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.queue.fqueue.exception; 2 | 3 | public class FileEOFException extends Exception { 4 | 5 | private static final long serialVersionUID = -1L; 6 | 7 | public FileEOFException(String message) { 8 | super(message); 9 | } 10 | 11 | @Override 12 | public Throwable fillInStackTrace() { 13 | return this; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mybatisplus/src/main/java/cn/hserver/plugin/mybatis/annotation/Tx.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.mybatis.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author hxm 7 | */ 8 | @Target({ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface Tx { 12 | 13 | int timeoutMillisecond() default -1; 14 | 15 | Class[] rollbackFor() default {}; 16 | } 17 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/validate/Max.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.validate; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 字段值必须大于这个值,number 7 | * 8 | * @author hxm 9 | */ 10 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | public @interface Max { 14 | 15 | long value(); 16 | 17 | String message() default "字段值必须大于设置的值"; 18 | } 19 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/validate/Min.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.validate; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 字段值必须小于这个值,number 7 | * 8 | * @author hxm 9 | */ 10 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | public @interface Min { 14 | 15 | long value(); 16 | 17 | String message() default "字段值必须小于设置的值"; 18 | } 19 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/ioc/annotation/Scope.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.ioc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target({ElementType.TYPE, ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface Scope { 11 | ScopeType value() default ScopeType.SINGLETON; 12 | } -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/validate/NotEmpty.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.validate; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * CharSequence 集合 map 数组 不是null 长度或者size 大于0 7 | * 8 | * @author hxm 9 | */ 10 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | public @interface NotEmpty { 14 | String message() default "字段不能为空,长度或者Size必须大于0 "; 15 | } 16 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/validate/Pattern.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.validate; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 字段CharSequence 必须满足这个正则 7 | * 8 | * @author hxm 9 | */ 10 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | public @interface Pattern { 14 | 15 | String value(); 16 | 17 | String message() default "字段不满足正则表达式"; 18 | } 19 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/router/RequestMapping.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.router; 2 | 3 | 4 | 5 | import cn.hserver.mvc.constants.HttpMethod; 6 | 7 | import java.lang.annotation.*; 8 | 9 | /** 10 | * @author hxm 11 | */ 12 | @Target({ElementType.METHOD}) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Documented 15 | public @interface RequestMapping { 16 | String value() default ""; 17 | HttpMethod[] method() default {}; 18 | } 19 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/validate/Length.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.validate; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 字段CharSequence 类型的长度必须是 length 长 7 | * 8 | * @author hxm 9 | */ 10 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | public @interface Length { 14 | 15 | long value(); 16 | 17 | String message() default "字段长度不满足条件"; 18 | } 19 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/server/StopServer.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.server; 2 | 3 | import cn.hserver.core.ioc.annotation.Component; 4 | import cn.hserver.core.life.CloseAdapter; 5 | import cn.hserver.mvc.MvcPlugin; 6 | 7 | @Component 8 | public class StopServer implements CloseAdapter { 9 | @Override 10 | public void close() { 11 | if (MvcPlugin.webServer != null) { 12 | MvcPlugin.webServer.stop(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /docs/zh-cn/index.md: -------------------------------------------------------------------------------- 1 | ```text 2 | HServer是一个基于Netty开发网络扩展库.使用插件方式来扩展我们的业务 HServer提供 web,gateway,rpc 等插件 3 | 同时用户也可以自定义插件,来完成各种各样的业务场景 4 | 如果你正在使用该框架建议加入QQ群,我们可以更好的交流 QQ交流群:1065301527 5 | ``` 6 | ### Hserver的理念 7 | 8 | **极简、高性能、扩展强** 9 | 10 | **极简** 代码只有几百KB 11 | 12 | **高性能** 使用Netty网络库作为核心,比起传统的web容器性能高数十倍. 13 | 14 | **扩展强** 预留了丰富的接口,以及netty直接自定义协议 15 | 16 | ### 使用该框架的公司 17 | 深圳市快读科技,深圳市聚美良品科技,广州家庭医生在线,德阳继圣科技,上海互软集团,吉安医海,深圳市巨和网络 百佳惠瑞丰大药房 18 | ... 19 | 20 | ## 原理图 21 | ![原理](..//img/planning_map.jpg) 22 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-common/src/main/java/cn/hserver/cloud/common/ConstConfig.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.cloud.common; 2 | 3 | 4 | public interface ConstConfig { 5 | String CLOUD_ADDRESS = "cloud.address"; 6 | String REGISTER_NAME = "cloud.register.name"; 7 | String REGISTER_MY_IP = "cloud.register.ip"; 8 | String REGISTER_MY_PORT = "cloud.register.port"; 9 | String REGISTER_GROUP_NAME = "cloud.register.group"; 10 | String DEFAULT_GROUP_NAME = "DEFAULT_GROUP"; 11 | } 12 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/ioc/annotation/Bean.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.ioc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface Bean { 11 | String value() default ""; // Bean名称(默认使用方法名) 12 | 13 | boolean primary() default false; // 是否为主候选Bean 14 | } -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/server/WebServer.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.server; 2 | 3 | 4 | import cn.hserver.core.config.ConfigData; 5 | import cn.hserver.mvc.router.Router; 6 | 7 | public interface WebServer { 8 | 9 | Router router=new Router(); 10 | 11 | static void webPort(int port) { 12 | ConfigData.getInstance().set("web.port", port); 13 | } 14 | 15 | 16 | void start(int port,int sslPort,SslData sslData); 17 | // 停止服务 18 | void stop(); 19 | } 20 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/annotation/validate/Size.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.annotation.validate; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 字段 CharSequence 集合 map 数组必须在这范围内 7 | * 8 | * @author hxm 9 | */ 10 | @Target({ElementType.FIELD, ElementType.PARAMETER}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | public @interface Size { 14 | 15 | long min(); 16 | 17 | long max(); 18 | 19 | String message() default "字段不在设置的min-max的范围内"; 20 | } 21 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/ioc/annotation/Qualifier.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.ioc.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface Qualifier { 11 | String value(); 12 | } -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/modelcontextprotocol/spec/ClientMcpTransport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 - 2024 the original author or authors. 3 | */ 4 | package cn.hserver.modelcontextprotocol.spec; 5 | 6 | /** 7 | * Marker interface for the client-side MCP transport. 8 | * 9 | * @author Christian Tzolov 10 | * @deprecated This class will be removed in 0.9.0. Use {@link McpClientTransport}. 11 | */ 12 | @Deprecated 13 | public interface ClientMcpTransport extends McpTransport { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/modelcontextprotocol/spec/ServerMcpTransport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 - 2024 the original author or authors. 3 | */ 4 | package cn.hserver.modelcontextprotocol.spec; 5 | 6 | /** 7 | * Marker interface for the server-side MCP transport. 8 | * 9 | * @author Christian Tzolov 10 | * @deprecated This class will be removed in 0.9.0. Use {@link McpServerTransport}. 11 | */ 12 | @Deprecated 13 | public interface ServerMcpTransport extends McpTransport { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /docs/zh-cn/mqtt.md: -------------------------------------------------------------------------------- 1 | ## **Mqtt** 2 | ```xml 3 | 4 | cn.hserver 5 | hserver-plugin-mqtt 6 | 7 | ``` 8 | 9 | 请继承MqttAdapter类 并用@Bean 标记 10 | 其他操作可以重写父类的一些方法 11 | 12 | ```java 13 | 14 | @Bean 15 | public class Mqtt extends MqttAdapter { 16 | 17 | @Override 18 | public void message(MqttMessageType mqttMessageType, MqttMessage mqttMessage, ChannelHandlerContext channelHandlerContext) { 19 | System.out.println(mqttMessageType); 20 | } 21 | } 22 | 23 | 24 | ``` 25 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/request/HeadMap.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.request; 2 | 3 | import java.util.concurrent.ConcurrentHashMap; 4 | 5 | /** 6 | * @author hxm 7 | */ 8 | public class HeadMap extends ConcurrentHashMap { 9 | 10 | @Override 11 | public String put(String key, String value) { 12 | return super.put(key.toLowerCase(), value); 13 | } 14 | 15 | public String get(String key) { 16 | return super.get(key.toLowerCase()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/context/handler/HookHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.context.handler; 2 | 3 | import cn.hserver.core.aop.annotation.Hook; 4 | import cn.hserver.core.ioc.bean.BeanDefinition; 5 | 6 | import java.util.Map; 7 | 8 | public class HookHandler implements AnnotationHandler { 9 | @Override 10 | public void handle(Class clazz, Map beanDefinitions) { 11 | if (clazz.isAnnotationPresent(Hook.class)) { 12 | defaultHandler(clazz, beanDefinitions); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/context/WebContext.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.context; 2 | 3 | 4 | import cn.hserver.mvc.request.Request; 5 | import cn.hserver.mvc.response.Response; 6 | 7 | /** 8 | * web 上下文 9 | * 10 | * @author hxm 11 | */ 12 | public class WebContext { 13 | 14 | public Request request; 15 | 16 | public Response response; 17 | 18 | public WebContext(Request request, Response response) { 19 | this.request = request; 20 | this.response = response; 21 | } 22 | 23 | 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/context/handler/TestRunWithHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.context.handler; 2 | 3 | import cn.hserver.core.ioc.bean.BeanDefinition; 4 | import org.junit.runner.RunWith; 5 | 6 | import java.util.Map; 7 | 8 | public class TestRunWithHandler implements AnnotationHandler { 9 | @Override 10 | public void handle(Class clazz, Map beanDefinitions) { 11 | if (clazz.isAnnotationPresent(RunWith.class)) { 12 | defaultHandler(clazz, beanDefinitions); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-druid/src/main/java/cn/hserver/plugin/druid/DruidPlugin.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.druid; 2 | 3 | 4 | import cn.hserver.core.plugin.bean.PluginInfo; 5 | import cn.hserver.core.plugin.handler.PluginAdapter; 6 | 7 | 8 | public class DruidPlugin extends PluginAdapter { 9 | 10 | @Override 11 | public PluginInfo getPluginInfo() { 12 | return new PluginInfo.Builder() 13 | .name("Druid") 14 | .description("Druid 是一个 JDBC 组件库,包含数据库连接池,安全检查,防火墙等功能") 15 | .build(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin/druid/index.md: -------------------------------------------------------------------------------- 1 | 添加依赖 2 | 3 | ```xml 4 | 5 | cn.hserver 6 | hserver-plugin-druid 7 | 8 | ``` 9 | 10 | 设置数据源 11 | 12 | ```java 13 | DruidDataSource ds=new DruidDataSource(); 14 | ds.setUrl(mySqlUrl); 15 | ds.setUsername(mySqlUserName); 16 | ds.setPassword(mySqlPassword); 17 | ds.setDriverClassName(mySqlDriver); 18 | //接入时需要把拦截器打开,不然不能监控 19 | ds.setFilters("stat,wall"); 20 | ``` 21 | 22 | ### 访问地址: 23 | 24 | http://127.0.0.1:端口/druid/index.html 25 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/logging/ProcessIdClassicConverter.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.logging; 2 | 3 | import ch.qos.logback.classic.pattern.ClassicConverter; 4 | import ch.qos.logback.classic.spi.ILoggingEvent; 5 | 6 | import java.lang.management.ManagementFactory; 7 | 8 | /** 9 | * @author hxm 10 | */ 11 | public class ProcessIdClassicConverter extends ClassicConverter { 12 | 13 | @Override 14 | public String convert(ILoggingEvent event) { 15 | return ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /hserver-web/hserver-netty-web/src/main/java/cn/hserver/netty/web/util/NettyIpUtil.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.netty.web.util; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | 5 | import java.net.InetSocketAddress; 6 | 7 | public class NettyIpUtil { 8 | public static String getClientIp(ChannelHandlerContext ctx) { 9 | return ((InetSocketAddress) ctx.channel().remoteAddress()).getHostString(); 10 | } 11 | public static int getClientPort(ChannelHandlerContext ctx) { 12 | return ((InetSocketAddress) ctx.channel().remoteAddress()).getPort(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/exception/QpsException.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.exception; 2 | 3 | /** 4 | * @author hxm 5 | */ 6 | public class QpsException extends Exception { 7 | 8 | private final Integer qps; 9 | 10 | private final Double rate; 11 | 12 | public QpsException(Integer qps, Double rate) { 13 | super("QPS异常"); 14 | this.qps = qps; 15 | this.rate = rate; 16 | } 17 | 18 | public Integer getQps() { 19 | return qps; 20 | } 21 | 22 | public Double getRate() { 23 | return rate; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-discovery/src/main/java/cn/hserver/cloud/discovery/DiscoveryPlugin.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.cloud.discovery; 2 | 3 | import cn.hserver.core.context.IocApplicationContext; 4 | import cn.hserver.core.plugin.bean.PluginInfo; 5 | import cn.hserver.core.plugin.handler.PluginAdapter; 6 | 7 | public class DiscoveryPlugin extends PluginAdapter { 8 | @Override 9 | public PluginInfo getPluginInfo() { 10 | return new PluginInfo.Builder() 11 | .name("服务发现") 12 | .description("提供服务发现能力,让你快速查询相关服务配置") 13 | .build(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/queue/annotation/QueueListener.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.queue.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 注解:事件处理器。用于事件处理器类
7 | * 用法: EventHandler("/模块名") 8 | * 9 | * @author hxm 10 | */ 11 | @Documented 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target(ElementType.TYPE) 14 | public @interface QueueListener { 15 | /** 16 | * 队列名 17 | * 18 | * @return 19 | */ 20 | String queueName(); 21 | 22 | /** 23 | * 线程数 24 | * 25 | * @return 26 | */ 27 | int threadSize() default 1; 28 | } 29 | -------------------------------------------------------------------------------- /doc/maven: -------------------------------------------------------------------------------- 1 | gpg -–gen-key 2 | 3 | gpg –-keyserver hkp://pool.sks-keyservers.net:11371 –-send-keys C6EED57A 4 | gpg –-keyserver hkp://pgp.mit.edu:11371 –-send-keys C6EED57A 5 | gpg –-keyserver hkp://keyserver.ubuntu.com:11371 –-send-keys C6EED57A 6 | 7 | 8 | gpg –-keyserver hkp://pool.sks-keyservers.net:11371 -–recv-keys C6EED57A 9 | gpg –-keyserver hkp://pgp.mit.edu:11371 –-recv-keys C6EED57A 10 | gpg –-keyserver hkp://keyserver.ubuntu.com:11371 -–recv-keys C6EED57A 11 | 12 | 13 | mvn clean deploy -P release 14 | https://oss.sonatype.org 15 | 16 | git checkout -b HServer-2.9.4 17 | git push -u origin HServer-2.9.4 18 | 19 | -------------------------------------------------------------------------------- /hserver-build/hserver-runner/src/main/java/cn/hserver/runner/JarURLStreamHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.runner; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | public class JarURLStreamHandler extends java.net.URLStreamHandler { 7 | private final ClassLoader classLoader; 8 | private final boolean inJar; 9 | 10 | public JarURLStreamHandler(ClassLoader classLoader,boolean inJar) { 11 | this.classLoader = classLoader; 12 | this.inJar=inJar; 13 | } 14 | protected java.net.URLConnection openConnection(URL u) throws IOException { 15 | return new JarURLConnection(u, classLoader,inJar); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/websoket/WebSocketHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.websoket; 2 | 3 | 4 | 5 | /** 6 | * @author hxm 7 | */ 8 | public interface WebSocketHandler { 9 | 10 | /** 11 | * 连接 12 | * 13 | * @param ws 14 | */ 15 | void onConnect(Ws ws); 16 | 17 | /** 18 | * 来消息 19 | * 20 | * @param ws 21 | */ 22 | void onMessage(Ws ws); 23 | 24 | /** 25 | * 断开 26 | * 27 | * @param ws 28 | */ 29 | void disConnect(Ws ws); 30 | 31 | default String getSubProtocols() { 32 | 33 | return null; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/mcp/McpAnnotationHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mcp; 2 | 3 | import cn.hserver.core.context.handler.AnnotationHandler; 4 | import cn.hserver.core.ioc.bean.BeanDefinition; 5 | import cn.hserver.mcp.annotation.McpServerEndpoint; 6 | 7 | import java.util.Map; 8 | 9 | public class McpAnnotationHandler implements AnnotationHandler { 10 | @Override 11 | public void handle(Class clazz, Map beanDefinitions) { 12 | if (clazz.isAnnotationPresent(McpServerEndpoint.class)) { 13 | defaultHandler(clazz, beanDefinitions); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /docs/zh-cn/log.md: -------------------------------------------------------------------------------- 1 | 2 | ## **日志拦截** 3 | 4 | 类必须要被@Bean注解,同时实现LogAdapter接口,操作吃接口不要阻塞, 5 | 可以用HServerQueue 转发出来处理,切记不能让这里卡住了 6 | 7 | - logback-hserver.xml中默认已经加入这个配置,用于扩展日志,此处了解即可 8 | ```xml 9 | 10 | 11 | ``` 12 | 13 | - 你需要完成下面的实现就可以进行拦截了 14 | ```java 15 | @Bean 16 | public class Log implements LogAdapter { 17 | @Override 18 | public void log(LoggingEvent loggingEvent) { 19 | System.out.println(loggingEvent.getMessage()); 20 | } 21 | } 22 | ``` 23 | 24 | 通过配置文件也可以来控制日志级别 25 | ```properties 26 | #日志级别 debug info error ... 27 | log=debug 28 | ``` -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/modelcontextprotocol/spec/McpClientTransport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 - 2024 the original author or authors. 3 | */ 4 | package cn.hserver.modelcontextprotocol.spec; 5 | 6 | import reactor.core.publisher.Mono; 7 | 8 | import java.util.function.Function; 9 | 10 | /** 11 | * Marker interface for the client-side MCP transport. 12 | * 13 | * @author Christian Tzolov 14 | * @author Dariusz Jędrzejczyk 15 | */ 16 | public interface McpClientTransport extends ClientMcpTransport { 17 | 18 | @Override 19 | Mono connect(Function, Mono> handler); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/context/WebContextHolder.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.context; 2 | 3 | 4 | /** 5 | * @author hxm 6 | */ 7 | public class WebContextHolder { 8 | 9 | private static final ThreadLocal WEBKIT_INHERITABLE_THREAD_LOCAL = new ThreadLocal<>(); 10 | 11 | public static void setWebContext(WebContext webKit) { 12 | WEBKIT_INHERITABLE_THREAD_LOCAL.set(webKit); 13 | } 14 | 15 | public static WebContext getWebContext() { 16 | return WEBKIT_INHERITABLE_THREAD_LOCAL.get(); 17 | } 18 | 19 | public static void remove() { 20 | WEBKIT_INHERITABLE_THREAD_LOCAL.remove(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/server/SslData.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.server; 2 | 3 | 4 | import java.io.InputStream; 5 | 6 | public class SslData { 7 | 8 | private final InputStream keyInputStream; 9 | private final InputStream certInputStream; 10 | 11 | public SslData(InputStream keyInputStream, InputStream certInputStream) { 12 | this.keyInputStream = keyInputStream; 13 | this.certInputStream = certInputStream; 14 | } 15 | 16 | public InputStream getCertInputStream() { 17 | return certInputStream; 18 | } 19 | 20 | public InputStream getKeyInputStream() { 21 | return keyInputStream; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/queue/bean/QueueInfo.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.queue.bean; 2 | 3 | public class QueueInfo { 4 | //剩余数 5 | private final long size; 6 | private final int threadSize; 7 | private final String queueName; 8 | 9 | public QueueInfo(long size,int threadSize,String queueName) { 10 | this.size = size; 11 | this.threadSize = threadSize; 12 | this.queueName = queueName; 13 | } 14 | 15 | public long getSize() { 16 | return size; 17 | } 18 | 19 | public String getQueueName() { 20 | return queueName; 21 | } 22 | 23 | public int getThreadSize() { 24 | return threadSize; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /docs/zh-cn/unit.md: -------------------------------------------------------------------------------- 1 | 2 | ## **单元测试** 3 | 4 | 1. web 服务测试 5 | 6 | ```java 7 | /** 8 | * @author hxm 9 | */ 10 | @RunWith(HServerTestServer.class) 11 | public class TestWebApp { 12 | 13 | @Test 14 | public void start(){ 15 | } 16 | 17 | } 18 | ``` 19 | 20 | 2. 非web服务测试 21 | 22 | ```java 23 | 24 | @RunWith(HServerTest.class) 25 | public class test2 { 26 | 27 | @Autowired 28 | private TestBean testBean; 29 | 30 | @Autowired 31 | private Tom tom; 32 | 33 | @Test 34 | public void test(){ 35 | System.out.println(testBean.hello()); 36 | } 37 | 38 | @Test 39 | public void test2(){ 40 | System.out.println(tom.toString()); 41 | } 42 | 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/modelcontextprotocol/spec/McpError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 - 2024 the original author or authors. 3 | */ 4 | package cn.hserver.modelcontextprotocol.spec; 5 | 6 | import cn.hserver.modelcontextprotocol.spec.McpSchema.JSONRPCResponse.JSONRPCError; 7 | 8 | public class McpError extends RuntimeException { 9 | 10 | private JSONRPCError jsonRpcError; 11 | 12 | public McpError(JSONRPCError jsonRpcError) { 13 | super(jsonRpcError.getMessage()); 14 | this.jsonRpcError = jsonRpcError; 15 | } 16 | 17 | public McpError(Object error) { 18 | super(error.toString()); 19 | } 20 | 21 | public JSONRPCError getJsonRpcError() { 22 | return jsonRpcError; 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/logging/HServerDataDefinerFile.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.logging; 2 | 3 | import ch.qos.logback.core.PropertyDefinerBase; 4 | 5 | public class HServerDataDefinerFile extends PropertyDefinerBase { 6 | 7 | @Override 8 | public String getPropertyValue() { 9 | String requestId = HServerPatternLayout.defaultConverterMap.get("requestId"); 10 | if (requestId!=null){ 11 | return "%d{yyyy-MM-dd HH:mm:ss.SSS} %5.5level --- [%17.17thread] %-40.40logger{40} [%4.4line] [%requestId] : %msg%n"; 12 | }else { 13 | return "%d{yyyy-MM-dd HH:mm:ss.SSS} %5.5level --- [%17.17thread] %-40.40logger{40} [%4.4line] : %msg%n"; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/test/HServerTest.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.test; 2 | 3 | import cn.hserver.core.boot.HServerApplication; 4 | import cn.hserver.core.context.IocApplicationContext; 5 | import org.junit.runners.BlockJUnit4ClassRunner; 6 | import org.junit.runners.model.InitializationError; 7 | 8 | /** 9 | * @author hxm 10 | */ 11 | public class HServerTest extends BlockJUnit4ClassRunner { 12 | 13 | public HServerTest(Class klass) throws InitializationError { 14 | super(klass); 15 | HServerApplication.runTest(klass); 16 | } 17 | 18 | @Override 19 | protected Object createTest() throws Exception { 20 | return IocApplicationContext.getBean(this.getTestClass().getJavaClass()); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /hserver-web/hserver-smart-web/src/main/java/cn/hserver/smart/Main.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.smart; 2 | 3 | //TIP 要运行代码,请按 或 4 | // 点击装订区域中的 图标。 5 | public class Main { 6 | public static void main(String[] args) { 7 | //TIP 当文本光标位于高亮显示的文本处时按 8 | // 查看 IntelliJ IDEA 建议如何修正。 9 | System.out.printf("Hello and welcome!"); 10 | 11 | for (int i = 1; i <= 5; i++) { 12 | //TIP 按 开始调试代码。我们已经设置了一个 断点 13 | // 但您始终可以通过按 添加更多断点。 14 | System.out.println("i = " + i); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/aop/HookAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.aop; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * Aop 7 | * @author hxm 8 | */ 9 | public interface HookAdapter { 10 | 11 | /** 12 | * 之前 13 | * @param args 14 | */ 15 | void before(Class clazz, Method method, Object[] args) throws Throwable; 16 | 17 | /** 18 | * 之后 19 | * @param object 20 | * @return 21 | */ 22 | default Object after(Class clazz, Method method, Object object){ 23 | return object; 24 | } 25 | 26 | 27 | /** 28 | * 异常 29 | * @param clazz 30 | * @param method 31 | * @param throwable 32 | */ 33 | void throwable(Class clazz, Method method, Throwable throwable); 34 | } 35 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/request/Cookie.java: -------------------------------------------------------------------------------- 1 | // 2 | // Source code recreated from a .class file by IntelliJ IDEA 3 | // (powered by FernFlower decompiler) 4 | // 5 | 6 | package cn.hserver.mvc.request; 7 | 8 | public interface Cookie { 9 | String name(); 10 | 11 | String value(); 12 | 13 | void setValue(String var1); 14 | 15 | boolean wrap(); 16 | 17 | void setWrap(boolean var1); 18 | 19 | String domain(); 20 | 21 | void setDomain(String var1); 22 | 23 | String path(); 24 | 25 | void setPath(String var1); 26 | 27 | long maxAge(); 28 | 29 | void setMaxAge(long var1); 30 | 31 | boolean isSecure(); 32 | 33 | void setSecure(boolean var1); 34 | 35 | boolean isHttpOnly(); 36 | 37 | void setHttpOnly(boolean var1); 38 | } 39 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-beetlsql/src/main/java/cn/hserver/plugin/beetlsql/handler/BeetlSQLHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.beetlsql.handler; 2 | 3 | import cn.hserver.core.context.handler.AnnotationHandler; 4 | import cn.hserver.core.ioc.bean.BeanDefinition; 5 | import cn.hserver.plugin.beetlsql.annotation.BeetlSQL; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class BeetlSQLHandler implements AnnotationHandler { 11 | private final List> beetlsql; 12 | public BeetlSQLHandler(List> beetlsql) { 13 | this.beetlsql=beetlsql; 14 | } 15 | 16 | @Override 17 | public void handle(Class clazz, Map beanDefinitions) { 18 | if (clazz.isAnnotationPresent(BeetlSQL.class)) { 19 | beetlsql.add(clazz); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /hserver-web/hserver-netty-web/src/main/java/cn/hserver/netty/web/constants/NettyConfig.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.netty.web.constants; 2 | 3 | 4 | import io.netty.handler.ssl.SslContext; 5 | 6 | public class NettyConfig { 7 | public static IoMultiplexer IO_MODE = IoMultiplexer.DEFAULT; 8 | 9 | /** 10 | * backlog 指定了内核为此套接口排队的最大连接个数; 11 | * 对于给定的监听套接口,内核要维护两个队列: 未连接队列和已连接队列 12 | * backlog 的值即为未连接队列和已连接队列的和。 13 | */ 14 | public static Integer BACKLOG = 8192; 15 | 16 | public static Integer WORKER_POOL = 0; 17 | public static Long WRITE_LIMIT = null; 18 | public static Long READ_LIMIT = null; 19 | public static Integer HTTP_CONTENT_SIZE = Integer.MAX_VALUE; 20 | 21 | public static Integer MAX_WEBSOCKET_FRAME_LENGTH = 65535; 22 | public static SslContext SSL_CONTEXT; 23 | public static Integer SSL_PORT; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /hserver-web/hserver-smart-web/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-web 9 | 4.0.0-beta.6 10 | 11 | 12 | hserver-smart-web 13 | hserver-smart-web 14 | 15 | 8 16 | 8 17 | UTF-8 18 | 19 | 20 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/queue/bean/QueueData.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.queue.bean; 2 | 3 | 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author hxm 9 | */ 10 | public class QueueData implements Serializable { 11 | 12 | private String queueName; 13 | 14 | private Object[] args; 15 | 16 | public QueueData() {} 17 | 18 | public QueueData(String queueName, Object[] args) { 19 | this.queueName = queueName; 20 | this.args = args; 21 | } 22 | 23 | public String getQueueName() { 24 | return queueName; 25 | } 26 | 27 | public void setQueueName(String queueName) { 28 | this.queueName = queueName; 29 | } 30 | 31 | public Object[] getArgs() { 32 | return args; 33 | } 34 | 35 | public void setArgs(Object[] args) { 36 | this.args = args; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /hserver-build/hserver-runner/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-build 9 | 4.0.0-beta.6 10 | 11 | 12 | hserver-runner 13 | hserver-runner 14 | 15 | 16 | 8 17 | 8 18 | UTF-8 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-cloud 9 | 4.0.0-beta.6 10 | 11 | 12 | hserver-cloud-common 13 | hserver-cloud-common 14 | 15 | 16 | 8 17 | 8 18 | UTF-8 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin/jar.md: -------------------------------------------------------------------------------- 1 | ## 打包jar 2 | 3 | Main函数类上添加@HServerBoot 注解用于标记是启动类。 4 | ```xml 5 | 6 | 7 | aaa 8 | 9 | 10 | hserver-plugin-maven 11 | cn.hserver 12 | 13 | 14 | 15 | 16 | true 17 | 18 | 19 | 20 | dm_pro_token_key 21 | 22 | 23 | 24 | 25 | 26 | 27 | ``` -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/config/ConfigMap.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.config; 2 | 3 | import java.util.concurrent.ConcurrentHashMap; 4 | 5 | /** 6 | * @author hxm 7 | */ 8 | public class ConfigMap extends ConcurrentHashMap { 9 | 10 | @Override 11 | public Object put(String key, Object value) { 12 | return super.put(key.toLowerCase(), value); 13 | } 14 | 15 | public Object get(String key) { 16 | return super.get(key.toLowerCase()); 17 | } 18 | 19 | @Override 20 | public Object get(Object key) { 21 | return super.get(key.toString().toLowerCase()); 22 | } 23 | 24 | @Override 25 | public Object getOrDefault(Object key, Object defaultValue) { 26 | return super.getOrDefault(key.toString().toLowerCase(), defaultValue); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/scheduling/bean/TaskDefinition.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.scheduling.bean; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | public class TaskDefinition { 6 | private final String name; 7 | private final String time; 8 | private final String beanName; 9 | private final Method method; 10 | 11 | public TaskDefinition(String name,String time,String beanName,Method method) { 12 | this.name=name; 13 | this.time=time; 14 | this.beanName=beanName; 15 | this.method=method; 16 | } 17 | 18 | public Method getMethod() { 19 | return method; 20 | } 21 | 22 | public String getBeanName() { 23 | return beanName; 24 | } 25 | 26 | public String getName() { 27 | return name; 28 | } 29 | 30 | public String getTime() { 31 | return time; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/aop/RefreshMethodHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.aop; 2 | 3 | import cn.hserver.core.context.IocApplicationContext; 4 | import cn.hserver.core.ioc.BeanFactory; 5 | import cn.hserver.core.ioc.bean.BeanDefinition; 6 | import javassist.util.proxy.MethodHandler; 7 | 8 | import java.lang.reflect.Method; 9 | 10 | public class RefreshMethodHandler implements MethodHandler { 11 | 12 | private final BeanDefinition beanDefinition; 13 | 14 | 15 | public RefreshMethodHandler(BeanDefinition beanDefinition) { 16 | this.beanDefinition = beanDefinition; 17 | } 18 | 19 | @Override 20 | public Object invoke(Object self, Method thismethod, Method proceed, Object[] args) throws Throwable { 21 | Object target=IocApplicationContext.getOrCreateRefreshTarget(beanDefinition); 22 | return thismethod.invoke(target, args); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/scheduling/CronExecutorService.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.scheduling; 2 | 3 | 4 | import java.lang.reflect.Method; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.ScheduledFuture; 7 | 8 | /** 9 | * @author hxm 10 | */ 11 | public interface CronExecutorService extends ExecutorService { 12 | 13 | ScheduledFuture submit(CronExpression expression, String className, Method method); 14 | ScheduledFuture submit(Integer expression, String className, Method method); 15 | ScheduledFuture submit(CronExpression expression, TaskJob taskJob, Object... args); 16 | ScheduledFuture submit(Integer expression, TaskJob taskJob, Object... args); 17 | 18 | default Object[] getNullParm(Method method){ 19 | int parameterCount = method.getParameterCount(); 20 | return new Object[parameterCount]; 21 | } 22 | } -------------------------------------------------------------------------------- /hserver-build/hserver-maven/src/main/java/cn/hserver/plugins/maven/AesUtil.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugins.maven; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.CipherInputStream; 5 | import javax.crypto.SecretKey; 6 | import javax.crypto.spec.SecretKeySpec; 7 | import java.io.InputStream; 8 | import java.nio.charset.StandardCharsets; 9 | 10 | public class AesUtil { 11 | private static final String ALGORITHM = "AES"; 12 | 13 | 14 | private static SecretKey getKey(byte[] key) { 15 | return new SecretKeySpec(key, ALGORITHM); 16 | } 17 | 18 | public static CipherInputStream encrypt(InputStream inputStream, String password) throws Exception { 19 | Cipher cipher = Cipher.getInstance(ALGORITHM); 20 | cipher.init(Cipher.ENCRYPT_MODE, getKey(password.getBytes(StandardCharsets.UTF_8))); 21 | return new CipherInputStream(inputStream,cipher); 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /docs/zh-cn/lifecycle.md: -------------------------------------------------------------------------------- 1 | 2 | ## **服务器启动完成执行的方法** 3 | 4 | 类必须要被@Bean注解,同时实现InitRunner接口, 5 | 6 | ```java 7 | @Bean 8 | public class RunInit implements InitRunner { 9 | 10 | @Autowired 11 | private User user; 12 | 13 | @Override 14 | public void init(String[] args) { 15 | System.out.println("初始化方法:注入的User对象的名字是-->"+user.getName()); 16 | } 17 | } 18 | ``` 19 | 20 | ## **服务器关闭回调执行的方法** 21 | 22 | 类必须要被@Bean注解,同时实现ServerCloseAdapter接口, 23 | 24 | ```java 25 | @Bean 26 | public class Close implements ServerCloseAdapter { 27 | @Override 28 | public void close() { 29 | System.out.println("服务开始关闭了,可以提前关闭资源或者有些没用处理完的,处理下"); 30 | System.out.println("延时5秒关闭"); 31 | try { 32 | Thread.sleep(5000); 33 | } catch (InterruptedException e) { 34 | e.printStackTrace(); 35 | } 36 | System.out.println("关闭了"); 37 | } 38 | } 39 | ``` -------------------------------------------------------------------------------- /hserver-build/hserver-runner/src/main/java/cn/hserver/runner/DataSafeUtil.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.runner; 2 | 3 | import javax.crypto.Cipher; 4 | import javax.crypto.CipherInputStream; 5 | import javax.crypto.SecretKey; 6 | import javax.crypto.spec.SecretKeySpec; 7 | import java.io.InputStream; 8 | import java.nio.charset.StandardCharsets; 9 | 10 | public class DataSafeUtil { 11 | private static final String ALGORITHM = "AES"; 12 | 13 | private static SecretKey getKey(byte[] key) { 14 | return new SecretKeySpec(key, ALGORITHM); 15 | } 16 | 17 | public static InputStream decrypt(InputStream encryptedInputStream, String password) throws Exception { 18 | Cipher cipher = Cipher.getInstance(ALGORITHM); 19 | cipher.init(Cipher.DECRYPT_MODE, getKey(password.getBytes(StandardCharsets.UTF_8))); 20 | return new CipherInputStream(encryptedInputStream, cipher); 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin/web/exception.md: -------------------------------------------------------------------------------- 1 | 2 | ## **全局异常处理** 3 | 4 | 类必须要被@Bean注解,同时实现GlobalException接口. 5 | 6 | 异常接口可以实现多个 ,但是得只要有输出将会中断链式调用. 7 | 8 | ```java 9 | 10 | @Bean 11 | public class WebException implements GlobalException { 12 | @Override 13 | public void handler(Throwable throwable, int httpStatusCode, String errorDescription, Webkit webkit) { 14 | HttpRequest httpRequest = webkit.httpRequest; 15 | StringBuilder error = new StringBuilder(); 16 | error.append("全局异常处理") 17 | .append("url") 18 | .append(httpRequest.getUri()) 19 | .append("错误信息:") 20 | .append(throwable.getMessage()) 21 | .append("错误描述:") 22 | .append(errorDescription); 23 | webkit.httpResponse.sendStatusCode(HttpResponseStatus.BAD_GATEWAY); 24 | webkit.httpResponse.sendText(error.toString()); 25 | } 26 | } 27 | 28 | ``` -------------------------------------------------------------------------------- /docs/zh-cn/plugin/web/websocket.md: -------------------------------------------------------------------------------- 1 | ## WebSocket 2 | 3 | 需要被@WebSocket标注同时给一个连接地址,最后实现WebSocketHandler接口, 4 | Ws类定义了简单的发送方法,如果有其他的业务操作,可以获取ChannelHandlerContext,进行操作 5 | 6 | ```java 7 | 8 | 9 | @WebSocket("/ws") 10 | public class WebSocketTest implements WebSocketHandler { 11 | 12 | @Autowired 13 | private TestService testService; 14 | 15 | @Override 16 | public void onConnect(Ws ws) { 17 | System.out.println("连接成功,分配的UID:" + ws.getUid()); 18 | } 19 | 20 | @Override 21 | public void onMessage(Ws ws) { 22 | ws.send("666" + testService.testa() + ws.getUid()); 23 | System.out.println("收到的消息,"+ws.getMessage()+",UID:" + ws.getUid()); 24 | } 25 | 26 | @Override 27 | public void disConnect(Ws ws) { 28 | System.out.println("断开连接,UID:" + ws.getUid()); 29 | } 30 | } 31 | ``` 32 | 33 | ws类提供了Netty原始的HttpRequest对象,你可以自由处理,同时提供了 query 函数,帮助你快速查找到websocket URL的参数 34 | 35 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/exception/ValidateException.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.exception; 2 | 3 | /** 4 | * 验证异常类型 5 | * @author hxm 6 | */ 7 | public class ValidateException extends RuntimeException{ 8 | private final Class type; 9 | private final Object data; 10 | public ValidateException(String message){ 11 | super(message); 12 | this.type=null; 13 | this.data=null; 14 | } 15 | 16 | public ValidateException(String message, Class type,Object data){ 17 | super(message); 18 | this.type=type; 19 | this.data=data; 20 | } 21 | public ValidateException(String message, Class type){ 22 | super(message); 23 | this.type=type; 24 | this.data=null; 25 | } 26 | 27 | 28 | 29 | public Class getType() { 30 | return type; 31 | } 32 | 33 | public Object getData() { 34 | return data; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /docs/zh-cn/track.md: -------------------------------------------------------------------------------- 1 | ## **Track跟踪** 2 | 3 | 使用动态字节码技术,字节码处理,可以跟踪任意方法,不跟踪HServer框架本身,不跟踪已经被jvm加载的,不跟踪已经被跟踪的类,不跟踪接口和抽象方法 4 | 5 | 1.在配置文件添加 6 | ```properties 7 | track=true 8 | 9 | 10 | #跟踪路径配置(可选)默认也有跟踪 11 | 12 | #添加其他的包跟踪,用引英文逗号隔开默认不用在操作了, 13 | #它是向下找,包名越短,扫码到的文件更多 14 | trackExtPackages=com.mysql,org.freemarker 15 | 16 | #排除这些包不跟踪 17 | trackNoPackages=com.mysql,org.freemarker 18 | 19 | 20 | ``` 21 | 2.实现TrackAdapter接口,并在类上用 @Bean标识 22 | 23 | ```java 24 | /** 25 | * @author hxm 26 | */ 27 | @Bean 28 | @Slf4j 29 | public class TrackImpl implements TrackAdapter { 30 | @Override 31 | public void track(Class clazz, CtMethod method, StackTraceElement[] stackTraceElements, long start, long end,long pSpanId,long spanId) throws Exception { 32 | log.info("当前类:{},当前方法:{},耗时:{}", clazz.getName(), stackTraceElements[1].getMethodName(), (end - start) + "ms"); 33 | JvmStack.printMemoryInfo(); 34 | JvmStack.printGCInfo(); 35 | } 36 | } 37 | 38 | ``` 39 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-impl/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-cloud 9 | 4.0.0-beta.6 10 | 11 | hserver-cloud-impl 12 | hserver-cloud-impl 13 | pom 14 | 15 | hserver-cloud-nacos 16 | 17 | 18 | 8 19 | 8 20 | UTF-8 21 | 22 | 23 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin/web/check.md: -------------------------------------------------------------------------------- 1 | 2 | ## **参数校验器** 3 | 4 | ``` 5 | 控制器参数是一个Bean时,字段可以使用校验器注解 6 | ``` 7 | 8 | | 注解 | 描述 | 9 | | ------------ | ------------------------------------------------------ | 10 | | @AssertFalse | 字段为必须为false | 11 | | @AssertTrue | 字段为必须为true | 12 | | @Length | 字段CharSequence 类型的长度必须是 length 长 | 13 | | @Max | 字段值必须大于这个值,number | 14 | | @Min | 字段值必须小于这个值,number | 15 | | @NotBlank | 字段不能为null同时不是 "" | 16 | | @NotEmpty | CharSequence 集合 map 数组 不是null 长度或者size 大于0 | 17 | | @NotNull | 字段不能为Null | 18 | | @Null | 字段必须为Null | 19 | | @Pattern | 字段CharSequence 必须满足这个正则 | 20 | | @Size | 字段 CharSequence 集合 map 数组必须在这范围内 | 21 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.exception; 2 | 3 | import cn.hserver.mvc.context.WebContext; 4 | 5 | public abstract class GlobalExceptionHandler { 6 | 7 | public abstract void handlerException(Throwable throwable, WebContext webContext); 8 | 9 | protected T getException(Throwable throwable,Class clazz){ 10 | // 如果传入的异常为null,直接返回null 11 | if (throwable == null) { 12 | return null; 13 | } 14 | // 如果当前异常就是目标类型,直接返回 15 | if (clazz.isInstance(throwable)) { 16 | @SuppressWarnings("unchecked") 17 | T result = (T) throwable; 18 | return result; 19 | } 20 | // 递归查找嵌套的异常(通过getCause()方法) 21 | Throwable cause = throwable.getCause(); 22 | if (cause != null) { 23 | return getException(cause, clazz); 24 | } 25 | // 整个异常链中都没有找到目标类型的异常 26 | return null; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /hserver-build/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-parent 9 | 4.0.0-beta.6 10 | 11 | 12 | hserver-build 13 | hserver-build 14 | pom 15 | 16 | hserver-maven 17 | hserver-runner 18 | 19 | 20 | 21 | 8 22 | 8 23 | UTF-8 24 | 25 | 26 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/util/NamedThreadFactory.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.util; 2 | 3 | import java.util.concurrent.ThreadFactory; 4 | import java.util.concurrent.atomic.LongAdder; 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | public class NamedThreadFactory implements ThreadFactory { 10 | 11 | private final String prefix; 12 | private final LongAdder threadNumber = new LongAdder(); 13 | private final boolean isDaemon; 14 | public NamedThreadFactory(String prefix) { 15 | this.prefix = prefix; 16 | this.isDaemon = true; 17 | } 18 | 19 | public NamedThreadFactory(String prefix, boolean daemon) { 20 | this.prefix = prefix; 21 | this.isDaemon = daemon; 22 | } 23 | 24 | @Override 25 | public Thread newThread(Runnable runnable) { 26 | threadNumber.add(1); 27 | Thread thread = new Thread(runnable, prefix + "@" + threadNumber.intValue()); 28 | //不要卡线程 29 | thread.setDaemon(isDaemon); 30 | return thread; 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/logging/HServerLogAsyncAppender.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.logging; 2 | 3 | import ch.qos.logback.classic.spi.LoggingEvent; 4 | import ch.qos.logback.core.AppenderBase; 5 | 6 | import java.util.List; 7 | 8 | public class HServerLogAsyncAppender extends AppenderBase { 9 | private static List listLogBean = null; 10 | 11 | public static void setHasLog(List listLogBean) { 12 | if (listLogBean != null && !listLogBean.isEmpty()) { 13 | HServerLogAsyncAppender.listLogBean = listLogBean; 14 | } 15 | } 16 | 17 | @Override 18 | protected void append(LoggingEvent eventObject) { 19 | if (listLogBean != null) { 20 | for (LogAdapter logAdapter : listLogBean) { 21 | try { 22 | logAdapter.log(eventObject); 23 | } catch (Throwable e) { 24 | System.err.println(e.getMessage()); 25 | } 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/queue/bean/QueueHandleInfo.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.queue.bean; 2 | 3 | import cn.hserver.core.queue.QueueEventHandler; 4 | 5 | /** 6 | * 处理器信息 7 | * 8 | * @author hxm 9 | */ 10 | public class QueueHandleInfo { 11 | private final String queueName; 12 | private int threadSize; 13 | private QueueEventHandler queueEventHandler; 14 | 15 | public QueueHandleInfo(String queueName) { 16 | this.queueName = queueName; 17 | } 18 | 19 | public String getQueueName() { 20 | return queueName; 21 | } 22 | 23 | public int getThreadSize() { 24 | return threadSize; 25 | } 26 | 27 | public QueueEventHandler getQueueEventHandler() { 28 | return queueEventHandler; 29 | } 30 | 31 | public void setThreadSize(int threadSize) { 32 | this.threadSize = threadSize; 33 | } 34 | 35 | public void setQueueEventHandler(QueueEventHandler queueEventHandler) { 36 | this.queueEventHandler = queueEventHandler; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-forest/readme.md: -------------------------------------------------------------------------------- 1 | ## 远程调用 2 | - 配置 3 | ```java 4 | 5 | @Bean 6 | public class ForestConfig extends ForestClientConfig { 7 | 8 | @Override 9 | public void config(ForestConfiguration forestConfiguration) { 10 | forestConfiguration.setVariableValue("apiBaseUrl","http://127.0.0.1:8080"); 11 | } 12 | } 13 | ``` 14 | 15 | - 接口定义 16 | ```java 17 | @ForestClient 18 | @BaseRequest( 19 | baseURL = "{apiBaseUrl}" 20 | ) 21 | public interface TestRemote { 22 | /** 23 | * 查询签到 24 | * @param address 25 | * @return 26 | */ 27 | @Get("/data/pub/blockSign") 28 | String blockSign(@Query("address")String address); 29 | 30 | /** 31 | * 购买金币 32 | * @param data 33 | * @return 34 | */ 35 | @Post("/data/pub/buyCoin") 36 | String buyCoin(@Body Map data); 37 | } 38 | ``` 39 | 40 | - 使用 41 | 42 | ```java 43 | @Bean 44 | @Slf4j 45 | public class GameService { 46 | @Autowired 47 | private TestRemote testRemote; 48 | 49 | //todo 其他业务调用 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/logging/HServerHighlightingCompositeConverter.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.logging; 2 | 3 | import ch.qos.logback.classic.Level; 4 | import ch.qos.logback.classic.spi.ILoggingEvent; 5 | import ch.qos.logback.core.pattern.color.ANSIConstants; 6 | import ch.qos.logback.core.pattern.color.ForegroundCompositeConverterBase; 7 | 8 | /** 9 | * @author hxm 10 | */ 11 | public class HServerHighlightingCompositeConverter extends ForegroundCompositeConverterBase { 12 | 13 | 14 | @Override 15 | protected String getForegroundColorCode(ILoggingEvent event) { 16 | switch (event.getLevel().toInt()) { 17 | case Level.ERROR_INT: 18 | return ANSIConstants.RED_FG; 19 | case Level.WARN_INT: 20 | return ANSIConstants.YELLOW_FG; 21 | case Level.INFO_INT: 22 | return ANSIConstants.GREEN_FG; 23 | case Level.DEBUG_INT: 24 | return ANSIConstants.MAGENTA_FG; 25 | default: 26 | return null; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/mcp/McpFilter.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mcp; 2 | 3 | import cn.hserver.core.ioc.annotation.Component; 4 | import cn.hserver.mvc.constants.HttpMethod; 5 | import cn.hserver.mvc.context.WebContext; 6 | import cn.hserver.mvc.filter.FilterAdapter; 7 | 8 | import static cn.hserver.mcp.McpPlugin.hServerSseServerTransportProviderList; 9 | 10 | @Component 11 | public class McpFilter implements FilterAdapter { 12 | 13 | @Override 14 | public void doFilter(WebContext webContext) throws Exception { 15 | if (hServerSseServerTransportProviderList.isEmpty()){ 16 | return; 17 | } 18 | hServerSseServerTransportProviderList.forEach(provider -> { 19 | if (webContext.request.getRequestMethod() == HttpMethod.POST) { 20 | provider.doPost(webContext.request,webContext.response); 21 | } 22 | if (webContext.request.getRequestMethod() == HttpMethod.GET) { 23 | provider.doGet(webContext.request,webContext.response); 24 | } 25 | }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /hserver-web/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-parent 9 | 4.0.0-beta.6 10 | 11 | 12 | hserver-web 13 | hserver-web 14 | pom 15 | 16 | hserver-mvc 17 | hserver-netty-web 18 | hserver-smart-web 19 | hserver-web-starter 20 | 21 | 22 | 23 | 8 24 | 8 25 | UTF-8 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/zh-cn/hum.md: -------------------------------------------------------------------------------- 1 | ## **HUM消息** 2 | 3 | HServer UPD Message HUM消息是在局域网内服务之间的通讯,实现数据共享,使用UPD广播方式,方便内网服务器相关的通讯,注意此协议是不可靠的,也就是可能会存在数据发生不过去的情况,或者接受不到数据,因此在编码过程中,需要注意这点。 4 | 5 | 6 | 7 | - 消息接受器 8 | - 提供了Hum用来区分和发送消息 9 | 10 | ```java 11 | import cn.hserver.core.interfaces.HumAdapter; 12 | import cn.hserver.core.ioc.annotation.Bean; 13 | import cn.hserver.core.server.handlers.Hum; 14 | 15 | @Bean 16 | public class HumMsg implements HumAdapter { 17 | 18 | @Override 19 | public void message(Object o, Hum hum) { 20 | 21 | //UDP其实不分服务端和客服端,但是为了开发理解方便,加入这个 22 | // hum是点对点推送 23 | System.out.println(hum.getType()+"-->Hum消息:"+o); 24 | if (hum.getType()== Hum.Type.CLIENT){ 25 | hum.sendMessage(System.currentTimeMillis()+"Server"); 26 | } 27 | else { 28 | hum.sendMessage(System.currentTimeMillis()+"Client"); 29 | } 30 | } 31 | } 32 | ``` 33 | 34 | - 主动发送消息 35 | - 默认9527端口,可以在配置文件中自定义端口: 36 | ```properties 37 | humPort=9527 38 | #开启hum 默认开启 39 | humOpen=true 40 | ``` 41 | ```java 42 | //广播推送 43 | HumClient.sendMessage("666"); 44 | ``` 45 | -------------------------------------------------------------------------------- /hserver-build/hserver-runner/src/main/java/cn/hserver/runner/JarURLStreamHandlerFactory.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.runner; 2 | 3 | import java.net.URLStreamHandler; 4 | import java.net.URLStreamHandlerFactory; 5 | 6 | public class JarURLStreamHandlerFactory implements URLStreamHandlerFactory { 7 | private final ClassLoader classLoader; 8 | private URLStreamHandlerFactory chainFac; 9 | 10 | public JarURLStreamHandlerFactory(ClassLoader cl) { 11 | this.classLoader = cl; 12 | } 13 | 14 | 15 | public URLStreamHandler createURLStreamHandler(String protocol) { 16 | if (RunnerConfig.IN_JAR.equals(protocol + ":")) 17 | return new JarURLStreamHandler(classLoader, true); 18 | else if (RunnerConfig.OUT_JAR.equals(protocol + ":")) { 19 | return new JarURLStreamHandler(classLoader, false); 20 | } 21 | if (chainFac != null) 22 | return chainFac.createURLStreamHandler(protocol); 23 | return null; 24 | } 25 | 26 | public void setURLStreamHandlerFactory(URLStreamHandlerFactory fac) { 27 | chainFac = fac; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/mcp/annotation/PromptMapping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 noear.org and authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.hserver.mcp.annotation; 17 | 18 | 19 | 20 | import java.lang.annotation.*; 21 | 22 | 23 | @Target({ElementType.METHOD}) 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Documented 26 | public @interface PromptMapping { 27 | /** 28 | * 名字 29 | */ 30 | String name(); 31 | 32 | /** 33 | * 描述 34 | */ 35 | String description(); 36 | 37 | } -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/mcp/annotation/ToolMapping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 noear.org and authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.hserver.mcp.annotation; 17 | 18 | 19 | import java.lang.annotation.*; 20 | 21 | 22 | @Target({ElementType.METHOD}) 23 | @Retention(RetentionPolicy.RUNTIME) 24 | @Documented 25 | public @interface ToolMapping { 26 | /** 27 | * 名字(没有时类名即为名) 28 | */ 29 | String name(); 30 | 31 | /** 32 | * 描述 33 | */ 34 | String description (); 35 | 36 | } -------------------------------------------------------------------------------- /hserver-cloud/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-parent 9 | 4.0.0-beta.6 10 | 11 | 12 | hserver-cloud 13 | hserver-cloud 14 | pom 15 | 16 | hserver-cloud-register 17 | hserver-cloud-discovery 18 | hserver-cloud-common 19 | hserver-cloud-impl 20 | 21 | 22 | 23 | 8 24 | 8 25 | UTF-8 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/zh-cn/prop.md: -------------------------------------------------------------------------------- 1 | ## **自定义Banner** 2 | resources文件夹里存放一个banner.txt 里面放入你图标就可以了. 3 | 4 | 5 | ```properties 6 | #外置配置大于jar中包配置文件,配置文件大于代码默认设置 7 | 8 | #应用名字,默认HServer 9 | appName=HServer 10 | 11 | #开启hum 12 | humOpen=true 13 | 14 | #hum消息端口,默认9527 15 | humPort=9527 16 | 17 | #端口动态指定,多个用英文逗号隔开 配置文件大于代码写死, 18 | ports=9090 19 | 20 | #动态配置文件 21 | env=dev 22 | 23 | #链路跟踪 默认不跟踪 24 | track=true 25 | 26 | #添加其他的包跟踪,用引英文逗号隔开默认不用在操作了,前缀匹配模式 27 | 28 | #它是向下找,包名越短,扫码到的文件更多 29 | trackExtPackages=com.mysql,org.freemarker 30 | 31 | #排除这些包不跟踪 32 | trackNoPackages=com.mysql,org.freemarker 33 | 34 | #taskPool定时任务线程池子配置,默认大小是cpu核心数+1 35 | taskPool=5 36 | 37 | #workerPool Netty worker线程组大小 默认核心数两倍 38 | workerPool=2 39 | 40 | 41 | #backlog 指定了内核为此套接口排队的最大连接个数; 42 | #对于给定的监听套接口,内核要维护两个队列: 未连接队列和已连接队列 43 | #backlog 的值即为未连接队列和已连接队列的和。 44 | backLog=8192 45 | 46 | #io模型默认 IO_URING >EPOLL>KQUEUE>JDK 47 | ioMode=DEFAULT 48 | 49 | #前置协议的最大大小,用于自定义拦截协议时的分析,如果1024字节都不能判断你的大小,可以将其调整大点 50 | preProtocolMaxSize=1024 51 | 52 | #日志级别 debug info error ... 53 | log=debug 54 | #自定义日志名字 55 | logbackName=logback-dev.xml 56 | 57 | #队列数据缓存位置 默认当前项目下 58 | persistPath=/user/mcl/data 59 | 60 | 61 | ``` 62 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/json/JsonAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.json; 2 | 3 | import java.lang.reflect.Parameter; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author hxm 8 | */ 9 | public interface JsonAdapter { 10 | 11 | /** 12 | * string 转对象 13 | * 14 | * @param data 15 | * @param type 16 | * @return 17 | */ 18 | Object convertObject(String data, Class type); 19 | 20 | 21 | /** 22 | * 参数类型转换 23 | * 24 | * @param data 25 | * @param type 26 | * @return 27 | */ 28 | Object convertObject(String data, Parameter type); 29 | 30 | /** 31 | * map转对象 32 | * 33 | * @param data 34 | * @param type 35 | * @return 36 | */ 37 | Object convertMapToObject(Map data, Class type); 38 | 39 | /** 40 | * obj转换 41 | * @param data 42 | * @param type 43 | * @return 44 | */ 45 | Object convertObjToObject(Object data, Class type); 46 | 47 | /** 48 | * 对象转String 49 | * 50 | * @param data 51 | * @return 52 | */ 53 | String convertString(Object data); 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/mcp/annotation/ResourcesMapping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 noear.org and authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.hserver.mcp.annotation; 17 | 18 | 19 | 20 | import java.lang.annotation.*; 21 | 22 | 23 | @Target({ElementType.METHOD}) 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Documented 26 | public @interface ResourcesMapping { 27 | 28 | String uri(); 29 | 30 | /** 31 | * 名字 32 | */ 33 | String name(); 34 | 35 | /** 36 | * 描述 37 | */ 38 | String description(); 39 | 40 | } -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/util/JarInputStreamUtil.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.util; 2 | 3 | 4 | import cn.hserver.core.config.ConstConfig; 5 | 6 | import javax.crypto.Cipher; 7 | import javax.crypto.CipherInputStream; 8 | import javax.crypto.SecretKey; 9 | import javax.crypto.spec.SecretKeySpec; 10 | import java.io.InputStream; 11 | import java.nio.charset.StandardCharsets; 12 | 13 | public class JarInputStreamUtil { 14 | private static final String ALGORITHM = "AES"; 15 | 16 | private static SecretKey getKey(byte[] key) { 17 | return new SecretKeySpec(key, ALGORITHM); 18 | } 19 | 20 | public static InputStream decrypt(InputStream encryptedInputStream) throws Exception { 21 | String password = ConstConfig.PASSWORD; 22 | if (password != null && !password.trim().isEmpty()) { 23 | Cipher cipher = Cipher.getInstance(ALGORITHM); 24 | cipher.init(Cipher.DECRYPT_MODE, getKey(password.getBytes(StandardCharsets.UTF_8))); 25 | return new CipherInputStream(encryptedInputStream, cipher); 26 | } else { 27 | return encryptedInputStream; 28 | } 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/ioc/handler/ConfigurationPropertiesHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.ioc.handler; 2 | 3 | import cn.hserver.core.config.ConfigData; 4 | import cn.hserver.core.config.annotation.ConfigurationProperties; 5 | 6 | import java.lang.reflect.Field; 7 | 8 | public class ConfigurationPropertiesHandler implements PopulateBeanHandler{ 9 | 10 | @Override 11 | public void populate(Object bean) { 12 | ConfigurationProperties configurationProperties = bean.getClass().getAnnotation(ConfigurationProperties.class); 13 | if (configurationProperties != null) { 14 | for (Field field : bean.getClass().getDeclaredFields()) { 15 | String configName = field.getName(); 16 | if (!configurationProperties.prefix().isEmpty()) { 17 | configName = configurationProperties.prefix() + "." + field.getName(); 18 | } 19 | Object fieldValue = ConfigData.getInstance().get(configName,null); 20 | if (fieldValue != null) { 21 | populateValue(bean, field, fieldValue); 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/context/handler/AnnotationHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.context.handler; 2 | 3 | import cn.hserver.core.ioc.bean.BeanDefinition; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | public interface AnnotationHandler { 10 | List ANNOTATION_HANDLERS = new ArrayList(){ 11 | { 12 | add(new ComponentHandler()); 13 | add(new ConfigurationHandler()); 14 | add(new HookHandler()); 15 | add(new QueueListenerHandler()); 16 | add(new TestRunWithHandler()); 17 | } 18 | }; 19 | 20 | static void addHandler(final AnnotationHandler annotationHandler) { 21 | ANNOTATION_HANDLERS.add(annotationHandler); 22 | } 23 | 24 | void handle(Class clazz, Map beanDefinitions); 25 | 26 | default void defaultHandler(Class clazz, Map beanDefinitions){ 27 | BeanDefinition configBeanDef = new BeanDefinition(); 28 | configBeanDef.setBeanClass(clazz); 29 | beanDefinitions.put(configBeanDef.getDefaultBeanName(), configBeanDef); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/ioc/handler/ValueHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.ioc.handler; 2 | 3 | import cn.hserver.core.config.ConfigData; 4 | import cn.hserver.core.config.annotation.Value; 5 | import cn.hserver.core.ioc.annotation.Autowired; 6 | import cn.hserver.core.ioc.annotation.Qualifier; 7 | 8 | import java.beans.BeanInfo; 9 | import java.beans.Introspector; 10 | import java.beans.PropertyDescriptor; 11 | import java.lang.reflect.Field; 12 | import java.lang.reflect.Method; 13 | import java.lang.reflect.Modifier; 14 | 15 | import static cn.hserver.core.context.IocApplicationContext.getBean; 16 | 17 | public class ValueHandler implements PopulateBeanHandler{ 18 | 19 | @Override 20 | public void populate(Object bean) { 21 | for (Field field : bean.getClass().getDeclaredFields()) { 22 | if (field.isAnnotationPresent(Value.class)) { 23 | Value value = field.getAnnotation(Value.class); 24 | Object fieldValue = ConfigData.getInstance().get(value.value(),null); 25 | if (fieldValue != null) { 26 | populateValue(bean, field, fieldValue); 27 | } 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-satoken/src/main/java/cn/hserver/plugin/satoken/mode/SaStorageForHServer.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.satoken.mode; 2 | 3 | import cn.dev33.satoken.context.model.SaStorage; 4 | import cn.hserver.mvc.request.Request; 5 | 6 | public class SaStorageForHServer implements SaStorage { 7 | 8 | /** 9 | * 底层Request对象 10 | */ 11 | protected Request request; 12 | 13 | /** 14 | * 实例化 15 | * @param request request对象 16 | */ 17 | public SaStorageForHServer(Request request) { 18 | this.request = request; 19 | } 20 | 21 | /** 22 | * 获取底层源对象 23 | */ 24 | @Override 25 | public Object getSource() { 26 | return request; 27 | } 28 | 29 | /** 30 | * 在 [Request作用域] 里写入一个值 31 | */ 32 | @Override 33 | public SaStorageForHServer set(String key, Object value) { 34 | request.setAttribute(key, value); 35 | return this; 36 | } 37 | 38 | /** 39 | * 在 [Request作用域] 里获取一个值 40 | */ 41 | @Override 42 | public Object get(String key) { 43 | return request.getAttribute(key); 44 | } 45 | 46 | /** 47 | * 在 [Request作用域] 里删除一个值 48 | */ 49 | @Override 50 | public SaStorageForHServer delete(String key) { 51 | request.removeAttribute(key); 52 | return this; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin/forest.md: -------------------------------------------------------------------------------- 1 | ## 远程调用 2 | 3 | 4 | ```xml 5 | 6 | cn.hserver 7 | hserver-plugin-forest 8 | 9 | ``` 10 | 11 | - 配置 12 | ```java 13 | 14 | @Bean 15 | public class ForestConfig extends ForestClientConfig { 16 | 17 | @Override 18 | public void config(ForestConfiguration forestConfiguration) { 19 | forestConfiguration.setVariableValue("apiBaseUrl","http://127.0.0.1:8080"); 20 | } 21 | } 22 | ``` 23 | 24 | - 接口定义 25 | ```java 26 | @ForestClient 27 | @BaseRequest( 28 | baseURL = "{apiBaseUrl}" 29 | ) 30 | public interface TestRemote { 31 | /** 32 | * 查询签到 33 | * @param address 34 | * @return 35 | */ 36 | @Get("/data/pub/blockSign") 37 | String blockSign(@Query("address")String address); 38 | 39 | /** 40 | * 购买金币 41 | * @param data 42 | * @return 43 | */ 44 | @Post("/data/pub/buyCoin") 45 | String buyCoin(@Body Map data); 46 | } 47 | ``` 48 | 49 | - 使用 50 | 51 | ```java 52 | @Bean 53 | @Slf4j 54 | public class GameService { 55 | @Autowired 56 | private TestRemote testRemote; 57 | 58 | //todo 其他业务调用 59 | } 60 | ``` 61 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/mcp/annotation/McpServerEndpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 noear.org and authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.hserver.mcp.annotation; 17 | 18 | 19 | 20 | import java.lang.annotation.*; 21 | 22 | 23 | @Target({ElementType.TYPE}) 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Documented 26 | public @interface McpServerEndpoint { 27 | /** 28 | * 名字(没有时类名即为名) 29 | */ 30 | String name() default "mcp-server"; 31 | 32 | /** 33 | * 版本 34 | */ 35 | String version() default "1.0.0"; 36 | 37 | /** 38 | * SSE 端点 39 | */ 40 | String sseEndpoint() default "/sse"; 41 | } -------------------------------------------------------------------------------- /docs/_navbar.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | * 代码案例 4 | 5 | * [BeetlSql使用案例](https://gitee.com/HServer/hserver-for-java-beetlsql) 6 | * [MYSQL-NEO案例](https://gitee.com/HServer/hserver-for-java-mysql) 7 | * [Redis操作源码](https://gitee.com/HServer/hserver-for-java-redis) 8 | * [mongodb操作源码](https://gitee.com/HServer/hserver-for-java-mongodb) 9 | * [MybatisPlus案例](https://gitee.com/HServer/hserver-system) 10 | * [7层代理(可做网关)](https://gitee.com/HServer/http-proxy) 11 | * [自定义协议](https://gitee.com/HServer/hsvevr-for-custom-protocol) 12 | * [简易统计demo](https://gitee.com/HServer/hserver-for-java-statistics) 13 | * [后台管理系统(权限校验相关操作)](https://gitee.com/HServer/hserver-system) 14 | * [docker自动部署工具](https://gitee.com/HServer/hserver-for-docker) 15 | * [HP内网穿透(单端口多协议)](https://gitee.com/HServer/hp) 16 | * [链路追踪](https://gitee.com/HServer/hserver-apm) 17 | * [HPLite基于quic内网穿透](https://gitee.com/HServer/hp-lite) 18 | * [Satoken+mybatis flex后台管理系统](https://gitee.com/HServer/hserver-admin) 19 | * [nsfw离线鉴黄](https://gitee.com/HServer/hserver-nsfw) 20 | * [webdav同步工具](https://gitee.com/HServer/cloud-sync) 21 | * [WebRtc聊天发文件](https://gitee.com/HServer/hfile) 22 | * [OAuth/OpenId(OIDC)演示](https://gitee.com/HServer/hserver-oauth-demo) 23 | -------------------------------------------------------------------------------- /hserver-plugin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-parent 9 | 4.0.0-beta.6 10 | 11 | 12 | pom 13 | hserver-plugin 14 | hserver-plugin 15 | 16 | 17 | 8 18 | 8 19 | UTF-8 20 | 21 | 22 | 23 | hserver-plugin-beetlsql 24 | hserver-plugin-mybatisplus 25 | hserver-plugin-druid 26 | hserver-plugin-mybatis_flex 27 | hserver-plugin-satoken 28 | hserver-plugin-forest 29 | hserver-plugin-mcp 30 | 31 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/queue/QueueEventHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.queue; 2 | 3 | import cn.hserver.core.context.IocApplicationContext; 4 | import cn.hserver.core.queue.bean.QueueData; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.lang.reflect.Method; 9 | 10 | /** 11 | * @author hxm 12 | */ 13 | 14 | public class QueueEventHandler { 15 | private static final Logger log = LoggerFactory.getLogger(QueueEventHandler.class); 16 | 17 | private final Method method; 18 | private final String handlerName; 19 | 20 | private Object handler; 21 | 22 | 23 | public QueueEventHandler(String handlerName, Method method) { 24 | this.method = method; 25 | this.handlerName = handlerName; 26 | } 27 | 28 | public void invoke(QueueData queueData) { 29 | try { 30 | if (handler == null) { 31 | handler = IocApplicationContext.getBean(handlerName); 32 | } 33 | Object[] args = queueData.getArgs(); 34 | if (!method.isAccessible()) { 35 | method.setAccessible(true); 36 | } 37 | method.invoke(handler, args); 38 | } catch (Exception e) { 39 | log.error(e.getMessage(), e); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/aop/bean/HookBeanDefinition.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.aop.bean; 2 | 3 | import cn.hserver.core.aop.HookAdapter; 4 | import cn.hserver.core.context.IocApplicationContext; 5 | 6 | import java.lang.reflect.Method; 7 | 8 | public class HookBeanDefinition { 9 | 10 | private final Class hookHandler; 11 | 12 | private final Method[] hookMethod; 13 | 14 | private HookAdapter hookAdapter; 15 | 16 | public Class getHookHandler() { 17 | return hookHandler; 18 | } 19 | 20 | public Method[] getHookMethod() { 21 | return hookMethod; 22 | } 23 | 24 | public HookBeanDefinition(Class hookHandler, Method[] hookMethod) { 25 | this.hookHandler = hookHandler; 26 | this.hookMethod = hookMethod; 27 | } 28 | 29 | 30 | public boolean isMatchMethod(Method method){ 31 | for (Method hookMethod : this.hookMethod) { 32 | if (hookMethod.equals(method)){ 33 | return true; 34 | } 35 | } 36 | return false; 37 | } 38 | 39 | public HookAdapter getHookAdapter() { 40 | if (hookAdapter == null){ 41 | hookAdapter= (HookAdapter)IocApplicationContext.getBean(hookHandler); 42 | } 43 | return hookAdapter; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-satoken/src/main/java/cn/hserver/plugin/satoken/config/SaTokenContextForHServer.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.satoken.config; 2 | 3 | import cn.dev33.satoken.context.SaTokenContextForReadOnly; 4 | import cn.dev33.satoken.context.model.SaRequest; 5 | import cn.dev33.satoken.context.model.SaResponse; 6 | import cn.dev33.satoken.context.model.SaStorage; 7 | import cn.hserver.mvc.context.WebContextHolder; 8 | import cn.hserver.plugin.satoken.mode.SaRequestForHServer; 9 | import cn.hserver.plugin.satoken.mode.SaResponseForHServer; 10 | import cn.hserver.plugin.satoken.mode.SaStorageForHServer; 11 | 12 | public class SaTokenContextForHServer implements SaTokenContextForReadOnly { 13 | @Override 14 | public boolean isValid() { 15 | return WebContextHolder.getWebContext()!=null; 16 | } 17 | 18 | @Override 19 | public SaRequest getRequest() { 20 | return new SaRequestForHServer(WebContextHolder.getWebContext().request); 21 | } 22 | 23 | @Override 24 | public SaResponse getResponse() { 25 | return new SaResponseForHServer(WebContextHolder.getWebContext().response); 26 | } 27 | 28 | @Override 29 | public SaStorage getStorage() { 30 | return new SaStorageForHServer(WebContextHolder.getWebContext().request); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/util/SslUtil.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.util; 2 | 3 | import cn.hserver.mvc.constants.WebConstConfig; 4 | import cn.hserver.mvc.server.SslData; 5 | 6 | import java.io.InputStream; 7 | import java.nio.file.Files; 8 | import java.nio.file.Paths; 9 | 10 | 11 | public class SslUtil { 12 | 13 | public static SslData loadSSlData() { 14 | try { 15 | if (WebConstConfig.SSL_KEY == null || WebConstConfig.SSL_CERT == null) { 16 | return null; 17 | } 18 | InputStream keyInputStream = Files.newInputStream(Paths.get(WebConstConfig.SSL_KEY)); 19 | InputStream certInputStream = Files.newInputStream(Paths.get(WebConstConfig.SSL_CERT)); 20 | return new SslData(keyInputStream, certInputStream); 21 | } catch (Exception ignored) { 22 | //看看是不是resources里面的 23 | InputStream keyInputStream = SslUtil.class.getResourceAsStream("/ssl/" + WebConstConfig.SSL_KEY); 24 | InputStream certInputStream = SslUtil.class.getResourceAsStream("/ssl/" + WebConstConfig.SSL_CERT); 25 | if (keyInputStream != null && certInputStream != null) { 26 | return new SslData(keyInputStream, certInputStream); 27 | } 28 | } 29 | return null; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-forest/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-plugin 9 | 4.0.0-beta.6 10 | 11 | 12 | hserver-plugin-forest 13 | hserver-plugin-forest 14 | 15 | 16 | 8 17 | 8 18 | UTF-8 19 | 20 | 21 | 22 | 23 | 24 | cn.hserver 25 | hserver-core 26 | provided 27 | 28 | 29 | 30 | com.dtflys.forest 31 | forest-core 32 | 1.7.3 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/util/ExceptionUtil.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.util; 2 | 3 | import java.io.PrintWriter; 4 | import java.io.StringWriter; 5 | 6 | public class ExceptionUtil { 7 | 8 | private static Throwable getExceptionType(Throwable e) { 9 | return e; 10 | } 11 | 12 | private static String getExceptionMessage(Throwable e) { 13 | return e.getMessage(); 14 | } 15 | 16 | private static String getExceptionSrintStackTrace(Throwable e) { 17 | StringWriter sw = new StringWriter(); 18 | PrintWriter pw = new PrintWriter(sw); 19 | e.printStackTrace(pw); 20 | return sw.toString(); 21 | } 22 | 23 | public static String getMessage(Throwable e) { 24 | return "\n" + ExceptionUtil.getExceptionSrintStackTrace(e); 25 | } 26 | 27 | public static String getHtmlMessage(Throwable e) { 28 | StringBuilder stringBuilder = new StringBuilder(); 29 | stringBuilder.append("
").append(getExceptionSrintStackTrace(e).replaceAll("\n", "
").replaceAll("\t", "
 
")); 30 | if (e.getMessage() != null) { 31 | stringBuilder.append("
 
"); 32 | } 33 | return stringBuilder.toString(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/src/main/java/cn/hserver/mcp/annotation/Param.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 noear.org and authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package cn.hserver.mcp.annotation; 17 | 18 | 19 | import cn.hserver.mcp.type.McpType; 20 | 21 | import java.lang.annotation.*; 22 | 23 | 24 | @Target({ElementType.PARAMETER}) 25 | @Retention(RetentionPolicy.RUNTIME) 26 | @Documented 27 | public @interface Param { 28 | /** 29 | * 类型 30 | */ 31 | McpType type() default McpType.string; 32 | /** 33 | * 描述 34 | */ 35 | String description() default ""; 36 | 37 | /** 38 | * 默认值 39 | */ 40 | String defaultValue() default ""; 41 | 42 | 43 | String[] enums() default {}; 44 | 45 | boolean required() default true; 46 | } 47 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-beetlsql/README.md: -------------------------------------------------------------------------------- 1 | # HServer SQL插件 2 | 3 | ``` 4 | 版本查询 https://repo1.maven.org/maven2/net/hserver/plugins/beetlsql/plugins.beetlsql/ 5 | 6 | 当前 3.14.2-RELEASE 7 | 8 | beetlsql 3.4.3-RELEASE 9 | 10 | ``` 11 | 12 | ``` 13 | 14 | cn.hserver 15 | hserver-plugin-beetlsql 16 | 17 | 18 | ``` 19 | 20 | ``` 21 | @BeetlSQL 22 | public interface UserDao2 extends BaseMapper { 23 | 24 | @Update 25 | @Sql("update user set age = ? where id = ?") 26 | void update(Integer age,int id); 27 | 28 | List select(); 29 | } 30 | ``` 31 | 32 | @Bean 33 | public class UserService { 34 | @Autowired 35 | private UserDao2 userDao2; 36 | 37 | @Tx(rollbackFor = ArithmeticException.class,timeoutMillisecond = 1000) 38 | public boolean update() { 39 | System.out.println("我的:"+Thread.currentThread().getName()); 40 | userDao2.update(2222, 1); 41 | // System.out.println(1 / 0); 42 | try { 43 | Thread.sleep(2000); 44 | } catch (InterruptedException e) { 45 | e.printStackTrace(); 46 | } 47 | return false; 48 | } 49 | } 50 | 51 | ``` -------------------------------------------------------------------------------- /docs/zh-cn/plugin/web/authentication.md: -------------------------------------------------------------------------------- 1 | ## **鉴权认证相关操作** 2 | 3 | @RequiresPermissions 4 | 5 | @RequiresRoles 6 | 7 | @Sign 8 | 9 | 请使用相关注解对控制器的方法做标记,这样在执行到被注解标记的方法就会执行下面的相关方法 10 | List routerPermissions = PermissionAdapter.getRouterPermissions(); 11 | 通过上面的代码可以获取到所有标记的注解,他可以干嘛? 12 | 同步后台数据库里面的权限,后台管理面里面可以动态给角色分配权限。 13 | 自己做一个下拉选择列表,创建角色分配权限时,多选即可。 14 | 15 | 16 | ```java 17 | @Bean 18 | public class TestPermission implements PermissionAdapter { 19 | 20 | @Override 21 | public void requiresPermissions(RequiresPermissions requiresPermissions, Webkit webkit) { 22 | //这里你可以实现一套自己的权限检查算法逻辑,判断, 23 | //如果满足权限,不用其他操作,如果不满足权限,那么你可以通过,Webkit里面的方法直接输出相关内容 24 | //或者自定义一个异常类,在全局异常类做相关操作 25 | System.out.println(requiresPermissions.value()[0]); 26 | } 27 | 28 | @Override 29 | public void requiresRoles(RequiresRoles requiresRoles, Webkit webkit) { 30 | //这里你可以实现一套自己的角色检查算法逻辑,判断, 31 | //其他逻辑同上 32 | System.out.println(requiresRoles.value()[0]); 33 | } 34 | 35 | @Override 36 | public void sign(Sign sign, Webkit webkit) { 37 | //这里你可以实现一套自己的接口签名算法检查算法逻辑,判断, 38 | //其他逻辑同上 39 | Map requestParams = webkit.httpRequest.getRequestParams(); 40 | String sign1 = webkit.httpRequest.getHeader("sign"); 41 | System.out.println(sign.value()); 42 | } 43 | } 44 | ``` -------------------------------------------------------------------------------- /docs/zh-cn/annotation.md: -------------------------------------------------------------------------------- 1 | ## 注解认识 2 | 3 | 根据上面的例子,大家应该理解是非常容易的,和springboot很相似。接下我们了解下注解这里,注解只是做简单描述,具体使用在后面的章节会演示出来 4 | 5 | | 注解 | 描述信息 | 6 | | :----------------------: | :----------------------------------------------------------: | 7 | | @Bean | 将当前类加入IOC中,类似spring的@Component注解,可以名字放入ioc 如@Bean("Test") | 8 | | @Autowired | 将ioc里的某个对象注入给某个字段,和spring用法类似,可以名字注入ioc 如@Autowired("Test") | 9 | | @Order | 排序注解 值越小,优先级越高 (LimitAdapter.class, FilterAdapter.class, GlobalException.class, InitRunner.class, ResponseAdapter.class, ProtocolDispatcherAdapter.class, ServerCloseAdapter.class) 这些子类支持排序 | 10 | | @Configuration | 配置注解,这个和springboot有相似之处(这个类中可以注入 @NacosClass,@NacosValue,@Value,@ConfigurationProperties这些注解产生的对象) | 11 | | @ConfigurationProperties | 配置类,和springboot相似 将Properties转为对象放入IOC | 12 | | @Hook | AOP操作使用 | 13 | | @Track | 链路跟踪注解,如果你想检查某些方法的耗时或者其他监控,可以用这个注解,具体看下面的介绍 | 14 | | @Value | 用来把Properties字段注入到类的字段里 | 15 | | @QueueListener | 标记一个类为队列处理类 | 16 | | @QueueHandler | 标记一个方法为队列处理方法 | 17 | 18 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-discovery/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-cloud 9 | 4.0.0-beta.6 10 | 11 | 12 | hserver-cloud-discovery 13 | hserver-cloud-discovery 14 | 15 | 16 | 8 17 | 8 18 | UTF-8 19 | 20 | 21 | 22 | cn.hserver 23 | hserver-core 24 | provided 25 | 26 | 27 | cn.hserver 28 | hserver-cloud-common 29 | ${hserver.version} 30 | compile 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-discovery/src/main/java/cn/hserver/cloud/discovery/DiscoveryService.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.cloud.discovery; 2 | 3 | 4 | import cn.hserver.cloud.common.ConstConfig; 5 | import cn.hserver.cloud.common.ServerInstance; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author hxm 11 | */ 12 | public abstract class DiscoveryService { 13 | 14 | /** 15 | * 查询服务 16 | */ 17 | public abstract List find(String group, String service); 18 | 19 | /** 20 | * 更具权重查询一个服务 21 | * @param group 22 | * @param service 23 | * @return 24 | */ 25 | public abstract ServerInstance findOne(String group, String service); 26 | 27 | public List find( String service){ 28 | return find(ConstConfig.DEFAULT_GROUP_NAME,service); 29 | } 30 | 31 | /** 32 | * 更具权重查询一个服务 33 | * @param service 34 | * @return 35 | */ 36 | public ServerInstance findOne(String service){ 37 | return findOne(ConstConfig.DEFAULT_GROUP_NAME,service); 38 | } 39 | 40 | /** 41 | * 订阅服务 42 | */ 43 | public abstract void subscribe(String group, String service,DiscoveryListener discoveryListener); 44 | public void subscribe(String service,DiscoveryListener discoveryListener) { 45 | subscribe(ConstConfig.DEFAULT_GROUP_NAME,service,discoveryListener); 46 | } 47 | } -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-register/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-cloud 9 | 4.0.0-beta.6 10 | 11 | 12 | hserver-cloud-register 13 | hserver-cloud-register 14 | 15 | 16 | 8 17 | 8 18 | UTF-8 19 | 20 | 21 | 22 | cn.hserver 23 | hserver-core 24 | provided 25 | 26 | 27 | cn.hserver 28 | hserver-cloud-common 29 | ${hserver.version} 30 | compile 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mybatisplus/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | cn.hserver 7 | hserver-plugin 8 | 4.0.0-beta.6 9 | 10 | 4.0.0 11 | 12 | hserver-plugin-mybatisplus 13 | hserver-plugin-mybatisplus 14 | 15 | 16 | 8 17 | 8 18 | UTF-8 19 | true 20 | 21 | 22 | 23 | 24 | com.baomidou 25 | mybatis-plus 26 | 3.5.12 27 | 28 | 29 | cn.hserver 30 | hserver-core 31 | provided 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin/rpc/index.md: -------------------------------------------------------------------------------- 1 | # hserver-rpc-plugin 2 | 3 | ## 不错得,纯异步RPC组件,性能管够 4 | 5 | ```xml 6 | 7 | 8 | cn.hserver 9 | hserver-plugin-rpc 10 | 11 | 12 | 13 | cn.hserver 14 | hserver-plugin-cloud 15 | 16 | 17 | 18 | cn.hserver 19 | hserver-plugin-nacos 20 | 21 | 22 | ``` 23 | 24 | ##### 服务都注册到注册中心上去 消费和提供者都注册进去 25 | ```properties 26 | app.cloud.reg.registerAddress=http://127.0.0.1:8848 27 | #注册名字 28 | app.cloud.reg.registerName=dsds 29 | #注册我的Ip 30 | app.cloud.reg.registerMyIp=127.0.0.1 31 | #注册我的端口 32 | app.cloud.reg.registerMyPort=8080 33 | #注册分组 34 | app.cloud.reg.groupName=DEFAULT_GROUP 35 | ``` 36 | 37 | ```java 38 | //调用服务 39 | public @interface Resource { 40 | String value() default ""; 41 | 42 | //服务名 43 | String serverName(); 44 | 45 | //组名 46 | String groupName() default ""; 47 | } 48 | 49 | @Resource(serverName="user") 50 | private UserService userService; 51 | 52 | 53 | 54 | //发布服务 55 | public @interface RpcService { 56 | String value() default ""; 57 | } 58 | 59 | @Bean 60 | @RpcService 61 | public class UserServiceImpl implements UserService { 62 | } 63 | //服务调用需要定义common接口UserService 64 | ``` -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/config/ConstConfig.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.config; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * @author hxm 7 | */ 8 | public class ConstConfig { 9 | /** 10 | * 内部自用名字 11 | */ 12 | public final static String SERVER_NAME = "HServer"; 13 | /** 14 | * 版本 15 | */ 16 | public final static String VERSION = "4.0.0-beta.6"; 17 | /** 18 | * 当前项目路径 19 | */ 20 | public static final String PATH = System.getProperty("user.dir") + File.separator; 21 | /** 22 | * 运行环境 23 | */ 24 | public static Boolean RUN_JAR = false; 25 | /** 26 | * classpat路径 27 | */ 28 | public static String CLASSPATH; 29 | /** 30 | * 加密密码 31 | */ 32 | public static String PASSWORD; 33 | 34 | /** 35 | * 定时任务线程数配置 36 | */ 37 | public static Integer taskPool = Runtime.getRuntime().availableProcessors() + 1; 38 | 39 | 40 | /** 41 | * 配置文件 42 | */ 43 | public static String EVN = System.getProperty("env"); 44 | 45 | 46 | /** 47 | * 持久化文件存储位置 48 | */ 49 | public static String PERSIST_PATH = PATH + "queue"; 50 | 51 | 52 | /** 53 | * 应用名字 54 | */ 55 | public static String APP_NAME = "HServer"; 56 | 57 | public static String LOGBACK_NAME = "logback-hserver.xml"; 58 | 59 | public static String LOG_LEVEL = "debug"; 60 | 61 | } 62 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-impl/hserver-cloud-nacos/src/main/java/cn/hserver/cloud/nacos/NamingConfig.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.cloud.nacos; 2 | 3 | import cn.hserver.cloud.common.CloudAddress; 4 | import cn.hserver.cloud.common.ConstConfig; 5 | import cn.hserver.core.config.ConfigData; 6 | import cn.hserver.core.config.annotation.Configuration; 7 | import cn.hserver.core.context.IocApplicationContext; 8 | import cn.hserver.core.ioc.annotation.Bean; 9 | import com.alibaba.nacos.api.naming.NamingFactory; 10 | import com.alibaba.nacos.api.naming.NamingService; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | @Configuration 15 | public class NamingConfig { 16 | private static final Logger log = LoggerFactory.getLogger(NamingConfig.class); 17 | 18 | @Bean 19 | public NamingService namingService() { 20 | CloudAddress cloudAddress = IocApplicationContext.getBeansOfTypeOne(CloudAddress.class); 21 | if (cloudAddress==null) { 22 | String string = ConfigData.getInstance().getString(ConstConfig.CLOUD_ADDRESS,null); 23 | cloudAddress=new CloudAddress(); 24 | cloudAddress.setCloudAddress(string); 25 | } 26 | try { 27 | return NamingFactory.createNamingService(cloudAddress.getCloudAddress()); 28 | } catch (Exception e) { 29 | log.error(e.getMessage(), e); 30 | } 31 | return null; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/session/HttpSession.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.session; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class HttpSession { 7 | 8 | private final Map attributes = new HashMap<>(); 9 | 10 | private String id = null; 11 | 12 | private long created = -1; 13 | 14 | private long expired = -1; 15 | 16 | public T attribute(String name) { 17 | Object object = this.attributes.get(name); 18 | return null != object ? (T) object : null; 19 | } 20 | 21 | public void attribute(String name, Object value) { 22 | this.attributes.put(name, value); 23 | } 24 | 25 | public Map attributes() { 26 | return attributes; 27 | } 28 | 29 | public void removeAttribute(String name) { 30 | this.attributes.remove(name); 31 | } 32 | 33 | public String id() { 34 | return id; 35 | } 36 | 37 | public void id(String id) { 38 | this.id = id; 39 | } 40 | 41 | public long created() { 42 | return this.created; 43 | } 44 | 45 | public void created(long created) { 46 | this.created = created; 47 | } 48 | 49 | public long expired() { 50 | return this.expired; 51 | } 52 | 53 | public void expired(long expired) { 54 | this.expired = expired; 55 | } 56 | 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /hserver-web/hserver-netty-web/src/main/java/cn/hserver/netty/web/context/HttpResponseFile.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.netty.web.context; 2 | 3 | import java.io.File; 4 | import java.io.InputStream; 5 | 6 | public class HttpResponseFile { 7 | //下载的文件 8 | private final File file; 9 | 10 | //下载的文件流 11 | private final InputStream inputStream; 12 | 13 | //文件名 14 | private final String fileName; 15 | 16 | private final boolean chunked; 17 | 18 | private final boolean supportContinue; 19 | 20 | private final byte[] content; 21 | 22 | 23 | public HttpResponseFile(byte[] content,File file, InputStream inputStream, String fileName, boolean chunked, boolean supportContinue) { 24 | this.file = file; 25 | this.content = content; 26 | this.inputStream = inputStream; 27 | this.fileName = fileName; 28 | this.chunked = chunked; 29 | this.supportContinue = supportContinue; 30 | } 31 | 32 | public File getFile() { 33 | return file; 34 | } 35 | 36 | public byte[] getContent() { 37 | return content; 38 | } 39 | 40 | public InputStream getInputStream() { 41 | return inputStream; 42 | } 43 | 44 | public String getFileName() { 45 | return fileName; 46 | } 47 | 48 | public boolean isChunked() { 49 | return chunked; 50 | } 51 | 52 | public boolean isSupportContinue() { 53 | return supportContinue; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin/web/json.md: -------------------------------------------------------------------------------- 1 | ## **自定义JSON序列化** 2 | 3 | ```java 4 | 5 | //默认使用Jackson,可以自己实现这个接口进行替换,这段代码放在main 函数里 6 | HServerApplication.setJson(new JsonAdapter() { 7 | /** 8 | * string 转对象 9 | * @param data 10 | * @param type 11 | * @return 12 | */ 13 | @Override 14 | public Object convertObject(String data, Class type) { 15 | return null; 16 | } 17 | 18 | 19 | /** 20 | * 参数类型转换 21 | * 22 | * @param data 23 | * @param type 24 | * @return 25 | */ 26 | @Override 27 | public Object convertObject(String data, Parameter type) { 28 | return null; 29 | } 30 | /** 31 | * map转对象 32 | * 33 | * @param data 34 | * @param type 35 | * @return 36 | */ 37 | @Override 38 | public Object convertMapToObject(Map data, Class type) { 39 | return null; 40 | } 41 | /** 42 | * 对象转String 43 | * 44 | * @param data 45 | * @return 46 | */ 47 | @Override 48 | public String convertString(Object data) { 49 | return null; 50 | } 51 | }); 52 | 53 | 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-common/src/main/java/cn/hserver/cloud/common/RegisterConfig.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.cloud.common; 2 | 3 | public class RegisterConfig extends CloudAddress{ 4 | //注册名字 5 | private String registerName; 6 | //注册我的Ip 7 | private String registerMyIp; 8 | //注册我的端口 9 | private Integer registerMyPort; 10 | //注册分组 11 | private String registerGroupName = "DEFAULT_GROUP"; 12 | 13 | public String getRegisterName() { 14 | return registerName; 15 | } 16 | 17 | public void setRegisterName(String registerName) { 18 | this.registerName = registerName; 19 | } 20 | 21 | public String getRegisterMyIp() { 22 | return registerMyIp; 23 | } 24 | 25 | public void setRegisterMyIp(String registerMyIp) { 26 | this.registerMyIp = registerMyIp; 27 | } 28 | 29 | public Integer getRegisterMyPort() { 30 | return registerMyPort; 31 | } 32 | 33 | public void setRegisterMyPort(Integer registerMyPort) { 34 | this.registerMyPort = registerMyPort; 35 | } 36 | 37 | public String getRegisterGroupName() { 38 | return registerGroupName; 39 | } 40 | 41 | public void setRegisterGroupName(String groupName) { 42 | this.registerGroupName = groupName; 43 | } 44 | 45 | public boolean hasNull() { 46 | return this.getCloudAddress() == null || this.registerMyIp == null || this.registerMyPort == null || this.registerName == null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin.md: -------------------------------------------------------------------------------- 1 | ## 插件开发 2 | 3 | 1. 添加POM依赖 scope 设置为 provided 4 | 5 | ```xml 6 | 7 | 8 | cn.hserver 9 | hserver 10 | ${hserver.version} 11 | provided 12 | 13 | ``` 14 | 15 | 2. 实现接口PluginAdapter 16 | 17 | ```java 18 | /** 19 | * @author hxm 20 | */ 21 | 22 | /** 23 | * 插件适配器 24 | * 25 | * @author hxm 26 | */ 27 | public interface PluginAdapter { 28 | 29 | /** 30 | * 启动APP时执行,此时日志类还没有被初始化,不要进行日志输出 31 | */ 32 | void startApp(); 33 | 34 | /** 35 | * 开始初始化 36 | */ 37 | void startIocInit(); 38 | 39 | /** 40 | * ioc初始化bean对象 41 | * @param classz 42 | * @return 43 | */ 44 | boolean iocInitBean(Class classz); 45 | 46 | 47 | /** 48 | * 开始初始化获取初始化的被扫描的的对象 49 | * @param packageScanner 50 | */ 51 | void iocInit(PackageScanner packageScanner); 52 | 53 | /** 54 | * 初始化完成 55 | */ 56 | void iocInitEnd(); 57 | 58 | /** 59 | * 开始注入 60 | */ 61 | void startInjection(); 62 | 63 | /** 64 | * 注入完成 65 | */ 66 | void injectionEnd(); 67 | 68 | } 69 | 70 | ``` 71 | 72 | 3. spi处理 73 | 74 | ``` 75 | 建立一个文件 resources/META-INF/services/cn.hserver.core.interfaces.PluginAdapter 76 | 文件内容 cn.hserver.plugins.beetlsql.BeetLSqlPlugin 77 | 这个文件内容是你实现接口的包名+类名 78 | ``` 79 | 80 | 4. 参考插件 https://gitee.com/HServer/hserver-plugs-beetlsql,或者在厂库里去找关于Plugin的代码。后期的插件会越来越多 81 | 82 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/logging/HServerDataDefinerConsole.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.logging; 2 | 3 | 4 | import ch.qos.logback.core.PropertyDefinerBase; 5 | import cn.hserver.core.config.ConstConfig; 6 | 7 | public class HServerDataDefinerConsole extends PropertyDefinerBase { 8 | 9 | @Override 10 | public String getPropertyValue() { 11 | Boolean runjar = ConstConfig.RUN_JAR; 12 | boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win"); 13 | //web框架会提供这个请求ID 14 | String requestId = HServerPatternLayout.defaultConverterMap.get("requestId"); 15 | if (runjar && isWindows) { 16 | //非高亮格式 17 | if (requestId!=null) { 18 | return "%d{yyyy-MM-dd HH:mm:ss.SSS} %5.5level --- [%17.17thread] %-40.40logger{40} [%4.4line] [%requestId] : %msg%n"; 19 | }else { 20 | return "%d{yyyy-MM-dd HH:mm:ss.SSS} %5.5level --- [%17.17thread] %-40.40logger{40} [%4.4line] : %msg%n"; 21 | } 22 | } else { 23 | if (requestId!=null) { 24 | //高亮格式 25 | return "%d{yyyy-MM-dd HH:mm:ss.SSS} %HServerHighlight(%5.5level) 线程名: [%17.17thread] %cyan(%-40.40logger{39} 行号:[%4.4line]) 请求ID: [%requestId] : %msg%n"; 26 | }else { 27 | return "%d{yyyy-MM-dd HH:mm:ss.SSS} %HServerHighlight(%5.5level) 线程名: [%17.17thread] %cyan(%-40.40logger{39} 行号:[%4.4line]) : %msg%n"; 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /hserver-web/hserver-netty-web/src/main/java/cn/hserver/netty/web/util/ByteBufUtil.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.netty.web.util; 2 | 3 | 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.buffer.Unpooled; 6 | 7 | import java.io.*; 8 | 9 | /** 10 | * @author hxm 11 | */ 12 | public class ByteBufUtil { 13 | 14 | public static ByteBuf fileToByteBuf(File file) { 15 | try { 16 | FileInputStream input = new FileInputStream(file); 17 | return fileToByteBuf(input); 18 | } catch (Exception e) { 19 | return null; 20 | } 21 | } 22 | 23 | public static ByteBuf fileToByteBuf(InputStream input) { 24 | try { 25 | ByteArrayOutputStream babs = new ByteArrayOutputStream(); 26 | byte[] buffer = new byte[1024]; 27 | int len; 28 | while ((len = input.read(buffer)) != -1) { 29 | babs.write(buffer, 0, len); 30 | } 31 | babs.flush(); 32 | byte[] byteArray = babs.toByteArray(); 33 | ByteBuf byteBuf = Unpooled.wrappedBuffer(byteArray); 34 | input.close(); 35 | babs.close(); 36 | return byteBuf; 37 | } catch (IOException e) { 38 | return null; 39 | } finally { 40 | try { 41 | if (input != null) { 42 | input.close(); 43 | } 44 | } catch (IOException ignored) { 45 | } 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-forest/src/main/java/cn/hserver/plugin/forest/ForestPlugin.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.forest; 2 | 3 | import cn.hserver.core.context.IocApplicationContext; 4 | import cn.hserver.core.plugin.bean.PluginInfo; 5 | import cn.hserver.core.plugin.handler.PluginAdapter; 6 | import cn.hserver.plugin.forest.config.ForestClientConfig; 7 | import com.dtflys.forest.Forest; 8 | import com.dtflys.forest.annotation.ForestClient; 9 | 10 | import java.util.List; 11 | 12 | public class ForestPlugin extends PluginAdapter { 13 | 14 | 15 | @Override 16 | public void iocStartScan(Class clazz) { 17 | if (clazz.isAnnotationPresent(ForestClient.class)) { 18 | Object data = Forest.client(clazz); 19 | if (data != null) { 20 | IocApplicationContext.addBean(data); 21 | } 22 | } 23 | } 24 | 25 | @Override 26 | public void startedApp() { 27 | List beansOfType = IocApplicationContext.getBeansOfType(ForestClientConfig.class); 28 | if (beansOfType != null && !beansOfType.isEmpty()) { 29 | for (ForestClientConfig bean : beansOfType) { 30 | bean.config(Forest.config()); 31 | } 32 | } 33 | } 34 | 35 | @Override 36 | public PluginInfo getPluginInfo() { 37 | return new PluginInfo.Builder() 38 | .name("Forest插件") 39 | .description("一个高级、轻量级的 Java 声明式 HTTP 客户端框架") 40 | .build(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/sse/SSeStream.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.sse; 2 | 3 | 4 | public abstract class SSeStream { 5 | private final Integer retryMilliseconds; 6 | public SSeStream(Integer retryMilliseconds) { 7 | this.retryMilliseconds = retryMilliseconds; 8 | } 9 | 10 | protected void init(){ 11 | this.sendStartHeader(); 12 | if (retryMilliseconds != null&&retryMilliseconds > 0) { 13 | sendRetryEvent(("retry: " + retryMilliseconds + "\n\n")); 14 | } 15 | } 16 | 17 | public SSeStream sendSseEvent(SSeEvent event) { 18 | String message; 19 | if (event.getEvent()==null||event.getEvent().isEmpty()) { 20 | message = "data: " + event.getData() + "\n\n"; 21 | } else if (event.getId() == null) { 22 | message = "event: " + event.getEvent() + "\n" + 23 | "data: " + event.getData() + "\n\n"; 24 | } else { 25 | message = "id: " + event.getId() + "\n" + 26 | "event: " + event.getEvent() + "\n" + 27 | "data: " + event.getData() + "\n\n"; 28 | } 29 | sendSseEvent(message); 30 | return this; 31 | } 32 | 33 | protected abstract SSeStream sendSseEvent(String event) ; 34 | protected abstract void sendStartHeader(); 35 | public abstract SSeStream addCloseListener(Runnable runnable); 36 | protected abstract void sendRetryEvent(String event) ; 37 | public abstract void close(); 38 | } 39 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/template/FreemarkerTemplate.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.template; 2 | 3 | import freemarker.cache.ClassTemplateLoader; 4 | import freemarker.template.Configuration; 5 | import freemarker.template.TemplateExceptionHandler; 6 | 7 | import java.io.StringWriter; 8 | import java.util.Map; 9 | 10 | 11 | /** 12 | * @author hxm 13 | */ 14 | public class FreemarkerTemplate implements Template{ 15 | 16 | private static final Configuration CFG = new Configuration(Configuration.VERSION_2_3_27); 17 | 18 | static { 19 | CFG.setClassForTemplateLoading(FreemarkerTemplate.class, "/template"); 20 | CFG.setTemplateLoader(new ClassTemplateLoader(FreemarkerTemplate.class, "/template")); 21 | CFG.setDefaultEncoding("UTF-8"); 22 | CFG.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 23 | CFG.setLogTemplateExceptions(false); 24 | CFG.setWrapUncheckedExceptions(true); 25 | } 26 | 27 | /** 28 | * 获取模板内容 29 | * 30 | * @param template 模板文件 31 | * @param map 模板参数 32 | * @return 渲染后的模板内容 33 | * @throws Exception Exception 34 | */ 35 | @Override 36 | public String getTemplate(String template, Map map) throws Exception { 37 | freemarker.template.Template cfgTemplate = CFG.getTemplate(template); 38 | StringWriter stringWriter = new StringWriter(); 39 | cfgTemplate.process(map, stringWriter); 40 | return stringWriter.toString(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/ioc/handler/AutowiredHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.ioc.handler; 2 | 3 | import cn.hserver.core.ioc.annotation.Autowired; 4 | import cn.hserver.core.ioc.annotation.Qualifier; 5 | 6 | import java.lang.reflect.Field; 7 | 8 | import static cn.hserver.core.context.IocApplicationContext.getBean; 9 | 10 | public class AutowiredHandler implements PopulateBeanHandler{ 11 | 12 | @Override 13 | public void populate(Object bean) { 14 | Class par = bean.getClass(); 15 | while (!par.equals(Object.class)) { 16 | for (Field field : par.getDeclaredFields()) { 17 | if (field.isAnnotationPresent(Autowired.class)) { 18 | Object fieldValue; 19 | String beanName = null; 20 | // 检查字段上是否有@Qualifier注解 21 | Qualifier qualifier = field.getAnnotation(Qualifier.class); 22 | if (qualifier != null) { 23 | beanName = qualifier.value(); 24 | } 25 | if (beanName != null) { 26 | fieldValue = getBean(beanName); 27 | } else { 28 | fieldValue = getBean(field.getType()); 29 | } 30 | if (fieldValue != null) { 31 | populateValue(bean, field, fieldValue); 32 | } 33 | } 34 | } 35 | par=par.getSuperclass(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /hserver-web/hserver-web-starter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-web 9 | 4.0.0-beta.6 10 | 11 | 12 | hserver-web-starter 13 | hserver-web-starter 14 | 15 | 16 | 8 17 | 8 18 | UTF-8 19 | 20 | 21 | 22 | 23 | cn.hserver 24 | hserver-core 25 | ${hserver.version} 26 | 27 | 28 | cn.hserver 29 | hserver-mvc 30 | ${hserver.version} 31 | 32 | 33 | cn.hserver 34 | hserver-netty-web 35 | ${hserver.version} 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-beetlsql/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | cn.hserver 7 | hserver-plugin 8 | 4.0.0-beta.6 9 | 10 | 4.0.0 11 | hserver-plugin-beetlsql 12 | hserver-plugin-beetlsql 13 | 14 | 15 | 1.8 16 | 1.8 17 | 1.8 18 | UTF-8 19 | true 20 | 3.35-RELEASE 21 | 22 | 23 | 24 | 25 | 26 | com.ibeetl 27 | beetlsql 28 | ${beetlsql.version} 29 | 30 | 31 | cn.hserver 32 | hserver-core 33 | provided 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/logging/HServerLogConfig.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.logging; 2 | 3 | import ch.qos.logback.classic.Level; 4 | import ch.qos.logback.classic.Logger; 5 | import ch.qos.logback.classic.LoggerContext; 6 | import cn.hserver.core.config.ConstConfig; 7 | import cn.hserver.core.util.JarInputStreamUtil; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import java.io.InputStream; 11 | 12 | /** 13 | * @author hxm 14 | */ 15 | public class HServerLogConfig { 16 | public static void init() { 17 | try { 18 | loadConfiguration(HServerLogConfig.class.getResourceAsStream("/"+ ConstConfig.LOGBACK_NAME)); 19 | } catch (Exception e) { 20 | System.err.println(e.getMessage()); 21 | } 22 | } 23 | 24 | private static void stopAndReset(LoggerContext loggerContext) { 25 | loggerContext.stop(); 26 | loggerContext.reset(); 27 | } 28 | 29 | private static void loadConfiguration(InputStream in) throws Exception { 30 | LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); 31 | stopAndReset(loggerContext); 32 | ch.qos.logback.classic.joran.JoranConfigurator configurator = new ch.qos.logback.classic.joran.JoranConfigurator(); 33 | configurator.setContext(loggerContext); 34 | configurator.doConfigure(in); 35 | in.close(); 36 | Logger root = loggerContext.getLogger("ROOT"); 37 | if (root != null) { 38 | root.setLevel(Level.toLevel(ConstConfig.LOG_LEVEL)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mybatis_flex/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-plugin 9 | 4.0.0-beta.6 10 | 11 | 12 | hserver-plugin-mybatis_flex 13 | hserver-plugin-mybatis_flex 14 | 15 | 16 | 17 | com.mybatis-flex 18 | mybatis-flex-core 19 | 1.11.1 20 | 21 | 22 | com.mybatis-flex 23 | mybatis-flex-processor 24 | 1.11.1 25 | provided 26 | 27 | 28 | cn.hserver 29 | hserver-core 30 | 31 | 32 | 33 | 34 | 8 35 | 8 36 | UTF-8 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin/web/filter.md: -------------------------------------------------------------------------------- 1 | 2 | ## Filter拦截器 3 | 4 | 拦截器的使用主要是用在跨域等操作,或者其他拦截, 5 | 6 | 接口可以实现多个 ,但是得只要有输出将会中断链式调用. 7 | 8 | ```java 9 | /** 10 | * @author hxm 11 | */ 12 | @Bean 13 | @Order(1) 14 | public class CorsFilter implements FilterAdapter { 15 | @Override 16 | public void doFilter(Webkit webkit) throws Exception { 17 | webkit.httpResponse.setHeader("Access-Control-Allow-Origin", "*"); 18 | webkit.httpResponse.setHeader("Access-Control-Allow-Methods", "*"); 19 | webkit.httpResponse.setHeader("Access-Control-Allow-Credentials", "*"); 20 | webkit.httpResponse.setHeader("Access-Control-Allow-Headers", "*"); 21 | if (webkit.httpRequest.getRequestType().equals(HttpMethod.OPTIONS)) { 22 | webkit.httpResponse.sendHtml(""); 23 | } 24 | } 25 | } 26 | ``` 27 | 28 | 29 | 30 | ## 响应拦截器 31 | 32 | ```java 33 | import io.netty.handler.codec.http.FullHttpResponse; 34 | import top.hserver.core.interfaces.ResponseAdapter; 35 | import top.hserver.core.ioc.annotation.Bean; 36 | 37 | @Bean 38 | public class MyResponse implements ResponseAdapter { 39 | @Override 40 | public String result(String response) { 41 | //可以拿到 String数据 ,可以做一些替换操作 ,比如 国际化之类的。 42 | // 文件操作不会进入这里 43 | System.out.println(response); 44 | return response; 45 | } 46 | 47 | @Override 48 | public FullHttpResponse response(FullHttpResponse response) { 49 | //Netty 的对象 最后一次经过这里 就会write出去 50 | System.out.println(response); 51 | return response; 52 | } 53 | } 54 | 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/router/Route.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.router; 2 | 3 | import cn.hserver.mvc.constants.HttpMethod; 4 | 5 | /** 6 | * 路由信息封装类,包含路径、处理器和路由类型 7 | */ 8 | public class Route { 9 | 10 | public enum Type { 11 | EXACT, // 精确匹配 12 | PATH_PARAM, // 路径参数匹配 13 | WILDCARD // 通配符匹配 14 | } 15 | 16 | private final String path; 17 | private final Handler handler; 18 | private final Type type; 19 | private final String[] pathSegments; // 路径分段,用于匹配 20 | private final HttpMethod[] methods; 21 | 22 | public Route(String path, Handler handler, Type type,HttpMethod[] methods) { 23 | this.path = path; 24 | this.handler = handler; 25 | this.type = type; 26 | this.methods = methods; 27 | this.pathSegments = normalizePath(path).split("/"); 28 | } 29 | 30 | // 标准化路径,移除多余的斜杠 31 | private String normalizePath(String path) { 32 | if (path == null || path.isEmpty()) { 33 | return "/"; 34 | } 35 | return path.replaceAll("//+", "/").replaceAll("/$", ""); 36 | } 37 | 38 | public HttpMethod[] getMethods() { 39 | return methods; 40 | } 41 | 42 | // getter 方法 43 | public String getPath() { 44 | return path; 45 | } 46 | 47 | public Handler getHandler() { 48 | return handler; 49 | } 50 | 51 | public Type getType() { 52 | return type; 53 | } 54 | 55 | public String[] getPathSegments() { 56 | return pathSegments; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mybatis_flex/src/main/java/cn/hserver/plugin/mybatis/flex/MybatisFlexPlugin.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.mybatis.flex; 2 | 3 | import cn.hserver.core.context.IocApplicationContext; 4 | import cn.hserver.core.plugin.bean.PluginInfo; 5 | import cn.hserver.core.plugin.handler.PluginAdapter; 6 | import cn.hserver.plugin.mybatis.flex.annotation.Mybatis; 7 | import com.mybatisflex.core.MybatisFlexBootstrap; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import java.util.*; 11 | 12 | public class MybatisFlexPlugin extends PluginAdapter { 13 | private static final Logger log = LoggerFactory.getLogger(MybatisFlexPlugin.class); 14 | private final Set> annotationList = new HashSet<>(); 15 | 16 | @Override 17 | public PluginInfo getPluginInfo() { 18 | return new PluginInfo.Builder() 19 | .name("MyBatis-Flex") 20 | .description("一个优雅的 MyBatis 增强框架") 21 | .build(); 22 | } 23 | 24 | @Override 25 | public void iocStartScan(Class clazz) { 26 | if (clazz.getAnnotation(Mybatis.class)!=null){ 27 | annotationList.add(clazz); 28 | } 29 | } 30 | 31 | @Override 32 | public void iocBeanPreparation() { 33 | MybatisFlexBootstrap mybatisFlexBootstrap = MybatisFlexConfig.init(annotationList); 34 | for (Class aClass : annotationList) { 35 | Object mapper = mybatisFlexBootstrap.getMapper(aClass); 36 | IocApplicationContext.addBean(mapper); 37 | } 38 | annotationList.clear(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/plugin/handler/PluginAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.plugin.handler; 2 | 3 | import cn.hserver.core.ioc.bean.BeanDefinition; 4 | import cn.hserver.core.plugin.bean.PluginInfo; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.util.Map; 9 | import java.util.Set; 10 | 11 | /** 12 | * 插件适配器 13 | * 14 | * @author hxm 15 | */ 16 | public abstract class PluginAdapter { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(PluginAdapter.class); 19 | 20 | 21 | 22 | /** 23 | * app 启动调用 24 | */ 25 | public void startApp(){ 26 | 27 | } 28 | 29 | /** 30 | * 添加扫描包 31 | * @return 32 | */ 33 | public Set extScanPackages(){ 34 | return null; 35 | } 36 | 37 | /** 38 | * 开始扫描 39 | */ 40 | public void iocStartScan(Class clazz){ 41 | 42 | } 43 | 44 | //扫描完成开始注册bean 45 | public void iocStartRegister(){ 46 | 47 | } 48 | 49 | //注册一些bean方便后面填充 50 | public void iocBeanPreparation(){ 51 | 52 | } 53 | 54 | 55 | 56 | //注册bean后开始填充bean 57 | public void iocStartPopulate(){ 58 | 59 | } 60 | 61 | /** 62 | * 启动完成 63 | */ 64 | public void startedApp(){ 65 | 66 | } 67 | 68 | public abstract PluginInfo getPluginInfo(); 69 | 70 | 71 | public void printPluginInfo(){ 72 | PluginInfo pluginInfo = getPluginInfo(); 73 | if (pluginInfo != null) { 74 | String info = pluginInfo.info(); 75 | if (info != null) { 76 | log.debug(info); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /docs/zh-cn/task.md: -------------------------------------------------------------------------------- 1 | 2 | ## 定时器 3 | 4 | ```java 5 | @Bean 6 | public class TaskTest { 7 | 8 | @Autowired 9 | private TestService testService; 10 | 11 | private boolean flag = true; 12 | 13 | public void dynamicAddTimer() { 14 | System.out.println("动态添加定时任务"); 15 | TaskManager.addTask("测试任务2", "2000", TestTask.class,"666"); 16 | } 17 | 18 | 19 | @Task(name = "测试定时任务1", time ="*/5 * * * * ?") 20 | public void timerTask() { 21 | System.out.println("测试定时任务,注入的对象调用结果:" + testService.testa()); 22 | if (flag) { 23 | dynamicAddTimer(); 24 | flag = false; 25 | } 26 | } 27 | 28 | @Task(name = "测试定时任务2", time = "2000") 29 | public void removeTask() { 30 | //干掉方法注解版本 31 | boolean task1 = TaskManager.removeTask("测试定时任务1"); 32 | //干掉动态添加的 33 | boolean task2 = TaskManager.removeTask("测试任务2"); 34 | //干掉自己 35 | boolean task3 = TaskManager.removeTask("测试定时任务2"); 36 | //结果 37 | System.out.println("任务已经被干掉了 tash1=" + task1 + ",task2=" + task2 + ",task3=" + task3); 38 | } 39 | 40 | } 41 | 42 | //动态添加定时任务的实现类必须要实现一个TaskJob,样才能被TaskManager管理 43 | //添加任务 TaskManager.addTask("测试任务2", "2000", TestTask.class,"666"); 44 | //删除任务 boolean is_success = TaskManager.removeTask("测试任务2"); 45 | public class TestTask implements TaskJob { 46 | 47 | @Override 48 | public void exec(Object... args) { 49 | String args_ = ""; 50 | for (Object arg : args) { 51 | args_ += arg.toString(); 52 | } 53 | System.out.println("测试定时器动态添加任务,参数是:" + args_); 54 | } 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-satoken/src/main/java/cn/hserver/plugin/satoken/mode/SaResponseForHServer.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.satoken.mode; 2 | 3 | import cn.dev33.satoken.context.model.SaResponse; 4 | import cn.dev33.satoken.exception.SaTokenException; 5 | import cn.hserver.mvc.constants.HttpResponseStatus; 6 | import cn.hserver.mvc.response.Response; 7 | 8 | public class SaResponseForHServer implements SaResponse { 9 | /** 10 | * 底层Request对象 11 | */ 12 | protected Response response; 13 | 14 | /** 15 | * 实例化 16 | * @param response response对象 17 | */ 18 | public SaResponseForHServer(Response response) { 19 | this.response = response; 20 | } 21 | 22 | /** 23 | * 获取底层源对象 24 | */ 25 | @Override 26 | public Object getSource() { 27 | return response; 28 | } 29 | 30 | /** 31 | * 设置响应状态码 32 | */ 33 | @Override 34 | public SaResponse setStatus(int sc) { 35 | response.setStatus(HttpResponseStatus.value(sc)); 36 | return this; 37 | } 38 | 39 | /** 40 | * 在响应头里写入一个值 41 | */ 42 | @Override 43 | public SaResponse setHeader(String name, String value) { 44 | response.addHeader(name, value); 45 | return this; 46 | } 47 | 48 | /** 49 | * 在响应头里添加一个值 50 | * @param name 名字 51 | * @param value 值 52 | * @return 对象自身 53 | */ 54 | public SaResponse addHeader(String name, String value) { 55 | response.addHeader(name, value); 56 | return this; 57 | } 58 | 59 | /** 60 | * 重定向 61 | */ 62 | @Override 63 | public Object redirect(String url) { 64 | try { 65 | response.redirect(url); 66 | } catch (Exception e) { 67 | throw new SaTokenException(e); 68 | } 69 | return null; 70 | } 71 | 72 | 73 | } 74 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/exception/WebException.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.exception; 2 | 3 | import cn.hserver.mvc.constants.HttpResponseStatus; 4 | import cn.hserver.mvc.context.WebContext; 5 | 6 | /** 7 | * 业务异常 8 | * @author hxm 9 | */ 10 | public class WebException extends RuntimeException { 11 | 12 | /** 13 | * 错误状态码 14 | */ 15 | private Integer httpCode; 16 | /** 17 | * 错误类型 18 | */ 19 | private String errorDescription; 20 | /** 21 | * req和resp 22 | */ 23 | private WebContext webContext; 24 | /** 25 | * 真实的报错 26 | */ 27 | private Throwable throwable; 28 | 29 | public WebException() { 30 | super(); 31 | } 32 | 33 | public WebException(Integer httpCode, String errorDescription, Throwable throwable, WebContext webContext) { 34 | super(); 35 | this.httpCode = httpCode; 36 | this.errorDescription = errorDescription; 37 | this.webContext=webContext; 38 | this.throwable=throwable; 39 | } 40 | 41 | public WebException(String s) { 42 | super(s); 43 | } 44 | 45 | public Integer getHttpCode() { 46 | if (httpCode != null) { 47 | return httpCode; 48 | } else { 49 | return HttpResponseStatus.INTERNAL_SERVER_ERROR.getCode(); 50 | } 51 | } 52 | 53 | 54 | public String getErrorDescription() { 55 | return errorDescription; 56 | } 57 | 58 | public WebContext getWebContext() { 59 | return webContext; 60 | } 61 | 62 | public Throwable getThrowable() { 63 | return throwable; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/util/RequestIdGen.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.util; 2 | 3 | 4 | import java.lang.management.ManagementFactory; 5 | import java.util.concurrent.atomic.AtomicLong; 6 | 7 | /** 8 | * @author hxm 9 | */ 10 | public class RequestIdGen { 11 | 12 | private static final AtomicLong lastId = new AtomicLong(); 13 | private static final String HEXIP = hexIp(IpUtil.getLocalIP()); 14 | private static final String PROCESSON = ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; 15 | 16 | 17 | public static long getRequestCount() { 18 | return lastId.get(); 19 | } 20 | 21 | public static String getId() { 22 | long currentTime = System.currentTimeMillis(); 23 | long sequence = lastId.incrementAndGet(); 24 | // 规则: hexIp(ip)-base36(timestamp)-process-seq 25 | return HEXIP + "-" + 26 | Long.toString(currentTime, Character.MAX_RADIX) + "-" + 27 | PROCESSON + "-" + sequence; 28 | } 29 | 30 | // 将ip转换为定长8个字符的16进制表示形式:255.255.255.255 -> FFFFFFFF 31 | private static String hexIp(String ip) { 32 | try { 33 | StringBuilder sb = new StringBuilder(); 34 | for (String seg : ip.split("\\.")) { 35 | String h = Integer.toHexString(Integer.parseInt(seg)); 36 | if (h.length() == 1) { 37 | sb.append("0"); 38 | } 39 | sb.append(h); 40 | } 41 | return sb.toString(); 42 | } catch (Exception e) { 43 | } 44 | //127.0.0.1 45 | return "7f000001"; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin/web/limit.md: -------------------------------------------------------------------------------- 1 | ## **并发限制** 2 | 3 | HServer提供了GlobalLimit(全局QPS限制),UrlLimit(更具URL来限制QPS)@QpsLimit注解使用案例如下 4 | 5 | - 继承方式 6 | 7 | ```java 8 | 9 | import cn.hserver.core.ioc.annotation.Bean; 10 | import cn.hserver.core.server.context.Webkit; 11 | import cn.hserver.core.server.util.JsonResult; 12 | 13 | @Bean 14 | public class TestLimit extends GlobalLimit{ 15 | 16 | public TestLimit() { 17 | //限制 qps = 100/s 18 | super(100); 19 | } 20 | 21 | //rate为当前速率 22 | @Override 23 | protected void result(Webkit webkit,Double rate, boolean status) { 24 | if (status){ 25 | webkit.httpResponse.sendJson(JsonResult.error("并发数限制")); 26 | } 27 | } 28 | } 29 | 30 | ``` 31 | 32 | - 注解方式 可以使用在所有存放在容器的对象,比如service controller 等等 33 | - @QpsLimit(qps = 1000) 34 | 35 | ```java 36 | 37 | @QpsLimit(qps = 1000) 38 | @GET("/b") 39 | public JsonResult b(){ 40 | return JsonResult.ok(); 41 | } 42 | 43 | //当被限制时,会抛出QpsException 异常 44 | 45 | @Bean 46 | public class QpsLimitException implements GlobalException { 47 | @Override 48 | public void handler(Throwable throwable, int i, String s, Webkit webkit) { 49 | if (throwable instanceof QpsException) { 50 | QpsException qpsException = (QpsException) throwable; 51 | Integer qps = qpsException.getQps(); 52 | Double rate = qpsException.getRate(); 53 | System.out.println("速率:"+rate); 54 | System.out.println("设定的QPS:"+qps); 55 | } 56 | webkit.httpResponse.sendJson(JsonResult.error()); 57 | } 58 | } 59 | 60 | ``` 61 | -------------------------------------------------------------------------------- /docs/zh-cn/plugin/web/prop.md: -------------------------------------------------------------------------------- 1 | ### HTTP Session 2 | ```properties 3 | #开启 http session功能 默认关闭 4 | web.openSession=true 5 | ``` 6 | 7 | ### SSL支持 8 | 9 | 在app.properties配置文件添加 10 | 11 | #举例:nginx版本的证书下载可能会得到 (xxx.pem或者xxx.cert) xxx.key 12 | #注意下载的证书中 key文件需要转换成 pk8 文件 13 | #因为netty4不支持pkcs12格式的私钥, 所以需要将私钥转换成pkcs8格式. 14 | #openssl pkcs8 -in my.key -topk8 -out my.pk8 15 | #转换过程需要你设置一个密码. 16 | 17 | 方案一: 18 | 19 | ```properties 20 | #jar路径,证书文件应该放在\src\main\resources\ssl\ 目录里,打包会一起打包 21 | web.certPath=hserver.pem 22 | web.privateKeyPath=hserver.pk8 23 | web.privateKeyPwd=123 24 | ``` 25 | 26 | 27 | 28 | 方案二: 29 | 30 | ```properties 31 | #外置路径,指定一个绝对路径即可 32 | web.certPath=/home/ssl/hserver.pem 33 | web.privateKeyPath=/home/ssl/hserver.pk8 34 | web.privateKeyPwd=123 35 | ``` 36 | 37 | 38 | 39 | 40 | ### 消息体大小,可以用于文件上传限制大小 41 | ```properties 42 | #消息体最大值 默认int.maxValue 43 | web.httpContentSize=999999 44 | ``` 45 | 46 | ```properties 47 | #业务线程池 48 | ### 业务线程数 49 | ### 业务线程数提示:使用了业务线程,整体QPS会有降低、 50 | ### 业务线程数优点:可以处理更多的并发耗时任务 51 | ### 业务线程数缺点:增加线程切换 52 | web.businessPool=50 53 | #读取限制 byte 单位 54 | web.readLimit=100 55 | 56 | #写出限制 byte 单位 57 | web.writeLimit=100 58 | 59 | #消息体大小 默认int.maxValue 60 | web.httpContentSize=999999 61 | 62 | 63 | #URL 全局更目录定义 64 | web.rootPath=/app1 65 | 66 | #-----------------ssl------------- 67 | #注意下载的证书中 key文件需要转换成 pk8 文件 68 | #因为netty4不支持pkcs12格式的私钥, 所以需要将私钥转换成pkcs8格式. 69 | #openssl pkcs8 -in my.key -topk8 -out my.pk8 70 | web.certPath=hserver.pem 71 | web.privateKeyPath=hserver.pk8 72 | web.privateKeyPwd=123 73 | 74 | ``` 75 | 76 | 77 | 78 | 79 | 80 | ### 静态资源路径 81 | 82 | ``` 83 | resources/static 84 | ``` 85 | 86 | ### 模板路径 87 | 88 | ``` 89 | resources/template 90 | ``` 91 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/queue/HServerQueue.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.queue; 2 | 3 | 4 | import cn.hserver.core.queue.bean.QueueInfo; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 队列调用 10 | * 11 | * @author hxm 12 | */ 13 | public class HServerQueue { 14 | 15 | /** 16 | * 获取所有队列名 17 | */ 18 | public static List getAllQueueName() { 19 | return QueueManager.getAllQueueName(); 20 | } 21 | /** 22 | * 删除Queue 23 | * 24 | * @param queueName 25 | */ 26 | public static void removeQueue(String queueName) { 27 | QueueManager.removeQueue(queueName,true); 28 | } 29 | 30 | 31 | public static void removeQueue(String queueName,boolean trueDeleteData) { 32 | QueueManager.removeQueue(queueName,trueDeleteData); 33 | } 34 | 35 | /** 36 | * 停止队列得数据处理 37 | * @param queueName 38 | */ 39 | public static void stopHandler(String queueName) { 40 | QueueManager.stopHandler(queueName); 41 | } 42 | 43 | /** 44 | * 启用队列得数据处理 45 | * @param queueName 46 | */ 47 | public static void restartHandler(String queueName) { 48 | QueueManager.restartHandler(queueName); 49 | } 50 | 51 | /** 52 | * 发送队列 53 | * 54 | * @param queueName 队列名 55 | * @param args 参数 56 | */ 57 | public static boolean sendQueue(String queueName, Object... args) { 58 | return QueueManager.dispatcherSerializationQueue(queueName, args); 59 | } 60 | 61 | /** 62 | * 队列信息 63 | * 64 | * @param queueName 65 | * @return 66 | */ 67 | public static QueueInfo queueInfo(String queueName) { 68 | return QueueManager.queueInfo(queueName); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-satoken/src/main/java/cn/hserver/plugin/satoken/config/SaAnnotationInterceptor.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.satoken.config; 2 | 3 | import cn.dev33.satoken.annotation.*; 4 | import cn.dev33.satoken.apikey.annotation.SaCheckApiKey; 5 | import cn.dev33.satoken.oauth2.annotation.SaCheckAccessToken; 6 | import cn.dev33.satoken.oauth2.annotation.SaCheckClientIdSecret; 7 | import cn.dev33.satoken.oauth2.annotation.SaCheckClientToken; 8 | import cn.dev33.satoken.sign.annotation.SaCheckSign; 9 | import cn.dev33.satoken.strategy.SaAnnotationStrategy; 10 | import cn.hserver.core.aop.HookAdapter; 11 | import cn.hserver.core.aop.annotation.Hook; 12 | 13 | import java.lang.reflect.Method; 14 | 15 | @Hook(value = { 16 | SaCheckDisable.class, 17 | SaCheckHttpBasic.class, 18 | SaCheckHttpDigest.class, 19 | SaCheckLogin.class, 20 | SaCheckOr.class, 21 | SaCheckPermission.class, 22 | SaCheckRole.class, 23 | SaCheckSafe.class, 24 | SaIgnore.class, 25 | SaCheckAccessToken.class, 26 | SaCheckClientIdSecret.class, 27 | SaCheckClientToken.class, 28 | SaCheckApiKey.class, 29 | SaCheckSign.class, 30 | }) 31 | public class SaAnnotationInterceptor implements HookAdapter { 32 | 33 | @Override 34 | public void before(Class clazz, Method method, Object[] args) throws Throwable { 35 | SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method); 36 | } 37 | 38 | @Override 39 | public Object after(Class clazz, Method method, Object object) { 40 | return object; 41 | } 42 | 43 | @Override 44 | public void throwable(Class clazz, Method method, Throwable throwable) { 45 | throw new RuntimeException(throwable); 46 | } 47 | } -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-druid/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | cn.hserver 7 | hserver-plugin 8 | 4.0.0-beta.6 9 | 10 | 4.0.0 11 | 12 | hserver-plugin-druid 13 | hserver-plugin-druid 14 | 15 | 16 | 17 | 18 | com.alibaba 19 | druid 20 | 1.2.21 21 | 22 | 23 | cn.hserver 24 | hserver-core 25 | provided 26 | 27 | 28 | cn.hserver 29 | hserver-mvc 30 | provided 31 | 32 | 33 | 34 | 35 | 8 36 | 8 37 | 1.8 38 | 1.8 39 | 1.8 40 | UTF-8 41 | true 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | * [HServer是什么](zh-cn/index.md) 4 | * [Hook操作](zh-cn/hook.md) 5 | * [定时器](zh-cn/task.md) 6 | * [日志拦截](zh-cn/log.md) 7 | * [消息队列的使用](zh-cn/mq.md) 8 | * [Track跟踪](zh-cn/track.md) 9 | * [HUM消息](zh-cn/hum.md) 10 | * [生命周期方法](zh-cn/lifecycle.md) 11 | * [配置文件](zh-cn/prop.md) 12 | * [单元测试](zh-cn/unit.md) 13 | * [插件开发](zh-cn/plugin.md) 14 | * [自定义协议](zh-cn/protocol.md) 15 | * [程序打包](zh-cn/plugin/jar.md) 16 | * [Linux内核优化](zh-cn/optimization.md) 17 | * 一 、Web插件 18 | * [注解认识](zh-cn/plugin/web/annotation.md) 19 | * [常见用例](zh-cn/plugin/web/example.md) 20 | * [参数校验器](zh-cn/plugin/web/check.md) 21 | * [文件上传下载](zh-cn/plugin/web/file.md) 22 | * [全局request,response获取](zh-cn/plugin/web/reqresp.md) 23 | * [拦截器](zh-cn/plugin/web/filter.md) 24 | * [SSE](zh-cn/plugin/web/sse.md) 25 | * [全局异常处理](zh-cn/plugin/web/exception.md) 26 | * [websocket](zh-cn/plugin/web/websocket.md) 27 | * [鉴权认证相关操作](zh-cn/plugin/web/authentication.md) 28 | * [文档生成](zh-cn/plugin/web/apidoc.md) 29 | * [并发限制](zh-cn/plugin/web/limit.md) 30 | * [自定义JSON序列化](zh-cn/plugin/web/json.md) 31 | * [配置文件](zh-cn/plugin/web/prop.md) 32 | 33 | * 二、Rpc插件 34 | * [Rpc](zh-cn/plugin/rpc/index.md) 35 | * 三、Mybatis插件 36 | * [Mybatis](zh-cn/plugin/mybatis.md) 37 | * 四、Mqtt插件 38 | * [Mqtt](zh-cn/mqtt.md) 39 | * 五、GateWay插件 40 | * [Gateway](zh-cn/plugin/gateway.md) 41 | * 六、Druid插件 42 | * [Druid](zh-cn/plugin/druid/index.md) 43 | * 七、Beetlsql插件 44 | * [Beetlsql](zh-cn/plugin/beetle.md) 45 | * 八、Redis插件 46 | * [Redis](zh-cn/plugin/redis.md) 47 | * 九、Mongodb 48 | * [Mongodb](zh-cn/plugin/mongodb.md) 49 | * 十、Mybatis-Flex 50 | * [mybatis-flex](zh-cn/plugin/mybatis-flex.md) 51 | * 十一、Sa-Token 52 | * [satoken](zh-cn/plugin/satoken.md) 53 | * 十二、Forest远程调用 54 | * [forest](zh-cn/plugin/forest.md) 55 | * 十三、MCP开发 56 | * [mcp](zh-cn/plugin/mcp.md) 57 | -------------------------------------------------------------------------------- /hserver-core/src/main/java/cn/hserver/core/context/handler/ComponentHandler.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.core.context.handler; 2 | 3 | import cn.hserver.core.ioc.annotation.Component; 4 | import cn.hserver.core.ioc.annotation.Scope; 5 | import cn.hserver.core.ioc.bean.BeanDefinition; 6 | import cn.hserver.core.scheduling.TaskManager; 7 | import cn.hserver.core.scheduling.annotation.Task; 8 | import cn.hserver.core.scheduling.bean.TaskDefinition; 9 | 10 | import java.lang.reflect.Method; 11 | import java.util.Map; 12 | 13 | public class ComponentHandler implements AnnotationHandler { 14 | @Override 15 | public void handle(Class clazz, Map beanDefinitions) { 16 | if (clazz.isAnnotationPresent(Component.class)) { 17 | Component component = clazz.getAnnotation(Component.class); 18 | BeanDefinition beanDefinition = new BeanDefinition(); 19 | beanDefinition.setBeanClass(clazz); 20 | String beanName = component.value(); 21 | if (beanName.isEmpty()) { 22 | beanName = beanDefinition.getDefaultBeanName(); 23 | } 24 | // 处理作用域 25 | if (clazz.isAnnotationPresent(Scope.class)) { 26 | Scope scope = clazz.getAnnotation(Scope.class); 27 | beanDefinition.setScope(scope.value()); 28 | } 29 | beanDefinitions.put(beanName, beanDefinition); 30 | // 处理task 31 | Method[] declaredMethods = clazz.getDeclaredMethods(); 32 | for (Method declaredMethod : declaredMethods) { 33 | if (declaredMethod.isAnnotationPresent(Task.class)) { 34 | Task task = declaredMethod.getAnnotation(Task.class); 35 | TaskManager.addTask(new TaskDefinition(task.name(),task.time(),beanName,declaredMethod)); 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/websoket/Ws.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.websoket; 2 | 3 | import cn.hserver.mvc.constants.WsType; 4 | import cn.hserver.mvc.request.Request; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.function.Consumer; 8 | 9 | /** 10 | * @author hxm 11 | */ 12 | public abstract class Ws { 13 | 14 | private final String message; 15 | private final byte[] binary; 16 | private final String uid; 17 | private final Request request; 18 | private final WsType type; 19 | 20 | public Ws(byte[] binary,String message, String uid, Request request, WsType type) { 21 | this.binary = binary; 22 | this.uid = uid; 23 | this.request = request; 24 | this.type=type; 25 | this.message = message; 26 | } 27 | 28 | public WsType getType() { 29 | return type; 30 | } 31 | 32 | public void send(String msg){ 33 | send(msg, null); 34 | } 35 | public void send(byte[] msg){ 36 | send(msg, null); 37 | } 38 | public void sendBinary(byte[] msg){ 39 | sendBinary(msg, null); 40 | } 41 | public abstract void send(String msg, Consumer callback); 42 | 43 | public abstract void send(byte[] msg,Consumer callback); 44 | 45 | public abstract void sendBinary(byte[] msg, Consumer callback); 46 | 47 | 48 | 49 | 50 | public String query(String name) { 51 | return request.query(name); 52 | } 53 | 54 | public String getMessage() { 55 | return message; 56 | } 57 | 58 | public String getUid() { 59 | return uid; 60 | } 61 | 62 | public Request getRequest() { 63 | return request; 64 | } 65 | 66 | public Map> getReqData() { 67 | return request.getRequestParams(); 68 | } 69 | 70 | public byte[] getBinary() { 71 | return binary; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.hserver 8 | hserver-plugin 9 | 4.0.0-beta.6 10 | 11 | 12 | hserver-plugin-mcp 13 | hserver-plugin-mcp 14 | 15 | 16 | cn.hserver 17 | hserver-core 18 | provided 19 | 20 | 21 | org.projectlombok 22 | lombok 23 | 1.18.36 24 | provided 25 | 26 | 27 | io.projectreactor 28 | reactor-core 29 | 3.6.2 30 | 31 | 32 | org.apache.httpcomponents.client5 33 | httpclient5 34 | 5.4.3 35 | 36 | 37 | cn.hserver 38 | hserver-mvc 39 | provided 40 | 41 | 42 | 43 | 8 44 | 8 45 | UTF-8 46 | 47 | 48 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mybatis_flex/src/main/java/cn/hserver/plugin/mybatis/flex/bean/MybatisConfig.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.mybatis.flex.bean; 2 | 3 | import org.apache.ibatis.plugin.Interceptor; 4 | import org.apache.ibatis.session.SqlSessionFactory; 5 | 6 | import javax.sql.DataSource; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * @author hxm 12 | */ 13 | public class MybatisConfig { 14 | private Map dataSources; 15 | 16 | private String mapperLocations = "mapper"; 17 | 18 | private Interceptor[] plugins; 19 | 20 | private Boolean mapUnderscoreToCamelCase = true; 21 | 22 | public Boolean getMapUnderscoreToCamelCase() { 23 | return mapUnderscoreToCamelCase; 24 | } 25 | 26 | public void setMapUnderscoreToCamelCase(Boolean mapUnderscoreToCamelCase) { 27 | this.mapUnderscoreToCamelCase = mapUnderscoreToCamelCase; 28 | } 29 | public Interceptor[] getPlugins() { 30 | return plugins; 31 | } 32 | 33 | public void setPlugins(Interceptor[] plugins) { 34 | this.plugins = plugins; 35 | } 36 | 37 | public Map getDataSources() { 38 | return dataSources; 39 | } 40 | 41 | public void addDataSource(DataSource dataSource) { 42 | if (dataSources == null) { 43 | dataSources = new HashMap<>(); 44 | } 45 | dataSources.put(SqlSessionFactory.class.getName(), dataSource); 46 | } 47 | public void addDataSource(String dataSourceName, DataSource dataSource) { 48 | if (dataSources == null) { 49 | dataSources = new HashMap<>(); 50 | } 51 | dataSources.put(dataSourceName, dataSource); 52 | } 53 | 54 | public String getMapperLocations() { 55 | return mapperLocations; 56 | } 57 | 58 | public void setMapperLocations(String mapperLocations) { 59 | this.mapperLocations = mapperLocations; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-druid/src/main/java/cn/hserver/plugin/druid/web/StatViewController.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.druid.web; 2 | 3 | 4 | import cn.hserver.mvc.annotation.Controller; 5 | import cn.hserver.mvc.annotation.router.RequestMapping; 6 | import cn.hserver.mvc.response.Response; 7 | import cn.hserver.plugin.druid.web.config.HtmlConst; 8 | import com.alibaba.druid.stat.DruidStatService; 9 | import com.alibaba.druid.util.Utils; 10 | 11 | import java.io.IOException; 12 | 13 | @Controller 14 | public class StatViewController { 15 | /** 16 | * 获取Druid的统计 17 | */ 18 | private final DruidStatService statService = DruidStatService.getInstance(); 19 | 20 | @RequestMapping("/druid/{uri}") 21 | public void druid(String uri, Response response) throws IOException { 22 | String druidPath = "support/http/resources/"; 23 | String url = druidPath + uri; 24 | if (uri.endsWith("json")) { 25 | response.sendJsonString(statService.service("/"+uri)); 26 | } else { 27 | if (url.endsWith(".jpg")) { 28 | byte[] bytes = Utils.readByteArrayFromResource(url); 29 | if (bytes != null) { 30 | response.downloadBytes(bytes, url); 31 | } 32 | } 33 | String text = Utils.readFromResource(url); 34 | if (url.contains("header.html")){ 35 | text= HtmlConst.HEADER; 36 | } 37 | if (text == null) { 38 | return; 39 | } 40 | if (url.endsWith(".html")) { 41 | response.addHeader("content-type", "text/html; charset=utf-8"); 42 | } 43 | if (url.endsWith(".css")) { 44 | response.addHeader("content-type", "text/css;charset=utf-8"); 45 | } else if (url.endsWith(".js")) { 46 | response.addHeader("content-type", "text/javascript;charset=utf-8"); 47 | } 48 | response.sendHtml(text); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | HServer开发文档 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-impl/hserver-cloud-nacos/src/main/java/cn/hserver/cloud/nacos/NacosRegisterService.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.cloud.nacos; 2 | 3 | import cn.hserver.cloud.common.RegisterConfig; 4 | import cn.hserver.cloud.register.RegisterService; 5 | import cn.hserver.core.ioc.annotation.Autowired; 6 | import cn.hserver.core.ioc.annotation.Component; 7 | import cn.hserver.core.life.CloseAdapter; 8 | import com.alibaba.nacos.api.exception.NacosException; 9 | import com.alibaba.nacos.api.naming.NamingService; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | 14 | 15 | @Component 16 | public class NacosRegisterService implements RegisterService, CloseAdapter { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(NacosRegisterService.class); 19 | 20 | @Autowired 21 | private NamingService naming; 22 | 23 | private RegisterConfig regProp; 24 | 25 | @Override 26 | public boolean register(RegisterConfig regProp) { 27 | this.regProp = regProp; 28 | try { 29 | //注册服务 30 | naming.registerInstance( 31 | regProp.getRegisterName(), 32 | regProp.getRegisterGroupName(), 33 | regProp.getRegisterMyIp(), 34 | regProp.getRegisterMyPort(), 35 | regProp.getRegisterName() 36 | ); 37 | } catch (Exception e) { 38 | log.error(e.getMessage(), e); 39 | return false; 40 | } 41 | return true; 42 | } 43 | 44 | @Override 45 | public boolean deregister() { 46 | try { 47 | naming.deregisterInstance(regProp.getRegisterName(), regProp.getRegisterGroupName(), regProp.getRegisterMyIp(), regProp.getRegisterMyPort()); 48 | } catch (NacosException e) { 49 | log.error(e.getMessage(), e); 50 | return false; 51 | } 52 | return true; 53 | } 54 | 55 | @Override 56 | public void close() { 57 | this.deregister(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/sse/SSeEvent.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.sse; 2 | 3 | public class SSeEvent { 4 | 5 | private String id; 6 | 7 | private String event; 8 | 9 | private String data; 10 | 11 | private int retry; 12 | 13 | public SSeEvent() {} 14 | 15 | public SSeEvent(Builder builder){ 16 | this.id = builder.id; 17 | this.event = builder.event; 18 | this.data = builder.data; 19 | this.retry = builder.retry; 20 | } 21 | 22 | public String getId() { 23 | return id; 24 | } 25 | 26 | public void setId(String id) { 27 | this.id = id; 28 | } 29 | 30 | public String getEvent() { 31 | return event; 32 | } 33 | 34 | public void setEvent(String event) { 35 | this.event = event; 36 | } 37 | 38 | public String getData() { 39 | return data; 40 | } 41 | 42 | public void setData(String data) { 43 | this.data = data; 44 | } 45 | 46 | public int getRetry() { 47 | return retry; 48 | } 49 | 50 | public void setRetry(int retry) { 51 | this.retry = retry; 52 | } 53 | 54 | public static class Builder { 55 | private String id; 56 | 57 | private String event; 58 | 59 | private String data; 60 | 61 | private int retry; 62 | 63 | // Setter 方法返回 Builder 本身,方便链式调用 64 | public Builder id(String id) { 65 | this.id = id; 66 | return this; 67 | } 68 | 69 | public Builder event(String event) { 70 | this.event = event; 71 | return this; 72 | } 73 | 74 | public Builder data(String data) { 75 | this.data = data; 76 | return this; 77 | } 78 | 79 | public Builder retry(int retry) { 80 | this.retry = retry; 81 | return this; 82 | } 83 | 84 | public SSeEvent build() { 85 | return new SSeEvent(this); 86 | } 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /hserver-web/hserver-mvc/src/main/java/cn/hserver/mvc/common/JsonResult.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.mvc.common; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * 返回结果对象 7 | * 8 | * @author hxm 9 | */ 10 | public class JsonResult extends HashMap { 11 | 12 | private static final long serialVersionUID = 1L; 13 | 14 | private JsonResult() { 15 | } 16 | 17 | /** 18 | * 返回成功 19 | */ 20 | public static JsonResult ok() { 21 | return ok("操作成功"); 22 | } 23 | 24 | /** 25 | * 返回成功 26 | */ 27 | public static JsonResult ok(String message) { 28 | return ok(200, message); 29 | } 30 | 31 | /** 32 | * 返回成功 33 | */ 34 | public static JsonResult ok(int code, String message) { 35 | JsonResult jsonResult = new JsonResult(); 36 | jsonResult.put("code", code); 37 | jsonResult.put("msg", message); 38 | return jsonResult; 39 | } 40 | 41 | /** 42 | * 返回失败 43 | */ 44 | public static JsonResult error() { 45 | return error("操作失败"); 46 | } 47 | 48 | /** 49 | * 返回失败 50 | */ 51 | public static JsonResult error(String messag) { 52 | return error(-1, messag); 53 | } 54 | 55 | /** 56 | * 返回失败 57 | */ 58 | public static JsonResult error(int code, String message) { 59 | return ok(code, message); 60 | } 61 | 62 | /** 63 | * 设置code 64 | */ 65 | public JsonResult setCode(int code) { 66 | super.put("code", code); 67 | return this; 68 | } 69 | 70 | /** 71 | * 设置message 72 | */ 73 | public JsonResult setMessage(String message) { 74 | super.put("msg", message); 75 | return this; 76 | } 77 | 78 | /** 79 | * 放入object 80 | */ 81 | @Override 82 | public JsonResult put(String key, Object object) { 83 | super.put(key, object); 84 | return this; 85 | } 86 | 87 | public JsonResult data(Object data) { 88 | super.put("data", data); 89 | return this; 90 | } 91 | } -------------------------------------------------------------------------------- /docs/zh-cn/protocol.md: -------------------------------------------------------------------------------- 1 | ## **自定义协议** 2 | 3 | 案例:https://gitee.com/HServer/hsvevr-for-custom-protocol 4 | 5 | ### ProtocolDispatcherAdapter 与 ProtocolDispatcherSuperAdapter 6 | 7 | 我们提供了两对象来实现数据分发 ProtocolDispatcherAdapter对应的使用要求客服端必须连接后发送相关指令数据才能鉴别对应协议 8 | ProtocolDispatcherSuperAdapter的出现就是解决客服端不发送数据的情况,比如mysql是连接后服务器端发送响应数据.这种情况我们只能通过端口来区分,实现协议分发 9 | 两者使用效果一样需要更具不同业务场景来实现不同效果 10 | 11 | HServer实现的是同端口多协议处理方式,如果有需要还可以构建其他协议。 构建协议特点,需要包含包头用于区分协议,选择对应的解码器处理。 HServer默认集成 websocket http mqtt websocketmqtt协议, 12 | 如果你还有更多的需求,可以在加协议。或者重写HServer提供的协议。 headers字节,最多提取头512个字节,所以定义头一定不要过长,不要过线. 13 | 14 | 比如重写Http协议; 15 | 16 | ```java 17 | 18 | @Order(3) 19 | @Bean 20 | public class HttpProtocol extends DispatchHttp { 21 | @Override 22 | public boolean dispatcher(ChannelHandlerContext ctx, ChannelPipeline pipeline, byte[] headers, ServerInitializer.ProtocolDispatcher protocolDispatcher) { 23 | return super.dispatcher(ctx, pipeline, headers, protocolDispatcher); 24 | } 25 | } 26 | ``` 27 | 28 | 这里需要注意一点的是@Order(3)注解,由于WebSocketMqtt是基于Http协议的,所以先判断的WebSocketMqtt协议,WebSocketMqtt为@Order(2),返回true者不向下执行。 29 | Order值越越小,优先级越高。 30 | 31 | 如何自定义协议呢?比如实现一个MQTT或者其他自定义的协议 32 | 33 | ```java 34 | 35 | @Order(2) 36 | @Bean 37 | public class DispatchWebSocketMqtt implements ProtocolDispatcherAdapter { 38 | @Override 39 | public boolean dispatcher(ChannelHandlerContext ctx, ChannelPipeline pipeline, byte[] headers, ServerInitializer.ProtocolDispatcher protocolDispatcher) { 40 | if (headers[0] == 'G' && headers[1] == 'E' && new String(headers).indexOf("Sec-WebSocket-Protocol: mqtt") > 0) { 41 | pipeline.addLast(MqttEncoder.INSTANCE); 42 | pipeline.addLast(new MqttDecoder()); 43 | pipeline.addLast(ConstConfig.BUSINESS_EVENT, MqttHeartBeatBrokerHandler.INSTANCE); 44 | return true; 45 | } 46 | return false; 47 | } 48 | } 49 | ``` 50 | 51 | 这里需要注意他的头包含GET 但是http协议也是包含GET,所以这个协议一定要优先于HTTP检查。自己在定义协议的时候,尽量采用特殊字符作为消息头,用来区分协议。 52 | 剩下的操作就和Netty原生开发方案类似了,定义编码解码器,最后到自己的Handler处理器里。 非常重要一点,一定不要在这里面有阻塞操作,不然会卡的批爆。切记切记。 53 | -------------------------------------------------------------------------------- /hserver-cloud/hserver-cloud-register/src/main/java/cn/hserver/cloud/register/RegisterPlugin.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.cloud.register; 2 | 3 | import cn.hserver.cloud.common.ConstConfig; 4 | import cn.hserver.cloud.common.RegisterConfig; 5 | import cn.hserver.core.config.ConfigData; 6 | import cn.hserver.core.context.IocApplicationContext; 7 | import cn.hserver.core.plugin.bean.PluginInfo; 8 | import cn.hserver.core.plugin.handler.PluginAdapter; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class RegisterPlugin extends PluginAdapter { 13 | private static final Logger log = LoggerFactory.getLogger(RegisterPlugin.class); 14 | 15 | @Override 16 | public PluginInfo getPluginInfo() { 17 | return new PluginInfo.Builder() 18 | .name("服务注册") 19 | .description("提供服务注册能力,让服务发现模块能够快速感知并实现服务调用") 20 | .build(); 21 | } 22 | 23 | @Override 24 | public void startedApp() { 25 | RegisterService beansOfTypeOne = IocApplicationContext.getBeansOfTypeOne(RegisterService.class); 26 | if (beansOfTypeOne == null) { 27 | log.warn("未找到注册服务实现类"); 28 | return; 29 | } 30 | //服务注册 31 | RegisterConfig regProp = IocApplicationContext.getBean(RegisterConfig.class); 32 | if (regProp == null) { 33 | regProp = new RegisterConfig(); 34 | regProp.setRegisterMyIp(ConfigData.getInstance().getString(ConstConfig.REGISTER_MY_IP)); 35 | regProp.setRegisterMyPort(ConfigData.getInstance().getInteger(ConstConfig.REGISTER_MY_PORT)); 36 | regProp.setRegisterName(ConfigData.getInstance().getString(ConstConfig.REGISTER_NAME)); 37 | regProp.setRegisterGroupName(ConfigData.getInstance().getString(ConstConfig.REGISTER_GROUP_NAME,ConstConfig.DEFAULT_GROUP_NAME)); 38 | regProp.setCloudAddress(ConfigData.getInstance().getString(ConstConfig.CLOUD_ADDRESS)); 39 | } 40 | if (!regProp.hasNull()) { 41 | beansOfTypeOne.register(regProp); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /docs/zh-cn/optimization.md: -------------------------------------------------------------------------------- 1 | 2 | ## Linux内核调优 3 | 4 | 除了epoll好用,优化linux内核也是重中之重,以下优化每一项都非常非常重要,请务必按逐一完成。 5 | 6 | ```text 7 | max-file: 表示系统级别的能够打开的文件句柄的数量。是针对整个OS而言,并不是针对用户的。 8 | 9 | ulimit -n: 表示控制进程级别能够打开的文件句柄的数量。针对当前shell的当前用户及其启动的进程的可用文件句柄控制。 10 | ``` 11 | 12 | 查看系统级别能够打开的文件句柄的数量: cat /pro/sys/fs/file-max 13 | 打开文件 /etc/sysctl.conf,增加以下设置 14 | ```properties 15 | #该参数设置系统的TIME_WAIT的数量,如果超过默认值则会被立即清除 16 | net.ipv4.tcp_max_tw_buckets = 20000 17 | #定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数 18 | net.core.somaxconn = 65535 19 | #对于还未获得对方确认的连接请求,可保存在队列中的最大数目 20 | net.ipv4.tcp_max_syn_backlog = 262144 21 | #在每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目 22 | net.core.netdev_max_backlog = 30000 23 | #此选项会导致处于NAT网络的客户端超时,建议为0。Linux从4.12内核开始移除了 tcp_tw_recycle 配置,如果报错"No such file or directory"请忽略 24 | net.ipv4.tcp_tw_recycle = 0 25 | #系统所有进程一共可以打开的文件数量 26 | fs.file-max = 6815744 27 | #防火墙跟踪表的大小。注意:如果防火墙没开则会提示error: "net.netfilter.nf_conntrack_max" is an unknown key,忽略即可 28 | net.netfilter.nf_conntrack_max = 2621440 29 | ``` 30 | 运行 sysctl -p 即刻生效。 31 | 32 | 说明: 33 | 34 | /etc/sysctl.conf 可设置的选项很多,其它选项可以根据自己的环境需要进行设置 35 | 36 | ### 打开文件数 37 | 38 | 设置系统打开文件数设置,解决高并发下 too many open files 问题。此选项直接影响单个进程容纳的客户端连接数。 39 | 40 | Soft open files 是Linux系统参数,影响系统单个进程能够打开最大的文件句柄数量,这个值会影响到长连接应用如聊天中单个进程能够维持的用户连接数, 运行ulimit -n能看到这个参数值,如果是1024,就是代表单个进程只能同时最多只能维持1024甚至更少(因为有其它文件的句柄被打开)。如果开启4个进程维持用户连接,那么整个应用能够同时维持的连接数不会超过4*1024个,也就是说最多只能支持4x1024个用户在线可以增大这个设置以便服务能够维持更多的TCP连接。 41 | 42 | #### Soft open files 修改三种方法: 43 | 44 | 第一种:在终端直接运行 ulimit -HSn 102400,然后重启应用。 45 | 46 | 这只是在当前终端有效,退出之后,open files 又变为默认值。 47 | 48 | 第二种:在/etc/profile文件末尾添加一行 ulimit -HSn 102400,这样每次登录终端时,都会自动执行。更改后需要重启应用。 49 | 50 | 第三种:令修改open files的数值永久生效,则必须修改配置文件:/etc/security/limits.conf. 在这个文件后加上: 51 | 52 | 53 | ``` 54 | root soft nofile 1024000 55 | root hard nofile 1024000 56 | ``` 57 | 这种方法需要重启机器才能生效。 58 | 59 | ## 文件数不能被修改 60 | 有的系统默认限制了大小,不能随意修改大小 则必须修改配置文件:/etc/security/limits.conf. 在这个文件后加上: 61 | 62 | ``` 63 | root soft nofile 1024000 64 | root hard nofile 1024000 65 | ``` 66 | 然后重启电脑或服务器,然后在进行 ulimit -HSn 102400 命令操作,或者放profile里启动shell就执行 67 | 68 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-druid/src/main/java/cn/hserver/plugin/druid/web/config/HtmlConst.java: -------------------------------------------------------------------------------- 1 | package cn.hserver.plugin.druid.web.config; 2 | 3 | public class HtmlConst { 4 | 5 | public static final String HEADER="
\n" + 6 | " English | 中文\n" + 7 | "
\n" + 8 | "
\n" + 9 | "
\n" + 10 | "
\n" + 11 | " Druid\n" + 12 | " Monitor\n" + 13 | "
\n" + 14 | " \n" + 21 | " Reset All\n" + 23 | " Log And Reset\n" + 25 | "
\n" + 26 | "
\n" + 27 | "
\n" + 28 | "
\n"; 29 | } 30 | -------------------------------------------------------------------------------- /hserver-plugin/hserver-plugin-mcp/readme.md: -------------------------------------------------------------------------------- 1 | # MCP-Server 模块 2 | 3 | ```java 4 | 5 | @McpServerEndpoint(sseEndpoint = "/sse",version = "1.0.0" ,name = "测试MCP") 6 | public class McpController { 7 | 8 | /** 9 | * 只能返回McpSchema.Content或者Collection子类实现 10 | * ImageContent 11 | * TextContent 12 | * @param name 13 | * @return 14 | */ 15 | @ToolMapping(name = "测试",description = "一个测试函数") 16 | public McpSchema.Content getTest(@Param(description = "输入名字",defaultValue = "测试",required = false) String name) { 17 | System.out.println(name); 18 | return new McpSchema.TextContent("aa"); 19 | } 20 | 21 | /** 22 | * 只能返回McpSchema.ResourceContents或者Collection子类实现 23 | * BlobResourceContents 24 | * TextResourceContents 25 | * @return 26 | */ 27 | @ResourcesMapping(uri = "db://aaaa", name = "测试",description = "一个测试函数") 28 | public McpSchema.ResourceContents getTest2() { 29 | return new McpSchema.TextResourceContents("db://aa","text/plan","测试数据"); 30 | } 31 | 32 | /** 33 | * 只能返回McpSchema.ResourceContents或者Collection子类实现 34 | * BlobResourceContents 35 | * TextResourceContents 36 | * @param userId 37 | * @return 38 | */ 39 | @ResourcesMapping(uri = "db://aa/{userId}/aa", name = "测试",description = "一个测试函数") 40 | public List getTest3(String userId) { 41 | List list = new ArrayList<>(); 42 | list.add(new McpSchema.TextResourceContents("db://aa",null,"测试数据")); 43 | return list; 44 | } 45 | 46 | /** 47 | * 只能返回McpSchema.PromptMessage或者Collection 48 | * @param userId 49 | * @return 50 | */ 51 | @PromptMapping(name = "测试",description = "一个测试函数") 52 | public McpSchema.PromptMessage getTest4(@Param(description = "用户ID",required = true) String userId) { 53 | return new McpSchema.PromptMessage(McpSchema.Role.USER,new McpSchema.TextContent("用户ID:"+userId)); 54 | } 55 | } 56 | 57 | ``` 58 | --------------------------------------------------------------------------------