#java #spring #multithreading
#java #spring #многопоточность
Вопрос:
Как мне заставить аннотации @Autowired работать в потоках, созданных .parallelStream() в контексте запроса spring REST?
Вот упрощенный пример того, чего я пытаюсь достичь:
@RestController
public class Controller {
@Autowired
private Service service;
@GetMapping(value = "getStrings")
public List<String> getAllStrings(List<String> request) {
return request.parallelStream()
.map(requestItem -> service.getString(requestItem))
.collect(Collectors.toList());
}
}
@Service
public class Service {
@Autowired
private RestTemplate restTemplate;
@Autowired
private HttpHeaders httpHeaders;
public String getString(String request) {
// some code that uses resttemplate and httpheaders here, returns string
// assume this request takes 2 sec to complete hence the need to make multiple calls in parallel
}
}
Ошибка, которую я получаю при фактическом запуске этого кода
org.springframework.beans.factory.Исключение BeanCreationException: ошибка при создании компонента с именем ‘scopedTarget.HttpHeaders’: область ‘request’ не активна для текущего потока; рассмотрите возможность определения прокси-сервера с ограниченной областью для этого компонента, если вы собираетесь ссылаться на него из синглтона; вложенным исключением является java.lang.Исключение IllegalStateException: запрос, связанный с потоком, не найден: вы ссылаетесь на атрибуты запроса вне фактического веб-запроса или обрабатываете запрос вне первоначально принимающего потока? Если вы на самом деле работаете с веб-запросом и все еще получаете это сообщение, ваш код, вероятно, выполняется за пределами DispatcherServlet: в этом случае используйте RequestContextListener или RequestContextFilter, чтобы предоставить текущий запрос.
Один из способов обойти эту проблему — передать HttpHeaders в качестве аргумента в getString(), но для этого потребуется множество рефакторингов для любого другого класса, который использует этот метод
Я обнаружил, что parallelStreams может использовать пользовательский пул потоков, но понятия не имею, как получить текущий пул потоков, который использует контекст запроса spring (или если повторное использование того же пула потоков даже решает мою проблему)
Ответ №1:
Вы можете попробовать добавить
@Scope(value="session", proxyMode = ScopedProxyMode.TARGET_CLASS)
на вашем сервисе.