#java #spring #http #logging #servlets
#java #весна #http #ведение журнала #сервлеты
Вопрос:
Я пытаюсь выполнить протоколирование всех исходящих HTTP-запросов из моего приложения. Однако мне нужно, чтобы перехватчик HTTP имел доступ к некоторым метаданным HTTP-вызовов. Эти данные устанавливаются вручную для каждого отдельного типа HTTP-вызова в самой логике приложения. Теперь, есть два способа, которые я нашел до сих пор, чтобы передать эти данные перехватчику:
- Включите эти метаданные во временный HTTP-заголовок, запишите его при перехвате вызова, удалите заголовок, выполните вызов
- Сохраните данные в статической переменной ThreadLocal, извлеките их в перехватчике и очистите хранилище ThreadLocal
Хотя оба эти метода работают нормально, у меня есть некоторые оговорки в отношении обоих методов. Для первого метода кажется неразумным изменять сам HTTP-запрос, поскольку в случае, если перехватчик не работает / не используется, метаданные будут переданы на удаленный сервер. Для второго метода использование ThreadLocal связано с проблемами управления памятью кучи, поскольку слишком много потоков может занять место в куче.
Существует ли какой-либо другой стандартный / рекомендуемый метод решения этой проблемы? Если нет, то какой из вышеупомянутых методов лучше подходит для решения этой проблемы?
Ответ №1:
Альтернативным методом в Spring является использование компонента с bean-scope, установленного как «Запрос». Компоненты одноэлементной области не являются потокобезопасными, однако с областью запроса компонент устанавливается только в контексте одного HTTP-запроса и как таковой. Такой компонент создается в начале HTTP-запроса, и его состояние сохраняется в течение всего срока действия только этого HTTP-запроса. Синтаксис для этого:
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloMessageGenerator requestScopedBean() {
return new HelloMessageGenerator();
}
или, альтернативно, более короткая версия того же кода:
@Bean
@RequestScope
public ScopedBeanClass requestScopedBean() {
return new ScopedBeanClass();
}
Теперь ScopedBeanClass
может использоваться для установки и чтения значений потокобезопасным способом в любой момент времени существования одного HTTP-запроса, после чего компонент очищается / сбрасывается в следующем запросе (возможно, из параллельного потока)
Область запроса — это одна из 4 веб-областей, которые можно использовать. Другими областями являются: область сеанса, область приложения и область веб-сокета. Дополнительная информация об этих областях представлена здесь
Ответ №2:
Пожалуйста, попробуйте spring cloud zuul. В его ZuulFilter вы можете регистрировать каждый запрос, а затем повторно отправлять запрос в target. Spring cloud gateway имеет тот же эффект.