InBoxServiceImpl.java 9.45 KB
package com.yohoufo.user.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yoho.core.common.utils.DateUtil;
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yohoufo.common.enums.InboxBusinessTypeEnum;
import com.yohoufo.common.enums.InboxTypeEnum;
import com.yohoufo.common.redis.NoSyncGracefulRedisTemplate;
import com.yohoufo.dal.user.IInBoxDao;
import com.yohoufo.dal.user.model.InBox;
import com.yohoufo.dal.user.model.TypeCountInbox;
import com.yohoufo.user.cache.CacheKeyHelper;
import com.yohoufo.user.constants.CacheEnum;
import com.yohoufo.user.requestVO.ListInboxReqVO;
import com.yohoufo.user.requestVO.ListInboxTypeInfoReqVO;
import com.yohoufo.user.responseVO.PageResponseVO;
import com.yohoufo.user.service.IInBoxService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * Created by shengguo.cai on 2018/9/11.
 */
@Service
public class InBoxServiceImpl implements IInBoxService {
    private static Logger log = LoggerFactory.getLogger(InBoxServiceImpl.class);
    @Autowired
    private IInBoxDao inBoxDao;
    @Resource(name="NoSyncGracefulRedisTemplate")
    private NoSyncGracefulRedisTemplate redisTemplate;

    @Override
    public JSONArray listInboxTypeInfo(ListInboxTypeInfoReqVO reqBO) {
        log.info("listInboxTypeInfo begin.param is {}",reqBO);
        Integer uid = reqBO.getUid();
        JSONArray result = getInboxTypeInfoByRedis(uid);
        if(result != null){
            return result;
        }
        Map<Integer,TypeCountInbox> typeCountMap = inBoxDao.selectTypeCount(getTableName(uid), uid, "N", "N");
        result = new JSONArray();
        for(InboxTypeEnum typeEnum : InboxTypeEnum.values()) {
            JSONObject obj = new JSONObject();
            obj.put("type", typeEnum.getId());
            obj.put("imgUrl", typeEnum.getImgUrl());
            obj.put("description", typeEnum.getDescription());
            obj.put("unReadCount", typeCountMap.containsKey(typeEnum.getId()) ? typeCountMap.get(typeEnum.getId()).getCount() : 0);
            result.add(obj);
        }
        setInboxTypeInfoByRedis(uid,result);
        return result;
    }

    private void setInboxTypeInfoByRedis(Integer uid, JSONArray inboxs) {
        for(int i=0;i<inboxs.size();i++){
            Integer unReadCount = inboxs.getJSONObject(i).getInteger("unReadCount");
            Integer type = inboxs.getJSONObject(i).getInteger("type");
            RedisKeyBuilder key = CacheEnum.USERS_INBOX_TYPE_UNREADCOUNT.generateKey(uid,type);
            redisTemplate.setEx(key,unReadCount,CacheEnum.USERS_INBOX_TYPE_UNREADCOUNT.getCacheTime());
        }
    }

    private JSONArray getInboxTypeInfoByRedis(Integer uid){
        JSONArray result = new JSONArray();
        for(InboxTypeEnum typeEnum : InboxTypeEnum.values()) {
            RedisKeyBuilder key = CacheEnum.USERS_INBOX_TYPE_UNREADCOUNT.generateKey(uid,typeEnum.getId());
            Integer unReadCount = redisTemplate.get(key,Integer.class);
            if(null == unReadCount){
                log.info("getInboxTypeInfoByRedis some caches are empty.key is {}",key);
                return null;
            }
            JSONObject obj = new JSONObject();
            obj.put("type", typeEnum.getId());
            obj.put("imgUrl", typeEnum.getImgUrl());
            obj.put("description", typeEnum.getDescription());
            obj.put("unReadCount", unReadCount);
            result.add(obj);
        }
        return result;
    }

    @Override
    public PageResponseVO<InBox> listInboxByTypes(ListInboxReqVO reqVO) {
        log.info("entre listInboxByTypes with param is {}", reqVO);
        //判断为空
        if (reqVO.getUid() <= 0) {
            log.warn("listInboxByTypes error because uid is null with param is {}", reqVO);
            throw new ServiceException(ServiceError.SMS_INBOX_UID_NULL);
        }
        //如果根据类型查看,设置未读为已读
        updateReaded(reqVO);
        PageResponseVO<InBox> response = listInboxByRedis(reqVO);
        if(null != response){
            return response;
        }
        response = new PageResponseVO<>();
        int total = inBoxDao.selectTotalInboxs(getTableName(reqVO.getUid()),reqVO.getType(),
                reqVO.getUid());
        if(total == 0){
            log.info("listInboxByTypes query inbox is empty with param is {}", reqVO);
            response.setPage(reqVO.getPage());
            response.setTotal(0);
            setInboxByRedis(reqVO,null,total);
            return response;
        }
        List<InBox> inBoxes = inBoxDao.selectInboxs(getTableName(reqVO.getUid()),reqVO.getType(),
                reqVO.getUid(),reqVO.getRowNo(),reqVO.getLimit());
        response.setList(inBoxes);
        response.setPage(reqVO.getPage());
        response.setSize(reqVO.getLimit());
        response.setTotal(total);
        setInboxByRedis(reqVO,inBoxes,total);
        return response;
    }

    private void setInboxByRedis(ListInboxReqVO reqVO, List<InBox> inBoxes, int total) {
        RedisKeyBuilder inboxKey = CacheEnum.USERS_INBOX_LIST.generateKey(reqVO.getUid());
        redisTemplate.put(inboxKey, CacheKeyHelper.getInboxRedisHashKey(reqVO.getType(),reqVO.getPage(),reqVO.getLimit()),
                inBoxes,CacheEnum.USERS_INBOX_LIST.getCacheTime());
        RedisKeyBuilder inboxTotalKey = CacheEnum.USERS_INBOX_LIST_TOTAL.generateKey(reqVO.getUid(),reqVO.getType() == null ?"N":reqVO.getType());
        redisTemplate.setEx(inboxTotalKey,total,CacheEnum.USERS_INBOX_LIST_TOTAL.getCacheTime());
    }

    private void updateReaded(ListInboxReqVO reqVO){
        if(null != reqVO.getType()){
            log.info("listInboxByTypes updateReadedByUidAndType param is {}", reqVO);
            inBoxDao.updateReadedByUidAndType(getTableName(reqVO.getUid()),reqVO.getUid(),reqVO.getType(),DateUtil.getCurrentTimeSecond());
            RedisKeyBuilder key = CacheEnum.USERS_INBOX_TYPE_UNREADCOUNT.generateKey(reqVO.getUid(),reqVO.getType());
            redisTemplate.delete(key);
        }
    }

    private PageResponseVO<InBox> listInboxByRedis(ListInboxReqVO reqVO) {
        PageResponseVO<InBox> response = new PageResponseVO<>();
        RedisKeyBuilder inboxKey = CacheEnum.USERS_INBOX_LIST.generateKey(reqVO.getUid());
        List<InBox> inboxes = redisTemplate.getList(inboxKey, CacheKeyHelper.getInboxRedisHashKey(reqVO.getType(),reqVO.getPage(),reqVO.getLimit()),InBox.class);
        RedisKeyBuilder inboxTotalKey = CacheEnum.USERS_INBOX_LIST_TOTAL.generateKey(reqVO.getUid(),reqVO.getType() == null ?"N":reqVO.getType());
        Integer total = redisTemplate.get(inboxTotalKey,Integer.class);
        if(inboxes == null || total == null){
            log.info("listInboxByRedis cache is empty.inboxes is {},inboxKey is {}," +
                    "total is {},totalKey is {}",inboxes,inboxKey,total,inboxTotalKey);
            return null;
        }
        response.setList(inboxes);
        response.setPage(reqVO.getPage());
        response.setSize(reqVO.getLimit());
        response.setTotal(total);
        return response;
    }

    @Override
    public void addInbox(int uid, Integer type, Integer businessType, String params) {
        log.info("entre addInbox with param .uid is {},type is {},businessType is {},params is {}", uid,type,businessType,params);
        InboxBusinessTypeEnum businessTypeEnum = InboxBusinessTypeEnum.getByTypeAndBusinessType(type,businessType);
        if(businessTypeEnum == null){
            log.warn("addInbox businessTypeEnum is null.type is {},businessType is {}",type,businessType);
            throw new ServiceException(ServiceError.SMS_TEMPLATE_NOT_EXIST);
        }
        InBox inBox = new InBox();
        inBox.setUid(uid);
        inBox.setType(type);
        inBox.setIsRead(InBox.N);
        inBox.setIsDel(InBox.N);
        inBox.setTitle(businessTypeEnum.getTitle());
        inBox.setCreateTime(DateUtil.getCurrentTimeSecond());
        inBox.setContent(createContent(businessTypeEnum.getContent(),params));
        inBox.setBusinessType(businessType);
        inBoxDao.insertInbox(getTableName(inBox.getUid()),inBox);
        deleteIboxsByRedis(uid,type);
    }

    private void deleteIboxsByRedis(int uid,int type){
        log.info("deleteIboxsByRedis params uid is {} type is {}",uid,type);
        RedisKeyBuilder inboxKey = CacheEnum.USERS_INBOX_LIST.generateKey(uid);
        redisTemplate.delete(inboxKey);
        RedisKeyBuilder key = CacheEnum.USERS_INBOX_TYPE_UNREADCOUNT.generateKey(uid,type);
        redisTemplate.delete(key);
        RedisKeyBuilder inboxTotalKey = CacheEnum.USERS_INBOX_LIST_TOTAL.generateKey(uid,"N");
        redisTemplate.delete(inboxTotalKey);
        RedisKeyBuilder inboxTypeTotalKey = CacheEnum.USERS_INBOX_LIST_TOTAL.generateKey(uid,type);
        redisTemplate.delete(inboxTypeTotalKey);
    }

    private String createContent(String template, String params){
        if(StringUtils.isBlank(params)){
            return template;
        }
        String[] paramArray = params.split(",");
        for(String param : paramArray){
            template=template.replaceFirst("\\{\\}",param);
        }
        return template;
    }

    private String getTableName(Integer uid) {
        return "inbox_" + uid % 10;
    }

}