学到更多。 开发更多。 连接更多。

新的developerWorks Premium会员计划可通过Safari图书在线访问强大的开发工具和资源,包括500项顶级技术标题(数十种专门针对Web开发人员),获得顶级开发人员活动的折扣,最近O'Reilly的视频重播,会议等。 立即注册 。

YouTube成立于2005年,现已发展成为占主导地位的视频共享网站。 播放列表是YouTube使用最广泛的功能之一。 您可以建立自己和其他用户上传的视频的播放列表,并在YouTube上共享您的播放列表。 您还可以通过将播放列表嵌入网站,博客或社交媒体页面来共享它们。 但是,嵌入式播放列表播放器缺少YouTube.com上本机播放器的全部功能。

图1显示了本机youtube.com播放列表播放器。

图1.本机播放列表播放器

图2显示了默认的嵌入式播放器。

图2.嵌入式播放列表播放器

在嵌入式播放器中:

  • 默认情况下,包含的视频列表处于隐藏状态,并且仅显示为叠加层,而不是播放器旁边(如YouTube.com上所示)。
  • 随机播放列表的功能已删除。
  • 由其作者添加到播放列表中的注释将被删除。

当我决定在自己的博客中嵌入一个播放列表,其中包含2014年FIFA世界杯资格赛中取得的一些最佳进球时,我遇到了这些限制。 在YouTube API,jQuery,JsRender模板引擎和Bootstrap前端框架的帮助下,我扩展并改进了默认嵌入式播放器,以创建与本地播放器等效的版本。 在本文中,我将带您完成相同的过程。 您将在YouTube上建立播放列表,添加带有精彩时刻(例如目标)的注释,然后使用相同的工具来构建嵌入式播放器,以恢复缺少的功能并改善用户体验。

完整的项目代码存储在DevOps Services上。 我已将该应用程序部署到IBM Bluemix™,因此您可以看到它的运行情况。 您可以使用任何主机站点(包括Bluemix )来部署代码。

运行播放器 获取代码

闪存安全设置

由于Flash对象具有安全沙箱,因此如果您在浏览器中从系统中打开index.html文件,则无法使用YouTube API进行调用。 该应用程序必须托管在Web服务器(例如Bluemix )上。

注意 :要派生本文项目的代码,请单击右上角的“ 编辑代码”按钮(如果尚未登录,请输入DevOps Services凭据),然后单击菜单上的“ 分叉”按钮以创建一个新的项目。

第一步是获取用于访问YouTube API的密钥。

获取YouTube API密钥

要访问任何Google服务(包括YouTube)的API,您必须首先在Google Developers Console上注册一个项目并创建一个API密钥。 每天最多可免费访问各种API,具体数量因服务而异,并且每个拥有Google帐户的人都可以使用。

使用您的Google凭据登录Google Developers Console ,然后点击创建项目 。 默认情况下,项目名称和项目ID文本框包含随机值。 输入项目名称和ID,然后点击创建

图3.创建一个新的Google API项目

在项目仪表板中,单击“ API和身份验证”以打开可用API的列表。 向下滚动到YouTube Data API v3 ,然后单击标为“ 关”的相关按钮,以启用对项目的访问权限。 选择“ API和身份验证”>“凭据”,然后在“公共API访问”下选择“ 创建新密钥 ”。 选择浏览器密钥

在“ 创建浏览器密钥并配置允许的引用程序”对话框中,可以将对API密钥的访问限制为来自某些域的请求,例如您自己的站点或Bluemix 。 除非您限制访问,否则您的API密钥将对应用程序HTML源中的所有人可见。 在开发过程中这不是问题,因此将对话框留空并单击创建 。 但是,在部署项目后,请返回此步骤并限制对您应用程序域中请求的访问权限,以使第三方无法在其他应用程序中使用密钥。

如果从DevOps Services克隆了项目,则可以立即在index.html文件中指示的位置插入密钥,以使代码成功运行。

配置Google JavaScript客户端库以访问YouTube API

Google提供了各种语言的客户端库,包括JavaScript。 通过将此HTML标记包含在文档的<body>标记(而不是<head>标记)中,将JavaScript客户端导入到HTML文档中:

<script src="https://apis.google.com/js/client.js?onload=function"></script>

建议的最佳做法是将此<script>标记放在<body>标记的末尾。

