有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

}

但作为响应,消息为空

我尝试将我的上下文提供程序添加到Singleton,建议如下:

@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.

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


共 (1) 个答案

  1. # 1 楼答案

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

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

    但是请注意,与特定于Jersey的方式相比,直接Application子类的功能是有限的。在Jersey,首选方法是使用^{}子类(实际上是Application的子类)。例如(您可以使用^{}扫描包)

    @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、 任何一件球衣都可以。如果您有x个依赖项/jar,则应将其清除。只使用球衣2。x依赖项,并确保它们只是编译时依赖项,因为您不希望冲突的版本成为Glassfish,因为Glassfish已经有了它们的版本

    这意味着DaoContextProvider的当前实现将无法工作。{}是Jersey 1。x级和球衣2。x运行时将忽略它

    在泽西岛2号。有几种方法可以配置可注入对象。一种方法是为对象创建一个Factory。比如说

    public class DaoContextProvider implements Factory<Bar> {
    
        @Override
        public Bar provide() {
            return new Bar("boo hoo!");
        }
    
        @Override
        public void dispose(Bar bar) {}
    }
    

    在泽西岛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。请记住,您应该使它们仅成为编译时依赖项。他们不应该被卷入战争

    另请参见: