将Web服务 - 客户端访问映射到@Stateful

时间:2015-02-22 17:40:18

标签: java web-services java-ee wildfly stateful-session-bean

如果我理解正确,@ Stateful bean会保存状态。如果客户端再次执行请求,则会返回到同一实例。因此可以保存类属性,这在@Stateless中是不可能的。在另一个帖子中,有人写道“它就像一个经典的java实例,每次注入都会获得它自己的bean实例”。

但是我不明白请求到@Stateful bean的映射是如何工作的 - 它有什么用呢?这个问题出现在两个案例中:

  1. 我通过客户端软件的web服务调用@Stateful。这是我必须随身携带的身份证吗?但是什么是ID以及容器如何知道这是识别属性并将其路由到正确的@Stateful bean?
  2. 我从@Stateless bean中调用@Stateful。例如,如果客户端首先调用@Stateless bean并重定向到他的@Stateful bean。
  3. 这个问题不适用于容器/服务器软件的技术过程,而是针对开发中的具体操作。感谢您的支持。

    问候

1 个答案:

答案 0 :(得分:0)

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

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

- 有状态的bean可以被容器破坏,而无状态的人仍然活着/在池中。

您可以将状态bean用于远程调用或Web应用程序,但不能用于Web服务的上下文。

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

如果您真的想要实现有状态的Web服务,则必须自己完成。以下示例适用于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