当前位置: 移动技术网 > IT编程>开发语言>Java > 解决SpringBoot2多线程无法注入的问题

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

2020年08月27日  | 移动技术网IT编程  | 我要评论
1、情况描述使用springboot2多线程,线程类无法实现自动注入需要的bean,解决思路,通过工具类获取需要的bean如下package com.ps.uzkefu.apps.ctilink.ha

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

补充知识:关于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彻底卸载之前执行。

到这里:关于spring/springboot在静态工具类中注入service的解决方案!分享完毕了,快去试试吧!希望大家多多支持移动技术网!

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网