首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

反向 Ajax,第 2 部分 WebSocket(3)

反向 Ajax,第 2 部分 WebSocket(3)

请求作用域服务许多框架都提供了服务或过滤器,处理到达 servlet 的 Web 请求。例如,过滤器将执行以下操作:
  • 将 JDBC 连接绑定到请求线程上,整个请求只使用一个连接。
  • 在请求结束时进行变更。
另一个示例是 Google Guice 的 Guice Servlet 扩展(一个依赖项注入库)。与 Spring 一样,Guice 能够在请求的作用域内绑定服务。对每个新请求,一次最多只能创建一个实例(参阅  以获得更多相关信息)。
典型用法包括使用来自集群 HTTP 会话的用户 id,缓存从请求中的信息库(如数据库)检索的用户对象。在 Google Guice 中,您可以获得类似于 清单 7 的代码。
清单 7. 请求作用域绑定
1
2
3
4
5
6
@Provides
@RequestScoped
Member member(AuthManager authManager,
              MemberRepository memberRepository) {
    return memberRepository.findById(authManager.getCurrentUserId());
}




在将一个成员注入某个类时,Guice 会尝试从请求中提取它。如果没有找到它,Guice 会执行信息库调用,并将结果放在请求中。
请求作用域的服务可以与任何反向 Ajax 解决方案配套使用,除了 WebSockets。任何其他解决方案,无论是短期还是长期的,都将依赖于 HTTP 请求,因此每个请求都通过 servlet 调度系统,并执行过滤。完成暂停的(长期)HTTP 请求后,您将在本系列的后续部分看到,还有一个选项可以使请求再次通过过滤器链。
对于 WebSockets,与在 TCP 套接字中一样,数据将直接到达 onMessage 回调。因为没有针对该数据而传入的 HTTP 请求,因此没有决定从哪个请求中获得并存储作用域对象的请求争用。因此,使用需要从 onMessage 回调的作用域对象的服务会失败。
中的 guice-and-websocket 示例展示了如何绕过限制,在 onMessage 回调中仍然使用请求作用域对象。当您运行该示例并单击页面上的每个按钮来测试 Ajax 调用(请求作用域)、WebSocket 调用、带有模拟请求作用域的 WebSocket 调用时,您将获得如 图 3 中所示的输出。
图 3. 使用请求作用域服务的 WebSocket 处理器的输出无论使用以下哪个选项,都可能都会遇到这样的问题:
  • Spring。
  • Hibernate。
  • 任何其他需要请求作用域或 “每个请求” 模型的框架,如 OpenSessionInViewFilter。
  • 使用 ThreadLocal 工具在过滤器中将变量限制在请求线程中并在以后对其进行访问的系统。
Guice 有一个良好的解决方法,如下所示 清单 8:
清单 8. 从 WebSocket onMessage 回调模拟请求作用域
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// The reference to the request is hold when the
// doWebSocketMethod is called
HttpServletRequest request = [...]
Map<Key<?>, Object> bindings = new HashMap<Key<?>, Object>();
// I have a service which needs a request to get the session,
// so I provide the request, but you could provide any other
// binding that may be needed
bindings.put(Key.get(HttpServletRequest.class), request);
ServletScopes.scopeRequest(new Callable<Object>() {
    @Override
    public Object call() throws Exception {
        // call your repository or any service using the scoped objects
        outbound.sendMessage([...]);
        return null;
    }
}, bindings).call();

返回列表