泽西岛 - 资源变量空值尽管非空初始化
Jersey - resource variables null value despite non-null initialization
我的 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);
}
}
在服务器 startup/restart 上,实例变量 someString
在 contextInitialized()
期间初始化并正确打印出来。但是,当我将 GET
请求设置为 http://localhost:8080/myapp/api/test
(即调用上面的 test()
方法)时,变量 someString
为 null
。
我该如何预防?
来自 JAX-RS 规范:
By default a new resource class instance is created for each request to that resource.
因此,您在资源 class 实例上设置的任何状态都没有意义,因为该实例再也不会被使用。如果你想保留一个值,把它放在 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
字段中存储值需要您实现线程安全,并且在分布式生产环境中不起作用。
我相信这应该是一个评论,但我没有足够的声誉。所以我写下来作为回答。
给出了 @Singleton 注释的示例。它提供了一种更清洁的方法。
我的 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);
}
}
在服务器 startup/restart 上,实例变量 someString
在 contextInitialized()
期间初始化并正确打印出来。但是,当我将 GET
请求设置为 http://localhost:8080/myapp/api/test
(即调用上面的 test()
方法)时,变量 someString
为 null
。
我该如何预防?
来自 JAX-RS 规范:
By default a new resource class instance is created for each request to that resource.
因此,您在资源 class 实例上设置的任何状态都没有意义,因为该实例再也不会被使用。如果你想保留一个值,把它放在 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
字段中存储值需要您实现线程安全,并且在分布式生产环境中不起作用。
我相信这应该是一个评论,但我没有足够的声誉。所以我写下来作为回答。