您的位置:首页 > 运维架构

Openmeetings4.0.0二次开发日志(三)使用webservice调用OM接口(1)

2017-12-03 16:04 489 查看
Openmeetings是将一些接口用webservice发布出来,可供调用的,今天讲一讲如何用利用webservice调用实现某些具体的业务场景。

首先启动Openmeetings,如果是linux上的,则切换到openmeetings的安装目录上运行nohup ./red5.sh start,windows版本下只需运行red5.bat文件即可,启动成功如下图:



然后可以访问:http://localhost:5080/openmeetings/services/services

在这上面你可以看到所有被发布出来的接口信息,有CalendarWebService,ErrorWebService,FileWebService,GroupWebService,InfoWebService,RecordingWebService,RoomWebService,UserWebService 8个接口,其中,我们主要使用RoomWebService和UserWebService两个,一个主要用于创建房间,一个主要用于人员登录。

新建一个项目,然后使用wsimport导入webservice的接口到项目里面。代开命令行工具,输入

wsimport -s D:\workspace\app\src\main\java  -p userwebService   http://localhost:5080/openmeetings/services/UserService?wsdl[/code] 
这句话的作用是将UserService生成的接口文件导入到我的项目中,wsimport是jdk自带的命令,可以根据wsdl文档生成客户端中间代码,基于生成的代码编写客户端,可以省很多麻烦。-s 表示 在指定的目录生成java源文件。-p会生成指定的包结构,最后是接口文件的路径。导入完成后的接口文件如下图:



接着,导入房间接口文件:

wsimport -s D:\workspace\app\src\main\java  -p roomService   http://localhost:5080/openmeetings/services/RoomService?wsdl[/code] 
如下图:



至此,接口导入完成,可以开始使用了。

现在来看几个业务场景:

现在有老师这个角色,他可以越过登录页面直接进入Openmeetings的公共房间。

老师也可以创建自定义的会议房间

有学生这个角色 ,学生没有自主进入公共房间或者创建房间的权限,但他可以被随意分配到一个老师创建的房间进行面试。

这三个需求的所有代码实现我先给出来,如下:

package com.avie.app.controller;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import roomService.OrgApacheOpenmeetingsWebserviceRoomWebService;
import roomService.RoomCountDTO;
import roomService.RoomDTO;
import roomService.RoomWebService;
import roomService.Type;
import userwebService.ExternalUserDTO;
import userwebService.OrgApacheOpenmeetingsWebserviceUserWebService;
import userwebService.RoomOptionsDTO;
import userwebService.ServiceResult;
import userwebService.UserWebService;

