如何让Jetty动态加载"静态"页面

mch*_*erm 28 java spring jetty

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

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

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

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

Ath*_*ena 18

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

故障排除Windows上的锁定文件(来自Jetty wiki)有说明.


kyb*_*kos 16

虽然上面的答案之一完全适合通过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();
Run Code Online (Sandbox Code Playgroud)

  • 如果在上下文中设置参数,则必须在键的前面添加"org.eclipse.jetty.servlet.Default.",因此这适用于我:webAppContext.setInitParameter("org.eclipse.jetty.servlet.Default. useFileMappedBuffer","false");. 适用于Jetty 8.1.4. (7认同)

FUD*_*FUD 10

虽然这是一个老问题,但我发现这篇文章非常有用,简而言之,只需将配置更改为

            <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>
Run Code Online (Sandbox Code Playgroud)

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


Jul*_*egg 7

Jetty 9.2文档提供了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();
Run Code Online (Sandbox Code Playgroud)

Jetty使用NIO(内存文件映射),因此锁定Windows操作系统上的文件.这是一个已知问题,可以找到servlet的许多变通方法.

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

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

resource_handler.setMinMemoryMappedContentLength(-1);
Run Code Online (Sandbox Code Playgroud)

注意:如写在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上提供静态文件,您可以编辑它们.

  • Jetty文档说,将"-1"传递给setMin..Length应该禁用内存映射(我个人无法以任何方式使其工作......) (2认同)

小智 5

在webdefault.xml设置假以useFileMappedBuffer根本不是为我工作(码头8.1.10.v20130312).幸运的是,将maxCachedFiles设置为0(也在webdefault.xml中)就可以了.


Yur*_*nko 5

我也有这个问题。

而且我不想创建任何额外的类并弄乱 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>
    
    Run Code Online (Sandbox Code Playgroud)
  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>
    
    Run Code Online (Sandbox Code Playgroud)

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

玩得开心 :)