REST Web 服务 - 如何像单例一样使用服务?

REST WebServise - how to use service like a singleton?

我的其余应用程序包含一个服务,我需要使该服务像单例一样运行以保存服务的状态。

一项服务:

@Path("/script")
public class ScriptEngineProvider {

private AtomicInteger idCounter;

public ScriptEngineProvider() {
    System.out.println("before AtomicInteger");
    idCounter = new AtomicInteger();
}

@POST
public Response executeScript( String x ) {
    idCounter.incrementAndGet();
    System.out.println("counter " + idCounter);
    ...

除所有其他代码外,客户端还具有:

WebTarget webTarget = client.target("http://localhost:8080/NashornEngine/rest").path("script");

web.xml

<url-pattern>/rest/*</url-pattern>

通过上述配置,应用程序可以正常工作,但每个请求都会创建变量 idCounter,因此 idCounter 总是 1.

现在我使用 next class 使 ScriptEngineProvider 成为单例:

@ApplicationPath("/services")
public class NashornApplication extends Application {
    private Set<Object> singletons = new HashSet<Object>();
    public NashornApplication() {
        singletons.add(new ScriptEngineProvider());
    }
    @Override
    public Set<Object> getSingletons() {
        return singletons;
    }
}

问题是我得到 The requested resource is not available 请求:

//path services was added
WebTarget webTarget = client.target("http://localhost:8080/NashornEngine/rest").path("services").path("script");

这个配置有什么问题?

试试这个:

@Singleton // this is the important line
@Path("/script")
public class ScriptEngineProvider {

private AtomicInteger idCounter;

public ScriptEngineProvider() {
    System.out.println("before AtomicInteger");
    idCounter = new AtomicInteger();
}

@POST
public Response executeScript( String x ) {
    idCounter.incrementAndGet();
    System.out.println("counter " + idCounter);
    ...

@ApplicationPath 实际上与 url-mapping 的目的相同。但是只能用一个。当您不想使用 web.xml 配置时,可以将 @ApplicationPathApplication subclass 一起使用。要上网。xml-less,您需要确定两件事

  1. 您正在部署到 3.x servlet 容器。
  2. 您拥有支持 servlet 可插入性的依赖项。查看更多

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>${jersey2.version}</version>
    </dependency>
    

也可以使用 Application subclass 没有 @ApplicationPath,然后将使用 url-mapping映射 Jersey servlet。例如

<servlet>
    <servlet-name>MyApplication</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.pkg.YourApplication</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>MyApplication</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

无论您选择哪种方式,都会使用 url-mapping 路径或 @ApplicationPath 值,但不会同时使用两者。因此,在您的情况下,如果您不使用 web.xml 配置,则路径将不包括 url-mapping 中的 /rest。如果你使用上面的 web.xml 配置,那么你应该去掉 Application subclass 上的 @ApplicationPath,你会使用 url有 /rest,没有 /services.

你一直得到一个的原因是

  1. 默认行为是为每个请求创建一个新资源class
  2. 你的Application子class没有被使用,你的web.xml配置正在被使用,你正在包扫描。

查看此 post 中的信息并进行相应的更改。