【功能开发】从钉钉接口同步部门数据
钉钉接口文档地址:
https://developers.dingtalk.com/document/app/queries-the-complete-information-of-a-department-user
我写的思路,是先获取所有的部门ID,再通过部门ID查询用户详情,遍历到一个List集合中,进行批量插入。
先贴代码,然后详细理清思路
SysDeptController.java
/**
* 同步钉钉子部门数据
* 此同步方式为全量同步
*/
@PreAuthorize(hasPermi = "system:dept:sync")
@Log(title = "同步钉钉部门数据", businessType = BusinessType.SYNC)
@GetMapping("/syncListDept")
public AjaxResult syncListDept () throws ApiException {
long startTime = System.currentTimeMillis();
SysDDToken token = deptService.getToken();
if(!DingConstant.SUCCESS_CODE.equals(token.getCode())){
return AjaxResult.error(token.getMsg());
}
// 删除根部门以下的全部数据
deptService.deleteDeptExceptRoot();
insertListDeptFromDD(token.getToken(), DingConstant.ROOT_DEPT_ID);
long EndTime = System.currentTimeMillis();
return AjaxResult.success("同步数据成功,耗时:"+(EndTime-startTime)/1000+" 秒");
}
/**
* @description: 根据部门ID获取子部门列表
* @throws ApiException
*/
public void insertListDeptFromDD(String token,Long deptId) throws ApiException {
// 当前部门为父部门
SysDept subDept = deptService.selectDeptById(deptId);
JSONObject rootObject = deptService.getListDeptFromDD(token, deptId);
// 判断是否成功
checkIsSuccess(rootObject);
JSONArray result = rootObject.getJSONArray("result");
if(result.size() == 0){
return;
}
if(result.size() > 0){
int num = 1;
for (Object o : result) {
JSONObject s = (JSONObject)o;
SysDept sd = new SysDept();
// 部门ID
sd.setDeptId(s.getLong("dept_id"));
// 部门名称
sd.setDeptName(s.getString("name"));
// 父级部门名称
sd.setParentId(s.getLong("parent_id"));
sd.setStatus("0");
sd.setDelFlag("0");
sd.setOrderNum(String.valueOf(num++));
sd.setCreateBy(SecurityUtils.getUsername());
//树状列表
sd.setAncestors(subDept.getAncestors() + "," + sd.getParentId());
deptService.insertDeptFromDD(sd);
insertListDeptFromDD(token,sd.getDeptId());
}
}
}
public void checkIsSuccess(JSONObject rootObject){
if (!DingConstant.SUCCESS_CODE.equals(rootObject.getString("errcode"))) {
throw new ServiceException(rootObject.getString("errmsg"));
}
}
SysDeptServiceImpl.java
/**
* 获取子部门详情
* @param token :钉钉 token
* @param deptId :部门ID,根部门为1
*/
public JSONObject getListDeptFromDD(String token, Long deptId) throws ApiException {
DingTalkClient client = new DefaultDingTalkClient(DingConstant.DEPT_LIST_API);
OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();
req.setDeptId(deptId);
OapiV2DepartmentListsubResponse rsp = client.execute(req, token);
return JSONObject.parseObject(rsp.getBody());
}
获取部门列表的接口
可以看到,Query参数中有个必填的参数:access_token
access_token:(调用服务端API的应用凭证)。
该参数必须要有,否则会报错。
不同的企业应用,获取token的方式并不相同,具体可以参考官网文档—>传送门
获取token的代码如下:
/**
* 获取钉钉应用的access_token
* @return SubToken
* @throws ApiException
*/
@Override
public SysDDToken getToken() throws ApiException {
DingTalkClient client = new DefaultDingTalkClient(DingConstant.TOKEN_API);
OapiGettokenRequest request = new OapiGettokenRequest();
request.setAppkey(DingConstant.APP_KEY);
request.setAppsecret(DingConstant.APP_SECRET);
request.setHttpMethod(DingConstant.GET_METHOD);
return JSON.parseObject(client.execute(request).getBody(), SysDDToken.class);
}
insertListDeptFromDD
是采用递归的方式,进行循环插入。
改进
OapiV2DepartmentListsubResponse rsp = client.execute(req, token);
return JSONObject.parseObject(rsp.getBody());
这里的rsp 已经可以获取数据了,完全没必要转为json,再解析。
JSONObject rootObject = deptService.getListDeptFromDD(token, deptId);
JSONArray result = rootObject.getJSONArray("result");
这里deptService.getListDeptFromDD(token, deptId)
不应该返回JSONObject
,而是应该直接返回OapiV2DepartmentListsubResponse
对象。
这个OapiV2DepartmentListsubResponse
对象它有个rsp.getResult()
可以直接获取result
何必多此一举。
这就去改动代码。