简体   繁体   English

Jersey自定义Context注入

[英]Jersey custom Context injection

I tried implementing custom context injection just like in this answer : 我尝试实现自定义上下文注入,就像在这个答案中

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

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

}

And here's my controller class, to witch I want to inject my context: 这是我的控制器类,对于女巫我想要注入我的上下文:

@Path("foo")
public class Foo {

    @Context
    private Bar message;

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

}

But in response message is null. 但作为响应消息为空。

I tried adding my context provider to singletons, as recomended: 我尝试将我的上下文提供程序添加到单例中,如下所示:

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

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

But then my artifact does not even deploy, and provides me with this error: 但后来我的工件甚至没有部署,并为我提供了这个错误:

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.

I would provide server.log, as described in exception, but I dont know where to find this log. 我会提供server.log,如异常中所述,但我不知道在哪里可以找到这个日志。

The set returned from getSingletons() is unmodifiable. getSingletons()返回的集是不可修改的。 Instead we need to override the method 相反,我们需要覆盖该方法

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

Note though that a direct Application subclass is limited in functionality compared to the Jersey specific way. 请注意,与Jersey特定方式相比,直接Application子类的功能有限。 In Jersey, the preferred approach is to use a ResourceConfig subclass (which is actually a subclass of Application ). 在Jersey中,首选方法是使用ResourceConfig子类(实际上是Application的子类)。 For example (you can use PackagesResourceConfig to scan packages). 例如(您可以使用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.
    }
}

This will scan for @Path and @Provider annotated classes, so we don't need to explicitly register everything. 这将扫描@Path@Provider注释的类,因此我们不需要显式注册所有内容。 Though some providers will need to be explicitly registered. 虽然某些提供商需要明确注册。 Your particular provider doesn't need to be registered though. 您的特定提供商不需要注册。 It i picked up in the package scan. 我在包扫描中找到了它。


UPDATE UPDATE

Ok since you say you are using Glassfish 4.1, the first thing you should understand is that Glassfish 4 uses Jersey 2.x. 好吧,既然你说你正在使用Glassfish 4.1,你应该首先理解的是Glassfish 4使用Jersey 2.x. So any Jersey 1.x dependencies/jars you have, you should get rid of them. 所以你有任何Jersey 1.x依赖/ jar,你应该摆脱它们。 Use only Jersey 2.x dependencies, and make sure that they are only compile-time dependencies, as you do not want conflicting versions making it's way to Glassfish, that already has a version of them. 仅使用Jersey 2.x依赖项,并确保它们只是编译时依赖项,因为您不希望冲突版本使其成为Glassfish的方式,而Glassfish已经有了它们的版本。

What this means is that your current implementation of the DaoContextProvider will not work. 这意味着您当前的DaoContextProvider实现将无法正常工作。 The SingletonTypeInjectableProvider is Jersey 1.x class, and the Jersey 2.x runtime will just ignore it. SingletonTypeInjectableProvider是Jersey 1.x类,Jersey 2.x运行时将忽略它。

In Jersey 2.x there are a few ways to configure injectable objects. 在Jersey 2.x中,有几种方法可以配置可注入对象。 One way is to create a Factory for the object. 一种方法是为对象创建Factory For example. 例如。

public class DaoContextProvider implements Factory<Bar> {

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

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

In Jersey 2.x, the API for ResourceConfig has change, and we can extend it directly. 在Jersey 2.x中, ResourceConfig的API已更改,我们可以直接扩展它。 For example 例如

@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);
            }
        });
    }
}

You can see the AbstractBinder . 你可以看到AbstractBinder That is how we register the DaoContextProvider with the Bar class. 这就是我们如何使用Bar类注册DaoContextProvider So now Bar can be injected to your resource classes. 所以现在Bar可以注入你的资源类。

The only Maven dependency you need to pull everything else in, is 你需要把所有其他东西都拉进来的唯一Maven依赖是

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

Notice the provided scope, so that it does not get built to the war. 注意提供的范围,以便它不会构建到战争中。 If you are not using Maven, then grab all the jars in the Jersey JAX-RS 2.0 RI bundle . 如果您没有使用Maven,那么抓住Jersey JAX-RS 2.0 RI包中的所有罐子。 Remember that you should make them only compile time dependencies. 请记住,您应该只使它们编译时依赖性。 They should no get built into the war. 他们不应该参与战争。

See Also: 也可以看看:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM