【问题标题】:Modifying Static Resource within Jar修改 Jar 中的静态资源
【发布时间】:2018-04-27 15:03:44
【问题描述】:

我构建的 jar 中包含许多静态资源。它是一个码头服务器,静态资源是一个 index.html 和一些其他的 js/css 文件。我需要在运行时编辑 index.html,我想知道如何在启动服务器的 Bootstrap 文件中进行此操作,或者在运行启动脚本时使用 sed 或类似的命令行从命令行进行。

有什么最好的方法来解决这个问题吗?我更喜欢后一种解决方案,我可以通过 shell 命令完成。

谢谢!

【问题讨论】:

  • Vim 可以做到这一点。
  • 我查看了那个答案,但它并没有真正说明我的具体问题。
  • 还有@LutzHorn 我需要能够以编程方式执行此操作,而不是手动操作。
  • 如果你想在运行时动态改变内容,那么内容不应该在jar中,而是在本地文件系统上(或者你需要从jar中拷贝到本地文件系统中)使用和编辑)。一旦构建,jar 应该被认为是不可变的。

标签: java sed jar jetty


【解决方案1】:

这会有问题。

JAR 本身会改变。

运行时不会看到更改(因为 JAR 内容缓存在 Java 中)

需要重新启动二进制文件才能获取更改。

如果您有可以在运行时更改的内容,请将这些内容放在文件系统中的 jar 之外,或者为静态 jar 内容提供文件系统覆盖。

要在 JAR 之外提供内容,请参阅先前的答案...

Serving static files from alternate path in embedded 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
    }

}

这会设置一个带有 2 个条目的 ResourceCollection

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 2012-11-07
    • 1970-01-01
    • 2014-10-02
    相关资源
    最近更新 更多