加载客户端库后, gapi (Google API)对象在页面上的窗口范围内可用。 您刚刚添加的<script>标记中的onload参数是指在库加载后立即调用的回调函数。 该函数的定义必须在加载客户端的<script>标记之前。 该函数调用gapi.client.load( api name , version , callback function )方法以加载客户端将使用的API。 在这种情况下,您可以使用gapi.client.load('youtube', 'v3', onYouTubeApiLoad)加载YouTube API。 onYouTubeApiLoad是一种单行函数,它调用setAPIKey方法。 在setAPIKey ,将密钥设置为Google浏览器密钥的值。

客户端提供了用于访问Google服务的各种API调用的方法。 要获取播放列表中的项目列表,您将使用异步函数解析YouTube API中playlistItems.list方法的响应,并将相关属性存储在名为YouTubePlayListJavaScript对象的实例中。 您将在本文中开发YouTubePlaylist对象。 对象的构造函数在下面显示JavaScript函数中定义。

清单1. YouTubePlaylist.js
function YouTubePlaylist(id, entries) {this.id = id;this.entries = entries;this.currently_playing = 0;this.randomizer = false;
}
  • id是播放列表的ID。
  • entries是播放列表中视频的JSON数组。
  • currently_playingentries数组中当前播放的视频的索引。
  • randomizer指示播放是否随机化。

创建带有响应参数的JSON对象

现在,使用响应中所需的参数创建一个JSON对象。 您只需要可用参数完整列表的一小部分。

part参数是要由调用返回的属性的逗号分隔值(CSV)列表。 使用contentDetailssnippet属性。 snippet属性包含有关每个视频的基本信息。 contentDetails包含视频ID和播放列表作者添加的所有注释。 当您确定视频中的亮点时, contentDetails将很重要。 playListId参数是您将使用的播放列表的ID。 出于本文的目的,我设置了一个播放列表,其突出显示的ID为PLLzJfby7cTLTbusOgXca-yIpVOImC1mWe 。 在播放列表中,请注意,目标时间已添加为注释。 JSON requestOptions对象现在看起来像这样:

var requestOptions = {playlistId: playlist_id,part: 'contentDetails,snippet'
};

调用gapi.client.youtube.playlistItems.list()与此JSON对象作为参数方法返回一个对象与两种方法: executesubscribe 。 使用异步函数调用execute方法,并将响应作为参数。

request.execute(function(response) {});

响应中的items数组包含播放列表中的视频列表。 您将使用jQuery each()方法来遍历所有项目。 您将视频ID,视频的中型缩略图,标题和注释存储在JSON对象中,然后将其添加到数组中。

清单2.添加JSON对象的entries阵列
var entries = [];
$.each( response.items, function( key, val ) {var entry = {};entry.video_id = val.snippet.resourceId.videoId;entry.image_src = val.snippet.thumbnails.medium.url;entry.title = val.snippet.title;entry.note = val.contentDetails.note;entries.push(entry);});

创建YouTubePlayList对象

通过调用具有播放列表ID和entries数组的构造函数(请参见清单1)来创建新的YouTubePlaylist对象,并将该对象作为以播放列表ID命名的新变量存储在window作用域中。

window[playlist_id] = new YouTubePlaylist(playlistId, entries);

现在,您可以使用window[playlist_id]访问YouTubePlaylist对象。 稍后,您将使用window[playlist_id]调用YouTubePlaylist对象的其他功能。

使用模板通过JsRender格式化播放器

播放器的轮廓类似于图4,右侧的缩略图,标题和注释列表由播放列表中的条目组成。

图4.新播放器的轮廓

默认情况下,HTML字符集不包含与本机YouTube播放器上的下一个,上一个和随机图标相似的图标。 您的应用将使用Bootstrap前端框架提供的图标。 要导入Bootstrap样式表,请将以下代码段添加到<head>标记中。

<link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">

您将使用JsRender模板引擎来渲染YouTubePlaylist对象。 您可以在<script>标记中定义一个JsRender模板,并将其type属性设置为text/x-jsrender 。 通过使用要渲染的对象调用x-jsrender模板的render()方法来生成HTML。 您可以使用双大括号符号{{:}}在模板中呈现变量。 例如, {{:id}}呈现传递给模板的对象的id属性。

清单3中所示的模板将YouTube播放器嵌入到网页中。

