我正在尝试使用 Jersey & Google Guice 3.0 将 2 个不同的 URL 模式映射到同一个 servlet,并将这些 URL 模式中的每一个应用于我项目中的不同包。
为了清楚起见,我正在粘贴下面的部分代码,我也会解释。
web.xml
<listener>
<listener-class>com.abc.web.listeners.GuiceContextListener</listener-class>
</listener>
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
GuiceContextListener
public final class GuiceContextListener extends GuiceServletContextListener {
...
private JerseyServletModule getJerseyServletModule() {
JerseyServletModule jerseyModule = new JerseyServletModule() {
@Override
protected void configureServlets() {
filter("/*").through(WebServerStateFilter.class);
final Map<String, String> params = new HashMap<String, String>();
StringBuilder sb = new StringBuilder();
sb.append("com.abc.web.stats.services");
params.put(PackagesResourceConfig.PROPERTY_PACKAGES, sb.toString());
serve("/api/v1/*").with(GuiceContainer.class, params);
final Map<String, String> params1 = new HashMap<String, String>();
StringBuilder sb1 = new StringBuilder();
sb1.append("com.abc.web.stats.otherservices");
params1.put(PackagesResourceConfig.PROPERTY_PACKAGES, sb1.toString());
serve("/api/*").with(GuiceContainer.class, params1);
}
}
}
...
}
所以基本上我想要:
我使用了上面的代码,但它似乎不起作用,似乎只考虑了第一个“服务”调用,所以在这种情况下,只提供匹配“/api/v1/*”的 URL。 我不想在我的服务中硬编码“v1”,因为将来版本可能会更改(到“v2”)。
有人能帮帮我吗?
谢谢, 保罗
也许您当前的端点应该重构,但无论如何您的代码看起来比需要的要复杂一些。就我而言,它是这样工作的。
...
String packages = "com.abc.web.stats.services;com.abc.web.stats.otherservices";
params.put(PackagesResourceConfig.PROPERTY_PACKAGES, packages);
serve("/api/v1/*").with(GuiceContainer.class, params);
serve("/api/*").with(GuiceContainer.class, params);
...
Jersey 可以扫描多个包裹,列表由 ;
分隔也许您应该更改您的“api/*”端点,但我不确定 Jersey 在这种情况下将如何工作。我敢打赌,这段代码可以正常工作。
我遇到了同样的问题。我认为默认情况下,服务函数中指定的 GuiceContainer 将被创建为单例,因此,即使你有不同的参数,它仍然会在相同的路径下服务。
为了解决这个问题,我不得不创建一个不同的 GuiceContainer。但是,创建 GuiceContainer 需要一个 Injector 作为参数,这在 configureServlets 函数中可能没有。因此,提供者用于在需要时注入 GuiceContainer。使用 Guice 密钥,因此我们确保创建它的不同实例。
public final class GuiceContextListener extends GuiceServletContextListener {
private JerseyServletModule getJerseyServletModule() {
JerseyServletModule jerseyModule = new JerseyServletModule() {
@Override
protected void configureServlets() {
filter("/*").through(WebServerStateFilter.class);
final Map<String, String> params1 = new HashMap<String, String>();
StringBuilder sb = new StringBuilder();
sb.append("com.abc.web.stats.services");
params.put(PackagesResourceConfig.PROPERTY_PACKAGES, sb.toString());
bind(GuiceContainer.class)
.annotatedWith(Names.named("path1"))
.toProvider(GuiceContainerProvider.class).in(Scopes.SINGLETON);
serve("/api/*").with(Key.get(GuiceContainer.class, Names.named("path1")), params1);
final Map<String, String> params2 = new HashMap<String, String>();
StringBuilder sb2 = new StringBuilder();
sb2.append("com.abc.web.stats.otherservices");
params2.put(PackagesResourceConfig.PROPERTY_PACKAGES, sb2.toString());
bind(GuiceContainer.class)
.annotatedWith(Names.named("path2"))
.toProvider(GuiceContainerProvider.class).in(Scopes.SINGLETON);
serve("/api/*").with(Key.get(GuiceContainer.class, Names.named("path2")), params2);
}
}
}
...
private GuiceContainerProvider implements Provider<GuiceContainer> {
@Inject
private Injector injector;
@Override
public GuiceContainer get() {
return new GuiceContainer(this.injector);
}
}
}
不确定这是否是最佳实践,但它帮助我解决了这个问题。