0

我的 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()上面的方法)时,变量someStringnull.

我怎样才能防止这种情况?

4

2 回答 2

2

来自 JAX-RS 规范:

默认情况下,会为对该资源的每个请求创建一个新的资源类实例。

因此,您在资源类实例上设置的任何状态都是没有意义的,因为该实例永远不会再次使用。如果要保留一个值,请将其放在ServletContext 的属性中:

// 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需要您实现线程安全,并且在分布式生产环境中不起作用。

于 2017-12-05T18:47:08.500 回答
1

我相信这应该是一个评论,但我没有足够的声誉。所以我写了一个答案。

这个问题给出了一个@Singleton注释的例子。它提供了一种更清洁的方法。

于 2017-12-06T07:59:54.680 回答