解决SpringBoot2多线程无法注入的问题

网友投稿 540 2022-11-25


解决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 bucket = redissonClient.getBucket(RedisKeyPhttp://refix.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().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();

}

HuQxZuLt}

private void saveVistorCdr() {

CallCdr callCdr = null;

RBucket 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().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

* @return

*/

public static T getBean(Class clazz) {

return getApplicationContext().getBean(clazz);

}

/**

* 通过name,以及Clazz返回指定的Bean

*

* @param name

* @param clazz

* @param

* @return

*/

public static T getBean(String name, Class clazz) {

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小时内删除侵权内容。

上一篇:mybatis 根据id批量删除的实现操作
下一篇:Mybatis plus 配置多数据源的实现示例
相关文章

 发表评论

暂时没有评论,来抢沙发吧~