奇怪的是,它只适用于我@PreMatching
的过滤器(它限制了对某些您可能需要或可能不需要的东西的访问)。不太清楚幕后发生了什么,导致没有它就无法工作:-(。下面是使用Jersey Test Framework进行的完整测试。
import java.io.IOException;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.internal.inject.AbstractContainerRequestValueFactory;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Assert;
import org.junit.Test;
public class FilterInjectionTest extends JerseyTest {
private static final String MESSAGE = "Inject OK";
private static final String OBJ_PROP = "myObject";
public static class MyObject {
private final String value;
public MyObject(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
@PreMatching
@Provider
public static class MyObjectFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext context) throws IOException {
MyObject obj = new MyObject(MESSAGE);
context.setProperty(OBJ_PROP, obj);
}
}
public static class MyObjectFactory
extends AbstractContainerRequestValueFactory<MyObject> {
@Override
@RequestScoped
public MyObject provide() {
return (MyObject) getContainerRequest().getProperty(OBJ_PROP);
}
@Override
public void dispose(MyObject t) {
}
}
@Path("method-param")
public static class MethodParamResource {
@GET
public String getResponse(@Context MyObject myObject) {
return myObject.getValue();
}
}
@Path("constructor")
public static class ConstructorResource {
private final MyObject myObject;
@Inject
public ConstructorResource(@Context MyObject myObject) {
this.myObject = myObject;
}
@GET
public String getResponse() {
return myObject.getValue();
}
}
@Path("field")
public static class FieldResource {
@Inject
private MyObject myObject;
@GET
public String getResponse() {
return myObject.getValue();
}
}
@Override
public Application configure() {
ResourceConfig config = new ResourceConfig();
config.register(MethodParamResource.class);
config.register(MyObjectFilter.class);
config.register(ConstructorResource.class);
config.register(FieldResource.class);
config.register(new AbstractBinder() {
@Override
protected void configure() {
bindFactory(MyObjectFactory.class)
.to(MyObject.class).in(Singleton.class);
}
});
return config;
}
@Test
public void methoParamInjectionOk() {
String response = target("method-param").request().get(String.class);
Assert.assertEquals(MESSAGE, response);
System.out.println(response);
}
@Test
public void costructorInjectionOk() {
String response = target("constructor").request().get(String.class);
Assert.assertEquals(MESSAGE, response);
System.out.println(response);
}
@Test
public void fieldInjectionOk() {
String response = target("field").request().get(String.class);
Assert.assertEquals(MESSAGE, response);
System.out.println(response);
}
}
更新
无需将其制成@PreMatching
过滤器的解决方案是注入javax.inject.Provider
. 这将允许您懒惰地检索对象。我猜构造函数和字段注入会发生什么,在匹配资源类之后,它立即创建并注入。因为过滤器还没有被调用,所以工厂没有对象。它适用于方法注入,因为它就像任何其他方法调用一样。调用方法时将对象传递给它。下面是一个例子javax.inject.Provider
@Path("constructor")
public static class ConstructorResource {
private final javax.inject.Provider<MyObject> myObjectProvider;
@Inject
public ConstructorResource(javax.inject.Provider<MyObject> myObjectProvider) {
this.myObjectProvider = myObjectProvider;
}
@GET
public String getResponse() {
return myObjectProvider.get().getValue();
}
}
@Path("field")
public static class FieldResource {
@Inject
private javax.inject.Provider<MyObject> myObjectProvider;;
@GET
public String getResponse() {
return myObjectProvider.get().getValue();
}
}