Java 如何将对象注入 jersey 请求上下文?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27665744/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to inject an object into jersey request context?
提问by armin
I have this scenario where I want to write a filter and I want this filter to insert some object into the current request and pass it on so that when the resource class gets the request it can use the object.
我有这样一个场景,我想编写一个过滤器,我希望这个过滤器将某个对象插入到当前请求中并传递它,这样当资源类收到请求时,它就可以使用该对象。
Filter class
过滤器类
@Override
public void filter(ContainerRequestContext request) throws IOException {
MyObject obj = new MyObject();
// Inject MyObject to request which I dont know how
}
Resource Class
资源类
@PUT @Consumes("application/json")
@Path("/")
public String create(
JSONParam sample,
@Context MyObject obj) {
System.out.println(obj.getName());
return "";
}
采纳答案by Paul Samsotha
You could just use ContainterRequestContext.setProperty(String, Object)
. Then just inject the ContainerRequestContext
你可以只使用ContainterRequestContext.setProperty(String, Object)
. 然后只需注入ContainerRequestContext
@Override
public void filter(ContainerRequestContext crc) throws IOException {
MyObject obj = new MyObject();
crc.setProperty("myObject", myObject);
}
@POST
public Response getResponse(@Context ContainerRequestContext crc) {
return Response.ok(crc.getProperty("myObject")).build();
}
Another option to inject the MyObject
directly is to use the HK2 functionality Jersey 2 offers.
MyObject
直接注入的另一种选择是使用 Jersey 2 提供的 HK2 功能。
Create a factory the inject the ContainerRequestContext
and return the MyObject
. For example
创建一个工厂,注入ContainerRequestContext
并返回MyObject
. 例如
import javax.inject.Inject;
import javax.ws.rs.container.ContainerRequestContext;
import jetty.plugin.test.domain.MyObject;
import org.glassfish.hk2.api.Factory;
public class MyObjectFactory implements Factory<MyObject> {
private final ContainerRequestContext context;
@Inject
public MyObjectFactory(ContainerRequestContext context) {
this.context = context;
}
@Override
public MyObject provide() {
return (MyObject)context.getProperty("myObject");
}
@Override
public void dispose(MyObject t) {}
}
You then need to bind the factory:
然后你需要绑定工厂:
public class InjectApplication extends ResourceConfig {
public InjectApplication() {
...
register(new AbstractBinder(){
@Override
protected void configure() {
bindFactory(MyObjectFactory.class)
.to(MyObject.class)
.in(RequestScoped.class);
}
});
}
}
With the same setting of the property as in the filter example above, you can then just inject the MyObject
with the @Context
随着财产如上面的例子过滤器相同的设置,则可以只注射MyObject
用@Context
@GET
public Response getTest(@Context MyObject myObject) {
return Response.ok(myObject.getMessage()).build();
}
- See more at
Custom Injection
- 更多信息请访问
Custom Injection
UPDATE
更新
Please see this questionfor a problem with this implementation.
See Also:
也可以看看:
回答by Kevin Day
I've got a solution to this that doesn't require a DI container, but still gives most of the benefit.
我有一个解决方案,不需要 DI 容器,但仍然提供大部分好处。
There's two parts. The first is how to get instances into the @Context injection mechanism instead of providing classes in the ApplicationConfig object.
有两部分。第一个是如何将实例引入@Context 注入机制,而不是在 ApplicationConfig 对象中提供类。
Here's a technique for doing that:
这是一种实现此目的的技术:
private static class CustomContextResteasyBootstrap extends org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap{
private final Map<Class<?>, Object> additionalContextObjects = new HashMap<Class<?>, Object>();
public <E> CustomContextResteasyBootstrap addContextObject(Class<? super E> clazz, E obj){
additionalContextObjects.put(clazz, obj);
return this;
}
@Override
public void contextInitialized(ServletContextEvent event) {
super.contextInitialized(event);
deployment.getDispatcher().getDefaultContextObjects().putAll(additionalContextObjects);
}
}
and you use it like this:
你像这样使用它:
webAppContext.addEventListener(
new CustomContextResteasyBootstrap()
.addContextObject(MyCustom.class, myCustom)
.addContextObject(AnotherCustom.class, anotherCustom)
// additional objects you wish to inject into the REST context here
);
now you can use those classes with the @Context annotation:
现在您可以将这些类与 @Context 注释一起使用:
@GET
public MyCustom echoService(@Context MyCustom custom) {
return custom;
}
The next part of the puzzle is how to provide per-request context objects. To do this, add the following code somewhere near the top of the jax-rs call hierarchy (basically, anything that gets called below this line will get access to the context object):
难题的下一部分是如何提供每个请求的上下文对象。为此,请在 jax-rs 调用层次结构顶部附近的某处添加以下代码(基本上,在此行下方调用的任何内容都可以访问上下文对象):
ResteasyProviderFactory.pushContext(MyContextSpecific.class, new MyContextSpecific());
You can then reference this via injection anywhere below that level:
然后,您可以通过注入在该级别以下的任何地方引用它:
@GET
public String contextSpecificEchoService(@Context MyContextSpecific contextSpecific) {
return custom.toString();
}
This is poor-man's DI, but it works really well for embedded rest servers.
这是穷人的 DI,但它非常适合嵌入式休息服务器。