为 JAR 文件启动嵌入式码头服务器 [英] Starting up embedded jetty server for a JAR file

查看:30
本文介绍了为 JAR 文件启动嵌入式码头服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做的是构建一个可执行的 JAR 文件,该文件将包含我的项目.我已经在它旁边包含了它的依赖项,也在 JAR 文件中,所以我的目录列表看起来像这样:

<块引用>

~/Projects/Java/web-app/out:

web-app.jar

dependency1.jar

dependency2.jar

dependency3.jar

我知道并确信我的问题不是由依赖引起的,因为我的应用程序运行正常,直到我启动嵌入式 Jetty 的那一刻.

我用来启动Jetty的代码是这样的:

public class ServerExecutionGoal 实现了 ExecutionGoal {私有最终静态记录器记录器 = Logger.getLogger(ServerExecutionGoal.class);私有 WebAppContext getWebAppContext() 抛出 IOException {WebAppContext context = new WebAppContext();System.out.println("context = "+ context);context.setResourceBase(new PathMatchingResourcePatternResolver().getResource("classpath:/webapp").getURL().toExternalForm());context.setContextPath("/");context.setLogger(new StdErrLog());返回上下文;}@覆盖public void execute(Map stringObjectMap) 抛出 ExecutionTargetFailureException {logger.info(正在实例化目标服务器...");最终服务器服务器 = 新服务器(8089);最终 ContextHandlerCollection handlerCollection = new ContextHandlerCollection();尝试 {handlerCollection.setHandlers(new Handler[]{new RequestLogHandler(), getWebAppContext()});} catch (IOException e) {throw new ExecutionTargetFailureException(无法创建 Web 应用程序上下文", e);}server.setHandler(handlerCollection);尝试 {logger.info("在端口 8089 上启动服务器......");服务器开始();server.join();logger.info(服务器已启动.等待请求.");} 捕获(异常 e){throw new ExecutionTargetFailureException(无法正确启动 Web 服务器", e);}}public static void main(String[] args) 抛出 ExecutionTargetFailureException {新的 ServerExecutionGoal().execute(null);}}

我可以验证webapp"文件夹在我的 JAR 中正确重定位到 /webapp,并且当通过我的 IDE (IntelliJ IDEA 11) context.setResourceBase(new PathMatchingResourcePatternResolver().getResource("classpath:/webapp").getURL().toExternalForm()) 有效地映射到相关资源.另外,我可以证明它可以解析为:

jar:file:~/Projects/Java/web-app/out/web-app.jar!/webapp

并且可以访问(我读过).

但是,当我启动应用程序的 main 方法并且 Jetty 启动时,在 http://localhost:8089 上,我得到以下信息:

<块引用>

HTTP 错误:503

访问/时出现问题.原因:

服务不可用


由 Jetty 提供支持://

我哪里出错了?

我知道通过设置resourceBase"到."地址http://localhost:8089";将作为位置~/Projects/Java/web-app/out/"的接口;在那里我可以看到所有 JAR 文件的列表,包括web-app.jar",点击后我可以下载它.

我看到了以下问题,但答案不适用:

  1. 嵌入式码头应用程序无法从 jar 工作:我收到 NullPointerException因为 Start.class.getProtectionDomain().getCodeSource() 解析为 null.
  2. 嵌入式 Jetty WebAppContext FilePermission 问题:不仅没有回答,而且这种情况显然不适用,因为我没有权限问题(我可以获得文件列表的事实应该证明这一点).
  3. 嵌入码头服务器问题:也没有回答,也不适用,因为我没有任何依赖问题(正如我之前在上面的评论中指出的那样).

我认为我应该以某种方式使 Jetty 能够访问 /webapp 文件夹,该文件夹位于我的 src/main/resources/ 目录下并捆绑到我的网站中应用.我是否应该放弃捆绑的 Web 应用程序并将分解的上下文路径部署到 Jetty 可访问的某个地方(这根本不可取,因为它给我和我的客户带来了许多问题).

解决方案

我不确定,Jetty 的WebAppContext 是否可以与 PathMatchingResourcePatternResolver 一起使用!

在我的一个项目中,我通过编写自己的 javax.servlet.Filter 解决了这个问题,它通过 Class#getResourceAsStream 加载请求的资源.Class#getResourceAsStream 从 jar 和资源路径(例如 maven)中读取资源.

