`
webcenterol
  • 浏览: 915730 次
文章分类
社区版块
存档分类
最新评论

如何实现对JVoicebridge的二次开发

 
阅读更多

如何实现对JVoicebridge的二次开发

作者:kagula

时间:2008-10-23

内容简介

JVoicebridge是个开源的音频会议软件。

本文主要介绍把JVoicebridge提供的功能,集成到自己程序中的手段。

JVoicebridge的使用可以参考《JVoiceBridge使用简介》

阅读前提

[1]Java开发经验

[2]Eclipse使用经验

[3]svn插件使用经验

[4]如何使用JVoicebridge

正文

我这里使用的环境是: JDK 1.6.xMyEclipse5.1.x svn1.2.x

进入官网首页,点击项目工具中的subversion项,根据里面的svn地址,把源码download下来。利用源码包中的softphone,新建一个softphone项目。

展开softphone源码,com.sun.mc.softphone包中的SipCommunicator类就是Softphone程序的入口。几个重要类之间实例化过程,如下图:

图一(实例化过程)

上图红色部份是我们重点要了解的,打开NewPhoneFrame.java文件,这里一个继续JFrameGUI表单类。用户通过它同Softphone的其它部份交互。

NewPhoneFrame的公共控件变量、公共成员函数,都是为了被NewGuiManager调用。而当用户的操作,激发NewPhoneFrame的某部份代码时,它的“执行流”,则会先流到NewGuiManager

如果,你只是想为Softphone换一个人机界面,那就从NewPhoneFrame入手吧!参考NewPhoneFrame为自己写一个MyPhoneFrame,替换NewGuiManager.java中出现的字符串NewPhoneFrameMyPhoneFrame。我这里替换了两次。再次运行SipCommunicator,你会发现Softphone的界面已经换成了你的NewPhoneFrame

更进一步

Softphone,进行API封装。

现在我们建立一个新类CSoftphone,用它来封装Softphone的应用程序接口。

图二(Softphone类图)

第一步,我们来构造CSoftphone

构造函数代码段如下:

private SipCommunicator sipCommunicator=null; //Softphone的全局对象,行28

private NewGuiManager gm=null; //GUI管理器,行29

/**

* @param args 控制台过来的,参数列表

* @throws Exception 构造失败,简单抛出异常

*/

public CSoftphone(String[] args) throws Exception

{

try {

sipCommunicator = new SipCommunicator(args); //38

} catch (ParseException e) {

SipCommunicator.usage();

System.exit(1);

throw new Exception("Initialization failed!");

}

gm = (NewGuiManager)sipCommunicator.guiManager; //44

}

上面的代码片段中,红色部份,是值得注意的。

38代码类同SipCommunicator::main()函数体部份。不要忘记,传给它的参数列表中包含”-nogui”,因为,我们不需要SipCommunicator提供给我们的缺省窗口。

44的代码是为了方便我们以后封装SoftphoneAPI

第二步,建立接口

接口代码如面。这里要注意的是,导入CSoftphone接口,你会发现很多来自Softphone的方法或类,不能被找到,请找到这些源码的位置,把它们的存取属性改为public

下面是拨号,代码

/**

* 拨打电话;它是异步的,你应该从回调函数中,获取,Dial是否成功的结果。请参考setRecall方法。

* 注意:已经在Dial的状态下,再dial会导致Softphone抛出异常

* @param strID PhoneNumber 例如:6666@192.168.0.112 c=cc

其中IP地址,是你bridge所在的地址,c=cc,表示,加入cc会议。

* @return

*/

public void dial(String strID)

{

//正文

gm.alertManager.stopAllAlerts();

String callee=gm.format(strID);

UserCallInitiationEvent commEvt = new UserCallInitiationEvent(callee);

for (int i = gm.listeners.size() - 1; i >= 0; i--) {

( (UserActionListener) gm.listeners.get(i)).handleDialRequest(commEvt);

}

}

/**

* 实例化这个类的对象后,应该调用下面的成员函数

* 释放Softphone

*/

public void exit()

{

for (int i = gm.listeners.size() - 1; i >= 0; i--) {

( (UserActionListener) gm.listeners.get(i)).handleExitRequest();

}

}

注意:exit函数,没有及时调用,可能会造成,你的程序退出了,但是Softphone还没有退出。

接口中封装的代码,都是来自Softphone包的NewGuiManager类,你只要如上,稍微修改,就能直接使用了。

第三步,如何回调

上面的Dial从某种角度上来说是异步的,怎么才能知道,你已经加入了通话状态, 这就需要一个接口。这里我定义了ISoftphone

图三(ISoftphone接口)

/**

* 设置状态通知

* @param objRecall Softphone会把当前工作情况通知给objRecall对象

*/

public void setRecall(ISoftphone objRecall)

{

gm.listenNGM=objRecall;

}

假设inst是你的应用对象,那么inst对象,所属的类必须继承ISoftphone。因为,只有这样,Softphone才能将消息,通知给你的应用对象。

同时,我们还必须稍微修改下NewGuiManager::update函数体,在update函数体的后部份,加入下面的代码:

/* public ISoftphone listenNGM=null; 这段代码是加在NewGuiManager,成员变量说明中的。

*/

if(listenNGM!=null)

{

listenNGM.updataStatus(state); // 352

}

352:的代码,是为了当NewGuiManager::update被激发时,实现ISoftphone接口的listenNGM::updataStatus也能被激发,这样才能把Softphone的状态,通知到你的应用对象。

第四步,如何使用接口

我们的接口,现在全部封装在CSoftphone类中[1]我们先要实例化CSoftphone [2]然后把CSoftphone的实例,告诉你的应用对象。[3]最后在CSoftphone实例中设置你的回调对象。

源码片段如下:

/**

* 开头部份代码,略

*/

Public static void main(String[] args) {

//启动Softphone

CSoftphone softphone=null;

/**

* 实例化CSoftphone,并为CSoftphoneargs数组中,添加”-nogui”,屏蔽掉Softphone自己的图形化人机界面。这里的代码略。

*/

//启动你的GUI 这里你的应用对象是inst

NewJFrame inst = new NewJFrame();

//设置回调,使softphone的状态更新能够通知到inst

softphone.setRecall(inst);

//softphone扔给inst,使在应用对象里可以调用它

inst.m_softphone = softphone;

/**

* 启动(Launch) inst应用对象,详细的代码略。

*/

后言

正文对如何实现Softphone的封装做了下简单的介绍,有些实现细节没有谈到,具体请参考CSoftphone.java文件中的内容,它可以给你更进一步的信息。希望此文可以带领你步入Softphone两次开发的大门。

参考资源

[1]JVoicebridge官网 jvoicebridge.dev.java.net

附CSoftphone.java源代码

  1. packagecom.cwebs.softphone;
  2. importjava.io.IOException;
  3. importjava.text.ParseException;
  4. importcom.sun.mc.softphone.SipCommunicator;
  5. importcom.sun.mc.softphone.common.Utils;
  6. importcom.sun.mc.softphone.gui.InterlocutorUI;
  7. importcom.sun.mc.softphone.gui.NewGuiManager;
  8. importcom.sun.mc.softphone.gui.event.UserActionListener;
  9. importcom.sun.mc.softphone.gui.event.UserCallControlEvent;
  10. importcom.sun.mc.softphone.gui.event.UserCallInitiationEvent;
  11. importcom.sun.mc.softphone.media.CallDoneListener;
  12. importcom.sun.mc.softphone.media.MediaManager;
  13. importcom.sun.mc.softphone.media.MediaManagerFactory;
  14. /**
  15. *这里定义Softphone的封装接口
  16. *警告!这里的接口基本上都未做入口参数,和调用合法性检查
  17. *请在你的应用层上完成该工作。
  18. *注意:虽然Softphone有Line1~Line4,四个语音通道,但是
  19. *根据JVoiceBridgeDocument,是只用到了Line1,而且
  20. *本接口的需求,也没有要求多Line,因此,本接口只使用Line1。
  21. *@authorkagula
  22. *
  23. */
  24. publicclassCSoftphone{
  25. privateSipCommunicatorsipCommunicator=null;//原Softphone的全局对象
  26. privateNewGuiManagergm=null;//GUI管理器
  27. /**
  28. *@paramargs控制台过来的,参数列表
  29. *@throwsException构造失败,简单抛出异常
  30. */
  31. publicCSoftphone(String[]args)throwsException
  32. {
  33. try{
  34. sipCommunicator=newSipCommunicator(args);
  35. }catch(ParseExceptione){
  36. SipCommunicator.usage();
  37. System.exit(1);
  38. thrownewException("Initializationfailed!");
  39. }
  40. gm=(NewGuiManager)sipCommunicator.guiManager;
  41. }
  42. /**
  43. *设置状态通知
  44. *@paramobjRecallSoftphone会把当前工作情况通知给objRecall对象
  45. */
  46. publicvoidsetRecall(ISoftphoneobjRecall)
  47. {
  48. gm.listenNGM=objRecall;
  49. }
  50. /**
  51. *拨打电话;它是异步的,你应该从回调函数中,获取,Dial是否成功的结果。请参考setRecall方法。
  52. *注意:已经在Dial的状态下,再dial会导致Softphone抛出异常
  53. *@paramstrIDPhoneNumber
  54. *@return
  55. */
  56. publicvoiddial(StringstrID)
  57. {
  58. //正文
  59. gm.alertManager.stopAllAlerts();
  60. Stringcallee=gm.format(strID);
  61. UserCallInitiationEventcommEvt=newUserCallInitiationEvent(callee);
  62. for(inti=gm.listeners.size()-1;i>=0;i--){
  63. ((UserActionListener)gm.listeners.get(i)).handleDialRequest(commEvt);
  64. }
  65. }
  66. /**
  67. *实例化这个类的对象后,应该调用下面的成员函数
  68. *释放Softphone
  69. */
  70. publicvoidexit()
  71. {
  72. for(inti=gm.listeners.size()-1;i>=0;i--){
  73. ((UserActionListener)gm.listeners.get(i)).handleExitRequest();
  74. }
  75. }
  76. /**
  77. *对Softphone进行设置
  78. *警告!函数不对strValue的合法性进行检查,
  79. *若strValue不在strKey的取值范围,可能会造成Softphone不能正常工作
  80. *设置注册表下面位置中的信息
  81. *HKEY_CURRENT_USER/Software/JavaSoft/Prefs/com/sun/mc/softphone/common
  82. *@paramstrKey取值范围请查看源代码内的注释
  83. *@paramstrValue取值范围请查看源代码内的注释
  84. */
  85. publicvoidsetPreference(StringstrKey,StringstrValue)
  86. {
  87. //media系列设置
  88. if(strKey.equalsIgnoreCase("CHANNELS"))
  89. {
  90. //设置声道,取值范围1,2
  91. Utils.setPreference("com.sun.mc.softphone.media.CHANNELS",strValue);
  92. Utils.setPreference("com.sun.mc.softphone.media.TRANSMIT_CHANNELS",strValue);
  93. }
  94. if(strKey.equalsIgnoreCase("SAMPLE_RATE"))
  95. {
  96. //设置采样率,建议8000,取值范围8000,16000
  97. Utils.setPreference("com.sun.mc.softphone.media.SAMPLE_RATE",strValue);
  98. Utils.setPreference("com.sun.mc.softphone.media.TRANSMIT_SAMPLE_RATE",strValue);
  99. }
  100. if(strKey.equalsIgnoreCase("MICROPHONE_BUFFER_SIZE"))
  101. {
  102. //设置Microphone缓存,建议60,取值范围0,大于等于60的正整数
  103. Utils.setPreference("com.sun.mc.softphone.media.MICROPHONE_BUFFER_SIZE",strValue);
  104. }
  105. //sip系列设置
  106. if(strKey.equalsIgnoreCase("REGISTRAR_ADDRESS"))
  107. {
  108. //设置bridge服务器地址,例如:192.168.0.112
  109. Utils.setPreference("com.sun.mc.softphone.sip.REGISTRAR_ADDRESS",strValue);
  110. }
  111. if(strKey.equalsIgnoreCase("USER_NAME"))
  112. {
  113. //设置登录到bridge去的,登录名,例如:Administrator
  114. Utils.setPreference("com.sun.mc.softphone.sip.AUTHENTICATION_USER_NAME",strValue);
  115. Utils.setPreference("com.sun.mc.softphone.sip.USER_NAME",strValue);
  116. }
  117. if(strKey.equalsIgnoreCase("OUTBOUND_PROXY_ADDRESS"))
  118. {
  119. //设置代理服务器地址及端口,缺省值为129.148.75.104:5060//udp
  120. Utils.setPreference("javax.sip.OUTBOUND_PROXY_ADDRESS",strValue);
  121. }
  122. //gui系列设置
  123. if(strKey.equalsIgnoreCase("LAST_FILE_PLAYED"))
  124. {
  125. //设置最近播放的文件名,遵循文件名命名规范,中文文件名未做测试。
  126. Utils.setPreference("com.sun.mc.softphone.gui.LAST_FILE_PLAYED",strValue);
  127. }
  128. if(strKey.equalsIgnoreCase("LAST_FILE_RECORDED"))
  129. {
  130. //设置最近录音的文件名,遵循文件名命名规范,中文文件名未做测试。
  131. Utils.setPreference("com.sun.mc.softphone.gui.LAST_FILE_RECORDED",strValue);
  132. }
  133. }
  134. /**
  135. *从注册表的下面位置中取配置信息
  136. *HKEY_CURRENT_USER/Software/JavaSoft/Prefs/com/sun/mc/softphone/common
  137. *@paramstrKey
  138. *@return
  139. */
  140. publicStringgetPreferece(StringstrKey)
  141. {
  142. //media系列设置
  143. if(strKey.equalsIgnoreCase("CHANNELS"))
  144. {
  145. //设置声道,取值范围1,2
  146. returnUtils.getPreference("com.sun.mc.softphone.media.CHANNELS");
  147. //Utils.setPreference("com.sun.mc.softphone.media.TRANSMIT_CHANNELS",strValue);
  148. }
  149. if(strKey.equalsIgnoreCase("SAMPLE_RATE"))
  150. {
  151. //设置采样率,建议8000,取值范围8000,16000
  152. returnUtils.getPreference("com.sun.mc.softphone.media.SAMPLE_RATE");
  153. //Utils.setPreference("com.sun.mc.softphone.media.TRANSMIT_SAMPLE_RATE",strValue);
  154. }
  155. if(strKey.equalsIgnoreCase("MICROPHONE_BUFFER_SIZE"))
  156. {
  157. //设置Microphone缓存,建议60,取值范围0,大于等于60的正整数
  158. returnUtils.getPreference("com.sun.mc.softphone.media.MICROPHONE_BUFFER_SIZE");
  159. }
  160. //sip系列设置
  161. if(strKey.equalsIgnoreCase("REGISTRAR_ADDRESS"))
  162. {
  163. //设置bridge服务器地址,例如:192.168.0.112
  164. returnUtils.getPreference("com.sun.mc.softphone.sip.REGISTRAR_ADDRESS");
  165. }
  166. if(strKey.equalsIgnoreCase("USER_NAME"))
  167. {
  168. //设置登录到bridge去的,登录名,例如:Administrator
  169. returnUtils.getPreference("com.sun.mc.softphone.sip.AUTHENTICATION_USER_NAME");
  170. //Utils.setPreference("com.sun.mc.softphone.sip.USER_NAME",strValue);
  171. }
  172. if(strKey.equalsIgnoreCase("OUTBOUND_PROXY_ADDRESS"))
  173. {
  174. //设置代理服务器地址及端口,缺省值为129.148.75.104:5060//udp
  175. returnUtils.getPreference("javax.sip.OUTBOUND_PROXY_ADDRESS");
  176. }
  177. //gui系列设置
  178. if(strKey.equalsIgnoreCase("LAST_FILE_PLAYED"))
  179. {
  180. //设置最近播放的文件名,遵循文件名命名规范,中文文件名未做测试。
  181. returnUtils.getPreference("com.sun.mc.softphone.gui.LAST_FILE_PLAYED");
  182. }
  183. if(strKey.equalsIgnoreCase("LAST_FILE_RECORDED"))
  184. {
  185. //设置最近录音的文件名,遵循文件名命名规范,中文文件名未做测试。
  186. returnUtils.getPreference("com.sun.mc.softphone.gui.LAST_FILE_RECORDED");
  187. }
  188. returnnull;
  189. }
  190. /**
  191. *开始录音
  192. *@paramstrPath文件名,文件的编码形式为wav,自动存放到当前目录。
  193. *@paramrecordingMic从Mic中记录,建议设为true
  194. *@paramobjListener实现CallDoneListener接口的对象,当Softphone关闭时,该
  195. *接口的callDone方法会被调用
  196. *@throwsIOException
  197. */
  198. publicvoidstartRecording(StringstrPath,booleanrecordingMic,CallDoneListenerobjListener)throwsIOException
  199. {
  200. //入口参数检查
  201. if(strPath==null||strPath.length()<1)
  202. {
  203. return;
  204. }
  205. //正文
  206. MediaManagermediaManager;
  207. mediaManager=MediaManagerFactory.getInstance();
  208. if(mediaManager!=null)
  209. {
  210. mediaManager.startRecording(strPath,newString("au"),recordingMic,objListener);
  211. }
  212. }
  213. /**
  214. *录音结束
  215. *@paramrecordingMic从Mic中记录,建议设为true
  216. */
  217. publicvoidstopRecording(booleanrecordingMic)
  218. {
  219. //正文
  220. MediaManagermediaManager;
  221. mediaManager=MediaManagerFactory.getInstance();
  222. if(mediaManager!=null)
  223. {
  224. mediaManager.stopRecording(recordingMic);
  225. }
  226. }
  227. /**
  228. *挂断Dialing
  229. *
  230. */
  231. publicvoidhangup()
  232. {
  233. InterlocutorUIinter=gm.interlocutors.getInterlocutorAt(0);
  234. if(inter!=null){
  235. UserCallControlEventcommEvt=newUserCallControlEvent(inter);
  236. for(inti=gm.listeners.size()-1;i>=0;i--){
  237. ((UserActionListener)gm.listeners.get(i)).handleHangupRequest(
  238. commEvt);
  239. }
  240. }
  241. }
  242. /**
  243. *应答
  244. *
  245. */
  246. publicvoidanswer()
  247. {
  248. InterlocutorUIinter=gm.interlocutors.getInterlocutorAt(0);
  249. if(inter!=null){
  250. UserCallControlEventcommEvt=newUserCallControlEvent(inter);
  251. for(inti=gm.listeners.size()-1;i>=0;i--){
  252. ((UserActionListener)gm.listeners.get(i)).handleAnswerRequest(
  253. commEvt);
  254. }
  255. }
  256. }
  257. /**
  258. *静音
  259. *
  260. */
  261. publicvoidmute()
  262. {
  263. InterlocutorUIinter=gm.interlocutors.getInterlocutorAt(0);
  264. if(inter!=null){
  265. UserCallControlEventcommEvt=newUserCallControlEvent(inter);
  266. for(inti=gm.listeners.size()-1;i>=0;i--){
  267. ((UserActionListener)gm.listeners.get(i)).handleMuteRequest(
  268. commEvt);
  269. }
  270. }
  271. }
  272. }

分享到:
评论

相关推荐

    red5-voicebridge:使用Red5的Adobe Flash开源SIP会议桥

    red5-语音桥使用Red5的Adobe Flash开源SIP会议桥= Red5VoiceBridge = Red5-voicebridge是一个基于SIP的语音桥引擎,基于Open Wonderland jVoiceBridge子项目。 它使Red5开发人员能够提供单个集成的,基于Web的开源...

    infrared-remote-candroid studiodemo

    android studio下载

    【新质生产力】新质生产力赋能智能制造数字化解决方案.pptx

    【新质生产力】新质生产力赋能智能制造数字化解决方案.pptx

    基于matlab实现的用于应用布格重力异常数据反演地下异常密度体.rar

    基于matlab实现的用于应用布格重力异常数据反演地下异常密度体.rar

    node-v8.10.0-linux-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于Yolov5目标检测和deepsort目标跟踪无人机跟踪.zip

    无人机最强算法源码,易于部署和学习交流使用

    数据库课程设计实战.zip

    数据库课程设计后端 使用Springboot + Mybatis + Redis + Maven 数据库课程设计实战.zip,使用到了所有的相关SQL 的操作,如增删改查等,让你可以在一个项目里面,锻炼到所有的数据库相关的知识。项目亲测可以运行,里面含有运行相关的文档,不会的可以丝我请求帮助。 数据库课程设计后端 使用Springboot + Mybatis + Redis + Maven 具体的表和相关的数据如下: 用户(电话号码,密码,身份证号,邮箱,真实姓名,用户类型,性别,地址) 乘客(用户电话号码,乘客身份证号,乘客真实姓名,乘客电话号码,乘客类型,地址) 列车信息(列车编号,车次,列车类型,列车车厢数,列车始发站,列车终点站,列车开车时间,列车到达时间,列车到达日期,列车运行时间,列车状态) 列车座位信息(列车编号,车厢号,座位类型,座位数) 列车经停信息(列车编号,车次,车站编号,车站名,到达时间,总运行时间,开车时间) 订单信息(订单编号,用户电话号码,乘客身份证号码,列车编号,出发站编号,到达站编号,车厢号,座位编号,订单创建时间,订单状态,开车时间)

    咨询的分析方法gl.ppt

    咨询的分析方法gl.ppt

    node-v10.14.0-linux-ppc64le.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    2019年电赛无人机题目(B题)OpenMV相关代码

    These're the OpenMV codes written by microPython in 2019 NUEDC. 2019年电赛无人机题目(B题)OpenMV相关代码(原创).zip

    无人机降落TRT版本.zip

    无人机最强算法源码,易于部署和学习交流使用

    熊出没.zip

    熊出没.zip

    基于SpringBoot和Vue的家教信息平台设计与实现.zip

    基于SpringBoot和Vue的家教信息平台设计与实现.zip 有完整的部署指导文档,源码也是完整的,可以直接运行,里面包含了所有的相关步骤。 本文旨在设计和实现一套基于Java技术的家教信息系统,采用Spring Boot框架构建后端服务,MySQL数据库存储数据,Vue.js作为前端框架实现用户界面。该系统旨在解决家教信息管理的问题,包括家教师资信息管理、用户信息管理以及家教入驻等功能。通过综合运用Java、Spring Boot、MySQL和Vue等技术,实现了系统的高效运行和良好的用户体验。系统提供了用户注册、登录、信息查看和编辑等功能,同时支持家教的发布和查看,用户信息的管理以及家教审核的后台管理。家长可以方便地寻找合适的家教老师,家教老师也能够更便捷地管理自己的信息和相关资料。通过本设计,展示了Java技术在现代化家教信息系统中的应用,为家教行业的信息化管理提供了一种有效的解决方案。该系统的设计与实现将为家长、家教老师和用户提供便利,促进家教行业的发展与进步。 关键词:SpringBoot; MySQL; 系统设计; 家教

    利用CNN进行无人售货机的商品识别.zip

    无人机最强算法源码,易于部署和学习交流使用

    node-v11.10.1-linux-armv6l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    (R语言)-6-箱线图的绘制

    (R语言)-6-箱线图的绘制

    麦肯锡-xx联通固定市场举措gl.ppt

    麦肯锡-xx联通固定市场举措gl.ppt

    在PyCharm中配置Python环境步骤

    附件是在PyCharm中配置Python环境步骤,文件绿色安全,请大家放心下载,仅供交流学习使用,无任何商业目的!

    【北京工业大学】集成电路分析与设计实验报告

    本课程实验分为数字集成电路设计实验与全定制设计实验两部分。 实验1—4为基于Cadence的数字集成电路设计实验部分,主要内容为通过一个简单数字低通滤波器的设计、综合、仿真,让学生熟悉数字集成电路前段实际设计流程,以培养学生实际设计集成电路的能力。具体为:实验1Matlab实现数字低通滤波器算法设计。 实验2Linux环境下基本操作。 实验3RTLCompiler对数字低通滤波器电路的综合。 实验4NC对数字低通滤波器电路的仿真。 其中,实验1主要目的是为了展示算法分析的方法和重要性。使用Matlab实现数字滤波器的算法设计和HDL代码生成。由于Matlab工具可以在Windows环境下工作,而其他集成电路EDA工具均需要在linux下工作,故建议本实验在课堂演示和讲述,学生课下练习。实验2的主要目的是学习linux下的基本操作。包括目录管理、文件管理、文件编辑以及文件压缩等在使用集成电路EDA工具时所需要的操作。本实验是实验3和实验4的基础,建议在实验室完成。

Global site tag (gtag.js) - Google Analytics