Подтвердить что ты не робот

Как заставить Jetty динамически загружать "статические" страницы

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

В то время как один из приведенных выше ответов точно подходит для настройки причала через 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();

Ответ 3

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

            <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 (но это не должно быть проблемой для debug puropse для простых случаев).

Ответ 4

Вы также можете установить useFileMappedBuffer из web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<context-param>
    <param-name>org.eclipse.jetty.servlet.Default.useFileMappedBuffer</param-name>
    <param-value>false</param-value>
</context-param>

<context-param>
    <param-name>org.mortbay.jetty.servlet.Default.useFileMappedBuffer</param-name>
    <param-value>false</param-value>
</context-param>


</web-app>

Ответ 5

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

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

Ответ 6

Настройка false для использованияFileMappedBuffer в webdefault.xml сделала НЕ для меня (Jetty 8.1.10.v20130312). К счастью, настройка maxCachedFiles на 0 (также в webdefault.xml) сделала трюк.

Ответ 7

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

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

Удачи:)

Ответ 8

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

Ответ 9

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

Вместо этого я посмотрел, где сконфигурировано создание буфера, и обнаружил, что могу подклассифицировать SelectChannelConnector, чтобы получить преимущества Continuation, но без блокировки файлов в окнах. Если вы просто используете 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 одним из решений является редактирование статического содержимого в целевом каталоге вместо исходного файла.

Ответ 11

Вероятно, браузер поддерживает это.

внутри I.E: Инструменты | Параметры Интернета | Временные файлы Интернетa > Настройки, нажмите кнопку "Все посещения страницы". нажмите ОК.

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