希望这个提示对你有帮助,干杯蒂洛

What I am trying to do, is to build an executable JAR file which will contain my project. I have included its dependencies right next to it, also in JAR files, so my directory listing looks something like this:

~/Projects/Java/web-app/out:

web-app.jar

dependency1.jar

dependency2.jar

dependency3.jar

I know and am sure that my problem does not arise from dependencies, as my application functions properly, right up to the moment I start up Jetty embedded.

The code I use to start Jetty is like this:

public class ServerExecutionGoal implements ExecutionGoal {    

    private final static Logger logger = Logger.getLogger(ServerExecutionGoal.class);    

    private WebAppContext getWebAppContext() throws IOException {    
        WebAppContext context = new WebAppContext();    
        System.out.println("context = " + context);    
        context.setResourceBase(new PathMatchingResourcePatternResolver().getResource("classpath:/webapp").getURL().toExternalForm());    
        context.setContextPath("/");    
        context.setLogger(new StdErrLog());    
        return context;    
    }    

    @Override    
    public void execute(Map<String, Object> stringObjectMap) throws ExecutionTargetFailureException {    
        logger.info("Instantiating target server ...");    
        final Server server = new Server(8089);    
        final ContextHandlerCollection handlerCollection = new ContextHandlerCollection();    
        try {    
            handlerCollection.setHandlers(new Handler[]{new RequestLogHandler(), getWebAppContext()});    
        } catch (IOException e) {    
            throw new ExecutionTargetFailureException("Could not create web application context", e);    
        }    
        server.setHandler(handlerCollection);    
        try {    
            logger.info("Starting server on port 8089 ...");    
            server.start();    
            server.join();    
            logger.info("Server started. Waiting for requests.");    
        } catch (Exception e) {    
            throw new ExecutionTargetFailureException("Failed to properly start the web server", e);    
        }    
    }    

    public static void main(String[] args) throws ExecutionTargetFailureException {    
        new ServerExecutionGoal().execute(null);    
    }    

}    

I can validate that the "webapp" folder gets relocated correctly inside my JAR to /webapp, and that when running the code through my IDE (IntelliJ IDEA 11) context.setResourceBase(new PathMatchingResourcePatternResolver().getResource("classpath:/webapp").getURL().toExternalForm()) maps validly to the resource in question. Also, I can show that it resolves to something like:

jar:file:~/Projects/Java/web-app/out/web-app.jar!/webapp

and is accessible (I read it).

However, when I start my application's main method, and Jetty starts, on http://localhost:8089 I get the following:

HTTP ERROR: 503

Problem accessing /. Reason:

Service Unavailable


Powered by Jetty://

Where am I going wrong?

I know that by setting "resourceBase" to "." the address "http://localhost:8089" will act as an interface to the location "~/Projects/Java/web-app/out/" where I can see a listing of all the JAR files, including the "web-app.jar", upon clicking on which I am offered to download it.

I have seen the following questions, and the answers do not apply:

  1. Embedded jetty application not working from jar: I get NullPointerException since Start.class.getProtectionDomain().getCodeSource() resolves to null.
  2. Embedded Jetty WebAppContext FilePermission issue: which not only isn't answered, but the situation clearly does not apply, as I do not have permission issues (the fact that I can get a file listing should prove that).
  3. embedding jetty server problems: also unanswered, also not applicable as I don't have any dependency problems (as pointed out previously in my comments above).

I think that I should somehow enable Jetty to access the /webapp folder, which is located under my src/main/resources/ directory and is bundled into my web application. Should I be forsaking a bundled web application and deploy the exploded context path to somewhere accessible by Jetty instead (this is not desirable at all as it poses a multitude of issues for me and my clients).

解决方案

I'm not sure, if the WebAppContext of Jetty can be used with PathMatchingResourcePatternResolver!

In one of my projects I solved this problem by writing my own javax.servlet.Filter, which loads the requested resources by Class#getResourceAsStream. Class#getResourceAsStream reads resources from inside a jars as well as inside a resource path (e.g. maven).

Hope this tip is helpful for you, cheers Thilo

这篇关于为 JAR 文件启动嵌入式码头服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