Playing Play!系列之三:不必Servlet3,Play框架的异步请求处理之道

[PS:离上一篇Play系列文章有近两个月了,当初是打算,大概在一、两个月的时间内,完成大致8篇左右的系列的。未料因新工作的安排,现在的时间和空间都不足够,只能断续完成了]

 

去年年底,JavaEE6规范正式发布,其中,新Servlet3规范的最引人注目特性,就是非阻塞的异步请求处理。一些流行的Servlet容器,如Jetty67,包括即将发布的Tomcat7,都已经或准备支持Servlet3特性。

 

在上一章“再见ServletPlay框架的启动”中,已经介绍到,Play框架有两种启动模式,一种是原生启动方式,一种是通过Servlet包装启动方式。其实这两种方式的最大区别,是后者通过符合Servlet的规范方式,提供传统的同步请求处理服务;而前者,则是通过内嵌ApacheMina/AsyncWeb框架,实现了的一套轻量级的、高性能的、异步的HTTP请求处理服务器。它的原生启动方式,首先就抛弃了传统的同步Servlet容器,直接引入了Servlet3规范中定义的异步请求处理模式。相对于Java领域的StrutsSpringMVC等其他一些流行Web框架,这是Play框架的最大不同。

 

前一章介绍了Play框架的初始化:Play.init()。在框架初始化后,接下来做的,就是启动容器了,Play框架通过两个简单的包装类,即实现了一个基础的,基于Mina/AsyncWeb框架的异步HTTP服务器,这两个类就是“服务器类”(play.server.Server)和“HTTP处理器”(play.server.HTTPHandler)。这一点,与其说是Play框架的简明,到不如说是Mina/AsyncWeb框架的易用。

 

Server类中,Play框架启动了一个Mina的服务器实例,并注册AsyncWebHTTP协议过滤器,和一个HTTPHandler实例。在HTTPHandler中,即是进行具体的HTTP请求处理、响应组装的地方。

 

我对MinaAsyncWeb框架并没有什么研究,这里也就不深入往这两个框架里展开了。下面我们来重点来看,Play框架是如何基于它们,来进行异步请求处理的:


1、  HTTP.RequestHTTP.Response,是Play框架对HTTP请求和响应的包装类,用于为应用开发提供请求和响应相关操作,它们实际是对AsyncWebMutableHttpRequestMutableHttpResponse接口的简单重包装。

2、  PlayPluginPlay框架提供的插件机制,让注册的插件,有机会处理原生的请求对象和响应对象。

3、  InvokerPlay框架对Java5线程池的简单包装,用于将(请求)处理对象加入到处理队列中,实现异步的操作调用,而Invoker.Invocation即为该被调用的(请求)处理对象的抽象基类

4、  MinaInvokerInvoker.Invocation的一个具体实现类,它会根据路由配置表,反射调用对应的由应用实现的控制器(Controller和对应的静态处理方法),这部分我们后面会再进一步分析。

 

可以看出,Play框架利用Mina/AysncWeb,加上Java5提供的ScheduledThreadPoolExecutor,并通过一些集成的中间类,即实现了一套完整而高效的异步HTTP服务器框架。简单的实现,诠释出一个深刻的道理,发明新车与发明新的轮子,没什么关系,关键是要能找到合适的轮子,并把它装到合适的位置。


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3-video-play是一个Vue3的视频播放组件库,可以帮助开发者快速构建视频播放页面。以下是一个使用Vue3-video-play写的视频播放组件: ```vue <template> <div class="video-play-wrapper"> <video-player :options="options" ref="player"></video-player> <div class="video-play-controls"> <div class="video-play-button" @click="togglePlay"> <i v-if="!isPlaying" class="fa fa-play"></i> <i v-else class="fa fa-pause"></i> </div> <div class="video-play-progress-wrapper" @click="updateProgress"> <div class="video-play-progress-bar"> <div class="video-play-progress" :style="{width: progress + '%'}"></div> </div> </div> <div class="video-play-timer">{{ currentTime }} / {{ duration }}</div> </div> </div> </template> <script> import { defineComponent, ref, onMounted } from "vue"; import { VideoPlayer } from "vue3-video-play"; export default defineComponent({ components: { VideoPlayer, }, props: { src: { type: String, required: true, }, }, setup(props) { const player = ref(null); const options = ref({ sources: [ { src: props.src, type: "video/mp4", }, ], autoplay: false, controls: false, }); const isPlaying = ref(false); const progress = ref(0); const currentTime = ref("0:00"); const duration = ref("0:00"); const togglePlay = () => { if (isPlaying.value) { player.value.pause(); } else { player.value.play(); } isPlaying.value = !isPlaying.value; }; const updateProgress = (event) => { const progressWrapper = event.target; const clickX = event.clientX - progressWrapper.getBoundingClientRect().left; const progressWidth = progressWrapper.offsetWidth; const percent = (clickX / progressWidth) * 100; player.value.currentTime = (percent / 100) * player.value.duration; }; const updateTime = () => { const currentTimeValue = Math.floor(player.value.currentTime); const durationValue = Math.floor(player.value.duration); progress.value = (currentTimeValue / durationValue) * 100; currentTime.value = formatTime(currentTimeValue); duration.value = formatTime(durationValue); }; const formatTime = (time) => { const minutes = Math.floor(time / 60); const seconds = time - minutes * 60; const formattedSeconds = seconds.toString().padStart(2, "0"); return `${minutes}:${formattedSeconds}`; }; onMounted(() => { player.value.addEventListener("timeupdate", updateTime); }); return { player, options, isPlaying, progress, currentTime, duration, togglePlay, updateProgress, }; }, }); </script> <style> .video-play-wrapper { position: relative; width: 100%; height: 0; padding-bottom: 56.25%; } .video-play-wrapper video { position: absolute; width: 100%; height: 100%; } .video-play-controls { position: absolute; bottom: 0; left: 0; right: 0; background-color: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: space-between; padding: 8px; z-index: 1; } .video-play-button { cursor: pointer; color: white; font-size: 20px; } .video-play-progress-wrapper { flex: 1; height: 8px; margin: 0 8px; cursor: pointer; } .video-play-progress-bar { height: 100%; background-color: white; border-radius: 4px; overflow: hidden; } .video-play-progress { height: 100%; background-color: red; } .video-play-timer { color: white; font-size: 12px; } </style> ``` 使用方式: ```vue <template> <video-play src="https://example.com/video.mp4"></video-play> </template> <script> import VideoPlay from "@/components/VideoPlay.vue"; export default { components: { VideoPlay, }, }; </script> ``` 该组件包含了视频播放器和控制条两部分,支持播放、暂停、拖动进度条、显示当前时间和总时间等功能。具体实现细节可见代码注释。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值