@RestController
@RequestMapping(value="/op")
@Api(value="测试对接openmeetings",tags="op")
public class SysmenuController {

private static RoomWebService roomService;
private static UserWebService userService;
private static Map<Long, Integer> roomCountersMap = new LinkedHashMap<>();

static {
OrgApacheOpenmeetingsWebserviceRoomWebService orgRoom = new OrgApacheOpenmeetingsWebserviceRoomWebService();
OrgApach
4000
eOpenmeetingsWebserviceUserWebService orgUser = new OrgApacheOpenmeetingsWebserviceUserWebService();
userService = orgUser.getUserService();
roomService = orgRoom.getRoomWebServicePort();
}

@ApiOperation(value="老师加入公共房间")
@RequestMapping(value="/addToRoom",method=RequestMethod.POST)
public ServiceResult createRoom(String id,String fname,String lname,Long roomId) throws RemoteException{

String sid = getSid("duyu","Dy@@2017");
//创建外部人员访问信息
ExternalUserDTO user = new ExternalUserDTO();
user.setEmail("zda@dwa.com");
user.setExternalId(id);
user.setExternalType("Teacher");
user.setFirstname(fname);
user.setLastname(lname);
user.setLogin("T"+id);

RoomOptionsDTO options = new RoomOptionsDTO();
options.setRoomId(roomId);
options.setShowAudioVideoTest(true);
options.setModerator(true);

userwebService.ServiceResult serviceRs = userService.getRoomHash(sid, user, options);
System.out.println(serviceRs.getMessage());

roomCountersMap.putIfAbsent(roomId, 1);

return serviceRs;
}

@ApiOperation(value="给学生随机分配面试房间")
@RequestMapping(value="/randomToRoom",method=RequestMethod.POST)
public ServiceResult randomToRoom(String id,String fname,String lname) throws RemoteException{

ServiceResult serviceRs;

//用户登录,获取sid
String sid = getSid("root","Avie@2017");

//创建外部人员访问信息
ExternalUserDTO user = new ExternalUserDTO();
user.setEmail("zda@dwa.com");
user.setExternalId(id);
user.setExternalType("student");
user.setFirstname(fname);
user.setLastname(lname);
user.setLogin("S"+id);

//取得所有开启的房间号,然后查询每个房间号的人数,如果有房间人数为1的房间,则视为空闲房间,可以进入面试
List<Long> list = new ArrayList<Long>();
Set<Long> set = roomCountersMap.keySet();
list.addAll(set);
OrgApacheOpenmeetingsWebserviceRoomWebService orgRoom = new OrgApacheOpenmeetingsWebserviceRoomWebService();
RoomWebService roomService = orgRoom.getRoomWebServicePort();
List<RoomCountDTO> rooms = roomService.counters(sid, list);
Long roomId = (long)0;
for(RoomCountDTO room : rooms) {
if(room.getRoomCount() == 1) {
roomId = room.getRoomId();
}
}
if(roomId == 0) {
serviceRs = new ServiceResult();
serviceRs.setMessage("对不起当前没有空闲房间,请等待!");
serviceRs.setType("noRoom");
return serviceRs;
}

RoomOptionsDTO options = new RoomOptionsDTO();
options.setRoomId(roomId);
options.setShowAudioVideoTest(true);
options.setModerator(false);

serviceRs = userService.getRoomHash(sid, user, options);
System.out.println(serviceRs.getMessage());

return serviceRs;
}

@ApiOperation(value="老师创建自定义房间")
@RequestMapping(value="/customizeRoom",method=RequestMethod.POST)
public ServiceResult customizeRoom(String id,String fname,String lname,String ty,long num) throws RemoteException{

//得到service
String sid = getSid("duyu","Dy@@2017");

RoomDTO room = new RoomDTO();
room.setType(Type.fromValue(ty));
room.setCapacity(num);
room.setAllowRecording(true);
room = roomService.add(sid, room);

//创建外部人员访问信息
ExternalUserDTO user = new ExternalUserDTO();
user.setEmail("zda@dwa.com");
user.setExternalId(id);
user.setExternalType("Teacher");
user.setFirstname(fname);
user.setLastname(lname);
user.setLogin("T"+id);

RoomOptionsDTO options = new RoomOptionsDTO();
options.setRoomId(room.getId());
options.setShowAudioVideoTest(true);
options.setModerator(true);

ServiceResult serviceRs = userService.getRoomHash(sid, user, options);
System.out.println(serviceRs.getMessage());

roomCountersMap.putIfAbsent(room.getId(), 1);

return serviceRs;
}

/**
* 得到某个登录用户的sid
*/
private String getSid(String name,String pwd) {
ServiceResult rs = userService.login(name, pwd);
return rs.getMessage();
}
}


让我们先来看第一个需求:

现在有老师这个角色,他可以越过登录页面直接进入Openmeetings的公共房间。

在第一章的时候我介绍过Openmeetings有7个公共房间,让我们先来看看如何利用webservice进入这几个公共房间。先看上面代码中的第一部分:



这里先通过静态代码块初始化两个参数:roomService和userService。通过OrgApacheOpenmeetingsWebserviceRoomWebService和OrgApacheOpenmeetingsWebserviceUserWebService各自的get方法来得到roomService和userService的实例。

接下来是老师进入公共房间的代码:



首先是得到了一个String类型的变量sid,那么这个sid是干什么的喃?,我们来看得到sid的getSid方法,如下图:



在这里,我们得到sid传入了两个参数,用户名和密码。这里先说明一下,Openmeetings的用户分为两类。一类是内部用户,这类用户需要通过openmeetings的注册页面完成之后才能使用,这类用户是必需要密码的;另一类用户为外部用户,通过调用webservice的接口创建,不需要密码,但要创建外部用户必需先使用拥有soap权限的内部用户登录。这个soap权限并非每个用户都有,一般情况下默认只有初始化Openmeetings时创建的root用户有,所以各位童鞋这里的用户名密码需要填你设置的root用户的用户名和密码。当然,你也可以通过root用户给其他内部用户分配soap权限,使得其他内部用户也可以创建外部用户。如果你的用户没有soap权限,则会抛出以下错误:

