当前位置: 首页 > 知识库问答 >
问题:

嵌入式jetty服务器启动后立即初始化servlet

东郭良弼
2023-03-14

在jetty嵌入式服务器启动后,我需要运行自己的逻辑。由于类加载器问题,我不会从主类开始。理想的解决方案似乎是从servlet初始化运行我的服务器逻辑。但是在jetty服务器启动后,不会调用init函数和构造函数。在第一个HTTP请求期间,正在创建servlet的一个实例。有没有可能让jetty立即初始化我的servlet,或者我真的需要用我的自定义类加载器加载所有类,然后启动jetty服务器?

这是主要类:

public class ServerLauncher {
    public static void main(String[] args) {
        JettyServerLauncher.launchHttp("target/server.war", "0.0.0.0", 8080);
        // Starting my own logic here is causing classloader issues, because WebSocket classes are loaded by other classloader than my classes, that is the reason why I moved it into the servlet
    }
}

这是我的jetty嵌入式服务器启动器:

import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.*;

import java.io.File;

public class JettyServerLauncher {
    private static boolean isHttps;
    private static File keyStoreFile;
    private static String warPath;
    private static String host;
    private static int httpPort;
    private static int httpsPort;
    private static String keyStorePath;
    private static String keyStorePass;
    private static boolean needClientAuth;

    public static void launchHttp(String warPath, String host, int httpPort) {
        JettyServerLauncher.isHttps = false;
        JettyServerLauncher.warPath = warPath;
        JettyServerLauncher.host = host;
        JettyServerLauncher.httpPort = httpPort;

        launch();
    }

    public static void launchHttps(String warPath, String host, String keyStorePath, String keyStorePass, int httpPort, int httpsPort, boolean needClientAuth) {
        JettyServerLauncher.isHttps = true;
        JettyServerLauncher.warPath = warPath;
        JettyServerLauncher.host = host;
        JettyServerLauncher.httpPort = httpPort;
        JettyServerLauncher.httpsPort = httpsPort;
        JettyServerLauncher.keyStorePath = keyStorePath;
        JettyServerLauncher.keyStorePass = keyStorePass;
        JettyServerLauncher.needClientAuth = needClientAuth;

        launch();
    }

    private static void launch() {
        Server server = null;

        try {
            System.out.println("Initializing jetty server...");

            if (isHttps) loadKeyStores(keyStorePath);

            // Create jetty server
            server = new Server(httpPort);

            // Setup connectors
            Connector httpConnector = createHttpConnector(server, host, httpPort, httpsPort);
            if (isHttps) {
                Connector httpsConnector = createHttpsConnector(server, host, httpsPort, keyStoreFile, keyStorePass, needClientAuth);
                server.setConnectors(new Connector[]{httpConnector, httpsConnector});
            } else {
                server.setConnectors(new Connector[]{httpConnector});
            }

            // Add handlers for requests to collection of handlers
            HandlerCollection handlers = new ContextHandlerCollection();
            //handlers.addHandler(new SecuredRedirectHandler());
            handlers.addHandler(createWebApp(warPath));

            server.setHandler(handlers);
            server.dump();

            System.out.println("Starting jetty websocket and web server...");
            server.start();
            server.join();
        } catch (Throwable t) {
            t.printStackTrace();
            System.err.println("Server initialization failed!");
            System.out.println("Stopping the server...");
            try {
                server.stop();
            } catch (Exception ignored) {}
        }
    }

    private static WebAppContext createWebApp(String warPath) {
        WebAppContext webApp = new WebAppContext();
        webApp.setContextPath("/");
        webApp.setWar(new File(warPath).getAbsolutePath());
        webApp.setThrowUnavailableOnStartupException(true);

        // Enable support for JSR-356 javax.websocket
        webApp.setAttribute("org.eclipse.jetty.websocket.jsr356", Boolean.TRUE);

        // Jetty will scan project for configuration files... This is very important for loading websocket endpoints by annotation automatically
        webApp.setConfigurations(new Configuration[] {
                new AnnotationConfiguration(),
                new WebInfConfiguration(),
                new WebXmlConfiguration(),
                new MetaInfConfiguration(),
                new FragmentConfiguration(),
                new EnvConfiguration(),
                new PlusConfiguration(),
                new JettyWebXmlConfiguration()
        });

        return webApp;
    }

    private static Connector createHttpConnector(Server server, String host, int httpPort, int httpsPort) {
        HttpConfiguration httpConf = new HttpConfiguration();
        httpConf.setSendServerVersion(false);
        if (isHttps) httpConf.setSecurePort(httpsPort);
        ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(httpConf));
        connector.setPort(httpPort);
        connector.setHost(host);

        return connector;
    }

    private static Connector createHttpsConnector(Server server, String host, int httpsPort, File keyStoreFile, String keyStorePass, boolean needClientAuth) {
        SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
        sslContextFactory.setKeyStorePath(keyStoreFile.getAbsolutePath());
        sslContextFactory.setKeyStorePassword(keyStorePass);
        sslContextFactory.setNeedClientAuth(needClientAuth);

        // Setup HTTPS Configuration
        HttpConfiguration httpsConf = new HttpConfiguration();
        httpsConf.setSendServerVersion(false);
        httpsConf.setSecureScheme("https");
        httpsConf.setSecurePort(httpsPort);
        httpsConf.setOutputBufferSize(32768);
        httpsConf.setRequestHeaderSize(8192);
        httpsConf.setResponseHeaderSize(8192);
        httpsConf.addCustomizer(new SecureRequestCustomizer()); // adds ssl info to request object

        // Establish the HTTPS ServerConnector
        ServerConnector httpsConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), new HttpConnectionFactory(httpsConf));
        httpsConnector.setPort(httpsPort);
        httpsConnector.setHost(host);

        return httpsConnector;
    }

    private static void loadKeyStores(String keyStorePath) {
        keyStoreFile = new File(keyStorePath);
        if (!keyStoreFile.exists()) {
            throw new RuntimeException("Key store file does not exist on path '"+keyStoreFile.getAbsolutePath()+"'");
        }
    }
}

