【问题标题】:Jersey custom Context injectionJersey 自定义上下文注入
【发布时间】:2015-08-20 13:43:30
【问题描述】:

我尝试像在this answer 中那样实现自定义上下文注入:

@Provider
public class DaoContextProvider extends SingletonTypeInjectableProvider<Context,Bar> {

    public DaoContextProvider() {
        super(Bar.class, new Bar("haha"));
    }

}

这是我的控制器类,我想注入我的上下文:

@Path("foo")
public class Foo {

    @Context
    private Bar message;

    @GET
    public String index() {
        return String.format("%s", message );
    }

}

但响应 message 为空。

我尝试按照建议将上下文提供程序添加到单例中:

@javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {

    public ApplicationConfig() {
        getSingletons().add(new DaoContextProvider());
    }
//...

然后我的工件甚至没有部署,并给我提供了这个错误:

Artifact server:war exploded: java.io.IOException: com.sun.enterprise.admin.remote.RemoteFailureException: Error occurred during deployment: Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.apache.catalina.LifecycleException: java.lang.UnsupportedOperationException. Please see server.log for more details.

我会提供 server.log,如异常中所述,但我不知道在哪里可以找到此日志。

【问题讨论】:

  • Foo资源类目前是如何注册的?在同一个ApplicationConfig类中,还是通过web.xml包扫描属性?
  • @peeskillet 在应用程序配置中

标签: java jakarta-ee dependency-injection jersey jax-rs


【解决方案1】:

getSingletons() 返回的集合是不可修改的。相反,我们需要重写方法

@Override
public Set<Object> getSingletons() {
    Set<Object> singletons = new HashSet<>();
    singletons.add(new new DaoContextProvider());
    return singletons;
}

请注意,与 Jersey 特定的方式相比,直接的 Application 子类在功能上是有限的。在泽西岛,首选方法是使用ResourceConfig 子类(实际上是Application 的子类)。例如(您可以使用PackagesResourceConfig 来扫描包)。

@ApplicationPath("/webresources")
public class AppConfig extends PackagesResourceConfig {
    
    public AppConfig() {
        // scans the package and sub-packages.
        super("package.where.all.your.resource.and.providers.are");
        getProperties().put("some properites", "to set");
        getContainerRequestFilters().add(new SomeFiltersToRegister());
        getProviderSingletons().add(new SomeProvidersToAdd());
        // see the ResourceConfig API for more methods.
    }
}

这将扫描@Path@Provider 带注释的类,因此我们不需要显式注册所有内容。虽然有些提供者需要明确注册。不过,您的特定提供商不需要注册。它是我在包裹扫描中找到的。


更新

好的,既然您说您使用的是 Glassfish 4.1,那么您首先应该了解的是 Glassfish 4 使用的是 Jersey 2.x。因此,您拥有的任何 Jersey 1.x 依赖项/jar 都应该摆脱它们。仅使用 Jersey 2.x 依赖项,并确保它们只是编译时依赖项,因为您不希望有冲突的版本导致 Glassfish 已经有了它们的版本。

这意味着您当前的DaoContextProvider 实现将不起作用。 SingletonTypeInjectableProvider 是 Jersey 1.x 类,Jersey 2.x 运行时会忽略它。

在 Jersey 2.x 中,有几种方法可以配置可注入对象。一种方法是为对象创建一个Factory。例如。

public class DaoContextProvider implements Factory<Bar> {

    @Override
    public Bar provide() {
        return new Bar("boo hoo!");
    }

    @Override
    public void dispose(Bar bar) {}
}

在 Jersey 2.x 中,ResourceConfig 的 API 发生了变化,我们可以直接对其进行扩展。例如

@ApplicationPath("/webresources")
public class AppConfig extends ResourceConfig {

    public AppConfig() {
        
        packages("com.stackoverflow.jersey");
        
        register(new AbstractBinder(){
            @Override
            protected void configure() {
                bindFactory(DaoContextProvider.class)
                        .to(Bar.class)
                        .in(RequestScoped.class);
            }
        });
    }
}

您可以看到AbstractBinder。这就是我们使用Bar 类注册DaoContextProvider 的方式。所以现在可以将Bar 注入到您的资源类中。

您需要将其他所有内容引入其中的唯一 Maven 依赖项是

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>2.19</version>
    <scope>provided</scope>
</dependency> 

注意提供的范围,以免它被构建为战争。如果您不使用 Maven,请获取 Jersey JAX-RS 2.0 RI bundle 中的所有 jar。请记住,您应该使它们仅编译时依赖项。他们不应该融入战争。

另请参阅:

【讨论】:

  • 我的 PackagesResourceConfig 类没有 getSingletonProviders 方法,而是有一个名称相似的方法 getProviderSingletons。我尝试使用它,也尝试不使用它,但它不起作用。
  • 也试图覆盖“getSingletons”,也没有帮助。也许是我的 Provider 类有问题,或者 @Context 注释有问题?
  • 是的,对不起拼写错误。但是我用 Jersey 1.19 测试了两种方式,它们都运行良好。我用你的确切代码进行了测试。可以肯定的是,您正在将其部署到 Glassfish 3.x?
  • glassfish 4.1,泽西岛 1.x
  • 我可能误导了你,getSingletons 方法可能有效,但我测试错了。但是第二种方法没有
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-18
  • 2015-08-09
  • 1970-01-01
  • 1970-01-01
  • 2014-03-20
  • 1970-01-01
  • 2015-05-22
相关资源
最近更新 更多