【问题标题】:Share data between JSF @ViewScoped and WebSocket @ServerEndpoint在 JSF @ViewScoped 和 WebSocket @ServerEndpoint 之间共享数据
【发布时间】:2015-05-20 03:03:54
【问题描述】:

我正在使用 JSR356 Web 套接字,并希望向我的服务器端点类添加一些函数和值,而不是创建另一个 ManagedBean。

我还想在请求之间保留 bean 属性,所以我用注释 @ViewScoped 注释了我的服务器端点。现在它看起来像这样:

@Named
@ViewScoped
@ServerEndpoint(value = "/session", encoders = ChatMessageEncoder.class, decoders = ChatMessageDecoder.class)
public class ChatEndpoint implements Serializable {

    @EJB
    private LanguageHelper languageHelper;
    private String language;

    public void filterByLanguage() {
        if (language == null)
            language = "US";
    }

    @OnOpen
    public void open(final Session session) throws IOException, EncodeException {
        // ...
    }

    @OnMessage
    public void onMessage(final Session session, final ChatMessage chatMessage) {
        // ...
    }

    @OnClose
    public void onClose(Session session) throws IOException {
        // ...
    }

    // getters & setters
}

在我的 view xhtml 上,我正在尝试使用 ajax 更新属性 language

 <h:form>
    <h:outputLabel value="Select languages you want to practice" for="languages"/>
    <h:selectOneMenu value="#{chatEndpoint.language}">
        <f:selectItems value="#{chatEndpoint.languageHelper.languages}" var="l"
                       itemLabel="#{l.language}" itemValue="#{l.code}"/>
        <f:ajax event="change" listener="#{chatEndpoint.filterByLanguage}" render="@form" execute="@this"/>
    </h:selectOneMenu>
</h:form>

起初,当 ajax 调用方法 filterByLanguage 时,值设置为字段 language,但之后,当我调用使用 @OnOpenjavascript 注释的方法时,language 为空。我认为 viewsocoped 应该在请求之间保持状态。谁能解释这种行为?提前致谢!

【问题讨论】:

    标签: jakarta-ee jsf-2 websocket view-scope


    【解决方案1】:

    你基本上得到了 2 个独立创建的类实例。一个通过@Named 作为CDI 托管bean,另一个通过@ServerEndpoint 作为JSR356 websocket 端点。它并没有像您预期的那样最终成为一个共享实例。两人互不相识,也不会分享任何东西。

    还有第二个问题:@ServerEndpoint 对当前 JSF 视图状态没有任何概念。此信息在 WS 请求中不可用。最接近您可以获得的是 HTTP 会话。如何在@ServerEndpoint中获取HttpSession在这个答案中有详细阐述:Accessing ServletContext and HttpSession in @OnMessage of a JSR-356 @ServerEndpoint

    您可能已经知道可以通过ExternalContext#getSessionMap() 在JSF 端访问HttpSession 的属性。如果您通过例如在 JSF 端生成一些唯一令牌UUID.randomUUID().toString() 并将其用作会话属性键,然后通过 JSF 视图作为 URL 路径或查询参数传递给 websocket,然后 websocket 可以利用它在共享的 HTTP 会话中查找关联的数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-28
      • 1970-01-01
      • 2017-05-09
      • 2015-08-14
      • 2019-10-19
      • 2017-10-18
      • 1970-01-01
      相关资源
      最近更新 更多