清单3.嵌入YouTube播放器的模板
<object width="640" height="360"
data="http://www.youtube.com/v/video id?version=3&amp;enablejsapi=1&amp;playerapiid=id"id="player id" type="application/x-shockwave-flash"><param value="always" name="allowScriptAccess"><param value="true" name="allowFullScreen">
</object>

在清单3中, video id是要播放的视频的ID,而播放器ID是播放器对象本身的ID。 初始化时,您将提示entries数组中的第一个视频,因此请在嵌入式播放器模板中输入{{:entries[0].video_id}}作为视频ID。 对于播放器ID,请使用播放列表ID,即{{:id}}

初始化YouTube播放器对象后,播放器将自动以播放器ID作为参数调用onYouTubePlayerReady()函数,以自定义其状态更改时的行为。 播放器的状态为未开始,结束,正在播放,暂停,正在缓冲和提示视频; 这些被枚举为-1、0、1、2、3和4。在API的当前版本中,无法自定义回调函数。 现在,您将在窗口范围内定义一个函数,以将下一个视频加载到播放列表中(稍后将在YouTubePlaylist对象中定义此函数),并将其作为事件侦听器添加到播放器。

清单4.用于在播放列表中加载下一个视频的函数
function onYouTubePlayerReady(playerApiId) {var player = document.getElementById(playerApiId);window["onStateChange" + playerApiId] = function(state) {   switch(state) {case 0:
var video_player = document.getElementById(player_id);
video_player.loadVideoById(window[player_id].getNextVideo(), 0, "large");break;}};player.addEventListener("onStateChange", "onStateChange" + playerApiId);
}

要遍历视频数组,您将使用JsRender {{for}}标签。 您将使用清单5中的模板在图4的右侧创建每个播放列表条目。

清单5.用于在列表中创建每个播放列表条目的模板
{{for entries}}
<div class="playListEntry {{if #index == 0}}nowPlaying{{/if}}" id="{{:video_id}}"><div class="playListEntryThumbnail"><img src="{{:image_src}}"/></div><div class="playListEntryDescription"><div class="playListEntryTitle">{{:title}}</div><div class="playListEntryNote">{{:note}}</div></div>
</div>
{{/for}}

在清单5中, entriesYouTubePlaylist对象中的entries属性。 数组中对象的索引存储在#index变量中。 因为列表中的第一个条目是创建时播放器中加载的视频,所以您将通过使用{{if}}标记在for循环中将nowPlaying CSS类应用于第一个playListEntry类。

通过将Bootstrap glyphicon类应用于span ,使用glyphicon-backwardglyphicon-forwardglyphicon-random类,可以创建播放器底部的控件。

<div class="playListControls"><span class="playListControl disabled glyphicon glyphicon-backward"/><span class="playListControl glyphicon glyphicon-forward"/><span class="playListControl glyphicon glyphicon-random"/>
</div>

请注意,最初,“上一个”图标被禁用,因为当播放器首次加载时,它默认为播放列表中的第一个条目,因此没有以前的视频可以播放。

您需要将呈现HTML添加到具有此代码段的ID playlist的页面上的空白div (请记住window[player_id]引用了您在“ 创建YouTubePlaylist ”部分中创建的对象。

$('#' + player_id).html($('#playListPlayerTemplate').render(window[player_id]));

要使此代码可重复使用,请将其移至带有签名addPlaylistToElement(playlist_id, element_id)的函数中,然后可以使用addPlaylistToElement('PLLzJfby7cTLTbusOgXca-yIpVOImC1mWe', 'playlist')进行调用。

添加控件

返回到YouTubePlaylist对象并开始添加功能。 稍后,您将使用该对象的增强版本来完成网页中的播放器。

向对象添加六个函数: previous()next()getCurrentlyPlaying()setCurrentlyPlaying()randomize()isRandomized()previousnext功能移至播放列表中的相关视频,如果操作成功,则返回true否则,则返回false(即,如果用户在播放列表中的第一个条目上单击“上一个”或在操作上单击“下一个”,则返回false)。最后一个条目)。 getCurrentlyPlaying()返回播放列表中当前正在播放的视频的ID。 randomize()设置或isRandomizer()设置对象中的random属性,而isRandomizer()返回random属性的值。

清单6显示了Next()函数。

