Kurento协议

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

Kurento媒体服务器可以被两种外部Kurento客户端控制,如Java或JavaScript。这些客户端使用Kuernto协议来和KMS通信。Kurento 协议是基于WebSocket协议,并使用了JSON-RPC V2.0 消息来提交请求和发送响应。

JSON-RPC 消息格式

Kurento协议使用JSON-RPC V2.0 编码它的消息,下面的章节将讨论如何在JSON消息中使用这种格式。

Request 消息

一个RPC调用可以表示为向服务端发送一个Request消息,Request消息有下列成员变量:

  • jsonrpc: 指定JSON-RPC 协议的版本的字符串,它必须是"2.0"。

  • id: 由客户端建立的唯一标识符,包含一个字符串或数字。 服务端必须在Response消息中以相同的值回复。 这个成员变量被用于在两个消息间地内容进行关联。

  • method: 被激活方法名 。

  • params: 用于被激活方法的结构体,它包含了参数值。

下面的JSON显示了一个示例请求的格式:

{"jsonrpc": "2.0","id": 1,"method": "create","params": {"type": "PlayerEndPoint","constructorParams": {"pipeline": "6829986","uri": "http://host/app/video.mp4"},"sessionId": "c93e5bf0-4fd0-4888-9411-765ff5d89b93"}
}

成功的响应消息

当一个RPC调用让服务端回复一个响应消息时,如果是一个成功的响应,那么响应消息将包含如下成员变量:

  • jsonrpc:指定JSON-RPC协议的版本的字符串,它必须是"2.0".

  • id:它强制性地和请求消息中的id值一致。

  • result: 它的值是由服务端被激活的方法来确定的。如果连接被拒绝,它返回一个拒绝属性的消息,拒绝属性包含了消息代码,以及为什么session被拒绝,并且不会有被定义的sessionId。

下面是一个成功响应示例:

{"jsonrpc": "2.0","id": 1,"result": {"value": "442352747","sessionId": "c93e5bf0-4fd0-4888-9411-765ff5d89b93"}
}

出错的响应消息

当一个RPC调用让服务端回复一个响应消息时,如果是一个出错的响应,那么响应消息将包含如下成员变量:

  • jsonrpc: 指定JSON-RPC协议的版本的字符串,它必须是"2.0".

  • id: 它强制性地和请求消息中的id值一致。如果检测到请求消息中id是错误的(如错误或无效的请求),它就为空。

  • error: 一个消息,通过下面成员变量来描述这个错误:

    • code: 标识遇到的错误类型的整数值

    • message: 错误的简单描述

    • data: 原始或结构体的值,包含了关于错误的额外信息。它可以被忽略,它的值是由服务端定义的。

下面显示了一个典型的出错响应:

{"jsonrpc": "2.0","id": 1,"error": {"code": "33","message": "Invalid paramter format"}
}

JSON-RPC之上的Kurento API

如在Kurento API章节所述,Kurento媒体服务器提供了一套完整成熟的API,让应用程序以多种方式处理媒体。

为了使用这些丰富的API, Kurento客户端要求在客户端和服务端之间实现全双式通信。基于这个原因,Kurento协议是基于WebSocket传输的。

在发出命令之前,Kurento客户端需要先请求和Kurento媒体服务器的URL: ws://hostname:port/kurento建立WebSocket连接。一旦这个WebSocket连接已建立,Kurento协议提供了五种不同的类型的请求/响应消息:

  • ping: 客户端和KMS之间保活。

  • create: 实例化一个新的媒体对象,如管道或媒体元件。

  • invoke: 调用已创建对象的方法。

  • subscribe: 创建对象中的事件订阅。

  • unsubscribe: 移除一个事件的订阅。

  • release: 删除对象并释放其资源。

Kurento协议还允许Kurento媒体服务器向客户端发送请求:

  • onEvent: 这个请求是在事件发生时,Kurento媒体服务器向客户端发送请求。

Ping

为了保证客户端和Kurento Media Server之间的WebSocket连接,实现了保持活动方法。 此方法基于客户端发送的ping方法,必须使用来自服务器的pong消息进行回复。 如果在时间间隔内未获得响应,则客户端知道与媒体服务器的连接已丢失。参数间隔是从服务器接收Pong消息的超时时间,以毫秒为单位。 默认情况下,此值为240000(即40秒)。 这是ping请求的示例:

