【问题标题】:How to manage a stateful webservice?如何管理有状态的 Web 服务?
【发布时间】:2011-09-23 23:13:30
【问题描述】:

我正在尝试了解 J2EE 和 Web 服务(在 GlassFish 3.1 中)。这个问题是this的后续问题。

我已经弄清楚了如何使用无状态会话 Bean 和 Web 服务。我真的只是出于方便才使用 Web 服务 (@WebService),因为我宁愿不手动解析消息。虽然如果可能的话,我更喜欢比 SOAP 更轻的东西。但是,当我想保持某种状态(例如通过有状态会话 Bean)时,我遇到了问题。我搜索了这个网站,其他几个人都建议我避免这种情况,因为它可能会导致难以找到错误并限制可扩展性。

假设我有一个用户刚刚执行了“userLogin”方法并且成功了。然后我如何在服务器上知道用户已经登录。例如,在登录后,用户可能会通过 SOAP(不带任何参数)调用“getProfile()”,我会为该用户返回正确的信息。我知道通过将 @WebService 附加到我的有状态会话 Bean 是不可能的,因为这仅对 @Stateless 有效。

如果我使用 HttpSession(带有 HttpServlet)和无状态会话 Bean,我知道如何存储状态,但是我无法使用生成良好的 SOAP 消息。

所以我的问题是:我将如何解决维护用户状态的问题,或者调整问题以使我不需要状态?

【问题讨论】:

    标签: java jakarta-ee glassfish ejb stateful-session-bean


    【解决方案1】:

    WS 可以是有状态的:使用@Stateful 注释和 WS-Addressing(例如,参见我的old question

    拥有有状态的服务器并没有犯罪。毕竟,如果需要有状态,为什么要避免呢?确实,无状态更容易扩展和调试,但如果您需要保持状态(例如在购物卡中)——那就保持它。

    需要考虑的是在超时后清理有状态的服务实例。使用 StatefulWebServiceManager 实例及其 setTimeout() 方法。

    此外,状态可以保存在 WS 之外(例如数据库),状态(会话)标识符作为参数之一传递。效果很好。

    使用 HTTP 会话是保持无状态服务状态的一种非常简单的方法,但与 @Stateful 相比,我认为它已经过时了。理由是请求不必通过 HTTP 来; @Stateful/WS-Addressing 适用于任何通道,而 HTTP 会话需要 HTTP 传输。当然,在现实世界中,HTTP 是盛行的,所以这个论点是相当纯粹的。

    【讨论】:

    • 关于有状态的东西要考虑的另一件事是您的系统是否足够大以进行集群。您要么必须有一种方法在盒子之间传输状态,要么必须有一种方法来确保来自同一源的请求最终在同一个盒子上。一切都很可行,但这是一个考虑因素。
    • 谢谢,但不幸的是,它似乎没有完成我想要的工作。这可能只是我对 API 不熟悉,但我在这里 ([blogs.oracle.com/sujit/entry/…) 阅读了有关 @Addressing 注释的信息,发现它为用户提供了对缓存资源的访问权限。我想要的是我可以在用户不知道被跟踪的情况下轻松访问的东西。
    • 即使是 HTTP 会话也需要 cookie。用户会知道的。在 WS 用户(客户端)的情况下,必须通过不少于 hack 显式地读取和添加 cookie。与 @Stateful 相比,这很整洁。
    【解决方案2】:

    将无状态 bean 公开为 Web 服务:

    import javax.ejb.Remote;
    import javax.jws.WebService;
    import javax.jws.WebMethod; 
    
    
    @WebService
    /**
    * This is an Enterprise Java Bean Service Endpoint Interface
    */
    public interface HelloServiceInf extends java.rmi.Remote {
    
        /**
        * @param phrase java.lang.String
        * @return java.lang.String
        * @throws String The exception description.
        */
        @WebMethod
        java.lang.String sayHello(java.lang.String name) throws java.rmi.RemoteException;
    }
    

    将 Web 服务实现为无状态 bean

    import java.rmi.RemoteException;
    import java.util.Properties;
    import javax.ejb.Stateless;
    
    /**
    * This is a session bean class
    */
    @Stateless(name="HelloServiceEJB")
    public class HelloServiceBean implements HelloServiceInf {
    
        public String sayHello(String name) {
            return("Hello "+name +" from first EJB3.0 Web Service");
        }
    }
    

    你需要在HttpSession中保留UserInfo(用户详细信息和配置信息对象),如果HttpSession中没有UserInfo,那么你需要调用bean(Web服务)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-10
      • 2023-03-05
      • 1970-01-01
      • 2011-02-05
      • 1970-01-01
      • 2010-10-29
      • 2018-12-25
      • 2011-06-22
      相关资源
      最近更新 更多