28

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

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

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

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

4

10 回答 10

18

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

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

于 2008-10-09T02:13:56.730 回答
16

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

您会在网上找到许多建议,包括

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();
于 2011-02-13T17:37:01.500 回答
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>

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

于 2012-06-12T20:34:41.480 回答
7

Jetty 9.2 文档ResourceHandler提供了一个 Jetty Embedded 示例来使用 a而不是 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(内存中文件映射),从而锁定 Windows 操作系统上的文件。这是一个已知问题,可以为 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:. 但是,我对 value 有相同的行为Integer.MAX_VALUE

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

于 2015-05-21T20:45:29.580 回答
5

在 webdefault.xml 中将 false 设置为 useFileMappedBuffer对我不起作用(Jetty 8.1.10.v20130312)。幸运的是,将 maxCachedFiles 设置为 0(也在 webdefault.xml 中)起到了作用。

于 2013-05-27T14:40:55.970 回答
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>
    
  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 添加一个属性,该属性将禁用静态资源锁定。

玩得开心 :)

于 2016-03-08T09:02:22.633 回答
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 的深处。但是通过在属性名称前面加上上述前缀,这个值是首选的。

于 2014-09-01T15:14:50.527 回答
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 一起使用。

于 2013-04-26T11:30:28.167 回答
-1

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

于 2015-10-10T14:59:44.137 回答
-16

可能是浏览器在坚持它。

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

在此之前,请删除所有临时 Internet 文件。

于 2008-10-08T19:44:02.430 回答