package org.voovan.http.server; import org.voovan.http.server.context.HttpModuleConfig; import org.voovan.http.server.context.HttpRouterConfig; import org.voovan.http.server.context.WebContext; import org.voovan.http.server.context.WebServerConfig; import org.voovan.http.websocket.WebSocketRouter; import org.voovan.network.SSLManager; import org.voovan.network.aio.AioServerSocket; import org.voovan.network.messagesplitter.HttpMessageSplitter; import org.voovan.tools.TEnv; import org.voovan.tools.TFile; import org.voovan.tools.TString; import org.voovan.tools.log.Logger; import java.io.IOException; /** * WebServer 对象 * * @author helyho * * Voovan Framework. * WebSite: https://github.com/helyho/Voovan * Licence: Apache v2 License */ public class WebServer { private AioServerSocket aioServerSocket; private HttpDispatcher httpDispatcher; private WebSocketDispatcher webSocketDispatcher; private SessionManager sessionManager; private WebServerConfig config; /** * 构造函数 * * @param config WEB 配对对象 * @throws IOException * 异常 */ public WebServer(WebServerConfig config) throws IOException { this.config = config; //[Socket] 准备 socket 监听 aioServerSocket = new AioServerSocket(config.getHost(), config.getPort(), config.getTimeout()*1000); //[HTTP] 构造 SessionManage sessionManager = SessionManager.newInstance(config); //[HTTP]请求派发器创建 this.httpDispatcher = new HttpDispatcher(config,sessionManager); this.webSocketDispatcher = new WebSocketDispatcher(config); //[Socket]确认是否启用 HTTPS 支持 if(config.isHttps()) { SSLManager sslManager = new SSLManager("TLS", false); sslManager.loadCertificate(System.getProperty("user.dir") + config.getHttps().getCertificateFile(), config.getHttps().getCertificatePassword(), config.getHttps().getKeyPassword()); aioServerSocket.setSSLManager(sslManager); } aioServerSocket.handler(new WebServerHandler(config, httpDispatcher,webSocketDispatcher)); aioServerSocket.filterChain().add(new WebServerFilter()); aioServerSocket.messageSplitter(new HttpMessageSplitter()); } /** * 将配置文件中的 Router 配置载入到 WebServer */ private void initConfigedRouter(){ for(HttpRouterConfig httpRouterConfig : config.getRouterConfigs()){ String method = httpRouterConfig.getMethod(); String route = httpRouterConfig.getRoute(); String className = httpRouterConfig.getClassName(); otherMethod(method,route,httpRouterConfig.getHttpRouterInstance()); } } /** * 模块安装 */ public void initModule() { for (HttpModuleConfig httpModuleConfig : config.getModuleonfigs()) { HttpModule httpModule = httpModuleConfig.getHttpModuleInstance(this); if(httpModule!=null){ httpModule.install(); } } } /** * 获取 Http 服务配置对象 * @return 返回 Http 服务配置对象 */ public WebServerConfig getWebServerConfig() { return config; } /** * 以下是一些 HTTP 方法的成员函数 */ /** * GET 请求 * @param routeRegexPath 匹配路径 * @param router HTTP处理请求句柄 * @return WebServer对象 */ public WebServer get(String routeRegexPath, HttpRouter router) { httpDispatcher.addRouteHandler("GET", routeRegexPath, router); return this; } /** * POST 请求 * @param routeRegexPath 匹配路径 * @param router HTTP处理请求句柄 * @return WebServer对象 */ public WebServer post(String routeRegexPath, HttpRouter router) { httpDispatcher.addRouteHandler("POST", routeRegexPath, router); return this; } /** * HEAD 请求 * @param routeRegexPath 匹配路径 * @param router HTTP处理请求句柄 * @return WebServer对象 */ public WebServer head(String routeRegexPath, HttpRouter router) { httpDispatcher.addRouteHandler("HEAD", routeRegexPath, router); return this; } /** * PUT 请求 * @param routeRegexPath 匹配路径 * @param router HTTP处理请求句柄 * @return WebServer对象 */ public WebServer put(String routeRegexPath, HttpRouter router) { httpDispatcher.addRouteHandler("PUT", routeRegexPath, router); return this; } /** * DELETE 请求 * @param routeRegexPath 匹配路径 * @param router HTTP处理请求句柄 * @return WebServer对象 */ public WebServer delete(String routeRegexPath, HttpRouter router) { httpDispatcher.addRouteHandler("DELETE", routeRegexPath, router); return this; } /** * TRACE 请求 * @param routeRegexPath 匹配路径 * @param router HTTP处理请求句柄 * @return WebServer对象 */ public WebServer trace(String routeRegexPath, HttpRouter router) { httpDispatcher.addRouteHandler("TRACE", routeRegexPath, router); return this; } /** * CONNECT 请求 * @param routeRegexPath 匹配路径 * @param router HTTP处理请求句柄 * @return WebServer对象 */ public WebServer connect(String routeRegexPath, HttpRouter router) { httpDispatcher.addRouteHandler("CONNECT", routeRegexPath, router); return this; } /** * OPTIONS 请求 * @param routeRegexPath 匹配路径 * @param router HTTP处理请求句柄 * @return WebServer对象 */ public WebServer options(String routeRegexPath, HttpRouter router) { httpDispatcher.addRouteHandler("OPTIONS", routeRegexPath, router); return this; } /** * 其他请求 * @param method 请求方法 * @param routeRegexPath 匹配路径 * @param router HTTP处理请求句柄 * @return WebServer对象 */ public WebServer otherMethod(String method, String routeRegexPath, HttpRouter router) { httpDispatcher.addRouteMethod(method); httpDispatcher.addRouteHandler(method, routeRegexPath, router); return this; } /** * WebSocket 服务 * @param routeRegexPath 匹配路径 * @param router WebSocket处理句柄 * @return WebServer对象 */ public WebServer socket(String routeRegexPath, WebSocketRouter router) { webSocketDispatcher.addRouteHandler(routeRegexPath, router); return this; } /** * 构建新的 WebServer,从配置对象读取配置 * @param config WebServer配置类 * @return WebServer 对象 */ public static WebServer newInstance(WebServerConfig config) { try { if(config!=null) { return new WebServer(config); }else{ Logger.error("Create WebServer failed: WebServerConfig object is null."); } } catch (IOException e) { Logger.error("Create WebServer failed.",e); } return null; } /** * 构建新的 WebServer,指定服务端口 * @param port HTTP 服务的端口号 * @return WebServer 对象 */ public static WebServer newInstance(int port) { WebServerConfig config = WebContext.getWebServerConfig(); config.setPort(port); return newInstance(config); } /** * 构建新的 WebServer,从配置文件读取配置 * * @return WebServer 对象 */ public static WebServer newInstance() { return newInstance(WebContext.getWebServerConfig()); } /** * 读取Classes目录和lib目录中的class或者jar文件 */ private static void loadContextBin(){ try { TEnv.loadBinary(TFile.getSystemPath("classes")); TEnv.loadJars(TFile.getSystemPath("lib")); } catch (NoSuchMethodException | IOException | SecurityException e) { Logger.warn("Voovan WebServer Loader ./classes or ./lib error." ,e); } } /** * 启动服务 * * @return WebServer 对象 */ public WebServer serve() { try { //输出欢迎信息 WebContext.welcome(config); WebContext.initWebServerPlugin(); loadContextBin(); initConfigedRouter(); initModule(); Logger.simple("Process ID: "+ TEnv.getCurrentPID()); Logger.simple("WebServer working on: http"+(config.isHttps()?"s":"")+"://"+config.getHost()+":"+config.getPort()+" ..."); aioServerSocket.start(); } catch (IOException e) { Logger.error("Start HTTP server error.",e); } return this; } /** * 启动 WebServer 服务 * @param args 启动参数 */ public static void main(String[] args) { WebServerConfig config = null; if(args.length>0){ for(int i=0;i<args.length;i++){ //服务端口 if(args[i].equals("-p")){ config = config==null?WebContext.getWebServerConfig():config; i++; config.setPort(Integer.parseInt(args[i])); } //连接超时时间(s) if(args[i].equals("-t")){ config = config==null?WebContext.getWebServerConfig():config; i++; config.setTimeout(Integer.parseInt(args[i])); } //上下文路径 if(args[i].equals("-cp")){ config = config==null?WebContext.getWebServerConfig():config; i++; config.setContextPath(args[i]); } //首页索引文件的名称,默认index.htm,index.html,default.htm,default.htm if(args[i].equals("-i")){ config = config==null?WebContext.getWebServerConfig():config; i++; config.setIndexFiles(args[i]); } //匹配路由不区分大小写,默认是 false if(args[i].equals("-mri")){ config = config==null?WebContext.getWebServerConfig():config; config.setMatchRouteIgnoreCase(true); } //默认字符集,默认 UTF-8 if(args[i].equals("-c")){ config = config==null?WebContext.getWebServerConfig():config; i++; config.setCharacterSet(args[i]); } //是否启用Gzip压缩,默认 true if(args[i].equals("--noGzip")){ config = config==null?WebContext.getWebServerConfig():config; config.setGzip(false); } //是否记录access.log,默认 true if(args[i].equals("--noAccessLog")){ config = config==null?WebContext.getWebServerConfig():config; config.setAccessLog(false); } //HTTPS 证书 if(args[i].equals("--https.CertificateFile")){ config = config==null?WebContext.getWebServerConfig():config; i++; config.getHttps().setCertificateFile(args[i]); } //证书密码 if(args[i].equals("--https.CertificatePassword")){ config = config==null?WebContext.getWebServerConfig():config; i++; config.getHttps().setCertificatePassword(args[i]); } //证书Key 密码 if(args[i].equals("--https.KeyPassword")){ config = config==null?WebContext.getWebServerConfig():config; i++; config.getHttps().setKeyPassword(args[i]); } //输出版本号 if(args[i].equals("-v")){ Logger.simple("Version:"+WebContext.getVERSION()); return; } if(args[i].equals("--help") || args[i].equals("-h") || args[i].equals("-?")){ Logger.simple("Usage: java -jar voovan-framework.jar [Options]"); Logger.simple(""); Logger.simple("Start voovan webserver"); Logger.simple(""); Logger.simple("Options:"); Logger.simple(TString.rightPad(" -p ",35,' ')+"Webserver bind port number"); Logger.simple(TString.rightPad(" -t ",35,' ')+"Socket timeout"); Logger.simple(TString.rightPad(" -cp ",35,' ')+"Context path, contain webserver static file"); Logger.simple(TString.rightPad(" -i ",35,' ')+"index file for client access to webserver"); Logger.simple(TString.rightPad(" -mri ",35,' ')+"Match route ignore case"); Logger.simple(TString.rightPad(" -c ",35,' ')+"set default charset"); Logger.simple(TString.rightPad(" --noGzip ",35,' ')+"Do not use gzip for client"); Logger.simple(TString.rightPad(" --noAccessLog ",35,' ')+"Do not write access log to access.log"); Logger.simple(TString.rightPad(" --https.CertificateFile ",35,' ')+"Certificate file for https"); Logger.simple(TString.rightPad(" --https.CertificatePassword ",35,' ')+"ertificate file for https"); Logger.simple(TString.rightPad(" --https.KeyPassword ",35,' ')+"Certificate file for https"); Logger.simple(TString.rightPad(" -h or --help ",35,' ')+"how to use this command"); Logger.simple(TString.rightPad(" -v ",35,' ')+"Show the version information"); Logger.simple(""); Logger.simple("This WebServer based on VoovanFramework."); Logger.simple("WebSite: http://www.voovan.org"); Logger.simple("Author: helyho"); Logger.simple("E-mail: helyho@gmail.com"); Logger.simple(""); return; } } } config = config==null?WebContext.getWebServerConfig():config; WebServer webServer = WebServer.newInstance(config); webServer.serve(); } }