class ManyThreads implements Callable{
//参数一个也可以是多个
private ParamClass paramClass;
private RequestAttributes requestAttributes;
public FinishedThread(RequestAttributes requestAttributes) {
this.requestAttributes=requestAttributes;
this.paramClass=paramClass;
}
//ReturnClass 需要返回的实例
@Override
public ReturnClass call() throws Exception {
//如果单线程此处可以加获取request信息包括token
RequestContextHolder.setRequestAttributes(requestAttributes);
//循环逻辑代码
//逻辑1 paramClass操作
//逻辑2
ReturnClass returnClass=new ReturnClass();
return returnClass;
}
}
上面callable多线程。
下面for循环:
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ArrayList<FutureTask<ReturnClass>> futureTasks = new ArrayList<>();
for(ParamClass paramClass : paramClasses) {
FutureTask<ReturnClass> futureTask = new FutureTask<>(new FinishedThread(paramClass ,requestAttributes));
taskExecutor.submit(futureTask);
futureTasks.add(futureTask);
}
远程调用出问题了
如果多线程主线程结束,子线程的request信息会被清除
那么就要将token信息放到ThredLocal当中去
public class TokenContextHolder {
private static ThreadLocal<String> threadToken = new ThreadLocal<>();
public static void addToken(String token) {
threadToken.set(token);
}
public static void remove() {
if (threadToken.get() != null)
threadToken.remove();
}
public static String getToken(){
return threadToken.get();
}
}
拦截器 此拦截器为feign拦截器
import com.iqv.common.request.TokenContextHolder;
import feign.*;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CommonConstant;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Slf4j
public class MyFeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (null != attributes) {
HttpServletRequest request = attributes.getRequest();
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
//从threadLocal中获取token信息
if(token == null ){
token = TokenContextHolder.getToken();
}
//CommonConstant.X_ACCESS_TOKEN token的名称
template.header(CommonConstant.X_ACCESS_TOKEN, token);
}
}
}
ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
String token = sra.getRequest().getHeader(CommonConstant.X_ACCESS_TOKEN);
FutureTask<Object> futureTask = new FutureTask<>(new ManyThread(paramClass sra, token));
taskExecutor.submit(futureTask);
上面为调用地方修改
下面为ManyThread中的修改
try{
//用的时候添加进ThreadLocal中
TokenContextHolder.addToken(token);
RequestContextHolder.setRequestAttributes(requestAttributes);
}catch (Exception e){
log.error(e.getMessage(),e);
}finally {
//用完清除不影响其他流程
TokenContextHolder.remove();
}