@ -2,6 +2,7 @@ package com.epmet.service.impl;
import com.epmet.commons.tools.constant.ServiceConstant ;
import com.epmet.commons.tools.exception.EpmetErrorCode ;
import com.epmet.commons.tools.exception.ExceptionUtils ;
import com.epmet.commons.tools.feign.ResultDataResolver ;
import com.epmet.dao.IcResiUserDao ;
import com.epmet.dao.UserBaseInfoDao ;
@ -16,7 +17,6 @@ import com.epmet.feign.GovOrgOpenFeignClient;
import com.epmet.feign.OperCustomizeOpenFeignClient ;
import com.epmet.service.VolunteerService ;
import lombok.extern.slf4j.Slf4j ;
import org.apache.commons.collections4.CollectionUtils ;
import org.apache.commons.lang3.StringUtils ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.stereotype.Service ;
@ -24,6 +24,8 @@ import org.springframework.stereotype.Service;
import com.google.common.collect.Lists ;
import java.util.* ;
import java.util.concurrent.CompletableFuture ;
import java.util.concurrent.ExecutionException ;
import java.util.stream.Collectors ;
/ * *
@ -94,136 +96,156 @@ public class VolunteerServiceImpl implements VolunteerService, ResultDataResolve
* @return
* /
public VolunteerDistributionResultDTO getVolunteerDistribution ( String customerId , String agencyId ) {
//epmetHeartOpenFeignClient.queryVolunteerPage()
VolunteerDistributionResultDTO r = new VolunteerDistributionResultDTO ( ) ;
// 1.==========分页查询出所有志愿者列表==========
String vcErrorMsg = "【志愿者分布】查询志愿者总数出错" ;
VolunteerCommonFormDTO volunteerCountForm = new VolunteerCommonFormDTO ( ) ;
volunteerCountForm . setCustomerId ( customerId ) ;
Integer volunteerCount = getResultDataOrThrowsException ( epmetHeartOpenFeignClient . getVolunteerCount ( volunteerCountForm ) ,
ServiceConstant . EPMET_HEART_SERVER ,
EpmetErrorCode . EPMET_COMMON_OPERATION_FAIL . getCode ( ) ,
vcErrorMsg ,
vcErrorMsg ) ;
if ( volunteerCount = = null | | volunteerCount = = 0 ) {
// 没得志愿者,直接返回
return r ;
}
// 1.分页查询出所有志愿者列表
int pageNo = 1 ;
// 计算页数
int pageSize = 200 ;
int pageCount = volunteerCount / pageSize ;
int lastPageItems = volunteerCount % pageSize ;
pageCount = lastPageItems > 0 ? + + pageCount : pageCount ;
// 志愿者epmet user id
// 志愿者epmet user id 集合
List < String > volunteerEpmetUserIds = new ArrayList < > ( ) ;
// 分页查询志愿者的epmet user id
while ( true ) {
VolunteerCommonFormDTO volunteerForm = new VolunteerCommonFormDTO ( ) ;
volunteerForm . setCustomerId ( customerId ) ;
volunteerForm . setSuperiorAgencyId ( agencyId ) ;
volunteerForm . setPageNo ( pageNo ) ;
volunteerForm . setPageSize ( pageSize ) ;
String errorMsg = "【志愿者分布】分页查询志愿者列表失败" ;
List < PageVolunteerInfoResultDTO > volunteerPage = getResultDataOrThrowsException ( epmetHeartOpenFeignClient . queryVolunteerPage ( volunteerForm ) ,
ServiceConstant . EPMET_HEART_SERVER ,
EpmetErrorCode . EPMET_COMMON_OPERATION_FAIL . getCode ( ) ,
errorMsg ,
errorMsg ) ;
// 将本页userId添加到总集中去
volunteerEpmetUserIds . addAll ( volunteerPage . stream ( ) . map ( v - > v . getUserId ( ) ) . collect ( Collectors . toSet ( ) ) ) ;
if ( volunteerPage . size ( ) < pageSize ) {
// 说明是最后一页了
break ;
}
List < CompletableFuture < Set < String > > > volsPageFutures = new ArrayList < > ( ) ;
pageNo + + ;
}
for ( int pageNo = 1 ; pageNo < = pageCount ; pageNo + + ) {
int pageNoTemp = pageNo ;
CompletableFuture < Set < String > > future = CompletableFuture . supplyAsync ( ( ) - > {
return listVolunteersByPage ( customerId , agencyId , pageNoTemp , pageSize )
. stream ( )
. map ( v - > v . getUserId ( ) )
. collect ( Collectors . toSet ( ) ) ;
} ) ;
VolunteerDistributionResultDTO r = new VolunteerDistributionResultDTO ( ) ;
volsPageFutures . add ( future ) ;
}
// 阻塞,等待子线程返回结果,然后添加到志愿者userId集合中去
for ( CompletableFuture < Set < String > > future : volsPageFutures ) {
try {
volunteerEpmetUserIds . addAll ( future . get ( ) ) ;
} catch ( InterruptedException e ) {
log . error ( "【志愿者分布】异步获取志愿者userId列表被中断:{}" , ExceptionUtils . getErrorStackTrace ( e ) ) ;
} catch ( ExecutionException e ) {
log . error ( "【志愿者分布】异步获取志愿者userId列表失败:{}" , ExceptionUtils . getErrorStackTrace ( e ) ) ;
}
}
log . info ( "【志愿者分布】查询到志愿者userId公{}个" , volunteerEpmetUserIds . size ( ) ) ;
// 2.填充ic居民信息
// 2.==========异步填充ic居民信息==========
List < CompletableFuture < List < VolunteerDistributionResultDTO . Distribution > > > volResiInfoFutures = new ArrayList < > ( ) ;
// 将所有的userId按100固定分割成多个部分,循环用每个部分去查询,然后填充
List < List < String > > volunteerEpmetUserIdParts = Lists . partition ( volunteerEpmetUserIds , 100 ) ;
for ( List < String > volunteerEpmetUserIdPart : volunteerEpmetUserIdParts ) {
List < VolunteerDistributionResultDTO . Distribution > icResiInfos = icResiUserDao . listIcResiInfosByUserIds ( volunteerEpmetUserIdPart ) ;
// 填充志愿者类型
for ( VolunteerDistributionResultDTO . Distribution icResiInfo : icResiInfos ) {
// 将志愿者类型列表字符串,切割放到set中
Set < String > volunteerTypes = new HashSet ( ) ;
String volunteerCategoriesStr = icResiInfo . getVolunteerCategoriesStr ( ) ;
if ( StringUtils . isNotEmpty ( volunteerCategoriesStr ) ) {
String [ ] vTypes = volunteerCategoriesStr . split ( "," ) ;
if ( vTypes ! = null & & vTypes . length > 0 ) {
volunteerTypes . addAll ( Arrays . asList ( vTypes ) ) ;
}
icResiInfo . setVolunteerCategories ( volunteerTypes ) ;
} else {
icResiInfo . setVolunteerCategories ( new HashSet < > ( ) ) ;
}
log . info ( "【志愿者分布】查询ic居民信息,切割后,本组的userId个数:{}" , volunteerEpmetUserIdPart . size ( ) ) ;
// 填充建筑坐标
String msg = "【志愿者分布】查询楼栋信息失败" ;
IcBuildingDTO building = getResultDataOrThrowsException ( govOrgOpenFeignClient . getBuildingById ( icResiInfo . getBuildingId ( ) ) ,
ServiceConstant . GOV_ORG_SERVER ,
EpmetErrorCode . EPMET_COMMON_OPERATION_FAIL . getCode ( ) , msg , msg ) ;
CompletableFuture < List < VolunteerDistributionResultDTO . Distribution > > future = CompletableFuture . supplyAsync ( ( ) - > {
return listIcResiInfosByUserIds ( volunteerEpmetUserIdPart ) ;
} ) ;
icResiInfo . setEpmetUserId ( icResiInfo . getEpmetUserId ( ) ) ;
icResiInfo . setIcResiUserId ( icResiInfo . getIcResiUserId ( ) ) ;
Optional . of ( building ) . ifPresent ( b - > {
icResiInfo . setLongitude ( b . getLongitude ( ) ) ;
icResiInfo . setLatitude ( b . getLatitude ( ) ) ;
} ) ;
volResiInfoFutures . add ( future ) ;
}
// 阻塞的,获取各个子线程计算结果
for ( CompletableFuture < List < VolunteerDistributionResultDTO . Distribution > > volResiInfoFuture : volResiInfoFutures ) {
try {
List < VolunteerDistributionResultDTO . Distribution > distributions = volResiInfoFuture . get ( ) ;
r . getDistributions ( ) . addAll ( distributions ) ;
} catch ( InterruptedException e ) {
log . error ( "【志愿者分布】异步获取志愿者的居民信息被中断:{}" , ExceptionUtils . getErrorStackTrace ( e ) ) ;
} catch ( ExecutionException e ) {
log . error ( "【志愿者分布】异步获取志愿者的居民信息失败:{}" , ExceptionUtils . getErrorStackTrace ( e ) ) ;
}
r . getDistributions ( ) . addAll ( icResiInfos ) ;
}
// 就有代码,稳定之后可以删掉
//for (String volunteerEpmetUserId : volunteerEpmetUserIds) {
//
// VolunteerDistributionResultDTO.Distribution distribution = new VolunteerDistributionResultDTO.Distribution();
//
// ResiUserBaseInfoResultDTO userBaseInfo = userBaseInfoDao.selecUserBaseInfoByUserId(volunteerEpmetUserId);
// if (userBaseInfo == null || StringUtils.isBlank(userBaseInfo.getIdNum())){
// log.warn("getVolunteerDistribution selecUserBaseInfoByUserId return null or idCard is null,volunteerEpmetUserId:{}", volunteerEpmetUserId);
// continue;
// }
// //使用身份证号查询ic resi信息
// IcResiUserDTO icResiUserInfo = icResiUserDao.selectIdByIdCard(customerId, userBaseInfo.getIdNum(), null);
// if (icResiUserInfo == null) {
// continue;
// }
//
// // 查询志愿者类别
// List<String> volunteerCategories = icResiUserDao.selectVolunteerByUserId(icResiUserInfo.getId());
// //if (CollectionUtils.isEmpty(volunteerCategories)) {
// // // 此人没有志愿者信息
// // continue;
// //}
//
// // 将志愿者类型列表字符串,切割放到set中
// Set<String> volunteerTypes = new HashSet();
// for (String vTypesString : volunteerCategories) {
// String[] vTypes = vTypesString.split(",");
// if (vTypes != null && vTypes.length > 0) {
// volunteerTypes.addAll(Arrays.asList(vTypes));
// }
// }
//
//
// String msg = "【志愿者分布】查询楼栋信息失败";
// IcBuildingDTO building = getResultDataOrThrowsException(govOrgOpenFeignClient.getBuildingById(icResiUserInfo.getBuildId()),
// ServiceConstant.GOV_ORG_SERVER,
// EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), msg, msg);
//
// distribution.setVolunteerCategories(volunteerTypes);
// distribution.setEpmetUserId(userBaseInfo.getUserId());
// distribution.setIcResiUserId(icResiUserInfo.getId());
// Optional.of(building).ifPresent(b -> {
// distribution.setLongitude(b.getLongitude());
// distribution.setLatitude(b.getLatitude());
// });
//
// r.getDistributions().add(distribution);
//}
return r ;
}
/ * *
* userId列表批量获取他们对应的志愿者信息
* @param volunteerEpmetUserIdPart
* @return
* /
private List < VolunteerDistributionResultDTO . Distribution > listIcResiInfosByUserIds ( List < String > volunteerEpmetUserIdPart ) {
List < VolunteerDistributionResultDTO . Distribution > icResiInfos = icResiUserDao . listIcResiInfosByUserIds ( volunteerEpmetUserIdPart ) ;
// 填充志愿者类型
for ( VolunteerDistributionResultDTO . Distribution icResiInfo : icResiInfos ) {
// 将志愿者类型列表字符串,切割放到set中
Set < String > volunteerTypes = new HashSet ( ) ;
String volunteerCategoriesStr = icResiInfo . getVolunteerCategoriesStr ( ) ;
if ( StringUtils . isNotEmpty ( volunteerCategoriesStr ) ) {
String [ ] vTypes = volunteerCategoriesStr . split ( "," ) ;
if ( vTypes ! = null & & vTypes . length > 0 ) {
volunteerTypes . addAll ( Arrays . asList ( vTypes ) ) ;
}
icResiInfo . setVolunteerCategories ( volunteerTypes ) ;
} else {
icResiInfo . setVolunteerCategories ( new HashSet < > ( ) ) ;
}
// 填充建筑坐标
String msg = "【志愿者分布】查询楼栋信息失败" ;
IcBuildingDTO building = getResultDataOrThrowsException ( govOrgOpenFeignClient . getBuildingById ( icResiInfo . getBuildingId ( ) ) ,
ServiceConstant . GOV_ORG_SERVER ,
EpmetErrorCode . EPMET_COMMON_OPERATION_FAIL . getCode ( ) , msg , msg ) ;
icResiInfo . setEpmetUserId ( icResiInfo . getEpmetUserId ( ) ) ;
icResiInfo . setIcResiUserId ( icResiInfo . getIcResiUserId ( ) ) ;
Optional . of ( building ) . ifPresent ( b - > {
icResiInfo . setLongitude ( b . getLongitude ( ) ) ;
icResiInfo . setLatitude ( b . getLatitude ( ) ) ;
} ) ;
}
return icResiInfos ;
}
/ * *
* 分页查询志愿者列表
* @param customerId
* @param pageNo
* @param pageSize
* @return
* /
private List < PageVolunteerInfoResultDTO > listVolunteersByPage ( String customerId , String agencyId , Integer pageNo , Integer pageSize ) {
VolunteerCommonFormDTO volunteerForm = new VolunteerCommonFormDTO ( ) ;
volunteerForm . setCustomerId ( customerId ) ;
volunteerForm . setSuperiorAgencyId ( agencyId ) ;
volunteerForm . setPageNo ( pageNo ) ;
volunteerForm . setPageSize ( pageSize ) ;
String errorMsg = "【志愿者分布】分页查询志愿者列表失败" ;
return getResultDataOrThrowsException ( epmetHeartOpenFeignClient . queryVolunteerPage ( volunteerForm ) ,
ServiceConstant . EPMET_HEART_SERVER ,
EpmetErrorCode . EPMET_COMMON_OPERATION_FAIL . getCode ( ) ,
errorMsg ,
errorMsg ) ;
}
}