组织与人员同步 #
- 组织与人员同步有以下三种方式,其中RPC,HTTP在集成系统中实现,DB方式由Yo信实现,下面将详细讲述它们的实现方式。
- 其中rpc和http方式提供集成源码供开发者参照。
RPC #
RPC框架使用的是UPush中的URPC,其性能在推送系统高并发的场景中得到了充分的验证,而且上手难度低,无需搭建额外的运行环境。 下载 (opens new window)UPush的最新版本,在libs文件夹中找到upush2-api.jar,upush2-rpc.jar复制到集成系统项目的libs文件夹,把yoxin-integration.jar放入libs, 在pom.xml中引用依赖:
<dependency>
<groupId>com.cmcim.yoxin</groupId>
<artifactId>yoxin-integration</artifactId>
<version>3.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/yoxin-integration.jar</systemPath>
</dependency>
<dependency>
<groupId>com.cmcim.upush</groupId>
<artifactId>upush2-api</artifactId>
<scope>system</scope>
<version>2.2.6</version>
<systemPath>${project.basedir}/libs/upush2-api.jar</systemPath>
</dependency>
<dependency>
<groupId>com.cmcim.upush</groupId>
<artifactId>upush2-rpc</artifactId>
<scope>system</scope>
<version>2.2.6</version>
<systemPath>${project.basedir}/libs/upush2-rpc.jar</systemPath>
</dependency>
- 在集成系统项目中包service下创建三个类用来实现同步接口,分别是YoUserServiceImpl用于用户同步,YoOrgServiceImpl用于组织同步,YoAppServiceImpl对用户可使用的集成系统应用进行鉴权,这三个类是同步的核心实现,但都是CURD并不复杂。接口参照
@Service
public class YoUserServiceImpl implements YoUserService {
...
}
@Service
public class YoOrgServiceImpl implements YoOrgService {
...
}
@Service
public class YoAppServiceImpl implements YoAppService {
...
}
- 在集成系统项目中创建上面三个类对应的UPRC代理类
public class YoUserServiceRpcProxy extends URpcProvider implements YoUserService {
private YoUserService userService;
public YoUserServiceRpcProxy(YoUserService userService) {
this.userService = userService;
}
// 方法实现举例,即把YoUserServiceImpl中在这里调用一遍
@Override
public YoUserDto getUserDto(String userId) throws Exception {
return userService.getUserDto(userId);
}
// ... 其他方法同上
}
public class YoOrgServiceRpcProxy extends URpcProvider implements YoOrgService {
private YoOrgService orgService;
public YoOrgServiceRpcImpl(YoOrgService service) {
this.orgService = service;
}
// 方法实现举例,即把YoOrgServiceImpl中在这里调用一遍
@Override
public YoPageInfo<YoOrgMemberDto> getOrgMembers(String orgId, Integer page, Integer count, Boolean hasSubOrg, String filter) throws Exception {
return orgService.getOrgMembers(orgId, page, count, hasSubOrg, filter);
}
// ... 其他方法同上
}
public class YoAppServiceRpcProxy extends URpcProvider implements YoAppService {
private YoAppService yoAppService;
public YoAppServiceRpcProxy(YoAppService yoAppService) {
this.yoAppService = yoAppService;
}
@Override
public List<YoAppDto> getWorkbenchApps(List<YoAppDto> list) throws Exception {
return yoAppService.getWorkbenchApps(list);
}
}
- 初始化URPC服务,需要在Springboot启动后,所有Bean都加载完之后再初始化URPC,所以在集成系统中创建如下类:
@Slf4j
@Component
public class AppLifeCycleConfig implements CommandLineRunner, DisposableBean {
// 注入三个同步实现类,用来构造代理对象
@Autowired
YoUserService yoUserService;
@Autowired
YoOrgService yoOrgService;
@Autowired
YoAppService yoAppService;
// 配置注入
@Autowired
UPushConfig upushConfig;
// rpc服务
private URpcServer rpcServer;
// 程序结束会执行destroy,停止rpc服务
@Override
public void destroy() {
rpcServer.stop();
}
// 所有Bean初始化完成后会执行run方法,初始化并启动rpc服务
@Override
public void run(String... args) throws Exception {
rpcServer = new URpcServer();
// 注册rpc 代理对象
rpcServer.register(new YoUserServiceRpcProxy(yoUserService));
rpcServer.register(new YoOrgServiceRpcProxy(yoOrgService));
rpcServer.register(new YoAppServiceRpcProxy(yoAppService));
// 对请求和应答的拦截,可在这里输入日志,添加上下文
rpcServer.setInterceptor(new IURpcServerInterceptor() {
@Override
public void beginReturn(IoSession ioSession, URpcReturn uRpcReturn) {
// 应答/返回
log.debug("[URpc Rsp] {}", uRpcReturn.toString());
}
@Override
public void beginInvoke(IoSession ioSession, URpcFunction uRpcFunction) {
// 请求/调用
log.debug("[URpc Req] {}, {}", uRpcFunction.getMethod(), uRpcFunction.getParams());
}
});
// 启动rpc服务,第一个参数为服务名,任意起名即可,第二个参数是rpc服务端口
rpcServer.start("urpc", upushConfig.getUrpcPort());
log.info("urpc server start success");
}
}
HTTP #
- http方式同样需要引入依赖,但只需要引入yoxin-integration即可
<dependency>
<groupId>com.cmcim.yoxin</groupId>
<artifactId>yoxin-integration</artifactId>
<version>3.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/yoxin-integration.jar</systemPath>
</dependency>
- http方式同样需要实现,YoUserService,YoOrgService,YoAppService这三个接口,具体可参照上面rpc方式
- http方式需要集成系统提供restful api接口。请按照下面的接口规范创建接口,接口参数说明参照
@RestController
// 请求的前缀可任何设置,但下面的Mapping路径保持固定
@RequestMapping(value = "/integration")
public class IntegrationController {
// 注入三个同步实现类,在接口中直接调用
@Autowired
YoOrgService orgService;
@Autowired
YoUserService userService;
@Autowired
YoAppService appService;
/**
* BaseResponseInfo 结构为:
* {
* code: 0, // 应该状态码 0 表示正确
* msg: "", // 错误内容
* data: {} // 应答内容
* }
*
* 实际集成时类名可任意定义,保持上面一样的数据结构即可
*/
@PostMapping("/apps")
public BaseResponseInfo getWorkbenchApps(@RequestBody List<YoAppDto> list) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = appService.getWorkbenchApps(list);
return res;
}
@GetMapping("/org/{orgId}/members")
public BaseResponseInfo getOrgMembers(@PathVariable("orgId") String orgId,
@RequestParam("page") Integer page,
@RequestParam("count") Integer count,
@RequestParam("hasSubOrg") Boolean hasSubOrg,
@RequestParam("filter") String filter) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = orgService.getOrgMembers(orgId, page, count, hasSubOrg, filter);
return res;
}
@GetMapping("/org/{orgId}/member/{memberId}/exist")
public BaseResponseInfo isMemberInOrg(@PathVariable("orgId") String orgId,
@PathVariable("memberId") String memberId) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = orgService.isMemberInOrg(orgId, memberId);
return res;
}
@GetMapping("/org/member/{userId1}/and/{userId2}/in/same/company")
public BaseResponseInfo isInSameCompany(@PathVariable("userId1") String userId1,
@PathVariable("userId2") String userId2) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = orgService.isInSameCompany(userId1, userId2);
return res;
}
@GetMapping("/org/customer/service")
public BaseResponseInfo getCustomerServiceAgent(@RequestBody String str) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = orgService.getCustomerServiceAgent(str);
return res;
}
@GetMapping("/org/{orgId}/all/parents")
public BaseResponseInfo parentOrgIds(@PathVariable("orgId") String orgId,
@RequestParam("companyId") String companyId,
@RequestParam("containCompany") Boolean containCompany) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = orgService.parentOrgIds(orgId, companyId, containCompany);
return res;
}
@GetMapping("/org/{orgId}/base")
public BaseResponseInfo getOrgBase(@PathVariable("orgId") String orgId) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = orgService.getOrgBase(orgId);
return res;
}
@GetMapping("/org/{orgId}")
public BaseResponseInfo getOrg(@PathVariable("orgId") String orgId,
@RequestParam("hasSubOrg") Boolean hasSubOrg,
@RequestParam("hasSubCompany") Boolean hasSubCompany,
@RequestParam("hasMemberNum") Boolean hasMemberNum) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = orgService.getOrg(orgId, hasSubOrg, hasSubCompany, hasMemberNum);
return res;
}
@GetMapping("/org/user/{userId}/company")
public BaseResponseInfo getUserCompany(@PathVariable("userId") String userId) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = orgService.getUserCompany(userId);
return res;
}
@GetMapping("/org/{orgId}/parent/{parentId}/exist")
public BaseResponseInfo isSubOrg(@PathVariable("orgId") String orgId, @PathVariable("parentId") String parentId) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = orgService.isSubOrg(orgId, parentId);
return res;
}
@GetMapping("/org/{orgId}/user/{userId}/role/exist")
public BaseResponseInfo isUserHasOrgRole(@PathVariable("orgId") String orgId,
@PathVariable("userId") String userId) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = orgService.isUserHasOrgRole(orgId, userId);
return res;
}
@GetMapping("/user/{userId}")
public BaseResponseInfo getUserDto(@PathVariable("userId") String userId) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = userService.getUserDto(userId);
return res;
}
@GetMapping("/user/{username}/category/{category}")
public BaseResponseInfo getUserBaseDto(@PathVariable("username") String username,
@PathVariable("category") String category) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = userService.getUserBaseDto(username, category);
return res;
}
@PutMapping("/user/{userId}/gender/{gender}")
public BaseResponseInfo updateUserGender(@PathVariable("userId") String userId,
@PathVariable("gender") Integer gender) throws Exception {
userService.updateUserGender(userId, gender);
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = null;
return res;
}
@PutMapping("/user/{userId}/phone/{phone}")
public BaseResponseInfo updateUserPhone(@PathVariable("userId") String userId,
@PathVariable("phone") String phone) throws Exception {
userService.updateUserPhone(userId, phone);
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = null;
return res;
}
@PutMapping("/user/{userId}/email/{email}")
public BaseResponseInfo updateUserEmail(@PathVariable("userId") String userId, @PathVariable("email") String email) throws Exception {
userService.updateUserEmail(userId, email);
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = null;
return res;
}
@PutMapping("/user/{userId}/password/{password}")
public BaseResponseInfo updateUserPassword(@PathVariable("userId") String userId, @PathVariable("password") String password) throws Exception {
userService.updateUserPassword(userId, password);
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = null;
return res;
}
@PostMapping("/user")
public BaseResponseInfo addUser(@RequestBody YoUserBaseDto baseDto) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = userService.addUser(baseDto);
return res;
}
@GetMapping("/user/{userId}/password/{password}")
public BaseResponseInfo checkUserPassword(@PathVariable("userId") String userId, @PathVariable("password") String password) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = userService.checkUserPassword(userId, password);
return res;
}
@GetMapping("/user/sync")
public BaseResponseInfo getUserSyncList(@RequestParam("page") Integer page,
@RequestParam("count") Integer count) throws Exception {
BaseResponseInfo res = new BaseResponseInfo();
res.code = 0;
res.data = userService.getUserSyncList(page, count);
return res;
}
}
DB #
- 前两种方式都是在集成系统中实现,通过网络调用,DB方式在Yo信服务端实现,直接读取数据库,是三种方式效率最高的方式
- DB方式直接连接到集成系统的数据库,通过读取用户,组织表来实现这个三个接口类(YoUserService,YoOrgService,YoAppService)
- DB方式需要集成系统提供相关的表结果说明
- DB可以在集成系统无源码,集成系统的开发团队无法继续开发时使用
同步效果展示 #
下面以PC端展示,移动端效果一致。
组织架构 #
- 集成系统组织架构
- Yo信组织架构
人员 #
- 集成系统人员
- Yo信人员
通过聊天选人功能来查看公司所有人