Я думаю, что вам не нужны ваши собственные ThreadLocal
, вы можете использовать атрибуты запроса.
@Override
public Object afterBodyRead(
Object body,
HttpInputMessage inputMessage,
MethodParameter parameter,
Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) {
var common = ((MyGenericPojo) body).getCommon();
if (common.getRequestId() == null) {
common.setRequestId(generateNewRequestId());
}
Optional.ofNullable((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.map(ServletRequestAttributes::getRequest)
.ifPresent(request -> {request.setAttribute(Common.class.getName(), common);});
return body;
}
@Override
public MyGenericPojo beforeBodyWrite(
MyGenericPojo body,
MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request,
ServerHttpResponse response) {
Optional.ofNullable(RequestContextHolder.getRequestAttributes())
.map(rc -> rc.getAttribute(Common.class.getName(), RequestAttributes.SCOPE_REQUEST))
.ifPresent(o -> {
Common common = (Common) o;
body.setCommon(common);
});
return body;
}
РЕДАКТИРОВАТЬ
Optional
с заменено на
RequestContextHolder.getRequestAttributes().setAttribute(Common.class.getName(),common,RequestAttributes.SCOPE_REQUEST);
RequestContextHolder.getRequestAttributes().getAttribute(Common.class.getName(),RequestAttributes.SCOPE_REQUEST);
РЕДАКТИРОВАТЬ 2
О безопасности потоков
1) стандартное веб-приложение Spring на основе сервлетов у нас есть поток-запрос сценарий. Запрос обрабатывается одним из рабочих потоков через все фильтры и процедуры. Цепочка обработки будет выполняться одним и тем же потоком от начала до конца. Так что afterBodyRead
и beforeBodyWrite
гарантированно будут выполняться одним и тем же потоком для данного запроса.
2) Ваш RequestResponseAdvice сам по себе не имеет состояния. Мы использовали RequestContextHolder.getRequestAttributes()
, который является ThreadLocal и объявлен как
private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
new NamedThreadLocal<>("Request attributes");
И ThreadLocal javado c сообщает:
его класс предоставляет локальные переменные потока. Эти переменные отличаются от своих обычных аналогов тем, что каждый поток, который обращается к одному (через метод get или set), имеет свою собственную, независимо инициализированную копию переменной.
Так что я не вижу ни одного потока вопросы безопасности в этом sulotion.