app开发者平台在数字化时代的重要性与发展趋势解析
686
2023-04-24
解决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.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
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();
}
HuQxZuLt}
private void saveVistorCdr() {
CallCdr callCdr = null;
RBucket
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
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
* @return
*/
public static
return getApplicationContext().getBean(clazz);
}
/**
* 通过name,以及Clazz返回指定的Bean
*
* @param name
* @param clazz
* @param
* @return
*/
public static
return getApplicationContext().getBean(name, clazz);
}
}
3、通过工具类的getBean方法即可获取bean
补充知识:关于Spring/SpringBoot在静态工具类中注入Service的解决方案
前言今天博主将为大家分享:关于Spring/SpringBoot在静态工具类中注入Service的解决方案!不喜勿喷,如有异议欢迎讨论!
最近遇到了需要在工具类中注入Service,由于工具类中方法一般都是静态的,所以要求该属性也要是静态的(Service)。但是由于Spring/SpringBoot正常情况下不能支持注入静态属性(会报空指针异常)。主要原因在于:Spring的依赖注入实际上是依赖于Set方法进行注入值的,Spring是基于对象层面的依赖注入,而静态属性/静态变量实际上是属于类的。
解决方案:
给当前的工具类加上@Component,使其成为一个bean对象
声明一个静态的属性(加上注解@Autowired),一个非静态的属性。
声明一个返回值为void并且不能抛出异常的方法,在其中将非静态属性赋值给静态属性。该方法上加上注解@PostConstruct
这样就将service的值注入了进来。示例代码如下:
/**
*
*@Description: 关于Spring/SpringBoot在静态工具类中注入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;
}
//下面的内容就省略了,需要调用specialLogSevice打点就行了
}
在上述代码中@PostConstruct是Java EE5规范之后,Servlet新增的两个影响servlet声明周期的注解之一,另外一个是@PreConstruct。这两个都可以用来修饰一个非静态的返回值为void的方法,并且该方法不能抛出异常。
被@PostConstruct注解修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet中的init方法。被该注解修饰的方法会在构造器执行之后,init方法执行之前执行。Spring中允许开发者在受理的Bean中去使用它,当IOC容器被实例化管理当前bean时,被该注解修饰的方法会执行,完成一些初始化的工作。
被PreConstruct注解修饰的方法会在服务器卸载Servlet的时候运行,类似于Servlet中的destroy方法。被该注解修饰的方法会在destroy方法执行之后,Servlet彻底卸载之前执行。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~