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

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

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

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

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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
28
0
22 076
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

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

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

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

Я думаю, он говорит о том, что окна / пристань блокируют файлы, чтобы их нельзя было редактировать.

Draemon 09.10.2008 06:10

Это совершенно неверный ответ. Я бы проголосовал против, но не могу.

Matt 11.10.2010 17:18
Ответ принят как подходящий

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

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

Спасибо! это именно то, что я хотел. Я бы отметил это как «принятый» ответ, если бы stackoverflow разрешил это (я не уверен, почему этого не произойдет).

mcherm 09.10.2008 18:11

Я попробовал эти инструкции, и после небольшого возни (в основном выясняя, как указать в моем POM, что я использую настроенный файл webdefault.xml), у меня все заработало. Еще раз спасибо.

mcherm 09.10.2008 19:20

Этот ответ больше не работает для Jetty 8. Я тестировал в 8.1.9 и 8.1.10, хотя он работал в Jetty 7. Я опубликую еще один ответ, чтобы избежать проблемы в Jetty 8.1.10, и, вероятно, другие версии тоже.

David Roussel 26.04.2013 15:24

Не использовать nio, например @FUD, проще.

ruseel 18.12.2013 06:26

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

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

context.getInitParams (). put ("useFileMappedBuffer", "ложь");

Или переопределив WebAppContext, или используя полное имя для параметра инициализации. Ни одно из этих предложений не помогло мне (с использованием 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();

Именно то, что я ищу! У вас есть ссылка на полный пример?

h3xStream 31.05.2011 06:12

Не пугайтесь, я нашел это методом проб и ошибок и не нашел никого, кто бы объяснил, как это сделать. У меня есть полный пример, который я создал сам (который выполняет jsps, регистрирует запросы и настраивает некоторые типы mimety и т. д.), Но если вы хотите немного больше, я добавлю немного больше к приведенному выше примеру.

kybernetikos 03.06.2011 19:49

Новый пример идеален. У меня было нечто подобное. Если я не могу заставить его работать, я задам новый вопрос.

h3xStream 03.06.2011 21:33

Если вы устанавливаете параметр в контексте, вам нужно добавить к ключу префикс org.eclipse.jetty.servlet.Default., Так что у меня это работает: webAppContext.setInitParameter («org.eclipse.jetty.servlet.De‌ fault.useFileMappedB‌ uffer "," false ") ;. У меня работает с Jetty 8.1.4.

Trygve Laugstøl 26.09.2012 12:11

Когда я впервые написал этот код, я увидел в Интернете множество ссылок на параметры с префиксом и параметры без префикса. Я попробовал оба, и смог заставить работать только тот код, который я показываю, но, по-видимому, он изменился между 7.2.2 и 8.1.4. Спасибо за внимание.

kybernetikos 26.09.2012 17:58

Это то, что я писал в то время, когда искал это: github.com/kybernetikos/QuickJetty

kybernetikos 06.12.2012 13:19

это работает, но заставляет вас добавлять ненужный непроизводственный код.

Yurii Bondarenko 08.03.2016 12:06

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

            <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 отладки).

Это просто. Я не хочу возиться с настройкой useFileMappedB‌uffer и webdefault.xml. Прекрасно работает.

ruseel 18.12.2013 06:23

Согласно GrepCode, класс org.eclipse.jetty.server.bio.SocketConnector существует только для Jetty 7 и Jetty 8.

Julien Kronegg 22.05.2015 00:13

При использовании встроенной 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 
 * 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.

По данным GrepCode, класс org.eclipse.jetty.server.nio.SelectChannelConnector существует только для Jetty 7 и Jetty 8.

Julien Kronegg 22.05.2015 00:09

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

Спасибо приятель! Этот метод у меня тоже сработал. Я использую Jetty Embedded 8.1.9 WebAppContext root = new WebAppContext (); root.setInitParameter ("org.eclipse.jetty.servlet.Default.max‌ CachedFiles", "0"); с useFileMappedBuffer ничего не произошло

ianaz 12.09.2013 00:17

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

Документация 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, и вы можете их редактировать.

Это единственное решение, которое отлично сработало для меня с Embedded Jetty 9 с использованием различных обработчиков, таких как resource_handler с gzip.

Ruwen 29.07.2015 14:07

В документации Jetty говорится, что передача «-1» в setMin..Length должна отключить отображение памяти (лично мне не удалось заставить его работать в любом случае ...)

nimrodm 13.08.2015 16:29

@nimrodm: вы правы, поэтому я улучшил ответ.

Julien Kronegg 15.08.2015 19:27

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

Проблема никак не связана с IDE.

Ravshan Samandarov 03.01.2016 05:20

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

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

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

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

Спасибо! Отлично работает с плагином jetty-maven-plugin 9.3.10.v20160621!

Dave Moten 07.07.2016 09:26

Другие вопросы по теме