You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus实现类似WebLogic虚拟Web目录的资源覆盖功能

在Quarkus中实现WebLogic风格的虚拟Web目录覆盖逻辑

你的需求是让请求优先读取指定磁盘目录中的资源,不存在时回退到应用JAR内的资源,单独使用undertow-handlers.conf的resource指令无法实现回退,以下是两种可行方案:

方案1:通过Undertow处理器链快速实现

利用Undertow的chain指令按顺序尝试资源来源,先检查磁盘目录,再回退到类路径资源:

  1. 编辑src/main/resources/META-INF/undertow-handlers.conf,添加以下配置:
path-prefix('/some/path/to') -> chain(
    resource(location='/真实磁盘虚拟目录路径', allow-listing=true),
    resource(location='classpath:/META-INF/resources/some/path/to', allow-listing=true)
)
  • 第一个resource指向你要优先读取的磁盘文件夹,替换/真实磁盘虚拟目录路径为实际路径
  • 第二个resource对应JAR内的资源路径,Quarkus默认把src/main/resources下的内容打包到classpath:/META-INF/resources/目录下,按需调整路径
  1. 若需要动态配置磁盘目录路径,可在application.properties中定义变量:
quarkus.virtual-web-dir=/真实磁盘虚拟目录路径

然后在undertow-handlers.conf中引用变量:

path-prefix('/some/path/to') -> chain(
    resource(location='${quarkus.virtual-web-dir}', allow-listing=true),
    resource(location='classpath:/META-INF/resources/some/path/to', allow-listing=true)
)

方案2:自定义ResourceManager(复杂场景适配)

如果需要更灵活的逻辑(比如动态切换目录、权限校验等),可以自定义Undertow的资源管理器:

  1. 编写自定义资源管理器类,组合磁盘和类路径资源读取逻辑:
import io.undertow.server.handlers.resource.ClassPathResourceManager;
import io.undertow.server.handlers.resource.FileResourceManager;
import io.undertow.server.handlers.resource.Resource;
import io.undertow.server.handlers.resource.ResourceManager;
import io.undertow.server.handlers.resource.ResourceChangeListener;
import java.io.IOException;
import java.nio.file.Paths;

public class FallbackResourceManager implements ResourceManager {

    private final ResourceManager diskResourceManager;
    private final ResourceManager classPathResourceManager;

    public FallbackResourceManager(String virtualDirPath, String classPathBase) {
        this.diskResourceManager = new FileResourceManager(Paths.get(virtualDirPath).toFile(), 1024);
        this.classPathResourceManager = new ClassPathResourceManager(Thread.currentThread().getContextClassLoader(), classPathBase);
    }

    @Override
    public Resource getResource(String path) throws IOException {
        // 优先读取磁盘资源
        Resource diskResource = diskResourceManager.getResource(path);
        if (diskResource != null && diskResource.exists()) {
            return diskResource;
        }
        // 磁盘不存在则读取类路径资源
        return classPathResourceManager.getResource(path);
    }

    @Override
    public boolean isResourceChangeListenerSupported() {
        return diskResourceManager.isResourceChangeListenerSupported() 
                || classPathResourceManager.isResourceChangeListenerSupported();
    }

    @Override
    public void registerResourceChangeListener(ResourceChangeListener listener) {
        diskResourceManager.registerResourceChangeListener(listener);
        classPathResourceManager.registerResourceChangeListener(listener);
    }

    @Override
    public void removeResourceChangeListener(ResourceChangeListener listener) {
        diskResourceManager.removeResourceChangeListener(listener);
        classPathResourceManager.removeResourceChangeListener(listener);
    }

    @Override
    public void close() throws IOException {
        diskResourceManager.close();
        classPathResourceManager.close();
    }
}
  1. 编写Undertow配置类,注册自定义资源管理器:
import io.quarkus.undertow.runtime.UndertowDeploymentInfoCustomizer;
import io.undertow.servlet.api.DeploymentInfo;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.eclipse.microprofile.config.inject.ConfigProperty;

@ApplicationScoped
public class VirtualWebDirConfig implements UndertowDeploymentInfoCustomizer {

    @Inject
    @ConfigProperty(name = "quarkus.virtual-web-dir")
    String virtualDirPath;

    @Override
    public void customize(DeploymentInfo deploymentInfo) {
        // 为指定路径前缀绑定自定义资源管理器
        deploymentInfo.addResourceManager(
                new FallbackResourceManager(virtualDirPath, "/META-INF/resources/some/path/to"),
                "/some/path/to"
        );
    }
}
  1. 在application.properties中配置磁盘虚拟目录:
quarkus.virtual-web-dir=/真实磁盘虚拟目录路径

注意事项

  • 确保Quarkus进程对磁盘虚拟目录有读取权限
  • 类路径资源路径需与JAR内实际资源位置对应,比如src/main/resources/some/path/to下的文件对应/META-INF/resources/some/path/to
  • 测试时可先在磁盘目录放入目标文件,验证优先读取逻辑;删除磁盘文件后,确认请求会返回JAR内的资源

内容的提问来源于stack exchange,提问作者Noam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 18:03:30