2、异步HTTP编程

1、处理异步结果

       在内部,play框架是自下而上异步的。Play以异步、非阻塞方式处理每个请求。应用程序代码应尽量避免阻塞控制器,这种阻塞操作的常见例子有JDBC调用、流式API、HTTP请求和长计算。因此应尽量通过保持控制器异步的方法使得应用进行扩展,使系统在负载下保持响应。就是说,对于控制器中的一些阻塞的操作,尽量使用异步的方式进行处理。

       Action中的处理要求尽可能的快,但是如果使用异步(Action默认处理请求就是异步的),那么可能会有这样的问题,结果没有计算出来,响应就已经返回了,这是怎么处理呢?Java 8中提供了类CompletionStage和CompletableFuture这两个类不具体介绍,只需要知道可以实现使得程序异步又可以获取返回值,CompletionStage<result>最终将用result类型的值。返回CompletionStage<result>是一种编写非阻塞代码的技术。可以使用如下方式获取:

        实现异步处理、非阻塞编程的关键就在于CompletionStage,下边介绍一下如何使用,第一种可以通过配合HttpExecutionContext使用,可以通过依赖项注入play提供的play.libs.concurrent.httpExecutionContext实例,如下:

       只是使用HttpExecutionContext和CompletableFuture还是使用的play默认的上下文执行器,还需要使用CustomExecutionContext和HttpExecution实现非阻塞编程,如下:

可以通过使用实现响应超时问题的处理:

2、流式HTTP响应

       为了保持单个连接的开放性以服务于多个HTTP请求和响应,服务器必须随响应一起发送适当的内容长度的HTTP头。对于响应一些简单的文本结果,play可以自动识别并自动添加头信息返回客户端,但是对于一些复杂的内容,就需要开发者自己指定头信息,play提供了类play.http.httpentity用来实现此功能,使用如下:   

       在这里就有一个问题,为了计算头长度获取头信息,就需要将所有返回内容加载到内存,这里就可能存在问题:返回内容太大怎么办?下边先来一个返回结果的例子:     

       这里返回到客户端一个流对象,由于需要判断头信息,而play不能在流中直接获取头信息,这是就需要将整个流添加到内存中进行分析。Play中对于此问题,早已提供实现,直接调用ok(new File(“文件路径”))即可。

       上边这种方式返回的文件大小必须是确定的,对于文件大小不能确定的、动态变化的就需要使用分块传输编码技术,使用如下: 

3、Comet套接字

      使用分块传输编码技术实现Comet。Comet套接字是一个分块的text/HTML响应,只包含<script>元素。对于每个块,我们编写一个包含JavaScript的<script>标记,该标记立即由Web浏览器执行。这样我们就可以从服务器向Web浏览器实时发送事件:对于每条消息,将其包装成一个调用javascript回调函数的<script>标记,并将其写入分块响应。

       因为ok().chunked利用akka流获取流<bytestring>,所以我们可以发送一个元素流并对其进行转换,以便在javascript方法中对每个元素进行转义和包装。Comet帮助程序自动执行Comet套接字,为浏览器兼容性推送初始空白缓冲区数据,并支持字符串和JSON消息。

下边介绍几个Comet的使用:

字符串流中使用Comet:    

Json流中使用Comet:

Iframe中使用Comet:

4、WebSockets(网络套接字)

        WebSockets是基于允许双向全双工通信的协议从Web浏览器使用的套接字。只要服务器和客户机之间有活动的WebSocket连接,客户机就可以发送消息,服务器就可以随时接收消息。WebSokets不能通过标准动作来处理。Play的WebSocket处理机制是围绕Akka流构建的。WebSocket被建模为流,传入的WebSocket消息被送入流中,流生成的消息被发送到客户机。play提供了一些在WebSocket中构造WebSocket的工厂方法。

接下来介绍play中如何处理websocket。

       使用actors处理websocket,可以使用play实用程序ActorFlow将actorRef转换为流。此实用程序接受一个函数,该函数将actorRef转换为向akka.actor.props对象发送消息,该对象描述在接收WebSocket连接时play应创建的参与者:  

从客户端接收到的任何消息都将发送给参与者,而由play提供的任何消息都将发送给客户端,当websocket关闭时,actor将被停止,可以通过实现actors的 poststop方法来处理需要关闭的资源:

有时候希望拒绝WebSocket请求,例如,如果必须对用户进行身份验证才能连接到WebSocket,Play为此目的提供了AcceptorResult  WebSocket  Builder:

想要实现异步接收WebSocket,直接使用CompletionStage<WebSocket<A>>代替WebSocket<A>即可。

处理其他类型数据的请求:

还可以直接使用akka流处理WebSockets,如下:

WebSocket可以访问请求头(来自启动WebSocket连接的HTTP请求),但是,它不能访问请求主体,也不能访问HTTP响应

发送hello之后丢弃输入数据并关闭套接字:

输入数据记录到标准输出,然后使用映射流发送回客户机:

配置websocket的帧长度有两种方式,在启动应用是使用:

play.server.websocket.frame.maxLength 或者

Sbt -Dwebsocket.frame.maxLength=256k run

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值