Как заставить Jetty динамически загружать «статические» страницы - PullRequest
28 голосов
/ 08 октября 2008

Я создаю веб-приложения на Java и ненавижу традиционный цикл "code-compile-deploy-test". Я хочу ввести одно крошечное изменение, а затем увидеть результат МГНОВЕННО, без необходимости компилировать и развертывать.

К счастью, Причал отлично подходит для этого. Это чисто Java-веб-сервер. Он поставляется с действительно хорошим maven плагином , который позволяет запускать чтение Jetty непосредственно из дерева сборки - нет необходимости упаковывать файл war или развертывать. Он даже имеет параметр scanInterval: установите его в ненулевое значение, и он будет следить за изменениями в ваших java-файлах и различных конфигурационных файлах и автоматически повторно развертывать их через несколько секунд после внесения изменений.

Есть только одна вещь, которая удерживает меня от нирваны. У меня есть javascript и css файлы в моем каталоге src / main / webapp, которые просто обслуживаются Jetty. Я хотел бы иметь возможность редактировать эти и отображать изменения при обновлении страницы в браузере. К сожалению, Jetty держит эти файлы открытыми, поэтому я не могу (в Windows) изменить их во время работы.

Кто-нибудь знает, как заставить Jetty отпустить эти файлы, чтобы я мог их отредактировать, а затем подать отредактированные файлы для последующих запросов?

Ответы [ 10 ]

18 голосов
/ 09 октября 2008

Jetty использует отображенные в памяти файлы для буферизации статического содержимого, что вызывает блокировку файлов в Windows. Попробуйте установить для параметра UseFileMappedBuffer для DefaultServlet значение false.

Устранение неполадок Заблокированные файлы в Windows (из Jetty wiki) содержит инструкции.

16 голосов
/ 13 февраля 2011

Хотя один из приведенных выше ответов является совершенно правильным для настройки jetty с помощью xml, если вы хотите настроить эту опцию в коде (для встроенного сервера), ответ будет другим и не найден на этой странице.

Вы найдете несколько предложений в Интернете, включая

context.getInitParams (). Put ("useFileMappedBuffer", "false");

Или переопределение WebAppContext, или использование полного имени для параметра init. Ни одно из этих предложений не сработало для меня (используя Jetty 7.2.2). Частично проблема заключалась в том, что параметр useFileMappedBuffer должен быть установлен в сервлете, который WebAppContext использует для обслуживания статических файлов, а не в контексте.

В конце я сделал что-то подобное на простом 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();
10 голосов
/ 13 июня 2012

Хотя это старая проблема, но я нашел этот пост очень полезным, короче просто измените ваш конфиг на

            <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>

Это отключает поддержку NIO в Jetty (но это не должно быть проблемой для отладки puropse для простых случаев).

7 голосов
/ 21 мая 2015

Документация Jetty 9.2 дает пример Jetty Embedded для обслуживания статических файлов с использованием ResourceHandler вместо сервлета:

// 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 . Это известная проблема, и для сервлетов можно найти множество обходных путей.

Однако, поскольку в этом примере не используются сервлеты, связанные ответы, основанные на параметрах веб-приложения (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 И вы можете редактировать их.

5 голосов
/ 27 мая 2013

Установка false для useFileMappedBuffer в webdefault.xml сделала для меня НЕ (Jetty 8.1.10.v20130312). К счастью, установка maxCachedFiles на 0 (также в webdefault.xml) сделала свое дело.

4 голосов
/ 08 марта 2016

У меня тоже была эта проблема.

И я не хотел создавать дополнительные классы и возиться с 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>

Это решение добавит в ваш сервлет-контекст атрибут, который отключит статическую блокировку ресурсов.

Веселитесь:)

4 голосов
/ 01 сентября 2014

Аналогично ответу @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. Но при добавлении префикса имени свойства, как указано выше, это значение является предпочтительным.

0 голосов
/ 10 октября 2015

При использовании IntelliJ и Jetty 9 с ResourceHandler одним из решений является редактирование статического содержимого в целевом каталоге вместо исходного файла.

0 голосов
/ 26 апреля 2013

При использовании встроенного Jetty 8.1.10 параметр 'useFileMappedBuffer = false' не работает ни в одном режиме. Я прочитал код для DefaultServlet, и он читает свойство, но ни для чего не используется.

Вместо этого я посмотрел, где было настроено создание буфера, и обнаружил, что могу использовать подкласс SelectChannelConnector, чтобы получить преимущества продолжения, но без блокировки файлов в 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 
 * /103505/kak-zastavit-jetty-dinamicheski-zagruzhat-staticheskie-stranitsy
 * 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);
    }
}

Я проверил это на проблему блокировки, и она исправляет проблему. Я еще не проверял, что он работает с продолжениями.

0 голосов
/ 08 октября 2008

Вероятно, это браузер, который держит его.

внутри I.E: Инструменты | Настройки интернета | Временные интернет-файлы> Настройки, установите переключатель «Каждый визит на страницу». нажмите ОК.

Прежде чем сделать это, удалите все временные интернет-файлы.

...