如何将UriInfo对象注入非资源类

时间:2015-12-10 12:05:20

标签: java jersey-2.0

在修改我的项目代码的过程中,我发现我没有机会将UriInfo对象插入资源类(使用@Context注释) 遗憾的是,我无法更改方法或构造函数签名,以便在将资源传递给服务类时检索资源中的uriinfo。

有没有选择将UriInfo插入到通常的类(不是jax-rs)中? 也许有一些选择可以说Jersey不仅扫描资源类而且定制扫描资源类? 修改

这是一些代码示例

@Path("path")
public class JerseyResource {
   @Get
   public Responce executeMethod(@QueryParam Criteria criteria, @QueryParam ObjType type) {
        return RestUtils.chooseServiceByType(type).process(criteria);
   }
}

RestUtils.chooseServiceByType(type)可以返回~15个不同的实例。 仅针对1个实例(即 Type2LogicProcessorServiceImpl ),我需要访问流程(标准)方法中的 uriInfo 对象

谢谢你, 迪马

1 个答案:

答案 0 :(得分:2)

您需要将该类绑定为Jersey的DI框架HK2中的服务。泽西岛使用HK2进行大部分注射,包括@Context注射。由于@Context与DI绑定,您的服务是否与DI绑定,您可以在服务中接受@Context次注入。

例如,如果您有Service

public class Service {

    @Context 
    UriInfo uriInfo;

    public String getUri() {
        return uriInfo.getRequestUri().toASCIIString();
    }
}

然后你需要绑定类似

的东西
public class Binder extends AbstractBinder {
    @Override
    protected void configure() {
        bind(Service.class).to(Service.class);
    }
}

然后在Jersey上注册活页夹。在ResourceConfig你可以做

public class AppConfig extends ResourceConfig {
    public AppConfig() {
        register(new Binder());
    }
}

如果您使用的是web.xml,则无法直接注册活页夹。您需要使用Feature并发现该功能。在那里你可以注册活页夹。

@Provider
public class BinderFeature implements Feature {
    @Override
    public boolean configure(FeatureContext ctx) {
        ctx.register(new Binder());
        return true;
    }
}

然后,您可以将Service注入资源类

@Path("uri")
public class UriResource {

    @Inject
    Service service;

    @GET
    public String get() {
        return service.getUri();
    }
}

更多信息:

更新

查看以下测试。它可以使用单个测试依赖项运行

<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
    <version>${jersey2.version}</version>
    <scope>test</scope>
</dependency>

我所做的是使用HK2 Factory注入查询参数ObjType,并获取Service(现在只是一个接口超类型)。如果它是需要UriInfo的类型,我会使用ServiceLocator明确地注入它。工厂和定位器可能是你的新概念,所以如果你想了解更多,我会浏览上面提到的两个文档链接。

import java.util.logging.Logger;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;

import org.junit.Test;
import static junit.framework.Assert.assertEquals;

public class UriInfoTest extends JerseyTest {

    public static interface Service {
        String getUri();
    }

    public static class ServiceOne implements Service {

        @Context 
        UriInfo uriInfo;

        @Override
        public String getUri() {
            return uriInfo.getRequestUri().toASCIIString();
        }
    }

    public static class ServiceTwo implements Service {
        @Override
        public String getUri() {
            return "Blah";
        }
    }

    public static class ObjType {
        String param;
        public ObjType(String param) {
            this.param = param;
        }
    }

    static class RestUtils {
        static Service getServiceByType(ObjType type) {
            switch (type.param) {
                case "one": return new ServiceOne();
                case "two": return new ServiceTwo();
                default: return new ServiceOne();
            }
        }
    }

    public static class ServiceFactory implements Factory<Service> {

        @QueryParam("type")
        ObjType type;

        @Inject
        ServiceLocator locator;

        @Override
        public Service provide() {
            Service service = RestUtils.getServiceByType(type);
            if (service instanceof ServiceOne) {
                locator.inject(service);
            }
            return service;
        }

        @Override
        public void dispose(Service t) {}     
    }

    public static class Binder extends AbstractBinder {
        @Override
        protected void configure() {
            bindFactory(ServiceFactory.class).to(Service.class);
        }
    }

    @Path("uri")
    public static class UriResource {

        @Inject
        Service service;

        @GET
        public String get() {
            return service.getUri();
        }
    }

    @Override
    public ResourceConfig configure() {
        return new ResourceConfig(UriResource.class)
                .register(new Binder())
                .register(new LoggingFilter(Logger.getAnonymousLogger(), true));
    }

    @Test
    public void doit() {
        Response response = target("uri").queryParam("type", "one").request().get();
        assertEquals(200, response.getStatus());
        String message = response.readEntity(String.class);
        assertEquals("http://localhost:9998/uri?type=one", message);
        response.close();
    }
}