OSGi环境下Pax Web 8+Jetty 9中WAB与Servlet路径冲突咨询
解决方案:Pax Web 8中WAB上下文与Servlet路径冲突问题
方案一:将WAB合并到默认上下文
Pax Web 8提供了系统配置项,可以强制让带有Web-ContextPath的WAB不创建独立上下文,而是将其资源、Servlet等注册到默认上下文的对应路径下。只需添加以下系统属性:
org.ops4j.pax.web.wab.context.merge=true
该配置会让所有WAB的内容合并到默认上下文,你的全局Servlet和WAB的资源将共享同一上下文,路径匹配会按照Servlet映射规则正常执行,不会出现上下文抢占的情况。无需修改外部依赖,也不用将你的Servlet注册到外部上下文。
方案二:自定义路径匹配策略,让Servlet优先匹配
如果不想合并上下文,可以通过自定义PathMatchingStrategy接口调整匹配优先级,让全局Servlet先被匹配:
- 实现
PathMatchingStrategy接口,在匹配逻辑中优先检查默认上下文的Servlet映射,再处理WAB的上下文:
import org.ops4j.pax.web.service.spi.PathMatchingStrategy; import org.osgi.service.http.HttpContext; import java.util.Map; public class ServletPrioritizedPathMatcher implements PathMatchingStrategy { private final PathMatchingStrategy defaultMatcher; public ServletPrioritizedPathMatcher(PathMatchingStrategy defaultMatcher) { this.defaultMatcher = defaultMatcher; } @Override public MatchResult match(String requestPath, Map<String, HttpContext> contexts) { // 先检查默认上下文(全局Servlet所在上下文) HttpContext defaultContext = contexts.get(""); if (defaultContext != null) { MatchResult servletMatch = checkDefaultContextServletMatch(requestPath, defaultContext); if (servletMatch != null) { return servletMatch; } } // 无匹配Servlet时,再使用默认逻辑匹配WAB上下文 return defaultMatcher.match(requestPath, contexts); } private MatchResult checkDefaultContextServletMatch(String path, HttpContext context) { // 实现具体的Servlet映射检查逻辑 // 例如遍历HttpService注册的Servlet,判断路径是否匹配 return null; // 示例返回,需根据实际情况实现 } }
- 将自定义策略注册为OSGi服务,指定属性让Pax Web使用该策略:
import org.osgi.framework.BundleContext; import java.util.Hashtable; public class Activator implements org.osgi.framework.BundleActivator { @Override public void start(BundleContext bundleContext) throws Exception { PathMatchingStrategy defaultMatcher = bundleContext.getService( bundleContext.getServiceReference(PathMatchingStrategy.class) ); bundleContext.registerService( PathMatchingStrategy.class, new ServletPrioritizedPathMatcher(defaultMatcher), new Hashtable<String, Object>() {{ put("org.ops4j.pax.web.path.matching.strategy", true); }} ); } }
方案三:修复DefaultServlet的资源加载问题
若你之前尝试使用DefaultServlet但资源加载失败,大概率是未正确配置资源根路径。可以显式指定资源来源:
import org.osgi.service.http.HttpService; import org.ops4j.pax.web.servlet.DefaultServlet; // 获取HttpService实例后注册 httpService.registerServlet( "/custom/route/*", new DefaultServlet(), new Hashtable<String, String>() {{ // 若资源在当前bundle的/webapp目录下 put("resourceBase", bundle.getEntry("/webapp").toExternalForm()); // 若资源在文件系统路径下 // put("resourceBase", "file:/path/to/your/resources"); }}, httpService.createDefaultHttpContext() );
该配置会让DefaultServlet优先匹配/custom/route/*路径,处理你的资源请求,同时不会被WAB的上下文抢占。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

