您好,登錄后才能下訂單哦!
1、情況描述
使用springboot2多線程,線程類無法實(shí)現(xiàn)自動(dòng)注入需要的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; //無法自動(dòng)注入 public RedissonClient redissonClient; //無法自動(dòng)注入 public UserService userService; //無法自動(dòng)注入 public CallRecordService callRecordService; public CdrHandler() { //new的時(shí)候注入需要的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() { // 外呼 通話結(jié)束 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 保存到數(shù)據(jù)庫 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()); //來電 通話結(jié)束 外部電話 呼入 接入分機(jī)的童虎記錄 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())) { //用戶在坐席未接來電時(shí) 未接來電無錄音 掛機(jī) 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 { /** * 上下文對(duì)象實(shí)例 */ 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
補(bǔ)充知識(shí):關(guān)于Spring/SpringBoot在靜態(tài)工具類中注入Service的解決方案
前言今天博主將為大家分享:關(guān)于Spring/SpringBoot在靜態(tài)工具類中注入Service的解決方案!不喜勿噴,如有異議歡迎討論!
最近遇到了需要在工具類中注入Service,由于工具類中方法一般都是靜態(tài)的,所以要求該屬性也要是靜態(tài)的(Service)。但是由于Spring/SpringBoot正常情況下不能支持注入靜態(tài)屬性(會(huì)報(bào)空指針異常)。主要原因在于:Spring的依賴注入實(shí)際上是依賴于Set方法進(jìn)行注入值的,Spring是基于對(duì)象層面的依賴注入,而靜態(tài)屬性/靜態(tài)變量實(shí)際上是屬于類的。
解決方案:
給當(dāng)前的工具類加上@Component,使其成為一個(gè)bean對(duì)象
聲明一個(gè)靜態(tài)的屬性(加上注解@Autowired),一個(gè)非靜態(tài)的屬性。
聲明一個(gè)返回值為void并且不能拋出異常的方法,在其中將非靜態(tài)屬性賦值給靜態(tài)屬性。該方法上加上注解@PostConstruct
這樣就將service的值注入了進(jìn)來。示例代碼如下:
/** * *@Description: 關(guān)于Spring/SpringBoot在靜態(tài)工具類中注入Service的解決方案 *@ClassName: XXUtils.java *@author ChenYongJia *@Date 2019年6月26日 晚上21:20 *@Email chen87647213@163.com */ @Component public class XXUtils { @Autowired private SpecialLogSevice sevice; private static SpecialLogSevice specialLogSevice; @PostConstruct public void init() { specialLogSevice = sevice; } //下面的內(nèi)容就省略了,需要調(diào)用specialLogSevice打點(diǎn)就行了 }
在上述代碼中@PostConstruct是Java EE5規(guī)范之后,Servlet新增的兩個(gè)影響servlet聲明周期的注解之一,另外一個(gè)是@PreConstruct。這兩個(gè)都可以用來修飾一個(gè)非靜態(tài)的返回值為void的方法,并且該方法不能拋出異常。
被@PostConstruct注解修飾的方法會(huì)在服務(wù)器加載Servlet的時(shí)候運(yùn)行,并且只會(huì)被服務(wù)器調(diào)用一次,類似于Servlet中的init方法。被該注解修飾的方法會(huì)在構(gòu)造器執(zhí)行之后,init方法執(zhí)行之前執(zhí)行。Spring中允許開發(fā)者在受理的Bean中去使用它,當(dāng)IOC容器被實(shí)例化管理當(dāng)前bean時(shí),被該注解修飾的方法會(huì)執(zhí)行,完成一些初始化的工作。
被PreConstruct注解修飾的方法會(huì)在服務(wù)器卸載Servlet的時(shí)候運(yùn)行,類似于Servlet中的destroy方法。被該注解修飾的方法會(huì)在destroy方法執(zhí)行之后,Servlet徹底卸載之前執(zhí)行。
到這里:關(guān)于Spring/SpringBoot在靜態(tài)工具類中注入Service的解決方案!分享完畢了,快去試試吧!希望大家多多支持億速云!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。