Java Jersey-尽管初始化为非null,但资源变量的值为null
我的Jersey REST api中有一个资源,它有一个私有实例变量:Java Jersey-尽管初始化为非null,但资源变量的值为null,java,spring,rest,jersey,spring-jersey,Java,Spring,Rest,Jersey,Spring Jersey,我的Jersey REST api中有一个资源,它有一个私有实例变量: @Path("test") public class TestResource implements ServletContextListener { private String someString; @GET public void test() { System.out.println("someString " + someString); } @
@Path("test")
public class TestResource implements ServletContextListener
{
private String someString;
@GET
public void test()
{
System.out.println("someString " + someString);
}
@Override
public void contextDestroyed(ServletContextEvent ctxt) {
System.out.println("Destroying context");
}
@Override
public void contextInitialized(ServletContextEvent ctxt) {
System.out.println("TestResource initialized!");
someString = "SET";
System.out.println("someString has been set. someString: " + someString);
}
}
在服务器启动/重新启动时,实例变量someString
在contextInitialized()
期间初始化并正确打印出来。但是,当我将GET
请求设置为http://localhost:8080/myapp/api/test
(即调用上面的test()
方法)变量someString
为null
如何防止这种情况发生?来自JAX-RS规范: 默认情况下,将为对该资源的每个请求创建一个新的资源类实例 因此,您在资源类实例上设置的任何状态都是无意义的,因为该实例将不再使用。如果要保留某个值,请将其放置在:
在
静态
字段中存储值将要求您实现线程安全,并且不会在分布式生产环境中工作。来自JAX-RS规范:
默认情况下,将为对该资源的每个请求创建一个新的资源类实例
因此,您在资源类实例上设置的任何状态都是无意义的,因为该实例将不再使用。如果要保留某个值,请将其放置在:
在
静态
字段中存储值需要实现线程安全,并且在分布式生产环境中无法工作。我认为这应该是一个评论,但我没有足够的声誉。所以我写这封信是作为回答
给出了@Singleton注释的示例。它提供了一种更干净的方法 我认为这应该是一个评论,但我没有足够的声誉。所以我写这封信是作为回答
给出了@Singleton注释的示例。它提供了一种更干净的方法 我将在此提出一个问题,并建议不会对创建用于处理GET的TestResource实例调用contextInitialized。只是说……啊,好吧,是有道理的。这对我来说很糟糕,因为我将不得不使用一个初始化成本非常高的变量,并且所有http请求都应该使用同一个实例。有什么想法吗?使变量静态有帮助,但我觉得我不是真的了解在这一点上的单一模式?是的,这也是一个选择。类似地,jersey中有一个
@Singleton
注释,您可以强制为每个请求重用资源,但我不知道这对于并发请求有多明智。看,我将在这里讨论一个问题,并建议在为处理GET而创建的TestResource实例上不调用contextInitialized。只是说……啊,好吧,是有道理的。这对我来说很糟糕,因为我将不得不使用一个初始化成本非常高的变量,并且所有http请求都应该使用同一个实例。有什么想法吗?使变量静态有帮助,但我觉得我不是真的了解在这一点上的单一模式?是的,这也是一个选择。类似地,jersey中有一个@Singleton
注释,您可以强制为每个请求重用资源,但我不知道这对于并发请求有多明智。看见
// All classes in the web app share a ServletContext, so attribute names
// need to start with package names to prevent collisions.
private static final String SOME_ATTRIBUTE = TestResource.class.getName() + ".someAttribute";
@Override
public void contextInitialized(ServletContextEvent ctxt) {
System.out.println("TestResource initialized!");
String someString = "SET";
System.out.println("someString has been set. someString: " + someString);
ctxt.getServletContext().setAttribute(SOME_ATTRIBUTE, someString);
}
@GET
public void test(@Context ServletContext context) {
System.out.println("someString " + context.getAttribute(SOME_ATTRIBUTE));
}