将 WebService-Client-Access 映射到 @Stateful

Mapping WebService-Client-Access to @Stateful

如果我理解正确的话,@Stateful bean 会保存状态。如果客户端再次发出请求,它会返回到同一个实例。所以可以保存 class-attributes,这在 @Stateless 中是不可能的。在另一个线程中,有人写道 "it's like a classical java instance, every injection gets it's own instance of this bean".

但我不明白请求到 @Stateful bean 的映射是如何工作的 - 怎么做才能使它工作?这个问题分两种情况:

  1. 我通过客户端软件通过网络服务调用@Stateful。它是我必须发送的 ID 吗?但是 ID 是什么以及容器如何知道这是标识属性并将其路由到正确的 @Stateful bean?
  2. 我从@Stateless bean 调用@Stateful。例如,如果客户端首先调用 @Stateless bean 并重定向到他的 @Stateful bean。

这个问题不是针对容器/服务端软件的技术流程,而是针对开发中具体做的事情。感谢您的支持。

问候

不幸的是,这不是网络服务的工作方式。有状态的bean 只对无状态的bean 是有状态的。而不是为客户。由于以下几个原因,这非常危险:

-无状态 bean 在其有状态引用中保存调用状态。但是无状态 bean 的下一次调用可能发生在另一个 context/by 另一个客户端中。

-有状态的 bean 可以被容器销毁,而无状态的仍然是 alive/in 池。

您可以通过远程调用或在 Web 应用程序中使用有状态 bean,但不能在 Web 服务上下文中使用。

根据定义,Web 服务没有任何应用程序状态。 Java EE-Servlet 侦听请求并从实例池中调用一个无状态 bean 实现。

如果你真的想实现有状态的网络服务,你必须自己动手。以下示例将在 Java EE 6 容器中运行:

///  Client depended values(your statefull bean)
public class SessionValues {
   private final List<String> values = new ArrayList<String>(); 

   public void addValue(String s){
        values.add(s);
    }

    public List<String> loadValues(){
        return Collections.unmodifiableList(values);
    }
}

您可以将会话存储在单例中(您自己的池)

 @Singleton
 @Startup
 public class StatefullSingleton {
   private final Map<String, SessionValues> sessions = new Hashtable<String, SessionValues>();

    @Lock(LockType.READ)
    public void addValue(String sessionId, String value) {
      if (!sessions.containsKey(sessionId))
          sessions.put(sessionId, new SessionValues());
      SessionValues p = sessions.get(sessionId);
      p.addValue(value);
  }

  @Lock(LockType.READ)
  public List<String> loadValues(String sessionId) {
    if (sessions.containsKey(sessionId))
        return sessions.get(sessionId).loadValues();
    else
        return new ArrayList<String>();
  }
}

并在无状态web服务bean中注入单例(池、单例和单例的调用由Java EE-Container管理):

@Stateless
@WebService
public class WebserviceBean {

@Inject
private StatefullSingleton ejb;

public void addvalue(String sessionId, String value) {
    ejb.addValue(sessionId, value);
}

public List<String> loadValues(String sessionId) {
    return ejb.loadValues(sessionId);
}

}

上面的例子只是一个模式。如果你想在生产中实现它,你必须非常小心地使用 session-id 和多线程。

编辑:删除不必要的@localBean