{"id": 1,"method": "ping","params": {"interval": 240000},"jsonrpc": "2.0"
}

对ping请求的响应必须包含具有固定名称为pong的value参数的result对象。 以下片段显示了对上一个ping请求的pong响应:

{"id": 1,"result": {"value": "pong"},"jsonrpc": "2.0"
}

Create

Create消息请求 Kurento API 对象的创建。参数 type 指定了被创建对象的类型。参数 constructorParams 包含了创建该对象需要的所有信息。每个消息都需要不同的 constructorParams 来创建对象,这些参数是在Kurento API章节中定义的。

最后,参数sessionId为当前session的标识符。这个参数的值是由Kurento Media Server在每次响应时发送给客户端。只有第一次的从客户端到服务端的请求不需要这个‘sessionId’(因为这时候客户端还未收到这个值)。

下面的例子展示了一个request消息请求,它请求创建一个MediaPipeline类型对象:

{"id": 2,"method": "create","params": {"type": "MediaPipeline","constructorParams": {},"properties": {}},"jsonrpc": "2.0"
}

响应消息中, 在域value中包含了媒体管道id。消息id还会要被用在协议的其它请求中,sessionId要在每个响应中返回, 标识当前会话。

{"id": 2,"result": {"value": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline","sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}

响应消息包含字段值中包含新对象的标识符。 像往常一样,消息id必须与请求消息匹配。 每个响应中还返回sessionId。 以下示例显示请求消息,请求在现有介质管道(由参数mediaPipeline标识)中创建WebRtcEndpoint类型的对象。 请注意,在此请求中,sessionId已存在,而在上一个示例中,它不是(因为在那一点对于客户端是未知的):

{"id": 3,"method": "create","params": {"type": "WebRtcEndpoint","constructorParams": {"mediaPipeline": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline"},"properties": {},"sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}

以下示例显示请求消息,请求在现有介质管道(由参数mediaPipeline标识)中创建WebRtcEndpoint类型的对象。 请注意,在此请求中,sessionId已存在,而在上一个示例中,它不是(因为在那一点对于客户端是未知的):

{"id": 3,"result": {"value": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline/087b7777-aab5-4787-816f-f0de19e5b1d9_kurento.WebRtcEndpoint","sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}

Invoke

Invoke 消息请求对指定对象调用一个操作。

参数 object 指示了被调用操作的对象的id,

参数 operation 指示了被调用操作的名称。

参数 operationParams 包含了执行操作需要的参数。

以下示例显示请求消息,请求调用连接到WebRtcEndpoint的PlayerEndpoint上的操作connect:

{"id": 5,"method": "invoke","params": {"object": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline/76dcb8d7-5655-445b-8cb7-cf5dc91643bc_kurento.PlayerEndpoint","operation": "connect","operationParams": {"sink": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline/087b7777-aab5-4787-816f-f0de19e5b1d9_kurento.WebRtcEndpoint"},"sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}

响应消息包含执行对象中调用操作时返回的值,如果操作未返回任何值,则返回空值。

以下示例显示调用操作connect(不返回任何内容)时的典型响应:

{"id": 5,"result": {"sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}

Release

Release 消息请求释放指定对象。参数 object 指定了要释放的对象的id:

{"id": 36,"method": "release","params": {"object": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline","sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}

响应消息只包含sessionID, 下面是一个示例:

{"id": 36,"result": {"sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}

Subscribe

Subscribe消息请求订阅指定对象的某种类型的事件。参数 object 指定了要订阅事件的对象id. 参数 type 指定了事件的类型。如果客户端订阅了一个对象的某种事件,每次对象的这个事件发生后, Kurento Media Server就会使用 onEvent 方法发送一个请求到客户端。这种类型的请求会在后面的章节再讲解。

以下示例显示请求消息,请求在PlayerEndpoint对象上预订事件类型EndOfStream:

{"id": 11,"method": "subscribe","params": {"type": "EndOfStream","object": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline/76dcb8d7-5655-445b-8cb7-cf5dc91643bc_kurento.PlayerEndpoint","sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}

响应消息包含了订阅标识符,这个值会在后面的解除订阅中要用到。

下面的示例显示一个订阅请求的响应消息,属性 value 的值包含了订阅id:

{"id": 11,"result": {"value": "052061c1-0d87-4fbd-9cc9-66b57c3e1280","sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}

Unsubscribe

Unsubscribe 消息请求解除前面事件的订阅。参数 subscription 包含了从服务端收到的成功订阅后的订阅id。

以下示例显示请求消息,请求取消给定对象353be312-b7f1-4768-9117-5c2f5a087429的订阅:

{"id": 38,"method": "unsubscribe","params": {"subscription": "052061c1-0d87-4fbd-9cc9-66b57c3e1280","object": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline/76dcb8d7-5655-445b-8cb7-cf5dc91643bc_kurento.PlayerEndpoint","sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}

响应消息包含了sessionId。下面的示例显示了一个解除订阅请求的响应:

{"id": 38,"result": {"sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}

OnEvent

当客户端订阅了对象的某类事件后,每当对象的这类事件发生时,服务端都会发送一个onEvent请求。这也是为什么Kurento协议要使用Websocket并要在客户端和服务端间使用全双工的工作模式。服务端发送到客户端的请求包含了事件的所有信息:

  • source: 事件的对象源。

  • type: 事件的类型。

  • timestamp:媒体服务器时间

  • tags: 可以使用setSendTagsInEvents和addTag方法在每个元素中标记媒体元素。 这些标记是键值元数据,可供开发人员用于自定义目的。 媒体服务器在此字段中为每个事件返回标签。

下面的显示了服务端发送到客户端的提醒:

{"jsonrpc":"2.0","method":"onEvent","params":{"value":{"data":{"source":"681f1bc8-2d13-4189-a82a-2e2b92248a21_kurento.MediaPipeline/e983997e-ac19-4f4b-9575-3709af8c01be_kurento.PlayerEndpoint","tags":[],"timestamp":"1441277150","type":"EndOfStream"},"object":"681f1bc8-2d13-4189-a82a-2e2b92248a21_kurento.MediaPipeline/e983997e-ac19-4f4b-9575-3709af8c01be_kurento.PlayerEndpoint","type":"EndOfStream"}}
}

通知消息没有 id 字段是因为响应不是必须的。

网络问题

KMS处理的资源是高消耗的,因此,KMS实现了一个垃圾收集器。

当客户端断开连接后超过4分钟,媒体元件就会被收集。在这个时间后,这些媒体元件会被自动处理。

因此,客户端和KMS间的websocket连接可以在任何时间激活。当网络临时中断中,KMS实现了一个和客户端重连的机制。

有一种基于上面格式特殊类型的消息,这个消息允许客户端重新连接到前面连接KMS:

{"jsonrpc": "2.0","id": 7,"method": "connect","params": {"sessionId":"4f5255d5-5695-4e1c-aa2b-722e82db5260"}
}

如果KMS回应如下:

{"jsonrpc": "2.0","id": 7,"result": {"sessionId":"4f5255d5-5695-4e1c-aa2b-722e82db5260"}
}

则表示客户端重新连接到了同一个KMS。如果连接到了其它KMS, 则消息如下:

{"jsonrpc":"2.0","id": 7,"error":{"code":40007,"message":"Invalid session","data":{"type":"INVALID_SESSION"}}
}

在这种情况下,客户端应该再次调用原始的连接以获得一个新的sessionId:

{"jsonrpc":"2.0","id": 7,"method":"connect"
}

Kurento API

为了实现一个Kurento客户端,你需要仔细阅读本文档。而知道所有细节的最好的方式是查看IDL文件,它定义了Kurento元件的接口。我们已经定义了基于JSON的通用IDL格式。从它开始,我们为Java和JavaScript生成了客户端代码。Kurento API定义了下列IDL文件:

  • KMS core
  • KMS elements
  • KMS filters

Example: WebRTC in loopback

本章节描述了Kurento客户端和Kurento Media Server实现了下WebRTC回话功能的消息交互。它完整地展示了教程中的过程 ,步骤如下:

[ 1 ] 客户端发送一个创建媒体管道的请求消息:

{"id":1,"method":"create","params":{"type":"MediaPipeline","constructorParams":{},"properties":{}},"jsonrpc":"2.0"
}

[ 2 ] KMS回应一个包含有媒体管道ID和媒体会话ID(sessionId)的响应消息:

{"id":1,"result":{"value":"c4a84b47-1acd-4930-9f6d-008c10782dfe_MediaPipeline","sessionId":"ba4be2a1-2b09-444e-a368-f81825a6168c"},"jsonrpc":"2.0"
}

[ 3 ] 这里是列表文本 客户端发送一个创建WebRtcEndpoint的请求:

{"id":2,"method":"create","params":{"type":"WebRtcEndpoint","constructorParams":{"mediaPipeline":"c4a84b47-1acd-4930-9f6d-008c10782dfe_MediaPipeline"},"properties": {},"sessionId":"ba4be2a1-2b09-444e-a368-f81825a6168c"},"jsonrpc":"2.0"
}

[ 4 ] KMS创建一个WebRtcEndpoint,并回给客户端这个媒体元件的标识符:

{"id":2,"result":{"value":"c4a84b47-1acd-4930-9f6d-008c10782dfe_MediaPipeline/e72a1ff5-e416-48ff-99ef-02f7fadabaf7_WebRtcEndpoint","sessionId":"ba4be2a1-2b09-444e-a368-f81825a6168c"},"jsonrpc":"2.0"
}

[ 5 ] 客户端调用WebRtcEndpoint的连接原语来创建一个回放:

{"id":3,"method":"invoke","params":{"object":"c4a84b47-1acd-4930-9f6d-008c10782dfe_MediaPipeline/e72a1ff5-e416-48ff-99ef-02f7fadabaf7_WebRtcEndpoint","operation":"connect","operationParams":{"sink":"c4a84b47-1acd-4930-9f6d-008c10782dfe_MediaPipeline/e72a1ff5-e416-48ff-99ef-02f7fadabaf7_WebRtcEndpoint"},"sessionId":"ba4be2a1-2b09-444e-a368-f81825a6168c"},"jsonrpc":"2.0"
}

[ 6 ] KMS执行连接并回应这个操作:

{"id":3,"result":{"sessionId":"ba4be2a1-2b09-444e-a368-f81825a6168c"},"jsonrpc":"2.0"
}

[ 7 ] 客户端调用WebRtcEndpoint的processOffer原语来进行WebRTC的SDP协商:

{"id":4,"method":"invoke","params":{"object":"c4a84b47-1acd-4930-9f6d-008c10782dfe_MediaPipeline/e72a1ff5-e416-48ff-99ef-02f7fadabaf7_WebRtcEndpoint","operation":"processOffer","operationParams":{"offer":"SDP"},"sessionId":"ba4be2a1-2b09-444e-a368-f81825a6168c"},"jsonrpc":"2.0"
}

[ 8 ] KMS执行SDP协商并返回SDP回答:

{"id":4,"result":{"value":"SDP"},"jsonrpc":"2.0"
}

Kurento Module Creator

默认的Kurento客户端(java和JavaScript)是使用一个叫作 Kurento Module Creator的工具创建的。因此,这个工具同样可以被用来创建基于其它语言的定制化客户端。

Kurento Module Creator在Ubuntu机器上使用如下命令安装:

sudo apt-get install kurento-module-creator

这个工具的目的是为了生成客户端代码,以及生成服务端需要的glue代码。对于代码生成,它通常使用Freemarker 作为模板引擎。通常的使用Kurento Module Creater 的方式是运行如下命令:

kurento-module-creator -c <CODEGEN_DIR> -r <ROM_FILE> -r <TEMPLATES_DIR>

在这里 :

  • CODEGEN_DIR: 生成文件的目的路径

  • ROM_FILE: 包含这个文件的 Kurento Media Element Description (kmd)文件列表或文件夹的空间划分。例如: 你可以看下 Kurento Media Server内部源代码。

  • TEMPLATES_DIR: 包含模版文件的目录。例如:你可以看一下内部 java 和 javascript 的模版。

转载于:https://my.oschina.net/997155658/blog/840265

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396733.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

升级php7_PhpStorm 2019.3 发布,全面支持 PHP 7.4

PhpStorm 2019.3 发布了&#xff0c;这个版本主要集中在性能和质量上&#xff0c;旨在提供一个更稳定、更快的 IDE。PhpStorm 2019.3 全面支持 PHP 7.4&#xff0c;还带来 PSR-12 代码样式&#xff0c;用于远程解释器的 WSL&#xff0c;MongoDB 支持&#xff0c;HTTP 客户端更新…

ftp 客户端 使用http代理 源码_代理服务器连接HTTPS过程

说到HTTPS代理很多人瞬间就会联想到HTTPS的各种证书和各种加密&#xff0c;觉得很高端很复杂的样子。其实不然&#xff0c;代理服务器不需要配置证书、也不需要处理任何加密。因为HTTPS代理是通过Web隧道(Web tunnel)工作的。Web隧道允许用户通过HTTP连接发送非HTTP流量(例如FT…

python解zuobiaoxi方程_Python还能解决数学相关问题?大学生:以后就靠他了,事半功倍...

问题背景高等数学应用非常广&#xff0c;基本上涉及到函数的地方都要用到微积分&#xff0c;还有在几何方面也是如此&#xff0c;计算机的应用让我们能简单快速处理各种高等数学中的计算&#xff0c;比如极限、导数、积分、微分方程等的计算。实验目的使用 Python 通过计算与作…

基础正则表达式介绍与练习

基础正则表达式介绍与练习 一、什么是正则表达式 在做文字处理或编写程序时&#xff0c;用到查找、替换等功能&#xff0c;使用正则表达式能够简单快捷的完成目标。简单而言&#xff0c;正则表达式通过一些特殊符号的帮助&#xff0c;使用户可以轻松快捷的完成查找、删除、替换…

android canvas 网络图,【巨坑:toDataURL】canvas合成网络图片

不知有没有小伙伴用过canvas合成图片&#xff0c;然后爆炸报错截图尼玛&#xff0c;然后各种搜索&#xff0c;不外乎以下几种坑爹处理方案&#xff1a;后端处理&#xff0c;比如Access-Control-Allow-Origin "*"(要是请求到其他网站的图片就不适用了&#xff0c;比如…

水晶报表如何查看sql_有了这个报表工具,一键生成自定义的各种报表,还可以导出Excel...

EasyReport是一个简单易用的Web报表工具,它的主要功能是把SQL语句查询出的数据转换成报表页面&#xff0c; 同时支持表格的跨行(RowSpan)与跨列(ColSpan)配置。 同时它还支持报表Excel导出、图表显示及固定表头与左边列的功能。功能介绍本工具从数据库(MySQL,Oracle,SQLServer,…

Sitemesh3的使用及配置

1 . Sitemesh 3 简介 Sitemesh 是一个网页布局和修饰的框架&#xff0c;基于 Servlet 中的 Filter&#xff0c;类似于 ASP.NET 中的‘母版页’技术。参考&#xff1a;百度百科&#xff0c;相关类似技术&#xff1a;Apache Tiles。 官网&#xff1a;http://wiki.sitemesh.org/wi…

鸿蒙系统r如何升级,高歌猛进,鸿蒙系统升级机型再次确认,花粉:终等到!...

虽然华为手机现在的压力非常大&#xff0c;但是在前进的道路上&#xff0c;真的充满了乐观精神&#xff0c;而且现在也算是一路高歌猛进了&#xff0c;发展路线开始加快了许多&#xff0c;无论是新机还是系统&#xff0c;都有着非常多的新消息。因为华为手机的实力很强&#xf…

android studio背景模糊_[Android翻译]CameraX:过去、现在和未来的一瞥

CameraX是一个未捆绑的Android Jetpack库&#xff0c;它可以帮助你在Android应用中轻松添加摄像头功能。传统上&#xff0c;由于Android设备种类繁多&#xff0c;编程模型复杂&#xff0c;在Android上构建具有相机功能的应用程序非常困难。现在成千上万的开发者都在使用CameraX…

export function函数传参_04 js高阶函数(惰性函数、柯里化函数、compose函数)和单例设计模式...

高阶函数的定义在《javascript设计模式和开发实践》中是这样定义的。函数可以作为参数被传递&#xff1b;函数可以作为返回值输出。结合这两个特点&#xff0c;首先想到的肯定是回调函数&#xff0c;回调函数也是高阶函数的一种&#xff0c;除了回调函数&#xff0c;还有很多的…

mysql相关命令操作

2019独角兽企业重金招聘Python工程师标准>>> 远程连接容器中的mysql&#xff1a;mysql -h 192.168.5.116 -P 3306 -u root -p123456 启动mysql容器&#xff1a; $ sudo docker pull mysql:5.6.35 $ sudo docker run --name mysql -p 12345:3306 -e MYSQL_ROOT_PASSW…

html实体注册商标,html 注册商标,html 注册商标代码

html中注册的页面用什么标签写好对于html中的注册页面&#xff0c;策朋专业办理商标注册、专利申请、版权登记保护&#xff0c;需要一个表格。使用标签&#xff0c;输入和按钮标签来组合成就。使用html作为注册页面。实际上&#xff0c;只要您能达到期望的效果&#xff0c;它的…

java已知一个二叉树_#二叉树复习#

#二叉树复习#目录满二叉树完全二叉树平衡二叉树二叉树的主要性质--二叉树的度--二叉树的深度计算二叉树的遍历其他符号变量结点总数深度度为0的结点数/叶子结点数度为1的结点数度为2的结点数什么是满二叉树&#xff1f;二叉树每层的结点数为。满二叉树总结点数&#xff1a;。图…

java 反射机制_基础篇:深入解析JAVA反射机制

反射的概念java 的放射机制&#xff1a;在程序运行时&#xff0c;程序有能力获取一个类的所有方法和属性&#xff1b;并且对于任意一个对象&#xff0c;可以调用它的任意方法或者获取其属性通俗解析&#xff1a;java 文件需要编译成. class 文件才能被 jvm 加载使用, 对象的. c…

html div float center,跨浏览器实现float:center

跨浏览器实现float:center互联网 发布时间&#xff1a;2008-10-17 19:26:11 作者&#xff1a;佚名 我要评论原文&#xff1a;http://www.macji.com/blog/article/to-achieve-cross-browser-css-float-center/to-achieve-cross-browser-css-float-center/我们都知道float…

oracle左连接没用_一周零基础学完Oracle数据库第三天02

四、 多表查询1 什么是多表查询多表查询&#xff1a;当查询的数据并不是来源一个表时&#xff0c;需要使用多表链接操作完成查询。根据 不同表中的数据之间的关系查询相关联的数据。多表链接方式&#xff1a; 内连接&#xff1a;连接两个表&#xff0c;通过相等或不等判断链接列…

weblogic启动项目报错找不到类_启动类报错是经常出现的事但是单一的从一个地方找原因会越找越错...

Error starting ApplicationContext. To display the conditions report rerun your application with debug enabled.当我们看到这个报错的时候有的说是jar包重复&#xff0c;有的说是Controller包和Application包处于平行位置&#xff0c;还有的觉得是RequestMapping的valu…

深入理解javascript原型和闭包(7)——原型的灵活性

在Java和C#中&#xff0c;你可以简单的理解class是一个模子&#xff0c;对象就是被这个模子压出来的一批一批月饼&#xff08;中秋节刚过完&#xff09;。压个啥样&#xff0c;就得是个啥样&#xff0c;不能随便动&#xff0c;动一动就坏了。 而在javascript中&#xff0c;就没…

c语言为什么有这么多的编程环境?_为什么98%的程序员学编程都会从C语言开始?...

在互联网蓬勃发展的时代&#xff0c;有一类人做出了巨大的贡献&#xff0c;这一群人被大家称之为程序员&#xff0c;怎样才能成为一名优秀的程序员呢&#xff0c;为什么每一个程序员都需要学习C语言呢&#xff1f;就让我来跟大家分享分享&#xff1a;壹第一&#xff1a;相比较其…

Angular 星级评分组件

一、需求演变及描述&#xff1a; 1. 有一个“客户对公司的总体评价”的字段&#xff08;evalutation&#xff09;。字段为枚举类型&#xff0c;0-5&#xff0c;对应关系为&#xff1a;0-暂无评价&#xff0c;1-很差&#xff0c;2-差&#xff0c;3-一般&#xff0c;4-好&#xf…