我的Jersey REST api中有一个资源,它有一个私有实例变量:
@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
。
我该如何防止这种情况?
答案 0 :(得分:2)
来自JAX-RS规范:
默认情况下,会为每个对该资源的请求创建一个新的资源类实例。
因此,您在资源类实例上设置的任何状态都是无意义的,因为实例永远不会再次使用。如果要保留值,请将其放在ServletContext’s attributes:
中// 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));
}
在static
字段中存储值将要求您实现线程安全,并且不能在分布式生产环境中工作。
答案 1 :(得分:1)
我认为这应该是一个评论,但我没有足够的声誉。所以我写的是答案。
This question为 @Singleton 注释提供了一个示例。它提供了更清洁的方法。