1. 程式人生 > >SpringBoot2多執行緒無法注入問題

SpringBoot2多執行緒無法注入問題

1、情況描述

使用springboot2多執行緒,執行緒類無法實現自動注入需要的bean,解決思路,通過工具類獲取需要的bean

如下

package com.ps.uzkefu.apps.ctilink.handler;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.ps.uzkefu.apps.callcenter.entity.CallRecord;
import com.ps.uzkefu.apps.callcenter.service.CallRecordService;
import com.ps.uzkefu.apps.ctilink.init.ApplicationContextProvider;
import com.ps.uzkefu.apps.ctilink.ommodel.CallCdr;
import com.ps.uzkefu.apps.ctilink.ommodel.Cdr;
import com.ps.uzkefu.apps.ctilink.rediskey.CdrType;
import com.ps.uzkefu.apps.ctilink.rediskey.EventType;
import com.ps.uzkefu.apps.ctilink.rediskey.RedisKeyPrefix;
import com.ps.uzkefu.apps.oms.account.entity.User;
import com.ps.uzkefu.apps.oms.account.service.UserService;
import com.ps.uzkefu.util.UUIDUtil;
import com.ps.uzkefu.utils.PhoneModel;
import com.ps.uzkefu.utils.PhoneUtils;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;

import java.util.Date;
import java.util.Objects;

/**
 * Author:ZhuShangJin
 * Date:2018/6/26
 */
public class CdrHandler implements Runnable {

    public Cdr cdr;
    //無法自動注入
    public RedissonClient redissonClient;
    //無法自動注入
    public UserService userService;
    //無法自動注入
    public CallRecordService callRecordService;

    public CdrHandler() {
        //new的時候注入需要的bean
        this.redissonClient = ApplicationContextProvider.getBean(RedissonClient.class);
        this.userService = ApplicationContextProvider.getBean(UserService.class);
        this.callRecordService = ApplicationContextProvider.getBean(CallRecordService.class);
    }

    public RedissonClient getRedissonClient() {
        return redissonClient;
    }