这是我的servlet:

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(displayName = "MyServlet", urlPatterns = { "/*" })
public class MyServlet extends HttpServlet {
    @Override
    public void init() {
        // start new Thread with my server logic here (avoid classloader issues)
        // but at least one HTTP request is needed to start it from this place
    }

    @Override
    public void destroy() {}

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
        // handle http requests
    }
}

我在谷歌上找到了这个,但我不知道如何在我的案例中使用它。https://www.eclipse.org/lists/jetty-users/msg02109.html

谢谢你的帮助。

共有1个答案

南宫喜
2023-03-14

如果您只是希望servlet在启动时初始化,那么使用注释...

@WebServlet(
    displayName = "MyServlet", 
    urlPatterns = { "/*" },
    loadOnStartup = 1
)

或者,您可以注册一个javax.servlet.ServletContextListener,它执行您需要的Context初始(ServletContextEvtionsce)行为。

提示:如果您为嵌入式使用定义了一个自定义的ServletContextListener,您可以从您正在使用的WAR外部将其添加到WebAppContext中。

例子:

webApp.getServletHandler()
    .addListener(new ListenerHolder(MyContextListener.class));

此外,这段代码是错误的,它显示了从旧代码片段复制/粘贴(这种技术来自circa Jetty 9.0.0到9.2.16)

        webApp.setConfigurations(new Configuration[] {
                new AnnotationConfiguration(),
                new WebInfConfiguration(),
                new WebXmlConfiguration(),
                new MetaInfConfiguration(),
                new FragmentConfiguration(),
                new EnvConfiguration(),
                new PlusConfiguration(),
                new JettyWebXmlConfiguration()
        });

在码头9.4。x您永远不会直接配置webApp。setConfigurations()像这样,使用配置。改为在服务器上定义的类列表。。。

起始时间:9.4.44。v20210927-嵌入式/LikeJettyXml。JAVA

Configuration.ClassList classlist = Configuration.ClassList
    .setServerDefault(server);
classlist.addAfter(
    "org.eclipse.jetty.webapp.FragmentConfiguration",
    "org.eclipse.jetty.plus.webapp.EnvConfiguration",
    "org.eclipse.jetty.plus.webapp.PlusConfiguration");
classlist.addBefore(
    "org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
    "org.eclipse.jetty.annotations.AnnotationConfiguration");

从Jetty 10.0.0开始,您永远不会指定配置类或它们的顺序,因为支持JAR的存在就足够了,在Jetty 10内部,顺序得到了正确的解析。

但是,如果需要添加配置(由于JavaServiceLoader不起作用的非标准部署问题),那么您仍然可以在服务器对象上配置其他配置(但不必担心这些配置的正确顺序)

从10.0.7开始-嵌入式/demos/LikeJettyXml。JAVA

Configurations.setServerDefault(server).add(
    new EnvConfiguration(), 
    new PlusConfiguration(), 
    new AnnotationConfiguration()
);

来源:embedded/LikeJettyXml。JAVA

 类似资料:
  • 问题内容: 我正在编写一些示例代码,其中启动了嵌入式Jetty服务器。服务器必须仅加载一个servlet,将所有请求发送到servlet并在localhost:80上侦听 到目前为止,我的代码: 我可以用更少的代码/行做同样的事情吗?(使用Jetty 6.1.0)。 问题答案: 删除了不必要的空格,并内联移动了ServletHolder创建。删除了5行。

  • 我有一个Spring Boot应用程序演示,遵循以下指南https://spring.io/guides/gs/rest-service/ PS:因为启动类不在我的bean的同一个包中,所以我显式地将@componentscan添加到我的启动类中。

  • 运行Spring Boot应用程序时,嵌入式tomcat服务器无法启动。我刚刚在pom.xml中添加了所需的依赖项,并创建了一个简单的java POJO类。应用程序属性已经按照oracle数据库所需的jdbc配置以及Hibernate方言信息进行了设置。 执行mvn spring-boot:run时的控制台日志

  • 我遇到这个问题已经有一段时间了,但没有找到解决方案。我正在rails中构建一个论坛应用程序。我刚刚完成将bootstrap和bootstrap gem添加到我的项目中。我去运行服务器,它以一个巨大的错误退出。在这里。

  • 我有能力安装jetty,我只是下载了jetty7 zip并提取了服务器。 我需要在3台linux机器上设置这个。在一台机器中,服务器启动得很好,没有问题。 但是在另外两个中,当服务器启动时,它会显示以下错误。

  • 问题内容: 我讨厌问这样一个模糊的问题,但是我很难找到一个简单的例子。这是我到目前为止的内容: 我可以找到的嵌入式Jetty示例始终显示如下内容,以启动运行的Server实例,但我不知道如何实例化WebSocketServlet。 如何创建可以处理WebSocket连接请求的嵌入式服务器? 问题答案: 更新:2013年12月2日 有关带有WebSocket的嵌入式码头的最新示例,请参见: http