大家一直在谈的领域驱动设计(DDD),我们在互联网业务系统是这么实践的

转载于:https: mp weixin qq com s?__biz=MjM5NjQ5MTI5OA==&mid=2651747236&idx=1&sn=b

转载于:https://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651747236&idx=1&sn=baf67052ec1961c3c6de1af26fba9b22

 

 

 

 

 

 

 

 

 

 

 

AwardPool awardPool = awardPoolDao.getAwardPool(poolId);//sql查询,将数据映射到AwardPool对象for (Award award : awardPool.getAwards()) {   //寻找到符合award.getProbability()概率的award}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

import com.company.team.bussiness.lottery.*;//抽奖上下文import com.company.team.bussiness.riskcontrol.*;//风控上下文import com.company.team.bussiness.counter.*;//计数上下文import com.company.team.bussiness.condition.*;//活动准入上下文import com.company.team.bussiness.stock.*;//库存上下文

 

 

import com.company.team.bussiness.lottery.domain.valobj.*;//领域对象-值对象import com.company.team.bussiness.lottery.domain.entity.*;//领域对象-实体import com.company.team.bussiness.lottery.domain.aggregate.*;//领域对象-聚合根import com.company.team.bussiness.lottery.service.*;//领域服务import com.company.team.bussiness.lottery.repo.*;//领域资源库import com.company.team.bussiness.lottery.facade.*;//领域防腐层

 

 

package com.company.team.bussiness.lottery.domain.aggregate;import ...;public class DrawLottery {    private int lotteryId; //抽奖id
    private List<AwardPool> awardPools; //奖池列表

    //getter & setter
    public void setLotteryId(int lotteryId) {        if(id<=0){            throw new IllegalArgumentException("非法的抽奖id"); 
        }        this.lotteryId = lotteryId;
    }    //根据抽奖入参context选择奖池
    public AwardPool chooseAwardPool(DrawLotteryContext context) {        if(context.getMtCityInfo()!=null) {            return chooseAwardPoolByCityInfo(awardPools, context.getMtCityInfo());
        } else {            return chooseAwardPoolByScore(awardPools, context.getGameScore());
        }
    }    //根据抽奖所在城市选择奖池
    private AwardPool chooseAwardPoolByCityInfo(List<AwardPool> awardPools, MtCifyInfo cityInfo) {        for(AwardPool awardPool: awardPools) {            if(awardPool.matchedCity(cityInfo.getCityId())) {                return awardPool;
            }
        }        return null;
    }    //根据抽奖活动得分选择奖池
    private AwardPool chooseAwardPoolByScore(List<AwardPool> awardPools, int gameScore) {...}
}

 

 

package com.company.team.bussiness.lottery.domain.valobj;
import ...;

public class AwardPool {
    private String cityIds;//奖池支持的城市
    private String scores;//奖池支持的得分
    private int userGroupType;//奖池匹配的用户类型
    private List<Awrad> awards;//奖池中包含的奖品

    //当前奖池是否与城市匹配
    public boolean matchedCity(int cityId) {...}

    //当前奖池是否与用户得分匹配
    public boolean matchedScore(int score) {...}

    //根据概率选择奖池
    public Award randomGetAward() {
        int sumOfProbablity = 0;
        for(Award award: awards) {
            sumOfProbability += award.getAwardProbablity();
        }
        int randomNumber = ThreadLocalRandom.current().nextInt(sumOfProbablity);
        range = 0;
        for(Award award: awards) {
            range += award.getProbablity();
            if(randomNumber<range) {
                return award;
            }
        }
        return null;
    }
}

 

 

//数据库资源import com.company.team.bussiness.lottery.repo.dao.AwardPoolDao;//数据库访问对象-奖池import com.company.team.bussiness.lottery.repo.dao.AwardDao;//数据库访问对象-奖品import com.company.team.bussiness.lottery.repo.dao.po.AwardPO;//数据库持久化对象-奖品import com.company.team.bussiness.lottery.repo.dao.po.AwardPoolPO;//数据库持久化对象-奖池import com.company.team.bussiness.lottery.repo.cache.DrawLotteryCacheAccessObj;//分布式缓存访问对象-抽奖缓存访问import com.company.team.bussiness.lottery.repo.repository.DrawLotteryRepository;//资源库访问对象-抽奖资源库

 

 

package com.company.team.bussiness.lottery.repo;import ...;@Repositorypublic class DrawLotteryRepository {    @Autowired
    private AwardDao awardDao;    @Autowired
    private AwardPoolDao awardPoolDao;    @AutoWired
    private DrawLotteryCacheAccessObj drawLotteryCacheAccessObj;    public DrawLottery getDrawLotteryById(int lotteryId) {
        DrawLottery drawLottery = drawLotteryCacheAccessObj.get(lotteryId);        if(drawLottery!=null){            return drawLottery;
        }
        drawLottery = getDrawLotteyFromDB(lotteryId);
        drawLotteryCacheAccessObj.add(lotteryId, drawLottery);        return drawLottery;
    }    private DrawLottery getDrawLotteryFromDB(int lotteryId) {...}
}

 

 

package com.company.team.bussiness.lottery.facade;import ...;@Componentpublic class UserCityInfoFacade {    @Autowired
    private LbsService lbsService;//外部用户城市信息RPC服务

    public MtCityInfo getMtCityInfo(LotteryContext context) {
        LbsReq lbsReq = new LbsReq();
        lbsReq.setLat(context.getLat());
        lbsReq.setLng(context.getLng());
        LbsResponse resp = lbsService.getLbsCityInfo(lbsReq);        return buildMtCifyInfo(resp);
    }    private MtCityInfo buildMtCityInfo(LbsResponse resp) {...}
}

 

 

package com.company.team.bussiness.lottery.service.implimport ...;@Servicepublic class LotteryServiceImpl implements LotteryService {    @Autowired
    private DrawLotteryRepository drawLotteryRepo;    @Autowired
    private UserCityInfoFacade UserCityInfoFacade;    @Autowired
    private AwardSendService awardSendService;    @Autowired
    private AwardCounterFacade awardCounterFacade;    @Override
    public IssueResponse issueLottery(LotteryContext lotteryContext) {
        DrawLottery drawLottery = drawLotteryRepo.getDrawLotteryById(lotteryContext.getLotteryId());//获取抽奖配置聚合根
        awardCounterFacade.incrTryCount(lotteryContext);//增加抽奖计数信息
        AwardPool awardPool = lotteryConfig.chooseAwardPool(bulidDrawLotteryContext(drawLottery, lotteryContext));//选中奖池
        Award award = awardPool.randomChooseAward();//选中奖品
        return buildIssueResponse(awardSendService.sendAward(award, lotteryContext));//发出奖品实体
    }    private IssueResponse buildIssueResponse(AwardSendResponse awardSendResponse) {...}
}

 

 

 

 

 

 

 

 

package ...;import ...;@Servicepublic class LotteryApplicationService {    @Autowired
    private LotteryRiskService riskService;    @Autowired
    private LotteryConditionService conditionService;    @Autowired
    private LotteryService lotteryService;    //用户参与抽奖活动
    public Response<PrizeInfo, ErrorData> participateLottery(LotteryContext lotteryContext) {        //校验用户登录信息
        validateLoginInfo(lotteryContext);        //校验风控 
        RiskAccessToken riskToken = riskService.accquire(buildRiskReq(lotteryContext));
        ...        //活动准入检查
        LotteryConditionResult conditionResult = conditionService.checkLotteryCondition(otteryContext.getLotteryId(),lotteryContext.getUserId());
        ...        //抽奖并返回结果
        IssueResponse issueResponse = lotteryService.issurLottery(lotteryContext);        if(issueResponse!=null && issueResponse.getCode()==IssueResponse.OK) {            return buildSuccessResponse(issueResponse.getPrizeInfo());
        } else {   
            return buildErrorResponse(ResponseCode.ISSUE_LOTTERY_FAIL, ResponseMsg.ISSUE_LOTTERY_FAIL)
        }
    }    private void validateLoginInfo(LotteryContext lotteryContext){...}    private Response<PrizeInfo, ErrorData> buildErrorResponse (int code, String msg){...}    private Response<PrizeInfo, ErrorData> buildSuccessResponse (PrizeInfo prizeInfo){...}
}