    public void setRedissonClient(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    public Cdr getCdr() {
        return cdr;
    }

    public void setCdr(Cdr cdr) {

        this.cdr = cdr;
    }

    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public CallRecordService getCallRecordService() {
        return callRecordService;
    }

    public void setCallRecordService(CallRecordService callRecordService) {
        this.callRecordService = callRecordService;
    }

    @Override
    public void run() {
        if (this.getCdr().getOuter() != null) {
            saveOuterCdr();
        } else if (this.getCdr().getVisitor() != null) {
            saveVistorCdr();
        }
    }

    private void saveOuterCdr() {
        //    外呼  通話結束
        CallCdr callCdr = null;
        RBucket<CallCdr> bucket = redissonClient.getBucket(RedisKeyPrefix.CALL_OUTER_CDR + this.getCdr().getOuter().getId() + "_" + cdr.getCpn());
        callCdr = bucket.get();
        callCdr.setRedisKey(RedisKeyPrefix.CALL_OUTER_CDR + this.getCdr().getOuter().getId() + "_" + cdr.getCpn());
        callCdr.setLastEvent(EventType.BYE);
        callCdr.setLastEventTime(new Date());
        callCdr.setTalkLength(Integer.parseInt(this.getCdr().getDuration()));
        callCdr.setTrunkNum(this.getCdr().getTrunkNumber());
        callCdr.setHangupTime(new Date());
        callCdr.setRecord(this.getCdr().getRecording());
        if (callCdr.getAnsweredTime() == null){
            callCdr.setCallTime(callCdr.getHangupTime());
        }else {
            long time = callCdr.getAnsweredTime().getTime() - callCdr.getRingLength()*1000;
            callCdr.setCallTime(new Date(time));
        }
        //todo 儲存到資料庫
        User user = userService.selectOne(new EntityWrapper<User>().eq("extension", callCdr.getExtensionNum() + ""));
        callCdr.setUserName(user.getUserName());
        callCdr.setCorpCode(user.getCorpCode());
        callCdr.setCreater(user.getId());
        callCdr.setId(UUIDUtil.genUUID());
        callCdr.setCreateTime(new Date());
        PhoneModel phoneModel = PhoneUtils.getPhoneModel(callCdr.getCustomerPhone());
        if (phoneModel != null) {
            callCdr.setCustomerCity(phoneModel.getCityName());
            callCdr.setCustomerProvince(phoneModel.getProvinceName());
        }
        callCdr.setCallId(System.currentTimeMillis() + "" + callCdr.getCallId());
        bucket.set(callCdr);
        CallRecord callRecord = callCdr;
        boolean result = callRecordService.insert(callRecord);
        if (result) {
            bucket.delete();
        }

    }


    private void saveVistorCdr() {
        CallCdr callCdr = null;
        RBucket<CallCdr> bucket = redissonClient.getBucket(RedisKeyPrefix.CALL_VISITOR_CDR + this.getCdr().getVisitor().getId() + "_" + cdr.getTrunkNumber());
        callCdr = bucket.get();
        callCdr.setRedisKey(RedisKeyPrefix.CALL_VISITOR_CDR + this.getCdr().getVisitor().getId() + "_" + cdr.getTrunkNumber());
        callCdr.setRecord(this.getCdr().getRecording());
        PhoneModel phoneModel = PhoneUtils.getPhoneModel(callCdr.getCustomerPhone());
        if (phoneModel != null) {
            callCdr.setCustomerCity(phoneModel.getCityName());
            callCdr.setCustomerProvince(phoneModel.getProvinceName());
        }
        callCdr.setCallId(System.currentTimeMillis() + "" + callCdr.getCallId());
        callCdr.setId(UUIDUtil.genUUID());
        //來電 通話結束  外部電話 呼入 接入分機的童虎記錄
        if (Objects.equals(CdrType.IN, this.getCdr().getType()) && this.getCdr().getCdpn().length() == 5) {
            callCdr.setExtensionNum(Integer.parseInt(this.getCdr().getCdpn()));
            User user = userService.selectOne(new EntityWrapper<User>().eq("extension", callCdr.getExtensionNum() + ""));
            callCdr.setUserName(user.getUserName());
            callCdr.setCorpCode(user.getCorpCode());
            callCdr.setCreater(user.getId());
            if (Objects.equals(EventType.RING, callCdr.getLastEvent())) {
                if (StringUtils.isBlank(this.getCdr().getRecording())) {
                    //使用者在坐席未接來電時 未接來電無錄音 掛機
                    int ringLength = (int) ((new Date().getTime() - callCdr.getLastEventTime().getTime()) / 1000);
                    callCdr.setRingLength(ringLength);
                    callCdr.setTalkLength(0);
                } else {
                    //特殊情況 坐席接聽後立馬掛掉
                    callCdr.setTalkLength(Integer.parseInt(this.getCdr().getDuration()));
                    callCdr.setRingLength(-1);
                    callCdr.setLastEvent(CdrType.UNUSUAL);
                }
            } else {
                //正常情況
                callCdr.setTalkLength(Integer.parseInt(this.getCdr().getDuration()));
            }
        } else if (Objects.equals(CdrType.IN, this.getCdr().getType()) && this.getCdr().getCdpn().length() != 5) {
            //客服沒接到
            callCdr.setExtensionNum(0);
            callCdr.setUserName("未接到");
            callCdr.setCorpCode(this.getCdr().getCdpn());
            callCdr.setCreater("未接到");
            callCdr.setTalkLength(0);
            int ringLength = (int) ((new Date().getTime() - callCdr.getCallTime().getTime())/1000);
            callCdr.setRingLength(ringLength);
        }
        callCdr.setCreateTime(new Date());
        callCdr.setHangupTime(new Date());
        bucket.set(callCdr);

        if (Objects.equals(CdrType.IN, this.getCdr().getType())
                && this.getCdr().getCdpn().length() == 5
                && Objects.equals(EventType.RING, callCdr.getLastEvent())
                && StringUtils.isNotBlank(this.cdr.getRecording())) {

        }else if(Objects.equals(CdrType.UNUSUAL,callCdr.getLastEvent())){

        }else {
            CallRecord callRecord = callCdr;
            boolean result = callRecordService.insert(callRecord);
            if (result) {
                bucket.delete();
            }
        }
    }
}

2、獲取bean的工具類 

package com.ps.uzkefu.apps.ctilink.init;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * Author:ZhuShangJin
 * Date:2018/7/3
 */
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
    /**
     * 上下文物件例項
     */
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 獲取applicationContext
     *
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通過name獲取 Bean.
     *
     * @param name
     * @return
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    /**
     * 通過class獲取Bean.
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     * 通過name,以及Clazz返回指定的Bean
     *
     * @param name
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}
3、通過工具類的getBean方法即可獲取bean