java – 泽西岛自定义上下文注入

我尝试实现自定义上下文注入,就像在
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 );
    }

}

但作为响应消息为空.

我尝试将我的上下文提供程序添加到单例中,如下所示:

@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,如异常中所述,但我不知道在哪里可以找到这个日志.

最佳答案 从getSingletons()返回的集是不可修改的.相反,我们需要覆盖该方法

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

请注意,与Jersey特定方式相比,直接Application子类的功能有限.在Jersey中,首选方法是使用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带注释的类,因此我们不需要显式注册所有内容.虽然某些提供商需要明确注册.您的特定提供商不需要注册.我在包扫描中找到了它.

UPDATE

好吧,既然你说你正在使用Glassfish 4.1,你应该首先理解的是Glassfish 4使用Jersey 2.x.所以你有任何Jersey 1.x依赖/ jar,你应该摆脱它们.仅使用Jersey 2.x依赖项,并确保它们只是编译时依赖项,因为您不希望冲突版本使其成为Glassfish的方式,而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.请记住,您应该只使它们编译时依赖性.他们不应该参与战争.

也可以看看:

> Custom Injection and Lifecycle Management

点赞