All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rebue.wheel.vertx.verticle.AbstractWebVerticle Maven / Gradle / Ivy

There is a newer version: 3.5.45
Show newest version
package rebue.wheel.vertx.verticle;

import com.google.inject.Injector;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
import io.vertx.core.eventbus.Message;
import io.vertx.core.eventbus.MessageConsumer;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.impl.Arguments;
import io.vertx.core.json.JsonObject;
import io.vertx.core.net.SelfSignedCertificate;
import io.vertx.ext.web.AllowForwardHeaders;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.*;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import lombok.extern.slf4j.Slf4j;
import rebue.wheel.vertx.config.WebProperties;
import rebue.wheel.vertx.guice.InjectorVerticle;
import rebue.wheel.vertx.skywalking.SkyWalkingUtils;
import rebue.wheel.vertx.skywalking.handler.SkyWalkingTraceIdWriteHandler;
import rebue.wheel.vertx.web.PrintSrcIpHandler;

import java.util.Map;

@Slf4j
public abstract class AbstractWebVerticle extends AbstractVerticle implements InjectorVerticle {
    private HttpServer httpServer;
    private HttpServer http2httpsServer;

    @Inject
    @Named("mainId")
    private String mainId;

    protected Injector injector;

    public void setInjector(Injector injector) {
        this.injector = injector;
    }

    private MessageConsumer startConsumer;

    @Override
    public void start(Promise startPromise) {
        log.info("WebVerticle start deployed");

        WebProperties webProperties = config().mapTo(WebProperties.class);
        final HttpServerOptions httpServerOptions = webProperties.getServer() == null ? new HttpServerOptions()
                : new HttpServerOptions(JsonObject.mapFrom(webProperties.getServer()));

        log.info("创建路由");
        final Router router = Router.router(this.vertx);

        AllowForwardHeaders allowForwardHeaders = AllowForwardHeaders.valueOf(webProperties.getAllowForward());
        log.info("设置allow forward: {}", allowForwardHeaders);
        router.allowForward(allowForwardHeaders);

        // 全局route
        final Route globalRoute = router.route();

        // 添加全局路由处理器
        addGlobalRouteHandler(globalRoute);

        // 是否启用SkyWalking Agent支持
        if (SkyWalkingUtils.isEnabled()) {
            log.info("开启SkyWalking Agent支持");
            globalRoute.handler(new SkyWalkingTraceIdWriteHandler());
        }
        // 响应内容类型处理(处理器会通过 getAcceptableContentType 方法来选择适当的内容类型)
//        log.info("开启响应内容类型处理");
//        globalRoute.handler(ResponseContentTypeHandler.create());
        // 全局返回响应时间
        if (webProperties.getIsResponseTime()) {
            log.info("开启返回响应时间");
            globalRoute.handler(ResponseTimeHandler.create());
        }
        // 超时时间
        final Long timeout = webProperties.getTimeout();
        if (timeout != null && timeout != 0) {
            final Integer timeoutErrorCode = webProperties.getTimeoutErrorCode();
            final int     errorCode        = timeoutErrorCode != null ? timeoutErrorCode : 503;
            log.info("开启超时{}毫秒未响应返回错误状态码{}", timeout, errorCode);
            globalRoute.handler(TimeoutHandler.create(timeout, errorCode));
        }
        // 记录日志
        if (webProperties.getIsLogging()) {
            log.info("开启Web日志记录");
            globalRoute.handler(LoggerHandler.create(webProperties.getLoggerFormat()));
        }
        // CORS
        if (webProperties.getIsCors()) {
            log.info("开启CORS");
            globalRoute.handler(CorsHandler.create());
        }
        // 全局路由错误处理
        final ErrorHandler errorHandler = ErrorHandler.create(this.vertx);
        globalRoute.failureHandler(ctx -> {
            log.error("全局路由错误处理: {}", ctx.statusCode());
            errorHandler.handle(ctx);
        });
        // 是否打印来源的IP
        if (webProperties.getPrintSrcIp()) {
            log.info("开启打印来源的IP");
            globalRoute.handler(new PrintSrcIpHandler());
        }

        // 添加全局子路由处理器
        addGlobalRouteSubHandler(globalRoute);


        // 是否实现自签名证书
        if (webProperties.getSelfSignedCertificate()) {
            log.info("实现自签名证书");
            SelfSignedCertificate certificate = SelfSignedCertificate.create();
            httpServerOptions
                    .setSsl(true)
                    .setKeyCertOptions(certificate.keyCertOptions())
                    .setTrustOptions(certificate.trustOptions());
        }

        log.info("配置路由器");
        configRouter(router);

        this.httpServer = this.vertx.createHttpServer(httpServerOptions).requestHandler(router);

        Map http2https = webProperties.getHttp2https();
        if (http2https != null) {
            final HttpServerOptions http2httpsServerOptions = new HttpServerOptions(JsonObject.mapFrom(webProperties.getHttp2https()));
            int                     http2httpsPort          = http2httpsServerOptions.getPort();
            int                     httpsPort               = httpServerOptions.getPort();
            Arguments.require(http2httpsPort != 0, "web.config.http2https.port不能为null或0");
            Arguments.require(httpsPort != 0, "web.config.server.port不能为null或0");

            this.http2httpsServer = this.vertx.createHttpServer(http2httpsServerOptions)
                    .requestHandler(req -> req.response()
                            .setStatusCode(301)
                            .putHeader("Location", req.absoluteURI()
                                    .replace("http", "https")
                                    .replace(":" + http2httpsPort, ":" + httpsPort)
                            )
                            .end());
        }

        final String address = AbstractMainVerticle.EVENT_BUS_DEPLOY_SUCCESS + "::" + this.mainId;
        log.info("WebVerticle注册消费EventBus事件-MainVerticle部署成功事件: {}", address);
        this.startConsumer = this.vertx.eventBus().consumer(address, this::handleStart);
        // 注册完成处理器
        this.startConsumer.completionHandler(res -> {
            log.info("WebVerticle end deployed");
            if (res.succeeded()) {
                log.info("WebVerticle deployed success");
                startPromise.complete();
            } else {
                log.error("WebVerticle deployed fail", res.cause());
                startPromise.fail(res.cause());
            }
        });
    }

    /**
     * 添加全局路由处理器
     *
     * @param globalRoute 全局路由
     */
    protected void addGlobalRouteHandler(Route globalRoute) {
        log.info("未重写addGlobalRouteHandler方法:{}", globalRoute.getName());
    }

    /**
     * 添加全局路由子处理器
     *
     * @param globalRoute 全局路由
     */
    protected void addGlobalRouteSubHandler(Route globalRoute) {
        log.info("未重写addGlobalRouteSubHandler方法: {}", globalRoute.getName());
    }

    @Override
    public void stop() {
        log.info("WebVerticle stop");
        if (http2httpsServer != null) http2httpsServer.close();
        this.httpServer.close();
    }

    /**
     * 配置路由
     *
     * @param router 路由器
     */
    protected abstract void configRouter(Router router);

    private void handleStart(final Message message) {
        log.info("WebVerticle start");
        this.startConsumer.unregister(result -> {
            this.httpServer.listen(res -> {
                if (res.succeeded()) {
                    log.info("HTTP server started on port " + res.result().actualPort());
                } else {
                    log.error("HTTP server start fail", res.cause());
                }
            });
            if (http2httpsServer != null) http2httpsServer.listen(res -> {
                if (res.succeeded()) {
                    log.info("HTTP to HTTPS server started on port " + res.result().actualPort());
                } else {
                    log.error("HTTP to HTTPS server start fail", res.cause());
                }
            });
        });
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy