Модификация статического ресурса в Jar - PullRequest
0 голосов
/ 27 апреля 2018

У меня есть несколько статических ресурсов, которые включены в сборку jar. Это джет-сервер, а статические ресурсы - это index.html и некоторые другие файлы js / css. Мне нужно отредактировать index.html во время выполнения, и мне интересно, как я могу это сделать, либо в моем файле Bootstrap, который запускает сервер, либо из командной строки, используя sed или что-то подобное, когда запускается скрипт запуска.

Есть идеи, как лучше всего это сделать? Я бы предпочел последнее решение, которое я могу сделать с помощью команды оболочки.

спасибо!

1 Ответ

0 голосов
/ 27 апреля 2018

Это было бы проблематично.

Сам JAR изменится.

Среда выполнения не увидит изменения (так как содержимое JAR кэшируется в Java)

Двоичный файл должен быть перезапущен для получения изменений.

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

Информацию о подаче контента за пределы JAR см. В предыдущем ответе ...

Обслуживание статических файлов по альтернативному пути во встроенном Jetty

Чтобы иметь альтернативные пути для переопределения, просто используйте org.eclipse.jetty.util.resource.ResourceCollection для вашего context.setBaseResource()

Вот так ...

package jetty;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.resource.PathResource;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;

public class ResourceCollectionDefaultServlet
{
    public static void main(String[] args) throws Exception
    {
        Server server = new Server();
        ServerConnector connector = new ServerConnector(server);
        connector.setPort(8080);
        server.addConnector(connector);

        // Jar Resource
        String resourceExample = "/webroot/index.html";
        URL jarUrl = server.getClass().getResource(resourceExample);
        if(jarUrl == null)
        {
            throw new FileNotFoundException("Unable to find JAR Resource: " + resourceExample);
        }
        URI jarUriBase = jarUrl.toURI().resolve("./");
        Resource jarResource = Resource.newResource(jarUriBase);

        // FileSystem Resource
        // Example here uses Path: $TEMP/resource/
        // You can pick a location on disk of your own choice (use a System property if you want)
        Path fsPath = new File(System.getProperty("java.io.tmpdir")).toPath().resolve("resource");
        if(!Files.exists(fsPath))
            Files.createDirectory(fsPath);
        Resource fsResource = new PathResource(fsPath);

        // Resource Collection
        ResourceCollection resourceCollection = new ResourceCollection(
                fsResource, // check FileSystem first
                jarResource // fall back to jar for all content not on filesystem
        );

        System.out.println("Resource Collection: " + resourceCollection);

        ServletContextHandler context = new ServletContextHandler();
        context.setContextPath("/");
        context.setBaseResource(resourceCollection);
        server.setHandler(context);
        context.setWelcomeFiles(new String[] { "index.html" });

        // TODO: Your servlets and filters here

        // Lastly, the default servlet for root content (always needed, to satisfy servlet spec)
        // It is important that this is last.
        ServletHolder holderPwd = new ServletHolder("default", DefaultServlet.class);
        holderPwd.setInitParameter("dirAllowed","true");
        context.addServlet(holderPwd,"/");

        server.setDumpAfterStart(true);
        server.start();
        server.join(); // wait on server to stop
    }

}

Это устанавливает ResourceCollection с 2 записями.

  1. Сначала проверьте файловую систему $TEMP/resource/<requestedResource>
  2. Проверьте файл JAR $JARBASEURI/<requestedResource>

Вывод выше говорит вам, как это работает.

В серверном дампе содержатся сведения о том, с чем работает база ресурсов ServletContextHandler.

2018-04-27 10:25:02.314:INFO::main: Logging initialized @338ms to org.eclipse.jetty.util.log.StdErrLog
Resource Collection: [file:///C:/Users/joakim/AppData/Local/Temp/resource/, jar:file:///C:/code/jetty-examples/target/project.jar!/webroot/]
2018-04-27 10:25:02.422:INFO:oejs.Server:main: jetty-9.4.9.v20180320; built: 2018-03-20T07:21:10-05:00; git: 1f8159b1e4a42d3f79997021ea1609f2fbac6de5; jvm 9.0.4+11
2018-04-27 10:25:02.477:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@13c10b87{/,[file:///C:/Users/joakim/AppData/Local/Temp/resource/, jar:file:///C:/code/jetty-examples/target/project.jar!/webroot/],AVAILABLE}
2018-04-27 10:25:02.609:INFO:oejs.AbstractConnector:main: Started ServerConnector@c267ef4{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
org.eclipse.jetty.server.Server@473b46c3[9.4.9.v20180320] - STARTING
...(snip)...
 += o.e.j.s.ServletContextHandler@13c10b87{/,[file:///C:/Users/joakim/AppData/Local/Temp/resource/, jar:file:///C:/code/jetty-examples/target/project.jar!/webroot/],AVAILABLE} - STARTED
 |   += org.eclipse.jetty.servlet.ServletHandler@1aa7ecca - STARTED
 |   |   += default@5c13d641==org.eclipse.jetty.servlet.DefaultServlet,jsp=null,order=-1,inst=false - STARTED
 |   |   |   +- dirAllowed=true
 |   |   +- [/]=>default
 |   +> No ClassLoader
 |   +> Handler attributes o.e.j.s.ServletContextHandler@13c10b87{/,[file:///C:/Users/joakim/AppData/Local/Temp/resource/, jar:file:///C:/code/jetty-examples/target/project.jar!/webroot/],AVAILABLE}
 |   |   +- org.eclipse.jetty.server.Executor=QueuedThreadPool[qtp1018298342]@3cb1ffe6{STARTED,8<=8<=200,i=3,q=0}
 |   +> Context attributes o.e.j.s.ServletContextHandler@13c10b87{/,[file:///C:/Users/joakim/AppData/Local/Temp/resource/, jar:file:///C:/code/jetty-examples/target/project.jar!/webroot/],AVAILABLE}
 |   |   +- org.eclipse.jetty.util.DecoratedObjectFactory=org.eclipse.jetty.util.DecoratedObjectFactory[decorators=1]
 |   +> Initparams o.e.j.s.ServletContextHandler@13c10b87{/,[file:///C:/Users/joakim/AppData/Local/Temp/resource/, jar:file:///C:/code/jetty-examples/target/project.jar!/webroot/],AVAILABLE}
2018-04-27 10:25:02.651:INFO:oejs.Server:main: Started @682ms

В этом исполнении я вижу, что ResourceCollection имеет 2 базы.

  • База файловой системы: file:///C:/Users/joakim/AppData/Local/Temp/resource/
  • База Jar: jar:file:///C:/code/jetty-examples/target/project.jar!/webroot/

Так что, если приходит запрос, скажем, https://myapp.com/js/config.js, происходит следующее ...

  1. Существует ли file:///C:/Users/joakim/AppData/Local/Temp/resource/js/config.js? Если так, подайте это.
  2. jar:file:///C:/code/jetty-examples/target/project.jar!/webroot/js/config.js существует? Если так, подайте это.
  3. Отчет 404 не найден
...