Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.voovan.http.server.WebServer Maven / Gradle / Ivy
package org.voovan.http.server;
import org.voovan.Global;
import org.voovan.http.message.HttpStatic;
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.server.router.OptionsRouter;
import org.voovan.http.websocket.WebSocketRouter;
import org.voovan.network.SSLManager;
import org.voovan.network.SocketContext;
import org.voovan.network.messagesplitter.HttpMessageSplitter;
import org.voovan.network.tcp.TcpServerSocket;
import org.voovan.tools.*;
import org.voovan.tools.threadpool.ThreadPool;
import org.voovan.tools.weave.Weave;
import org.voovan.tools.hotswap.Hotswaper;
import org.voovan.tools.json.JSON;
import org.voovan.tools.log.Logger;
import org.voovan.tools.reflect.TReflect;
import java.io.File;
import java.io.IOException;
import java.nio.channels.ShutdownChannelGroupException;
import java.util.Map;
/**
* WebServer 对象
*
* @author helyho
*
* Voovan Framework.
* WebSite: https://github.com/helyho/Voovan
* Licence: Apache v2 License
*/
public class WebServer {
private SocketContext serverSocket;
private HttpDispatcher httpDispatcher;
private WebSocketDispatcher webSocketDispatcher;
private SessionManager sessionManager;
private WebServerConfig config;
private WebServerLifeCycle webServerLifeCycle;
/**
* 构造函数
*
* @param config WEB 配对对象
* 异常
*/
public WebServer(WebServerConfig config) {
this.config = config;
initAop();
initHotSwap();
initWebServer(config);
}
/**
* 返回 Session 管理器
* @return Session 管理器
*/
public SessionManager getSessionManager(){
return this.sessionManager;
}
/**
* 初始化热部署
*/
private void initHotSwap() {
//热加载
if(config.getHotSwapInterval() > 0) {
try {
Hotswaper hotSwaper = new Hotswaper();
hotSwaper.autoReload(config.getHotSwapInterval());
} catch (Exception e) {
Logger.error("Init hotswap failed: " + e.getMessage());
}
}
}
/**
* 初始化热部署
*/
private void initAop() {
//热加载
if(config.getWeaveConfig()!=null) {
try {
Weave.init(config.getWeaveConfig());
} catch (Exception e) {
Logger.error("Init aop failed: " + e.getMessage());
}
}
}
private void initWebServer(WebServerConfig config) {
//[HTTP] 构造 SessionManage
this.sessionManager = SessionManager.newInstance(config);
//[HTTP]请求派发器创建
this.httpDispatcher = new HttpDispatcher(config, sessionManager);
this.webSocketDispatcher = new WebSocketDispatcher(config, sessionManager);
}
private void initSocketServer(WebServerConfig config) throws IOException{
//[Socket] 准备 socket 监听
serverSocket = new TcpServerSocket(config.getHost(), config.getPort(), config.getReadTimeout()*1000, config.getSendTimeout()*1000, 0);
//构造 Web 独立的事件组执行器
serverSocket.setAcceptEventRunnerGroup(SocketContext.createEventRunnerGroup("Web", SocketContext.ACCEPT_THREAD_SIZE, true));
serverSocket.setIoEventRunnerGroup(SocketContext.createEventRunnerGroup("Web", SocketContext.IO_THREAD_SIZE, false));
//[Socket]确认是否启用 HTTPS 支持
if(config.isHttps()) {
SSLManager sslManager = new SSLManager("TLS", false);
sslManager.loadKey(System.getProperty("user.dir") + config.getHttps().getCertificateFile(),
config.getHttps().getCertificatePassword(), config.getHttps().getKeyPassword());
serverSocket.setSSLManager(sslManager);
}
serverSocket.handler(new WebServerHandler(config, httpDispatcher, webSocketDispatcher));
serverSocket.filterChain().add(new WebServerFilter());
serverSocket.messageSplitter(new HttpMessageSplitter());
}
/**
* 将配置文件中的 Router 配置载入到 WebServer
*/
private void initRouter(){
for(HttpRouterConfig httpRouterConfig : config.getRouterConfigs()){
String method = httpRouterConfig.getMethod();
String route = httpRouterConfig.getRoute();
String className = httpRouterConfig.getClassName();
if(!method.equals("WEBSOCKET")) {
otherMethod(method, route, httpRouterConfig.getHttpRouterInstance());
}else{
socket(route, httpRouterConfig.getWebSocketRouterInstance());
}
}
}
/**
* 模块安装
*/
public void initModule() {
for (HttpModuleConfig httpModuleConfig : config.getModuleonfigs()) {
HttpModule httpModule = httpModuleConfig.getHttpModuleInstance(this);
if(httpModule!=null){
httpModule.runModuleInit();
httpModule.install();
}
}
}
/**
* 模块卸载
*/
public void unInitModule() {
//卸载模块
for (HttpModuleConfig moduleConfig : this.config.getModuleonfigs().toArray(new HttpModuleConfig[0])) {
HttpModule httpModule = moduleConfig.getHttpModuleInstance(this);
httpModule.runModuleDestory();
httpModule.unInstall();
Logger.simple("[HTTP] Module ["+moduleConfig.getName()+"] uninstall");
}
}
/**
* 获取 Http 服务配置对象
* @return 返回 Http 服务配置对象
*/
public WebServerConfig getWebServerConfig() {
return config;
}
public HttpDispatcher getHttpDispatcher() {
return httpDispatcher;
}
public WebSocketDispatcher getWebSocketDispatcher() {
return webSocketDispatcher;
}
public SocketContext getServerSocket() {
return serverSocket;
}
public WebServerLifeCycle getWebServerLifeCycle() {
return webServerLifeCycle;
}
/**
* 以下是一些 HTTP 方法的成员函数
*/
/**
* GET 请求
* @param routeRegexPath 匹配路径
* @param router HTTP处理请求句柄
* @return WebServer对象
*/
public WebServer get(String routeRegexPath, HttpRouter router) {
httpDispatcher.addRouter(HttpStatic.GET_STRING, routeRegexPath, router);
return this;
}
/**
* POST 请求
* @param routeRegexPath 匹配路径
* @param router HTTP处理请求句柄
* @return WebServer对象
*/
public WebServer post(String routeRegexPath, HttpRouter router) {
httpDispatcher.addRouter(HttpStatic.POST_STRING, routeRegexPath, router);
return this;
}
/**
* 同时注册 GET 和 POST 请求
* @param routeRegexPath 匹配路径
* @param router HTTP处理请求句柄
* @return WebServer对象
*/
public WebServer getAndPost(String routeRegexPath, HttpRouter router) {
get(routeRegexPath, router);
post(routeRegexPath, router);
return this;
}
/**
* HEAD 请求
* @param routeRegexPath 匹配路径
* @param router HTTP处理请求句柄
* @return WebServer对象
*/
public WebServer head(String routeRegexPath, HttpRouter router) {
httpDispatcher.addRouter(HttpStatic.HEAD_STRING, routeRegexPath, router);
return this;
}
/**
* PUT 请求
* @param routeRegexPath 匹配路径
* @param router HTTP处理请求句柄
* @return WebServer对象
*/
public WebServer put(String routeRegexPath, HttpRouter router) {
httpDispatcher.addRouter(HttpStatic.PUT_STRING, routeRegexPath, router);
return this;
}
/**
* DELETE 请求
* @param routeRegexPath 匹配路径
* @param router HTTP处理请求句柄
* @return WebServer对象
*/
public WebServer delete(String routeRegexPath, HttpRouter router) {
httpDispatcher.addRouter(HttpStatic.DELETE_STRING, routeRegexPath, router);
return this;
}
/**
* TRACE 请求
* @param routeRegexPath 匹配路径
* @param router HTTP处理请求句柄
* @return WebServer对象
*/
public WebServer trace(String routeRegexPath, HttpRouter router) {
httpDispatcher.addRouter(HttpStatic.TRACE_STRING, routeRegexPath, router);
return this;
}
/**
* CONNECT 请求
* @param routeRegexPath 匹配路径
* @param router HTTP处理请求句柄
* @return WebServer对象
*/
public WebServer connect(String routeRegexPath, HttpRouter router) {
httpDispatcher.addRouter(HttpStatic.CONNECTION_STRING, routeRegexPath, router);
return this;
}
/**
* OPTIONS 请求
* @param routeRegexPath 匹配路径
* @param router HTTP处理请求句柄
* @return WebServer对象
*/
public WebServer options(String routeRegexPath, HttpRouter router) {
httpDispatcher.addRouter(HttpStatic.OPTIONS_STRING, 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.addRouter(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) {
if(config!=null) {
return new WebServer(config);
}else{
Logger.error("Create WebServer failed: WebServerConfig object is null.");
}
return null;
}
/**
* 构建新的 WebServer,从配置JSON中读取配置
* 方便从集中配置中心加载配置
* @param json WebServer配置JSON
* @return WebServer 对象
*/
public static WebServer newInstance(String json) {
if(json!=null) {
return new WebServer(WebContext.buildConfigFromJSON(json));
}else{
Logger.error("Create WebServer failed: WebServerConfig object is null.");
}
return null;
}
/**
* 构建新的 WebServer,从配置文件中读取配置
* 方便从集中配置中心加载配置
* @param configFile WebServer配置文件
* @return WebServer 对象
*/
public static WebServer newInstance(File configFile) {
try {
if(configFile!=null && configFile.exists()) {
return new WebServer(WebContext.buildConfigFromFile(configFile.getCanonicalPath()));
}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());
}
/**
* 通用服务启动
*/
private void commonServe() throws IOException {
WebContext.getAuthToken();
WebContext.logo();
//运行初始化 Class
WebServerInit(this);
//加载过滤器,路由,模块
WebContext.initWebServerPluginConfig(true);
//初始化路由
initRouter();
//初始化模块
initModule();
//初始化管理路由
InitManagerRouter();
initSocketServer(this.config);
//输出欢迎信息
WebContext.welcome();
//保存 PID
Long pid = TEnv.getCurrentPID();
System.out.println(" Pid: \t"+ pid.toString());
File pidFile = new File("logs/.pid");
try {
TFile.writeFile(pidFile, false, pid.toString().getBytes());
} catch (IOException e) {
Logger.error("Write pid to file: " + pidFile.getPath() + " error", e);
}
String serviceUrl = "http" + (config.isHttps()?"s":"") + "://"
+ (config.getHost().equals("0.0.0.0") ? "127.0.0.1" : config.getHost())
+ ":"+config.getPort();
Logger.simple(" Listen: " + serviceUrl);
Logger.simple(" Time: \t" + TDateTime.now());
}
/**
* 重新读取 WebConfig 的配置
* @param reloadInfoJson 重新读取 WebConfig 的配置信息
*/
public void reload(String reloadInfoJson){
WebContext.PAUSE = true;
//卸载模块
unInitModule();
WebServerConfig config = null;
Map reloadInfo = (Map)JSON.parse(reloadInfoJson);
if("FILE".equals(reloadInfo.get("Type"))) {
config = WebContext.buildConfigFromFile(reloadInfo.get("Content").toString());
}
if("HTTP".equals(reloadInfo.get("Type"))) {
config = WebContext.buildConfigFromRemote(reloadInfo.get("Content").toString());
}
if("JSON".equals(reloadInfo.get("Type"))) {
config = WebContext.buildConfigFromJSON(reloadInfo.get("Content").toString());
}
this.config = config;
//构造新的请求派发器创建
this.httpDispatcher = new HttpDispatcher(config,sessionManager);
this.webSocketDispatcher = new WebSocketDispatcher(config, sessionManager);
//更新 WebServer 的 http 和 websocket 的分发
serverSocket.handler(new WebServerHandler(config, httpDispatcher,webSocketDispatcher));
//输出欢迎信息
WebContext.welcome();
//加载过滤器,路由,模块
WebContext.initWebServerPluginConfig(false);
//初始化路由
initRouter();
//初始化模块
initModule();
//初始化管理路由
InitManagerRouter();
WebContext.PAUSE = false;
}
/**
* 加载并运行初始化类
* @param webServer WebServer对象
*/
private void WebServerInit(WebServer webServer){
String lifeCycleClass = WebContext.getWebServerConfig().getLifeCycleClass();
if(lifeCycleClass==null) {
Logger.info("None WebServer lifeCycle class to load.");
return;
}
if(lifeCycleClass.isEmpty()){
Logger.info("None WebServer lifeCycle class to load.");
return;
}
try {
Class clazz = Class.forName(lifeCycleClass);
if(TReflect.isImpByInterface(clazz, WebServerLifeCycle.class)){
webServerLifeCycle = (WebServerLifeCycle)TReflect.newInstance(clazz);
webServerLifeCycle.init(webServer);
}else{
Logger.warn("The WebServer lifeCycle class " + lifeCycleClass + " is not a class implement by " + WebServerLifeCycle.class.getName());
}
} catch (Exception e) {
Logger.error("Initialize WebServer lifeCycle class error: ", e);
}
}
/**
* 加载并运行初始化类
* @param webServer WebServer对象
*/
private void WebServerDestory(WebServer webServer){
if(webServerLifeCycle!=null) {
try {
webServerLifeCycle.destory(webServer);
} catch (Exception e) {
Logger.error("Initialize WebServer destory lifeCycle error: ", e);
}
}
}
/**
* 是否具备管理权限
* 这里控制必须是 127.0.0.1的 ip 地址, 并且需要提供 authToken
* @param request http请求对象
* @return true: 具备管理权限, false: 不具备管理权限
*/
public static boolean hasAdminRight(HttpRequest request){
if(!TPerformance.getLocalIpAddrs().contains(request.getSession().getSocketSession().remoteAddress())){
request.getSession().close();
}
String authToken = request.header().get("AUTH-TOKEN");
if(authToken!=null && authToken.equals(WebContext.AUTH_TOKEN)) {
return true;
} else {
return false;
}
}
/**
* 初始化服务管理相关的路由
*/
public void InitManagerRouter(){
final WebServer innerWebServer = this;
otherMethod("ADMIN", "/voovan/admin/status", new HttpRouter() {
@Override
public void process(HttpRequest request, HttpResponse response) throws Exception {
String status = "RUNNING";
if(hasAdminRight(request)) {
if(WebContext.PAUSE){
status = "PAUSE";
}
response.write(status);
}else{
request.getSession().close();
}
}
});
otherMethod("ADMIN", "/voovan/admin/shutdown", new HttpRouter() {
@Override
public void process(HttpRequest request, HttpResponse response) throws Exception {
if(hasAdminRight(request)) {
request.getSocketSession().close();
innerWebServer.stop();
Logger.info("WebServer is stoped");
}else{
request.getSession().close();
}
}
});
otherMethod("ADMIN", "/voovan/admin/pause", new HttpRouter() {
@Override
public void process(HttpRequest request, HttpResponse response) throws Exception {
if(hasAdminRight(request)) {
WebContext.PAUSE = true;
response.write("OK");
Logger.info("WebServer is paused");
}else{
request.getSession().close();
}
}
});
otherMethod("ADMIN", "/voovan/admin/unpause", new HttpRouter() {
@Override
public void process(HttpRequest request, HttpResponse response) throws Exception {
if(hasAdminRight(request)) {
WebContext.PAUSE = false;
response.write("OK");
Logger.info("WebServer is running");
}else{
request.getSession().close();
}
}
});
otherMethod("ADMIN", "/voovan/admin/pid", new HttpRouter() {
@Override
public void process(HttpRequest request, HttpResponse response) throws Exception {
if(hasAdminRight(request)) {
response.write(Long.valueOf(TEnv.getCurrentPID()).toString());
}else{
request.getSession().close();
}
}
});
otherMethod("ADMIN", "/voovan/admin/reload", new HttpRouter() {
@Override
public void process(HttpRequest request, HttpResponse response) throws Exception {
if(hasAdminRight(request)) {
reload(request.body().getBodyString());
response.write("OK");
}else{
request.getSession().close();
}
}
});
otherMethod("ADMIN", "/voovan/admin/authtoken", new HttpRouter() {
@Override
public void process(HttpRequest request, HttpResponse response) throws Exception {
if(hasAdminRight(request)) {
if(!request.body().getBodyString().isEmpty()){
//重置 AUTH_TOKEN
WebContext.AUTH_TOKEN = request.body().getBodyString();
response.write("OK");
} else {
response.write("NOTHING");
}
} else {
request.getSession().close();
}
}
});
this.options("/voovan/admin/*", new OptionsRouter("ADMIN", "*", "auth-token"));
}
/**
* 启动服务
* 阻塞方式启动
*
* @return WebServer 对象
*/
public WebServer serve() {
//接受并处理 SIGTERM 消息结束进程
final WebServer innerWebServer = this;
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
innerWebServer.stop();
}
});
try {
commonServe();
serverSocket.start();
} catch (IOException e) {
Logger.error("Start HTTP server error",e);
TEnv.sleep(1000);
System.exit(0);
}
return this;
}
/**
* 启动服务
* 非阻塞方式启动
* @return WebServer 对象
*/
public WebServer syncServe() {
try {
commonServe();
serverSocket.syncStart();
} catch (IOException e) {
Logger.error("Start HTTP server error",e);
}
return this;
}
/**
* 获取 Http 的路由配置
* @return 路由配置信息
*/
public Map>> getHttpRouters(){
return httpDispatcher.getRoutes();
}
/**
* 获取 WebSocket 的路由配置
* @return 路由配置信息
*/
public Map> getWebSocketRouters(){
return webSocketDispatcher.getRouters();
}
/**
* 是否处于服务状态
* @return true: 处于服务状态, false: 不处于服务状态
*/
public boolean isServing(){
return serverSocket.isConnected();
}
/**
* 服务暂停
*/
public void pause(){
WebContext.PAUSE = true;
}
/**
* 服务恢复
*/
public void unPause(){
WebContext.PAUSE = false;
}
/**
* 启动 WebServer 服务
* @param args 启动参数
*/
public static void main(String[] args) {
WebServer webServer = newInstance(args);
webServer.serve();
}
/**
* 启动服务
* @param args 启动参数
* @return WebServer对象
*/
public static WebServer newInstance(String[] args) {
//先初始化环境参数, 否则会导致 framework.properties 无法加载到对应环境的配置
for(int i=0;i0){
for(int i=0;i0 || config.getWeaveConfig()!=null) {
if(TEnv.JDK_VERSION > 8 && !"true".equals(System.getProperty("jdk.attach.allowAttachSelf"))){
System.out.println("Your are working on: JDK-" +TEnv.JDK_VERSION+". " +
"You should add java command arguments: " +
"-Djdk.attach.allowAttachSelf=true");
System.exit(0);
}
}
WebServer webServer = WebServer.newInstance(config);
return webServer;
}
/**
* 停止 WebServer
*/
public void stop(){
try {
System.out.println("=============================================================================================");
System.out.println("[" + TDateTime.now() + "] Try to stop WebServer....");
unInitModule();
this.WebServerDestory(this);
if(serverSocket!=null) {
serverSocket.close();
}
System.out.println("[" + TDateTime.now() + "] Socket closed");
SocketContext.gracefulShutdown();
if(serverSocket.getAcceptEventRunnerGroup()!=null) {
ThreadPool.gracefulShutdown(serverSocket.getAcceptEventRunnerGroup().getThreadPool());
}
if(serverSocket.getIoEventRunnerGroup()!=null) {
ThreadPool.gracefulShutdown(serverSocket.getIoEventRunnerGroup().getThreadPool());
}
ThreadPool.gracefulShutdown(Global.getThreadPool());
System.out.println("[" + TDateTime.now() + "] Thread pool is shutdown.");
System.out.println("[" + TDateTime.now() + "] Now webServer is fully stoped.");
TEnv.sleep(1000);
}catch(ShutdownChannelGroupException e){
return;
}
}
}