AiFei知识图谱
杜福忠
2026-05-05
详解详解详解Aifei.start(new AppConfig(), args);项目main方法启动commandLineArgumentToSystemProperty(args);将来自 main 入口方法的命令行参数转换为系统属性,约定参数以 "--" 打头。如【java -jar app.jar --aifei.profiles.active=pro】会在 PropKit 中获取使用PathUtil.init(aifeiConfig);初始化整个 PathUtil,路径有: static Path appHome; static Path webRootPath; static Path uploadPath; static Path downloadPath; static List<Path> classPathList;aifeiConfig.config(settings);系统配置settings.setLogFactory(不设置,有默认处理:slf4j > log4j2)settings.setServer配置 Server、Dispatcher、Handler(本方法内容较多,下面开主题分支)settings.configArgument配置 Argument,定制 action 注入参数(本方法内容较多,下面开主题分支)settings.setProxyFactory开启业务层 AOP。若不开启,则只注入原始对象而非 AOP 代理对象。【JavassistProxyFactory、CglibProxyFactory】settings.addGlobalInterceptor添加全局拦截器settings.setDownloadPath配置文件下载路径,默认值为 "download"settings.setUploadPath配置文件上传路径,默认值为 "upload"settings.setInjectSuperClass配置超类是否注入,默认 falseaifeiConfig.config(routes);路由add(String path, Class<?> target)手动添加路由。 应用场景:对性能有极致要求,或者路由极少但 Class 文件却极多。add(String path, Class<?> target, Interceptor... interceptors)Routes 拦截器调用优先级高于全局拦截器。scan(String basePackage)扫描路由scan(String basePackage, Interceptor... interceptors)路由添加 Routes 级别拦截器scan(String basePackage, Interceptor[] interceptors, Predicate<Class<?>> skip)通过 skip 函数跳过指定 Class。aifeiConfig.config(plugins);interface Plugin插件接口void start();void stop();内置插件AifeiDbPlugin数据库操作(本方法内容较多,下面开主题分支)startPlugins(plugins);启动 PluginaifeiConfig.onStart();回调 onStartHandler<I, O> handler = makeHandlerChain(settings.getHandlerList());settings.getDispatcher().init(handler);创建 Handler 链、初始化 Dispatchersettings.getServer().start();启动 ServerRuntime.getRuntime().addShutdownHook(new Thread(Aifei::stop));关闭 JVM:只支持 kill pid 不支持 kill -9 pid必须配置下页:嵌入式ServerArgumentAifeiDbPluginAifei::stop()关闭settings.getServer().stop();关闭 ServeraifeiConfig.onStop();回调 onStop,仍可使用 pluginstopPlugins(plugins);关闭 PluginHandler<I, O> ret = handlerList.get(handlerList.size() - 1); for (int i = handlerList.size() - 2; i >= 0; i--) { Handler<I, O> current = handlerList.get(i); current.next = ret; ret = current; } return ret;如有5个H:最终返回 H1,形成链:H1 → H2 → H3 → H4 → H5调用关系线关系线关系线关系线Server<P1, P2>interface Server<P1, P2>web服务接口定义void init(Dispatcher<P1, P2, ?, ?> dispatcher);初始化。至少需要持有下游 Dispatcher 对象void start();启动void stop();关闭UndertowServerAiFei内置的web服务UndertowConfig配置 默认取undertow.txt(配置规则同jfinal-undertow)主要默认值:port=80、host=0.0.0.0config(Consumer<UndertowConfig> configConsumer)可代码进行配置:new UndertowServer().config(uc -> {uc.setPort(8000);});onStart(Consumer<Builder> onStartConsumer)启动前回调setUndertowHandler(UndertowHandler undertowHandler)定制 UndertowHandler 实现:init、handleRequest与Servlet 过滤器功能类似:init、doFilter有默认实现UndertowHandler请求入口 Undertow 的HttpHandler 连接下游 Aifei 的Dispatcher,Dispatcher 进一步连接 Aifei 的Handler。init(Dispatcher<HttpServerExchange, Void, ?, ?> dispatcher)初始化 undertowHandler.init(dispatcher);init(Dispatcher<HttpServerExchange, Void, ?, ?> dispatcher)设置Aifei的Dispatcherpublic synchronized void start()启动doStart()启动项处理printServerUrls();控制台输出访问地址,配置文件中可关闭:undertow.printServerUrls=falseconfigConsumer.accept(config);配置回调configUndertow();builder的各配置项:https、IO 线程与 Worker 线程、Buffer、静态资源处理器configHandler();HttpHandler的配置:Gzip、ServerName、Ssl、监听端口HostonStartConsumer.accept(builder);启动前回调undertow = builder.build();undertow.start();Builder 构建 Undertow 对象并启动public synchronized void stop()关闭undertow.stop();handleRequest(final HttpServerExchange exchange)Undertow的请求调用,web系统的流量入口处理静态资源:if (path.indexOf('.') != -1)resourceHandler.handleRequest(exchange);一般:开发的时候才用到,上线后会有nginx进行代理高效处理处理动态资源:dispatcher.dispatch(exchange, null);转发到AiFei的Dispatcher,(Dispatcher内容较多,下面开主题分支)下页 Dispatcher调度器SmartAifeiServer计划用国产项目smart 实现Aifei web服务,smart-aifei(原因:学校的全国大学生创业大赛等信创项目更有吸引力)Dispatcher调度器1: 引入 Dispatcher 对上游 Server 与下游 Handler 进行解耦。2: Server 持有 Dispatcher,Dispatcher 持有 Handler。3: Server 调用 Dispatcher.dispatch(...) 发送请求给 Dispatcher。Dispatcher 调用 Handler.handle(...) 发送请求给 Handler。4: 上游 Server 传递泛型参数 P1、P2 给 Dispatcher,它将P1、P2 转化或封装成泛型参数 I、O 再传递给下游 Handler。Server ---P1、P2---> Dispatcher ---I、O---> Handler5: Dispatcher 将 Server 与 Handler 解耦之后,基于 aifei 开发的项目可以任意切换底层 Server 实现。例如切换 undertow、tomcat、netty。interface Dispatcher<P1, P2, I extends Input, O extends Output>调度器代码 需要自己项目去实现,AiFei内核无该功能(推荐加入Aifei官方的VIP获取aifei-vip-arch项目完整HIO实现)(PS:陕农大的实训学员使用aifei-dev-admin项目中smart-aifei已默认实现HIOhttps://aifei.cn 是Aifei框架唯一官网。https://aifei.dev 是“陕农大 信工分院 AI应用技术社团”发起的技术孵化社区,免费提供域名+服务器 托管Aifei项目(含校外开源项目)。void init(Handler<I, O> handler);初始化。至少需要持有下游 Handler 对象。Aifei::start调用settings.getDispatcher().init(handler);传参过来void dispatch(P1 p1, P2 p2);接收 Server 请求,将 P1、P2 转化为 I、O 并调用 Handler.handle(...)自定义示例:ExchangeDispatcher基于UndertowServer实现一个简单调度器包装public class ExchangeDispatcher implements Dispatcher<HttpServerExchange, Void, ExchangeInput, Output> { private Handler<ExchangeInput, Output> handler; @Override public void init(Handler<ExchangeInput, Output> handler) { this.handler = handler; } @Override public void dispatch(HttpServerExchange exchange, Void unused) { try { handler.handle(exchange.getRequestPath(), new ExchangeInput(exchange), null); } catch (Throwable e) { exchange.endExchange(); } }}代码:public class ExchangeInput implements Input { private final HttpServerExchange exchange; public ExchangeInput(HttpServerExchange httpServerExchange) { this.exchange = httpServerExchange; } public HttpServerExchange getExchange() { return exchange; }... 其他接口实现方法 此处不用书写 IDEA可自动生成(主要是从exchange取值)Aifei Handlerabstract class Handler<I extends Input, O extends Output>抽象父类 H I O 模型protected Handler<I, O> next;下一个处理器(最后一个没有)public abstract void handle(String path, I input, O output)请求Server ---P1、P2---> Dispatcher ---I、O---> Handler调用到本方法自定义示例:JsonHandler基于前面自定义的ExchangeDispatcher实现一个简单Json返回值处理示例代码:public class JsonHandler extends Handler<ExchangeInput, Output> { @Override public void handle(String path, ExchangeInput input, Output output) throws Throwable { // 匹配路径获取 action Action action = RouterKit.get().getRouter().getAction(path, input); Class<?> targetClass = action.getTargetClass(); Object target = targetClass.newInstance(); Invocation invocation = new Invocation(action, target, input, output); invocation.invoke(); //返回值 Object returnValue = invocation.getReturnValue(); HttpServerExchange exchange = input.getExchange(); OutputStream outputStream = exchange.getOutputStream(); exchange.getResponseHeaders().put(io.undertow.util.Headers.CONTENT_TYPE, "application/json; charset=utf-8"); //写入Json字符串IO流 Json.of(returnValue).toJson(outputStream); outputStream.close(); }}//仅实现核心原理,不做健壮判断等处理//简单使用示例public class DemoAppConfig implements AifeiConfig<ExchangeInput, Output> { @Override public void config(Settings<ExchangeInput, Output> settings) { // 配置 Server、Dispatcher、Handler settings.setServer(new UndertowServer(), new ExchangeDispatcher()); settings.addHandler(new JsonHandler()); } @Override public void config(Routes routes) { routes.add("/", IndexService.class); } @Override public void config(Plugins plugins) { }}public static void main(String[] args) { Aifei.start(new DemoAppConfig(), args);}Argument参数待继续编写