此次项目中使用的多线程批量处理数据,使用过程中遇到了以下几个问题:

1、线程类没有被Spring容器托管,只是一个普通的类,在线程类中需要使用@Value注解以获得yaml配置文件中的信息,直接使用这种注解方式是获取不到信息:

        ①如果需要使用@Value这种注解获取值,则类的本身需要被Spring容器进行托管(但是线程类使用@Component注解会有点问题,原因是虽然此时线程类被Spring托管了,但是由于在调用这个组件(线程类)的时候不能使用@Autowired或者@Resource进行注入使用,只能够使用new的方式调用,导致这个值初始化的时候就为null,导致@Value注解无效,取不到配置的值)

        ②变量被关键字static修饰的时候,获取不到值,如下图

@Component
public class TestValue implements InitializingBean {
    @Value("${kafka.bootstrap.servers}")
    private String kafkaServers;

    //这里的topic被static修饰,是取不到值的
    @Value("${kafka.servers.first.topic}")
    private static String topic;
 
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println(kafkaServers);
        System.out.println(topic);
    }
}
/**
     * orgbuildUrl
     */
    @Value("${paas.orgbuild-url}")
    private String orgbuildUrl;

解决方式:因为线程类在使用的时候需要调用run方法,所以必定会在一个Impl中实例化线程类对象(此处的实例化的方式为new),此时在线程类的构造方法中将需要的配置信息作为参数,而Impl中获得之后,通过构造方法传入即可。

2、当项目中使用分库的时候,会在yaml配置文件中配置数据源,使用one、two的形式指定在此次接口处理中使用哪个数据源作为处理对象,但在多线程中,原先在Controller层接口中指定的数据源会失效,而线程处理的数据库永远只会是配置文件中指定的默认数据源,从而导致如果需要处理的表数据不在默认的数据源中,程序处理就会报错,找不到对应的表。

解决方式:

        ①将需要处理的数据表放入默认的数据源

        ②使用服务调用的方式重新调用一个Controller中的接口,这个接口指定需要处理的数据源即可

3、如果在线程类或者一般的类中使用@Autowired或者@Resource无法注入需要的类,可以使用如下方式进行注入:

import com.aliyun.hzdj.party.common.utils.SpringUtils;
 
@Resource
private PaasHttpUtil paasHttpUtil;

public UpdateMyPersonThread(List<MyPerson> selectionMyPersonList, String orgbuildUrl) {
    this.paasHttpUtil = SpringUtils.getBean("paasHttpUtil");
}

4、关于服务调用的总结

        ①web端服务调用接口中所使用的的注解,@FeignClient("hzdj-party-admin"),注解加在类上即可,如下图:

spring boot 接口多线程模式 springboot多线程读取文件_spring boot 接口多线程模式

 这是一个服务调用接口,并不是一个具体的类,在调用的时候只需要在Impl类中将此接口注入进来,直接调用里面的方法即可。

        ②此服务调用接口中的方法并不需要自己重新实现,每个方法实际访问的是需要被调用的Controller路径所指定的方法,在调用此接口方法的时候只需要传入对应的参数,将自动找到对应的MVC接口处理业务逻辑,返回数据,如下:

spring boot 接口多线程模式 springboot多线程读取文件_服务调用_02

        注:使用服务调用的目的是为了解决单个接口中使用多线程之后,线程中无法处理多个数据源的问题,利用另一个接口中指定需要处理的数据源就可以巧妙的解决此问题。