清单6. Next()函数
next: function() {var retVal = false;if(this.randomizer) {retVal = true;this.currently_playing = Math.floor((Math.random() * this.entries.length));}else if(this.currently_playing <= this.entries.length) {retVal = true;this.currently_playing++;} return retVal;

Next()函数,首先检查如果random属性被设置,并且如果是,则设置currently_playing索引中的随机值entries阵列。 如果未设置random属性,并且currently_playing索引小于数组中的视频数量(也就是说,您尚未传递播放列表中的最后一个视频),则将索引的值增加1以移至下一个视频并返回true表示操作成功。 如果失败,则返回false

清单7显示了previous()函数。 如果currently_playing索引大于零(也就是说,用户正在观看播放列表中除第一个视频以外的任何视频),则将索引减1并返回true表示操作成功;否则,返回true 。 否则,返回false

清单7. previous()函数
previous: function() {var retVal = false;if(this.currently_playing > 0) {retVal = true;this.currently_playing--;} return retVal;
}

getCurrentlyPlaying()函数中,返回getCurrentlyPlaying()数组中当前播放索引的视频ID。

getCurrentlyPlaying: function() {return this.entries[this.currently_playing].video_id;
}

清单8显示了setCurrentlyPlaying()函数。 给定一个video_id从当前播放列表中,设置currently_playing到在元件的索引entries array与该值。

清单8. setCurrentlyPlaying()函数
setCurrentlyPlaying: function(video_id) {for(var index = 0; index < this.entries.length; index++) {if (this.entries[index].video_id === video_id) {this.currently_playing = index;break;}}
}

randomize()函数中,将randomizer属性的值反转(从true到false,反之亦然),并返回新值。

randomize: function() {this.randomizer = !(this.randomizer);return this.randomizer;
}

isRandomized()函数返回播放列表的randomizer属性的值,即播放列表是否在随机播放中:

isRandomized: function() {return this.randomizer;
}

使用添加的功能

现在添加功能以使用JavaScript对象的添加功能。

首先,添加一个辅助函数来安排播放列表的控件。 如果播放器是随机播放:

  • “随机”图标突出显示。
  • 由于您不在任何地方录制以前播放的视频,因此始终禁用“上一个”图标。
  • 由于播放列表永远不会随机播放“最后一个”视频,因此始终启用“下一个”图标。 (考虑一下:当您的MP3播放器随机播放时,它会停止播放吗?)

如果播放列表不是随机播放的:

  • 仅当播放列表中的第一个条目正在播放时,“上一个”图标才被禁用。
  • 仅当播放列表中的最后一个条目正在播放时,“下一个”图标才被禁用。
  • 禁用“随机”图标,直到再次单击它。

清单9显示了helper函数。

清单9.用于安排播放列表控件的Helper函数
function arrangePlayerControls(player_id) {var playListPlayer = $('#' + player_id + 'playListPlayer');if(window[player_id].isRandomized()) {$('#' + player_id + 'Backward').addClass('disabled');$('#' + player_id + 'Forward').removeClass('disabled');$('#' + player_id + 'Random').addClass('randomizeActive');}else {$('#' + player_id + 'Random').removeClass('randomizeActive');var playListEntries = $('#' + player_id + 'playListEntries');if(playListEntries.children(":first").hasClass('nowPlaying')) {$('#' + player_id + 'Backward').addClass('disabled');}else {$('#' + player_id + 'Backward').removeClass('disabled');}if(playListEntries.children(":last").hasClass('nowPlaying')) {$('#' + player_id + 'Forward').addClass('disabled');}else {$('#' + player_id + 'Forward').removeClass('disabled');}}
}

接下来,添加一个功能,以给定的播放列表ID和开始播放的时间索引将视频加载到播放器中。 请记住从当前播放视频的div删除nowPlaying类,并将其添加到新视频的div中。 然后,调用清单9中的helper函数来安排播放列表图标。 清单10显示了视频加载功能。

清单10.将视频加载到播放器中的函数
function loadVideoForPlayer(currently_playing_video_id, player_id, time) {time = time || 0;var video_id = window[player_id].getCurrentlyPlaying();$('#' + currently_playing_video_id).removeClass('nowPlaying')$('#' + video_id).addClass('nowPlaying');$('#' + player_id + 'playListEntries').scrollTop($('#' + video_id).index() * 80);document.getElementById(player_id).loadVideoById(video_id, time, "large");arrangePlayerControls(player_id);
}

最后,添加一个功能以在给定播放列表中加载下一个视频,但前提是该播放列表中有另一个视频(也就是说,您不在随机播放中,并且当前视频不是最后一个视频)。

清单11.如果存在下一个视频,则加载视频的函数
function loadNextVideo(player_id) {var currently_playing_video_id = window[player_id].getCurrentlyPlaying();if(window[player_id].next()) {loadVideoForPlayer(currently_playing_video_id, player_id);}
}

这个功能类似于您在声明匿名函数onYouTubePlayerReady()见清单4 ),所以重构case 0onYouTubePlayerReady()调用loadNextVideo()来代替。