com.sun.xml.internal.ws.fault.ServerSOAPFaultException: Client received SOAP Fault from server: Marshalling Error: class org.apache.openmeetings.webservice.error.ServiceException以及其任何超类对此上下文都是未知的。 Please see the server log to find more detail regarding exact cause of the failure.
at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:178) ~[na:1.8.0_111]
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:116) ~[na:1.8.0_111]
at com.sun.xml.internal.ws.client.sei.StubHandler.readResponse(StubHandler.java:238) ~[na:1.8.0_111]
at com.sun.xml.internal.ws.db.DatabindingImpl.deserializeResponse(DatabindingImpl.java:189) ~[na:1.8.0_111]
at com.sun.xml.internal.ws.db.DatabindingImpl.deserializeResponse(DatabindingImpl.java:276) ~[na:1.8.0_111]
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:104) ~[na:1.8.0_111]
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:77) ~[na:1.8.0_111]
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:147) ~[na:1.8.0_111]
at com.sun.proxy.$Proxy116.getRoomHash(Unknown Source) ~[na:na]
at com.avie.app.controller.SysmenuController.createRoom(SysmenuController.java:64) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_111]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_111]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_111]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:871) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.0.30.jar:8.0.30]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) ~[shiro-web-1.2.3.jar:1.2.3]
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) ~[shiro-web-1.2.3.jar:1.2.3]
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) ~[shiro-core-1.2.3.jar:1.2.3]
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) ~[shiro-core-1.2.3.jar:1.2.3]
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383) ~[shiro-core-1.2.3.jar:1.2.3]
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) ~[shiro-web-1.2.3.jar:1.2.3]
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) ~[shiro-web-1.2.3.jar:1.2.3]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) [tomcat-embed-core-8.0.30.jar:8.0.30]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) [tomcat-embed-core-8.0.30.jar:8.0.30]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.30.jar:8.0.30]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]


接下来通过userService调用其登录方法,sid正是其返回的实体ServiceResult中的message参数。那么其实很多童鞋应该能猜到了,sid其实是在Openmeetings类似于token的东西,在登录时取得,以后的任何操作都需带上这个sid,否则视为没有登录,不予操作。

拿到了sid之后。再往后看,创建了一个ExternalUserDTO的类,这个类是用来存放外部人员信息的类,其中比较关键是externalId和externalType这两个参数,分别代表外部人员的id和外部人员的类型,若这两个参数与openmeetings数据库中已有外部人员的参数一致,openmeetings则会直接使用这这个账号,如果没有一致的,则会创建一个新的账号。

再往后走,创建房间信息。首先设置房间参数的id,公共房间的id为1-7。随后setShowAudioVideoTest(true)这个方法是设置是否开启摄像头测试,最后一个setModerator(true)为设置该外部用户是否为该房间的主持人。

所有参数设置完成后,调用userService.getRoomHash(sid, user, options)方法,将上面的sid,创建的用户及设置的房间参数信息传入该方法,得到的返回值为userwebService.ServiceResult这个实体bean,如下图:



可以看到,该实体bean一个message,一个type。其实我们这里主要是拿Openmeetings返回的message,这里面方的是登录的密钥,有了它我们通过http://localhost:5080/openmeetings/hash?secure=fa1f9381-bd03-42ae-9fd9-332b5f775a1b 这条链接即可实现访问公共房间,secure后面的参数其实就是我们得到的userwebService.ServiceResult中message的值。

现在完全模拟一下这个场景,我用springBoot新建了一个web项目,在这里面,输入名字和id号,选择一个房间即可进入该房间。如下图:



这里我把用户名和密码在页面上做成可配的只是为了演示方便,生产环境中我们可以从session或者数据库拿用户名和密码,用户只需去选择房间即可。点击老师进入公共房间后,如下图:



成功以主持人身份进入到房间。

由于时间有限,后面两个需求的实现我在下篇博客中再讲解,喜欢的童鞋可以跟进以下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息