如何将 UriInfo 对象注入非资源 类
How to inject UriInfo object into non-resource classes
在修改我的项目代码的过程中,我发现我没有机会将 UriInfo 对象插入到资源中 class(使用 @Context 注释)
不幸的是,我无法更改方法或构造函数签名以检索资源中的 uriinfo 并将其传递给服务 class.
是否有任何选项可以将 UriInfo 插入到通常的 class(不是 jax-rs)中?
也许有一些选项可以说 Jersey 不仅扫描资源 classes,还扫描自定义资源?
编辑:
这是一些代码示例
@Path("path")
public class JerseyResource {
@Get
public Responce executeMethod(@QueryParam Criteria criteria, @QueryParam ObjType type) {
return RestUtils.chooseServiceByType(type).process(criteria);
}
}
RestUtils.chooseServiceByType(type) 可以 return ~15 个不同的实例。
并且仅针对 1 个实例(即 Type2LogicProcessorServiceImpl)我需要访问 uriInfo 对象 process(criteria)方法
谢谢,
迪马
您需要将 class 绑定为 Jersey 的 DI 框架 HK2 中的服务。泽西岛使用 HK2 进行大部分注入,包括 @Context
注入。由于 @Context
与 DI 绑定,如果您的服务与 DI 绑定,您可以在您的服务中接受 @Context
注入。
例如,如果你有这个 Service
class
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
注入你的资源 class
@Path("uri")
public class UriResource {
@Inject
Service service;
@GET
public String get() {
return service.getUri();
}
}
更多信息:
- Custom Injection and Lifecycle Management 来自 Jersey 文档。
- 上面的 HK2 link 有关直接使用 HK2 的更多信息
更新
看看下面的测试。可以都是运行,有一个测试依赖
<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
注入它。工厂和定位器对您来说可能是新概念,所以如果您想了解更多信息,我将阅读我提供的上述两个文档 link。
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();
}
}
在修改我的项目代码的过程中,我发现我没有机会将 UriInfo 对象插入到资源中 class(使用 @Context 注释) 不幸的是,我无法更改方法或构造函数签名以检索资源中的 uriinfo 并将其传递给服务 class.
是否有任何选项可以将 UriInfo 插入到通常的 class(不是 jax-rs)中? 也许有一些选项可以说 Jersey 不仅扫描资源 classes,还扫描自定义资源? 编辑:
这是一些代码示例
@Path("path")
public class JerseyResource {
@Get
public Responce executeMethod(@QueryParam Criteria criteria, @QueryParam ObjType type) {
return RestUtils.chooseServiceByType(type).process(criteria);
}
}
RestUtils.chooseServiceByType(type) 可以 return ~15 个不同的实例。 并且仅针对 1 个实例(即 Type2LogicProcessorServiceImpl)我需要访问 uriInfo 对象 process(criteria)方法
谢谢, 迪马
您需要将 class 绑定为 Jersey 的 DI 框架 HK2 中的服务。泽西岛使用 HK2 进行大部分注入,包括 @Context
注入。由于 @Context
与 DI 绑定,如果您的服务与 DI 绑定,您可以在您的服务中接受 @Context
注入。
例如,如果你有这个 Service
class
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
注入你的资源 class
@Path("uri")
public class UriResource {
@Inject
Service service;
@GET
public String get() {
return service.getUri();
}
}
更多信息:
- Custom Injection and Lifecycle Management 来自 Jersey 文档。
- 上面的 HK2 link 有关直接使用 HK2 的更多信息
更新
看看下面的测试。可以都是运行,有一个测试依赖
<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
注入它。工厂和定位器对您来说可能是新概念,所以如果您想了解更多信息,我将阅读我提供的上述两个文档 link。
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();
}
}