您可能已经注意到,我在播放列表中为每个视频添加了目标时间。 借助这些新功能,您可以将目标时间用作链接热点,直接跳到视频中的目标,而无需全程观看。 在$.each()在环addPlaylistToElement()存储所述注释每一个的值playlistItem对象在局部变量,然后使用JavaScript match()函数以从纸币返回的次阵列,使用正则表达式/[0-9]*:[0-5][0-9]/g进行查找。 然后,您可以遍历此数组,并用链接替换变量中每次的值,以使用播放器ID,要播放的视频和开始的时间索引来调用cueThisVideo()函数。 请记住,YouTube API loadVideoById()调用花费的时间以秒为单位,因此请使用字符串中的冒号作为分隔符,将时间分成一个数组。 将第一个索引(分钟)中的值乘以60,将其转换为秒,然后将其添加到第二个索引中的秒,以获取秒的总数。 例如,1:30变成数组[1,30](1 * 60)+ 30 = 90秒。 最后,用新的链接替换注释中的时间。 每次处理便笺中的内容时,都将完整的字符串作为该条目的便笺存储在entries数组中,如清单12所示。

清单12.用链接替换笔记中的时间
var note = val.contentDetails.note;
var times = note.match(/[0-9]*:[0-5][0-9]/g);
times.forEach(function(value, index, array) {var time = value.split(":");var seconds = parseInt(time[0]) * 60;seconds += parseInt(time[1]);note = note.replace(value, "<span class='timeLink' onclick='cueThisVideo(\"" + player_id + "\", \"" + video_id + "\", " + seconds + ");'>" + value + "</span>");
});
entry.note = note;

剩下的就是重新访问模板并添加对这些新功能的调用。 您希望用户能够通过单击标题或缩略图来使视频排队,将播放列表中的上一个或下一个视频排队,并使用控制面板中的相关按钮将播放列表随机化。 清单13显示了模板中完成的更改,以使用添加的功能。

清单13.重构的模板代码
<div onclick="cueThisVideo('{{:~player_id}}', '{{:video_id}}');" class="playListEntryThumbnail"><img src="{{:image_src}}"/>
</div>
<div onclick="cueThisVideo('{{:~player_id}}', '{{:video_id}}');" class="playListEntryTitle">{{:title}}
</div><span id="{{:id}}Backward" class="playListControl disabled glyphicon glyphicon-backward" onclick="if(!$(this).hasClass('disabled'))    {   loadPreviousVideo('{{:id}}')   }">
</span>
<span id="{{:id}}Forward" class="playListControl glyphicon glyphicon-forward" onclick="if(!$(this).hasClass('disabled')) {   loadNextVideo('{{:id}}')   }">
</span>
<span id="{{:id}}Random" class="playListControl glyphicon glyphicon-random" onclick="window['{{:id}}'].randomize();arrangePlayerControls('{{:id}}');">
</span>

现在,您的自定义播放器已准备就绪,可以摇滚!

结论

本文演示了如何使用YouTube API和一些简单JavaScript和样式来呈现嵌入式YouTube播放列表,并具有与YouTube.com上的本地播放列表相同的功能。 有关用于进一步增强播放器的一些建议,请参阅我的DevOps Services页面中的README文件。 随意分叉项目代码以实施任何或所有这些建议。


翻译自: https://www.ibm.com/developerworks/web/library/wa-bluemix-youtube/index.html

