Как заставить Jetty динамически загружать "статические" страницы
Я создаю веб-приложения Java, и я ненавижу традиционный цикл "code-compile-deploy-test". Я хочу ввести одно крошечное изменение, а затем увидеть результат МГНОВЕННО, без необходимости компилирования и развертывания.
К счастью, Jetty отлично подходит для этого. Это чистый веб-сервер Java. Он поставляется с действительно приятным maven plugin, который позволяет вам запускать Jetty прямо из вашего дерева сборки - не нужно упаковывать военный файл или развертывать. У него даже есть параметр scanInterval: поместите это в ненулевое значение, и он будет смотреть ваши файлы java и различные файлы конфигурации для изменений и автоматически повторно развертывать через несколько секунд после внесения изменений.
Есть только одна вещь, которая удерживает меня от нирваны. У меня есть javascript и css файлы в моем каталоге src/main/webapp, которые просто обслуживаются Jetty. Я хотел бы иметь возможность редактировать их и появляться при обновлении страницы в браузере. К сожалению, Jetty держит эти файлы открытыми, поэтому я не могу (в Windows) изменять их во время работы.
Кто-нибудь знает, как заставить Jetty отпустить эти файлы, чтобы я мог их редактировать, а затем обслуживать отредактированные файлы для последующих запросов?
Ответы
Ответ 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 > Настройки, нажмите кнопку "Все посещения страницы". нажмите ОК.
Прежде чем вы это сделаете, удалите все временные интернет файлы.