在spring上下文初始化时显示静态html页面

yizd12fk  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(351)

springboot2.3.7,嵌入式jetty,jsp和war打包。我想在spring上下文初始化时显示一些静态html页面。它应该在应用程序启动时和spring上下文刷新之前可见。我试着以这本手册为例https://www.nurkiewicz.com/2015/09/displaying-progress-of-spring.html 但这行不通。当jetty初始化时,我需要直接启动嵌入式jetty。但SpringBoot只有在上下文刷新时才会启动嵌入式jetty。我该怎么做?

ffdz8vbo

ffdz8vbo1#

我创建了一个jetty warpper预热类:

public final class WarmupServer {

    private final String contextPath;
    private final String displayName;
    private final DefaultApplicationArguments arguments;

    private final String[] welcomeFiles;
    private final Resource baseResource;

    private Server server;

    public WarmupServer(String contextPath,
                        String displayName,
                        Resource baseResource,
                        String[] welcomeFiles,
                        String... runArgs) {
        this.contextPath = StringUtils.defaultIfBlank(contextPath, "/");
        this.displayName = StringUtils.defaultIfBlank(displayName, "Warmup");
        this.baseResource = ObjectUtils.defaultIfNull(baseResource, Resource.newClassPathResource("/static"));
        this.welcomeFiles = ArrayUtils.isEmpty(welcomeFiles) ? new String[]{"html/warmup.html"} : welcomeFiles;
        this.arguments = new DefaultApplicationArguments(ArrayUtils.nullToEmpty(runArgs));
    }

    public Server start() throws Exception {
        if (server != null && server.isStarted()) {
            throw new IllegalStateException("Server already started");
        }
        server = new Server();
        server.setHandler(buildServletHandler());

        final String configPath = parseArg(OPT_CONFIG);
        if (StringUtils.isBlank(configPath)) {
            throw new RuntimeException(OPT_CONFIG + " argument is not set");
        }
        final Config config = ConfigUtils.parseFile(new File(configPath), DEFAULT_CONFIG_FILE_NAME);

        configureHttpConnector(config);
        configureHttpsConnector(config);

        server.start();
        return server;
    }

    public void registerWarmupServerStopLifecycle(ConfigurableApplicationContext context) {
        context.getBeanFactory()
                .registerSingleton(WarmupStopLifecycle.class.getSimpleName(), new WarmupStopLifecycle(server));
    }

    private ServletContextHandler buildServletHandler() {
        final ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS);
        handler.addServlet(DefaultServlet.class, "/");
        handler.setDisplayName(displayName);
        handler.setContextPath(contextPath);
        handler.setWelcomeFiles(welcomeFiles);
        handler.setBaseResource(baseResource);
        return handler;
    }

    private void configureHttpConnector(Config config) {
        final int httpPort = NumberUtils.toInt(parseArg(OPT_HTTP_PORT), config.getInt(OPT_HTTP_PORT));
        final ServerConnector connector = new ServerConnector(server);
        connector.setPort(httpPort);
        server.addConnector(connector);
    }

    private void configureHttpsConnector(Config config) {
        final int httpsPort = NumberUtils.toInt(
                parseArg(OPT_HTTPS_PORT), config.getInt(OPT_HTTPS_PORT));
        final String keyStorePath = StringUtils.defaultIfBlank(
                parseArg(OPT_KEYSTORE_FILE), config.getString(OPT_KEYSTORE_FILE));

        final boolean sslEnabled = StringUtils.isNotBlank(keyStorePath)
                && Files.isReadable(Paths.get(keyStorePath));

        if (sslEnabled) {
            final HttpConfiguration configuration = new HttpConfiguration();
            configuration.setSecurePort(httpsPort);
            configuration.setSecureScheme(HTTPS_SCHEME);

            final ServerConnector httpsConnector = new HttpsConnector()
                    .createConnector(server, configuration, config.getConfig(JETTY_HTTPS_CONFIG), httpsPort);
            server.addConnector(httpsConnector);
        }
    }

    private String parseArg(String optionName) {
        final List<String> values = arguments.getOptionValues(optionName);
        return CollectionUtils.isEmpty(values) ? StringUtils.EMPTY : values.get(0);
    }

    public static WarmupServer start(String contextPath,
                                     String displayName,
                                     Resource baseResource,
                                     String[] welcomeFiles,
                                     String... runArgs) throws Exception {
        final WarmupServer server = new WarmupServer(contextPath, displayName, baseResource, welcomeFiles, runArgs);
        server.start();
        return server;
    }

}

此 Package 器解析命令行参数,并使用提供的命令行参数创建jetty处理程序和http和(或)https连接器。
以及简单的spring生命周期实现类:

@RequiredArgsConstructor
class WarmupStopLifecycle implements SmartLifecycle {

    private static final Logger logger = LogManager.getFormatterLogger();

    private final Server warmupServer;
    private volatile boolean isRunning;

    @Override
    public void start() {
        try {
            warmupServer.stop();
            isRunning = true;
        } catch (Exception e) {
            logger.error("Failed to stop warmup server", e);
            throw new RuntimeException("Failed to stop warmup server", e);
        }
    }

    @Override
    public void stop() {
    }

    @Override
    public boolean isRunning() {
        return isRunning;
    }

    /**
     * Returns phase of this lifecycle.
     * A phase MUST be before the Spring web server starts.
     * See {@code org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle} phase.
     */
    @Override
    public int getPhase() {
        return Integer.MAX_VALUE - 2;
    }
}

所以这个的用法是:

@SpringBootApplication
public class SpringApplication {

    public static void main(String[] args) throws Exception {
        final WarmupServer warmupServer = WarmupServer.start(
                "/my_context_path", "My Warmup server handler", args);

        new SpringApplicationBuilder()
                .sources(SpringApplication.class)
                .initializers(warmupServer::registerWarmupServerStopLifecycle)
                .run(args);
    }
}
``` `WarmupServer` 在应用程序运行之后立即启动,并在启动spring的web服务器之前停止。

相关问题