建立自定义的YouTube播放列表播放器相关推荐

  1. python播放器模块_python建立属于自己的vip播放器

    可以去复制其他平台VIP电影的链接,粘贴解析,不行就换一个接口 理论是通过爬虫调用接口,通过gui展示出来,源码如下 import re import requests import tkinter ...

  2. YouTube iframe嵌入式播放器及播放器参数 自动播放,循环播放,播放列表,不显示 YouTube 徽标

    YouTube 嵌入式播放器及播放器参数 概览 本文档介绍如何在应用中嵌入 YouTube 播放器,并定义了 YouTube 嵌入式播放器可以使用的参数. 通过将参数附加到 iframe 网址末尾,您 ...

  3. 亲测好用的油管音乐播放器:Tuner Mac版

    Tuner for YouTube music Mac版是一款优质的youtube音乐播放器,Tuner支持快速搜索想要听的音乐,支持创建自定义播放列表.在线播放等功能,另外Tuner for You ...

  4. 基于android音频感知系统,本科毕业论文—基于android音乐播放器的设计与实现专科.doc...

    本科毕业论文-基于android音乐播放器的设计与实现专科.doc 专科毕业设计(论文) 题 目 基于Android的音乐播放器设计与实现 毕业论文(设计)原创性声明 本人所呈交的毕业论文(设计)是我 ...

  5. android 自定义音乐圆形进度条,Android自定义View实现音频播放圆形进度条

    本篇文章介绍自定义View配合属性动画来实现如下的效果 实现思路如下: 根据播放按钮的图片大小计算出圆形进度条的大小 根据音频的时间长度计算出圆形进度条绘制的弧度 通过Handler刷新界面来更新圆形 ...

  6. 如何使用uni-app做一个音乐播放器

    如何使用uni-app做一个音乐播放器 uni-app提供给我们非常棒的API,可以做出很好看的自定义样式的音乐播放器 好的编译器可以让我们的项目事半功倍,HBuilderX可以很方便的创建uni-a ...

  7. 苹果cms怎么设置播放器

    苹果cms怎么设置播放器?今天就详细介绍下苹果cmsv10播放器的各个名称的功能与使用. 1.排序:播放器的序号 数字越大越靠前. 2.编码:采集视频的时候,资源站有个来源,对应的是我们自己程序的播放 ...

  8. ckplayer html5 添加广告,CKplayer纯净播放器设置示例(可不显示广告)

    ckplayer,可以能够自定义视频风格,播放器自身是无广告的,你可以自定义显示自己的广告,也可以什么都不显示,这一切,均可以在风格文件中设置,两种风格文件 xml 和 js 设置参数一致. 软件名称 ...

  9. css3音乐播放器,CSS3-自定义视频与音乐播放器!

    今天说一下自定义视频和音乐播放器!直接先看看完成后的效果图把! 视频: video.jpg 音乐: 音乐.jpg 哈哈,是不是觉得太难看了,根本没心情往下继续看了?那就对了.我也觉得难看,但是重点来了 ...

最新文章

  1. IO流 带行号的缓冲区
  2. 路径搜索算法 python实现_A*算法在栅格地图上的路径搜索(python实现)
  3. 基于visual Studio2013解决C语言竞赛题之1081shell排序
  4. java字符串去重复_java去除字符串中重复、不重复、消除重复后字符
  5. https安全传输协议
  6. linux网络通信移植,基于socket API的C/S通信:将Qt程序从Linux移植到windows
  7. ArrayList 动态数组 0119
  8. mybatis+Druid连接池的问题
  9. 【KMP】KMP 字符串匹配算法
  10. 音乐类APP竞品分析报告 酷狗音乐 QQ音乐酷我音乐网易云音乐
  11. 计算机网络第五版笔记
  12. 理论+实验:LAMP网站服务器部署(超详细版本)
  13. Flutter获取网络图片:The following SocketException was thrown resolving an image codec:
  14. 【NumPy中数组创建】
  15. 基因测序仪四十年:回顾、致敬与展望
  16. 一个老百姓眼中的次贷危机
  17. 大二下小结与暑假展望
  18. 浮华,原来青春是一场梦
  19. 苹果官方iCloud中的照片如何迁移到Google Photo教程来了
  20. 计算机访问控制机制,访问控制策略和机制-信息安全工程师知识点

热门文章

  1. 记录一次SM3281折腾记
  2. 2019秋招海康测试一面
  3. 基于RK3288安卓Android5.1平台移植RTL8152驱动
  4. 009 简单的渗透测试流程
  5. Maxon将在Siggraph 2019公布下一代Cinema 4D RELEASE 21
  6. 网易云信入选《SegmentFault 思否 2019 中国技术品牌影响力企业榜单》!
  7. 计算机网络技能鉴定三级,计算机网络管理员(三级)技能鉴定试题A
  8. 个推推送,APP接收到推送后的操作(前台与非前台的处理不同)
  9. 国货美妆需要“诗和远方”
  10. [转载]TMS320F2812引脚详细分析(转帖整理)