Я хотел бы пролить свет на этот вопрос.
FeignSSOTokenRequestInterceptor - ваш пользовательский RequestInterceptor, и вы пытаетесь получить доступ к ServletRequest внутри метода apply, что видно из трассировки стека
RequestObjectFactory.getObject (WebApplicationContextUtils.java:320)
Этот RequestObjectFactory является статическим внутренним классом, который дает вам доступ к текущему запросу
private static class RequestObjectFactory implements ObjectFactory<ServletRequest>, Serializable {
private RequestObjectFactory() {
}
public ServletRequest getObject() {
return WebApplicationContextUtils.currentRequestAttributes().getRequest();
}
public String toString() {
return "Current HttpServletRequest";
}
}
, текущий запрос получен изкласс RequestContextHolder, который получает атрибут из текущего потока, как показано ниже после серии вызовов метода
//This is the current thread which holds the request attributes
private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal("Request attributes");
//This is the place where you get the actual exception from the spring RequestContextHolder class.
public static RequestAttributes currentRequestAttributes() throws IllegalStateException {
RequestAttributes attributes = getRequestAttributes();
if (attributes == null) {
if (jsfPresent) {
attributes = RequestContextHolder.FacesRequestAttributesFactory.getFacesRequestAttributes();
}
if (attributes == null) {
throw new IllegalStateException("No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.");
}
}
return attributes;
}
public static RequestAttributes getRequestAttributes() {
RequestAttributes attributes = (RequestAttributes)requestAttributesHolder.get();
if (attributes == null) {
attributes = (RequestAttributes)inheritableRequestAttributesHolder.get();
}
return attributes;
}
окончательный вердикт: , поэтому убедитесь, что вы не пытаетесь получить доступ к ServletRequest изRequestInterceptor, если вы используете параллельные потоки.поскольку параллельные потоки должны использоваться только с операциями без учета состояния, не мешающими и ассоциативными
, поскольку requestAttributesHolder.get () ищет текущий поток, не использует параллельные потоки в нем, как показано ниже. Что не рекомендуется, и в параллелизме есть много вещей, которые следует учитывать (см. link )
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
, если у вас нет кода, который обращается ктекущий запрос, и он вызывается из файлов класса OpenFeign , тогда единственный способ - использовать последовательные потоки вместо параллельных. Это просто
accountIds.stream().forEach(accountId -> {
AccountDTO accountDTO = accountMaintenanceRestClient.getAccount(accountId);
// More logic
}