组织架构同步: 实时获取最新的部门、人员、角色信息
2025/9/6大约 12 分钟
组织架构同步:实时获取最新的部门、人员、角色信息
在企业级BPM平台中,组织架构同步是确保平台能够准确反映企业实际组织结构的关键功能。通过与企业现有的人力资源系统或目录服务实时同步部门、人员、角色等组织信息,可以确保流程中的任务分配、权限控制等功能基于最新的组织数据进行操作。
组织架构同步的核心价值
数据一致性保障
通过实时同步机制,确保BPM平台中的组织信息与企业实际组织架构保持一致,避免因数据滞后导致的流程执行错误。
自动化管理
减少人工维护组织信息的工作量,通过自动化同步机制实现组织信息的实时更新,提高管理效率。
准确的流程执行
基于最新的组织信息进行任务分配和权限控制,确保流程能够准确执行,提升业务处理效率。
组织架构同步架构设计
一个高效的组织架构同步系统需要具备良好的架构设计,以确保数据同步的实时性、准确性和可扩展性。
// 组织架构同步服务
@Service
public class OrganizationSyncService {
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private DepartmentRepository departmentRepository;
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Autowired
private SyncHistoryRepository syncHistoryRepository;
@Value("${organization.sync.schedule}")
private String syncSchedule;
/**
* 全量同步组织架构
* @return 同步结果
*/
public OrganizationSyncResult fullSync() {
OrganizationSyncResult result = new OrganizationSyncResult();
result.setSyncType(SyncType.FULL);
result.setStartTime(new Date());
try {
// 记录同步开始
SyncHistory syncHistory = createSyncHistory(SyncType.FULL);
// 同步部门信息
SyncResult departmentSyncResult = syncDepartments();
result.setDepartmentSyncResult(departmentSyncResult);
// 同步用户信息
SyncResult userSyncResult = syncUsers();
result.setUserSyncResult(userSyncResult);
// 同步角色信息
SyncResult roleSyncResult = syncRoles();
result.setRoleSyncResult(roleSyncResult);
// 更新同步历史
syncHistory.setEndTime(new Date());
syncHistory.setStatus(SyncStatus.SUCCESS);
syncHistory.setDepartmentCount(departmentSyncResult.getSuccessCount());
syncHistory.setUserCount(userSyncResult.getSuccessCount());
syncHistory.setRoleCount(roleSyncResult.getSuccessCount());
syncHistoryRepository.save(syncHistory);
result.setSuccess(true);
result.setEndTime(new Date());
result.setMessage("全量组织架构同步完成");
} catch (Exception e) {
log.error("全量组织架构同步失败", e);
result.setSuccess(false);
result.setEndTime(new Date());
result.setErrorMessage("全量组织架构同步过程中发生错误: " + e.getMessage());
}
return result;
}
/**
* 增量同步组织架构
* @param lastSyncTime 上次同步时间
* @return 同步结果
*/
public OrganizationSyncResult incrementalSync(Date lastSyncTime) {
OrganizationSyncResult result = new OrganizationSyncResult();
result.setSyncType(SyncType.INCREMENTAL);
result.setStartTime(new Date());
try {
// 记录同步开始
SyncHistory syncHistory = createSyncHistory(SyncType.INCREMENTAL);
// 同步变更的部门信息
SyncResult departmentSyncResult = syncChangedDepartments(lastSyncTime);
result.setDepartmentSyncResult(departmentSyncResult);
// 同步变更的用户信息
SyncResult userSyncResult = syncChangedUsers(lastSyncTime);
result.setUserSyncResult(userSyncResult);
// 同步变更的角色信息
SyncResult roleSyncResult = syncChangedRoles(lastSyncTime);
result.setRoleSyncResult(roleSyncResult);
// 更新同步历史
syncHistory.setEndTime(new Date());
syncHistory.setStatus(SyncStatus.SUCCESS);
syncHistory.setDepartmentCount(departmentSyncResult.getSuccessCount());
syncHistory.setUserCount(userSyncResult.getSuccessCount());
syncHistory.setRoleCount(roleSyncResult.getSuccessCount());
syncHistoryRepository.save(syncHistory);
result.setSuccess(true);
result.setEndTime(new Date());
result.setMessage("增量组织架构同步完成");
} catch (Exception e) {
log.error("增量组织架构同步失败", e);
result.setSuccess(false);
result.setEndTime(new Date());
result.setErrorMessage("增量组织架构同步过程中发生错误: " + e.getMessage());
}
return result;
}
/**
* 创建同步历史记录
* @param syncType 同步类型
* @return 同步历史
*/
private SyncHistory createSyncHistory(SyncType syncType) {
SyncHistory syncHistory = new SyncHistory();
syncHistory.setId(UUID.randomUUID().toString());
syncHistory.setSyncType(syncType);
syncHistory.setStartTime(new Date());
syncHistory.setStatus(SyncStatus.IN_PROGRESS);
syncHistoryRepository.save(syncHistory);
return syncHistory;
}
}部门信息同步实现
部门是组织架构的基本单位,准确同步部门信息对于流程中的组织相关操作至关重要。
// 部门同步实现
@Component
public class DepartmentSyncHandler {
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private DepartmentRepository departmentRepository;
/**
* 同步所有部门信息
* @return 同步结果
*/
public SyncResult syncDepartments() {
SyncResult result = new SyncResult();
result.setEntityType("department");
result.setStartTime(new Date());
try {
// 从LDAP获取所有部门信息
List<LdapDepartment> ldapDepartments = getAllDepartmentsFromLdap();
int successCount = 0;
int failureCount = 0;
for (LdapDepartment ldapDept : ldapDepartments) {
try {
// 同步单个部门
syncSingleDepartment(ldapDept);
successCount++;
} catch (Exception e) {
log.error("同步部门信息失败 - 部门DN: {}", ldapDept.getDn(), e);
failureCount++;
}
}
result.setSuccessCount(successCount);
result.setFailureCount(failureCount);
result.setEndTime(new Date());
result.setSuccess(true);
result.setMessage("部门信息同步完成,成功: " + successCount + ",失败: " + failureCount);
} catch (Exception e) {
log.error("同步部门信息过程中发生错误", e);
result.setSuccess(false);
result.setEndTime(new Date());
result.setErrorMessage("同步部门信息过程中发生错误: " + e.getMessage());
}
return result;
}
/**
* 从LDAP获取所有部门信息
* @return 部门列表
*/
private List<LdapDepartment> getAllDepartmentsFromLdap() {
List<LdapDepartment> departments = new ArrayList<>();
try {
// 搜索所有部门
String searchBase = "ou=departments,dc=company,dc=com";
String searchFilter = "(objectClass=organizationalUnit)";
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setReturningAttributes(new String[]{
"ou", "description", "manager", "dn"
});
ldapTemplate.search(searchBase, searchFilter, searchControls,
new AttributesMapper<LdapDepartment>() {
@Override
public LdapDepartment mapFromAttributes(Attributes attrs) throws NamingException {
LdapDepartment dept = new LdapDepartment();
dept.setName(getAttributeStringValue(attrs, "ou"));
dept.setDescription(getAttributeStringValue(attrs, "description"));
dept.setManagerDn(getAttributeStringValue(attrs, "manager"));
// DN会自动设置
return dept;
}
}
).forEach(departments::add);
} catch (Exception e) {
log.error("从LDAP获取部门信息失败", e);
}
return departments;
}
/**
* 同步单个部门信息
* @param ldapDepartment LDAP部门信息
*/
private void syncSingleDepartment(LdapDepartment ldapDepartment) {
try {
// 查找现有部门
Department existingDept = departmentRepository.findByLdapDn(ldapDepartment.getDn());
if (existingDept == null) {
// 创建新部门
Department newDept = new Department();
newDept.setId(UUID.randomUUID().toString());
newDept.setName(ldapDepartment.getName());
newDept.setDescription(ldapDepartment.getDescription());
newDept.setLdapDn(ldapDepartment.getDn());
newDept.setCreateTime(new Date());
newDept.setLastSyncTime(new Date());
// 设置父部门
String parentDn = getParentDn(ldapDepartment.getDn());
if (parentDn != null) {
Department parentDept = departmentRepository.findByLdapDn(parentDn);
if (parentDept != null) {
newDept.setParentId(parentDept.getId());
}
}
departmentRepository.save(newDept);
} else {
// 更新现有部门
existingDept.setName(ldapDepartment.getName());
existingDept.setDescription(ldapDepartment.getDescription());
existingDept.setLastSyncTime(new Date());
departmentRepository.save(existingDept);
}
} catch (Exception e) {
log.error("同步单个部门信息失败 - 部门DN: {}", ldapDepartment.getDn(), e);
throw e;
}
}
/**
* 获取父部门DN
* @param dn 当前部门DN
* @return 父部门DN
*/
private String getParentDn(String dn) {
// 例如: ou=IT,ou=departments,dc=company,dc=com
// 父DN应该是: ou=departments,dc=company,dc=com
String[] parts = dn.split(",");
if (parts.length > 1) {
return String.join(",", Arrays.copyOfRange(parts, 1, parts.length));
}
return null;
}
/**
* 获取属性字符串值
* @param attrs 属性集
* @param attrName 属性名
* @return 属性值
*/
private String getAttributeStringValue(Attributes attrs, String attrName) {
try {
Attribute attr = attrs.get(attrName);
return attr != null ? (String) attr.get() : null;
} catch (Exception e) {
return null;
}
}
/**
* 同步变更的部门信息
* @param lastSyncTime 上次同步时间
* @return 同步结果
*/
public SyncResult syncChangedDepartments(Date lastSyncTime) {
SyncResult result = new SyncResult();
result.setEntityType("department");
result.setStartTime(new Date());
try {
// 从LDAP获取变更的部门信息
List<LdapDepartment> changedDepartments = getChangedDepartmentsFromLdap(lastSyncTime);
int successCount = 0;
int failureCount = 0;
for (LdapDepartment ldapDept : changedDepartments) {
try {
syncSingleDepartment(ldapDept);
successCount++;
} catch (Exception e) {
log.error("同步变更部门信息失败 - 部门DN: {}", ldapDept.getDn(), e);
failureCount++;
}
}
result.setSuccessCount(successCount);
result.setFailureCount(failureCount);
result.setEndTime(new Date());
result.setSuccess(true);
result.setMessage("变更部门信息同步完成,成功: " + successCount + ",失败: " + failureCount);
} catch (Exception e) {
log.error("同步变更部门信息过程中发生错误", e);
result.setSuccess(false);
result.setEndTime(new Date());
result.setErrorMessage("同步变更部门信息过程中发生错误: " + e.getMessage());
}
return result;
}
/**
* 从LDAP获取变更的部门信息
* @param lastSyncTime 上次同步时间
* @return 变更的部门列表
*/
private List<LdapDepartment> getChangedDepartmentsFromLdap(Date lastSyncTime) {
List<LdapDepartment> departments = new ArrayList<>();
try {
// 使用LDAP的增量同步功能(如果支持)
String searchBase = "ou=departments,dc=company,dc=com";
String searchFilter = "(&(objectClass=organizationalUnit)(modifyTimestamp>=" +
formatLdapDate(lastSyncTime) + "))";
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setReturningAttributes(new String[]{
"ou", "description", "manager", "dn", "modifyTimestamp"
});
ldapTemplate.search(searchBase, searchFilter, searchControls,
new AttributesMapper<LdapDepartment>() {
@Override
public LdapDepartment mapFromAttributes(Attributes attrs) throws NamingException {
LdapDepartment dept = new LdapDepartment();
dept.setName(getAttributeStringValue(attrs, "ou"));
dept.setDescription(getAttributeStringValue(attrs, "description"));
dept.setManagerDn(getAttributeStringValue(attrs, "manager"));
// DN会自动设置
return dept;
}
}
).forEach(departments::add);
} catch (Exception e) {
log.error("从LDAP获取变更部门信息失败", e);
}
return departments;
}
/**
* 格式化LDAP日期
* @param date 日期
* @return LDAP格式日期字符串
*/
private String formatLdapDate(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
return sdf.format(date) + "Z";
}
}用户信息同步实现
用户是组织架构的核心组成部分,准确同步用户信息对于任务分配和权限控制至关重要。
// 用户同步实现
@Component
public class UserSyncHandler {
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private UserRepository userRepository;
@Autowired
private DepartmentRepository departmentRepository;
/**
* 同步所有用户信息
* @return 同步结果
*/
public SyncResult syncUsers() {
SyncResult result = new SyncResult();
result.setEntityType("user");
result.setStartTime(new Date());
try {
// 从LDAP获取所有用户信息
List<LdapUser> ldapUsers = getAllUsersFromLdap();
int successCount = 0;
int failureCount = 0;
for (LdapUser ldapUser : ldapUsers) {
try {
syncSingleUser(ldapUser);
successCount++;
} catch (Exception e) {
log.error("同步用户信息失败 - 用户DN: {}", ldapUser.getDn(), e);
failureCount++;
}
}
result.setSuccessCount(successCount);
result.setFailureCount(failureCount);
result.setEndTime(new Date());
result.setSuccess(true);
result.setMessage("用户信息同步完成,成功: " + successCount + ",失败: " + failureCount);
} catch (Exception e) {
log.error("同步用户信息过程中发生错误", e);
result.setSuccess(false);
result.setEndTime(new Date());
result.setErrorMessage("同步用户信息过程中发生错误: " + e.getMessage());
}
return result;
}
/**
* 从LDAP获取所有用户信息
* @return 用户列表
*/
private List<LdapUser> getAllUsersFromLdap() {
List<LdapUser> users = new ArrayList<>();
try {
// 搜索所有用户
String searchBase = "ou=users,dc=company,dc=com";
String searchFilter = "(objectClass=person)";
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setReturningAttributes(new String[]{
"cn", "sn", "givenName", "mail", "telephoneNumber",
"department", "title", "manager", "dn", "employeeNumber"
});
ldapTemplate.search(searchBase, searchFilter, searchControls,
new AttributesMapper<LdapUser>() {
@Override
public LdapUser mapFromAttributes(Attributes attrs) throws NamingException {
LdapUser user = new LdapUser();
user.setFullName(getAttributeStringValue(attrs, "cn"));
user.setLastName(getAttributeStringValue(attrs, "sn"));
user.setFirstName(getAttributeStringValue(attrs, "givenName"));
user.setEmail(getAttributeStringValue(attrs, "mail"));
user.setPhone(getAttributeStringValue(attrs, "telephoneNumber"));
user.setDepartmentName(getAttributeStringValue(attrs, "department"));
user.setTitle(getAttributeStringValue(attrs, "title"));
user.setManagerDn(getAttributeStringValue(attrs, "manager"));
user.setEmployeeNumber(getAttributeStringValue(attrs, "employeeNumber"));
// DN会自动设置
return user;
}
}
).forEach(users::add);
} catch (Exception e) {
log.error("从LDAP获取用户信息失败", e);
}
return users;
}
/**
* 同步单个用户信息
* @param ldapUser LDAP用户信息
*/
private void syncSingleUser(LdapUser ldapUser) {
try {
// 查找现有用户
User existingUser = userRepository.findByLdapDn(ldapUser.getDn());
if (existingUser == null) {
// 创建新用户
User newUser = new User();
newUser.setId(UUID.randomUUID().toString());
newUser.setUsername(extractUsernameFromDn(ldapUser.getDn()));
newUser.setFullName(ldapUser.getFullName());
newUser.setFirstName(ldapUser.getFirstName());
newUser.setLastName(ldapUser.getLastName());
newUser.setEmail(ldapUser.getEmail());
newUser.setPhone(ldapUser.getPhone());
newUser.setTitle(ldapUser.getTitle());
newUser.setEmployeeNumber(ldapUser.getEmployeeNumber());
newUser.setLdapDn(ldapUser.getDn());
newUser.setSource(UserSource.LDAP);
newUser.setCreateTime(new Date());
newUser.setLastSyncTime(new Date());
// 设置部门
if (ldapUser.getDepartmentName() != null) {
Department dept = departmentRepository.findByName(ldapUser.getDepartmentName());
if (dept != null) {
newUser.setDepartmentId(dept.getId());
}
}
userRepository.save(newUser);
} else {
// 更新现有用户
existingUser.setFullName(ldapUser.getFullName());
existingUser.setFirstName(ldapUser.getFirstName());
existingUser.setLastName(ldapUser.getLastName());
existingUser.setEmail(ldapUser.getEmail());
existingUser.setPhone(ldapUser.getPhone());
existingUser.setTitle(ldapUser.getTitle());
existingUser.setEmployeeNumber(ldapUser.getEmployeeNumber());
existingUser.setLastSyncTime(new Date());
// 更新部门
if (ldapUser.getDepartmentName() != null) {
Department dept = departmentRepository.findByName(ldapUser.getDepartmentName());
if (dept != null) {
existingUser.setDepartmentId(dept.getId());
}
}
userRepository.save(existingUser);
}
} catch (Exception e) {
log.error("同步单个用户信息失败 - 用户DN: {}", ldapUser.getDn(), e);
throw e;
}
}
/**
* 从DN中提取用户名
* @param dn 用户DN
* @return 用户名
*/
private String extractUsernameFromDn(String dn) {
// 例如: cn=john.doe,ou=users,dc=company,dc=com
String[] parts = dn.split(",");
for (String part : parts) {
String trimmedPart = part.trim();
if (trimmedPart.toLowerCase().startsWith("cn=")) {
return trimmedPart.substring(3);
}
}
return dn;
}
/**
* 获取属性字符串值
* @param attrs 属性集
* @param attrName 属性名
* @return 属性值
*/
private String getAttributeStringValue(Attributes attrs, String attrName) {
try {
Attribute attr = attrs.get(attrName);
return attr != null ? (String) attr.get() : null;
} catch (Exception e) {
return null;
}
}
}角色信息同步实现
角色是权限控制的基础,通过同步角色信息可以实现基于角色的访问控制。
// 角色同步实现
@Component
public class RoleSyncHandler {
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private RoleRepository roleRepository;
@Autowired
private UserRepository userRepository;
/**
* 同步角色信息
* @return 同步结果
*/
public SyncResult syncRoles() {
SyncResult result = new SyncResult();
result.setEntityType("role");
result.setStartTime(new Date());
try {
// 从LDAP获取所有组信息(映射为角色)
List<LdapGroup> ldapGroups = getAllGroupsFromLdap();
int successCount = 0;
int failureCount = 0;
for (LdapGroup ldapGroup : ldapGroups) {
try {
syncSingleRole(ldapGroup);
successCount++;
} catch (Exception e) {
log.error("同步角色信息失败 - 组DN: {}", ldapGroup.getDn(), e);
failureCount++;
}
}
result.setSuccessCount(successCount);
result.setFailureCount(failureCount);
result.setEndTime(new Date());
result.setSuccess(true);
result.setMessage("角色信息同步完成,成功: " + successCount + ",失败: " + failureCount);
} catch (Exception e) {
log.error("同步角色信息过程中发生错误", e);
result.setSuccess(false);
result.setEndTime(new Date());
result.setErrorMessage("同步角色信息过程中发生错误: " + e.getMessage());
}
return result;
}
/**
* 从LDAP获取所有组信息
* @return 组列表
*/
private List<LdapGroup> getAllGroupsFromLdap() {
List<LdapGroup> groups = new ArrayList<>();
try {
// 搜索所有组
String searchBase = "ou=groups,dc=company,dc=com";
String searchFilter = "(objectClass=groupOfNames)";
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setReturningAttributes(new String[]{
"cn", "description", "member", "dn"
});
ldapTemplate.search(searchBase, searchFilter, searchControls,
new AttributesMapper<LdapGroup>() {
@Override
public LdapGroup mapFromAttributes(Attributes attrs) throws NamingException {
LdapGroup group = new LdapGroup();
group.setName(getAttributeStringValue(attrs, "cn"));
group.setDescription(getAttributeStringValue(attrs, "description"));
group.setMemberDns(getMemberDns(attrs));
// DN会自动设置
return group;
}
}
).forEach(groups::add);
} catch (Exception e) {
log.error("从LDAP获取组信息失败", e);
}
return groups;
}
/**
* 获取组成员DN列表
* @param attrs 属性集
* @return 成员DN列表
*/
private List<String> getMemberDns(Attributes attrs) {
List<String> memberDns = new ArrayList<>();
try {
Attribute memberAttr = attrs.get("member");
if (memberAttr != null) {
NamingEnumeration<?> values = memberAttr.getAll();
while (values.hasMore()) {
memberDns.add((String) values.next());
}
}
} catch (Exception e) {
log.error("获取组成员信息失败", e);
}
return memberDns;
}
/**
* 同步单个角色信息
* @param ldapGroup LDAP组信息
*/
private void syncSingleRole(LdapGroup ldapGroup) {
try {
// 查找现有角色
Role existingRole = roleRepository.findByLdapDn(ldapGroup.getDn());
if (existingRole == null) {
// 创建新角色
Role newRole = new Role();
newRole.setId(UUID.randomUUID().toString());
newRole.setName(ldapGroup.getName());
newRole.setDescription(ldapGroup.getDescription());
newRole.setLdapDn(ldapGroup.getDn());
newRole.setCreateTime(new Date());
newRole.setLastSyncTime(new Date());
roleRepository.save(newRole);
// 同步角色成员关系
syncRoleMembers(newRole, ldapGroup.getMemberDns());
} else {
// 更新现有角色
existingRole.setName(ldapGroup.getName());
existingRole.setDescription(ldapGroup.getDescription());
existingRole.setLastSyncTime(new Date());
roleRepository.save(existingRole);
// 同步角色成员关系
syncRoleMembers(existingRole, ldapGroup.getMemberDns());
}
} catch (Exception e) {
log.error("同步单个角色信息失败 - 组DN: {}", ldapGroup.getDn(), e);
throw e;
}
}
/**
* 同步角色成员关系
* @param role 角色
* @param memberDns 成员DN列表
*/
private void syncRoleMembers(Role role, List<String> memberDns) {
try {
// 获取当前角色的所有用户
List<User> currentRoleUsers = userRepository.findByRoleId(role.getId());
Set<String> currentUserIdSet = currentRoleUsers.stream()
.map(User::getId)
.collect(Collectors.toSet());
// 获取LDAP中的用户ID集合
Set<String> ldapUserIdSet = new HashSet<>();
for (String memberDn : memberDns) {
User user = userRepository.findByLdapDn(memberDn);
if (user != null) {
ldapUserIdSet.add(user.getId());
}
}
// 找出需要添加的角色成员
Set<String> usersToAdd = new HashSet<>(ldapUserIdSet);
usersToAdd.removeAll(currentUserIdSet);
// 找出需要移除的角色成员
Set<String> usersToRemove = new HashSet<>(currentUserIdSet);
usersToRemove.removeAll(ldapUserIdSet);
// 添加新成员
for (String userId : usersToAdd) {
User user = userRepository.findById(userId);
if (user != null) {
user.getRoleIds().add(role.getId());
userRepository.save(user);
}
}
// 移除旧成员
for (String userId : usersToRemove) {
User user = userRepository.findById(userId);
if (user != null) {
user.getRoleIds().remove(role.getId());
userRepository.save(user);
}
}
} catch (Exception e) {
log.error("同步角色成员关系失败 - 角色ID: {}", role.getId(), e);
}
}
/**
* 获取属性字符串值
* @param attrs 属性集
* @param attrName 属性名
* @return 属性值
*/
private String getAttributeStringValue(Attributes attrs, String attrName) {
try {
Attribute attr = attrs.get(attrName);
return attr != null ? (String) attr.get() : null;
} catch (Exception e) {
return null;
}
}
}定时同步机制
为了确保组织架构信息的实时性,需要建立定时同步机制。
// 定时同步任务
@Component
public class OrganizationSyncScheduler {
@Autowired
private OrganizationSyncService organizationSyncService;
@Autowired
private SyncHistoryRepository syncHistoryRepository;
/**
* 定时执行增量同步
*/
@Scheduled(cron = "${organization.sync.incremental.cron:0 0/30 * * * ?}")
public void scheduleIncrementalSync() {
try {
log.info("开始执行增量组织架构同步");
// 获取上次同步时间
Date lastSyncTime = getLastSuccessfulSyncTime();
// 执行增量同步
OrganizationSyncResult result = organizationSyncService.incrementalSync(lastSyncTime);
if (result.isSuccess()) {
log.info("增量组织架构同步成功: {}", result.getMessage());
} else {
log.error("增量组织架构同步失败: {}", result.getErrorMessage());
}
} catch (Exception e) {
log.error("执行增量组织架构同步时发生错误", e);
}
}
/**
* 定时执行全量同步
*/
@Scheduled(cron = "${organization.sync.full.cron:0 0 2 * * ?}")
public void scheduleFullSync() {
try {
log.info("开始执行全量组织架构同步");
// 执行全量同步
OrganizationSyncResult result = organizationSyncService.fullSync();
if (result.isSuccess()) {
log.info("全量组织架构同步成功: {}", result.getMessage());
} else {
log.error("全量组织架构同步失败: {}", result.getErrorMessage());
}
} catch (Exception e) {
log.error("执行全量组织架构同步时发生错误", e);
}
}
/**
* 获取上次成功同步时间
* @return 上次同步时间
*/
private Date getLastSuccessfulSyncTime() {
try {
SyncHistory lastSync = syncHistoryRepository.findLatestSuccessfulSync();
if (lastSync != null) {
return lastSync.getStartTime();
}
} catch (Exception e) {
log.warn("获取上次同步时间失败,使用默认时间", e);
}
// 默认返回24小时前
return new Date(System.currentTimeMillis() - 24 * 3600000L);
}
}最佳实践与注意事项
在实现组织架构同步时,需要注意以下最佳实践:
1. 数据一致性
- 建立完善的事务处理机制,确保数据同步的原子性
- 实施数据校验机制,防止异常数据影响系统稳定性
- 定期进行数据一致性检查和修复
2. 性能优化
- 合理设置同步频率,平衡实时性和系统负载
- 对大数据量同步采用分批处理机制
- 使用缓存机制减少重复查询
3. 容错处理
- 建立完善的错误处理和重试机制
- 提供同步失败的告警和通知功能
- 记录详细的同步日志便于问题排查
4. 安全保障
- 使用加密连接与LDAP服务器通信
- 妥善保管连接凭证,避免硬编码在代码中
- 实施严格的访问控制和权限验证
通过合理设计和实现组织架构同步机制,可以确保BPM平台中的组织信息与企业实际组织架构保持一致,为流程的准确执行提供可靠的数据基础。
