首页 文章

如何让Jetty动态加载“静态”页面

提问于
浏览
28

我正在构建Java Web应用程序,我讨厌传统的“代码 - 编译 - 部署 - 测试”循环 . 我想键入一个微小的更改,然后立即查看结果,而无需编译和部署 .

幸运的是,Jetty非常适合这一点 . 它是一个纯java的Web服务器 . 它带有一个非常好的maven plugin,它允许您直接从构建树启动Jetty读取 - 无需打包war文件或部署 . 它甚至还有一个scanInterval设置:将它设置为非零值,它将监视您的java文件和各种配置文件以进行更改,并在您进行更改后自动重新部署几秒钟 .

只有一件事让我远离天堂 . 我的src / main / webapp目录中有javascript和css文件,这些文件只能由Jetty提供 . 我希望能够编辑这些并在浏览器中刷新页面时显示更改 . 不幸的是,Jetty将这些文件保持打开状态,因此我无法(在Windows上)在运行时修改它们 .

有谁知道如何让Jetty放开这些文件,以便我可以编辑它们,然后为后续请求提供编辑后的文件?

10 回答

  • -16

    Jetty使用内存映射文件来缓冲静态内容,这会导致Windows中的文件锁定 . 尝试将DefaultServlet的useFileMappedBuffer设置为false .

    Troubleshooting Locked files on Windows (from the Jetty wiki)有说明 .

  • 4

    虽然上面的答案之一完全适合通过xml配置jetty,但如果要在代码中配置此选项(对于嵌入式服务器),答案是不同的,并且在该页面上找不到 .

    你会在网上找到一些建议,包括

    context.getInitParams() . put(“useFileMappedBuffer”,“false”);

    或者重写WebAppContext,或者使用init参数的完全限定名称 . 这些建议都不适用于我(使用Jetty 7.2.2) . 部分问题是需要在WebAppContext用于提供静态文件而不是上下文的servlet上设置useFileMappedBuffer选项 .

    最后,我在一个简单的ServletContextHandler上做了类似的事情

    // Startup stuff
    final Server server = new Server(port);
    ServletContextHandler handler = new ServletContextHandler();
    handler.setResourceBase(path);
    
    SessionManager sm = new HashSessionManager();
    SessionHandler sh = new SessionHandler(sm);
    handler.setSessionHandler(sh);
    
    DefaultServlet defaultServlet = new DefaultServlet();
    ServletHolder holder = new ServletHolder(defaultServlet);
    holder.setInitParameter("useFileMappedBuffer", "false");
    handler.addServlet(holder, "/");
    
    server.setHandler(handler);
    server.start();
    server.join();
    
  • 5

    虽然这是一个老问题,但我发现this帖子非常有用,简而言之就是将配置更改为

    <plugin>
                    <groupId>org.mortbay.jetty</groupId>
                    <artifactId>jetty-maven-plugin</artifactId>
                    <configuration>
                    <connectors>
                        <connector implementation="org.eclipse.jetty.server.bio.SocketConnector">
                            <port>8080</port>
                        </connector>
                    </connectors>
                    </configuration>
                </plugin>
    

    这会禁用Jetty中的NIO支持(但对于简单的情况,它不应该是调试问题的问题) .

  • 0

    Jetty 9.2 documentation给出了Jetty Embedded示例,使用 ResourceHandler 而不是servlet来提供静态文件:

    // Create a basic Jetty server object that will listen on port 8080.  Note that if you set this to port 0
    // then a randomly available port will be assigned that you can either look in the logs for the port,
    // or programmatically obtain it for use in test cases.
    Server server = new Server(8080);
    
    // Create the ResourceHandler. It is the object that will actually handle the request for a given file. It is
    // a Jetty Handler object so it is suitable for chaining with other handlers as you will see in other examples.
    ResourceHandler resource_handler = new ResourceHandler();
    // Configure the ResourceHandler. Setting the resource base indicates where the files should be served out of.
    // In this example it is the current directory but it can be configured to anything that the jvm has access to.
    resource_handler.setDirectoriesListed(true);
    resource_handler.setWelcomeFiles(new String[]{ "index.html" });
    resource_handler.setResourceBase(".");
    
    // Add the ResourceHandler to the server.
    HandlerList handlers = new HandlerList();
    handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });
    server.setHandler(handlers);
    
    // Start things up! By using the server.join() the server thread will join with the current thread.
    // See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details.
    server.start();
    server.join();
    

    Jetty使用NIO(内存中文件映射),因此locks files on Windows operating systems . 这是一个已知问题,可以找到servlet的许多变通方法 .

    但是,由于此示例不依赖于servlet,因此基于webapp参数(useFileMappedBuffer,maxCachedFiles)的相关答案不起作用 .

    为了防止内存中文件映射,您需要添加以下配置行:

    resource_handler.setMinMemoryMappedContentLength(-1);
    

    注意:如在Javadoc中所写(并且由nimrodm注意到): the minimum size in bytes of a file resource that will be served using a memory mapped buffer, or -1 for no memory mapped buffers . 然而,我的值与 Integer.MAX_VALUE 具有相同的行为 .

    设置此参数后,您的Jetty可以在Windows上提供静态文件,您可以编辑它们 .

  • -1

    在webdefault.xml中将false设置为useFileMappedBuffer确实 NOT 为我工作(Jetty 8.1.10.v20130312) . 幸运的是,将maxCachedFiles设置为0(也在webdefault.xml中)就可以了 .

  • 4

    与@kybernetikos答案类似,但无需重新创建DefaultServlet:

    // Startup stuff
    final Server server = new Server(port);
    WebAppContext webAppContext = new WebAppContext(path, "/")
    webAppContext.setInitParam(
            "org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false");
    
    server.setHandler(webAppContext);
    server.start();
    server.join();
    

    DefaultServlet将查找它自己的useFileMappedBuffer副本,它似乎设置在Jetty的深处 . 但是,如上所述为属性名称添加前缀,则首选此值 .

  • 16

    我也有这个问题 .

    And I didn't want to create any additional classes and messing with web.xml

    所以这是你可以做的:

    假设您的项目是基于maven并且(假设)称为“my-web-app”

    1)创建一个文件my-web-app / jetty / jetty-config.xml

    2)把这些东西放进去:

    <?xml version="1.0" encoding="UTF-8"?>
    <Configure class="org.eclipse.jetty.webapp.WebAppContext">
      <Call name="setInitParameter">
        <Arg>org.eclipse.jetty.servlet.Default.useFileMappedBuffer</Arg>
        <Arg>false</Arg>
      </Call>
    </Configure>
    

    3)这是你的码头配置:

    <plugin>
        <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <configuration>
                <httpConnector>
                    <host>localhost</host>
                    <port>8801</port>
                </httpConnector>
                <webApp>
                    <contextPath>/${project.artifactId}</contextPath>
                </webApp>
            <contextXml>${project.basedir}/jetty/jetty-config.xml</contextXml>
        </configuration>
    </plugin>
    

    此解决方案将向您的servlet-context添加一个属性,该属性将禁用静态资源锁定 .

    玩得开心 :)

  • 18

    使用嵌入式Jetty 8.1.10时,'useFileMappedBuffer=false'设置不适用于任何模式 . 我读了 DefaultServlet 的代码,它读取了属性但它没有用于任何东西 .

    相反,我查看了缓冲区创建的配置位置,发现我可以继承 SelectChannelConnector 来获得Continuation的好处,但是没有锁定Windows上的文件 . 如果您只是使用 org.mortbay.jetty.bio.SocketConnector ,那么您将无法获得持续支持 .

    这是我的例子:

    import org.eclipse.jetty.io.Buffers.Type;
    import org.eclipse.jetty.server.nio.SelectChannelConnector;
    
    /**
     * A Connector that has the advantages NIO, but doesn't lock files in Windows by
     * avoiding memory mapped buffers.
     * <p> 
     * It used to be that you could avoid this problem by setting "useFileMappedBuffer" as described in 
     * http://stackoverflow.com/questions/184312/how-to-make-jetty-dynamically-load-static-pages
     * However that approach doesn't seem to work in newer versions of jetty.
     * 
     * @author David Roussel
     * 
     */
    public class SelectChannelConnectorNonLocking extends SelectChannelConnector {
    
        public SelectChannelConnectorNonLocking() {
            super();
    
            // Override AbstractNIOConnector and use all indirect buffers
            _buffers.setRequestBufferType(Type.INDIRECT);
            _buffers.setRequestHeaderType(Type.INDIRECT);
            _buffers.setResponseBufferType(Type.INDIRECT);
            _buffers.setResponseHeaderType(Type.INDIRECT);
        }
    }
    

    我已经针对锁定问题对此进行了测试,并解决了这个问题 . 我还没有测试它是否适用于Continuations .

  • 10

    将IntelliJ和Jetty 9与ResourceHandler一起使用时,其中一个解决方案是编辑目标目录中的静态内容,而不是源文件 .

  • 7

    它可能是持有它的浏览器 .

    在I.E:工具|互联网选项| Internet临时文件>设置,单击单选按钮“每次访问该页面” . 按确定 .

    在你做之前那,删除所有临时的互联网文件 .

相关问题