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

时间:2008-10-08 18:57:28

标签: java spring jetty

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

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

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

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

10 个答案:

答案 0 :(得分:18)

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

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

答案 1 :(得分: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();

答案 2 :(得分:10)

虽然这是一个老问题,但我发现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支持(但对于简单的情况,它不应该是调试目的的问题)。

答案 3 :(得分:7)

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上提供静态文件,您可以编辑它们。

答案 4 :(得分:5)

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

答案 5 :(得分: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的深处。但是,如上所述为属性名称添加前缀,则首选此值。

答案 6 :(得分:4)

我也有这个问题。

我不想创建任何其他类并搞乱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添加一个属性,该属性将禁用静态资源锁定。

玩得开心:)

答案 7 :(得分:0)

使用嵌入式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。

答案 8 :(得分:-1)

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

答案 9 :(得分:-16)

可能是浏览器坚持使用它。

内部I.E:工具|互联网选项|临时互联网文件&gt;设置,单击单选按钮“每次访问页面”。按OK。

在此之前,请删除所有临时互联网文件。