Перехватчики в потоке Struts2 небезопасны? - PullRequest
9 голосов
/ 26 марта 2012

Я понимаю, что классы Struts2 Action являются поточно-ориентированными, потому что действия помещаются в стек значений. Стек значений, в свою очередь, является частью контекста действия. Поскольку контекст действия является локальным для потока, значения, хранящиеся в контексте действия (включая стек значений), являются уникальными для каждого потока. Таким образом, действия являются потокобезопасными.

Но рассмотрим перехватчики: они действительно полезны, они выполняют всю эту утомительную небольшую работу для программиста ... как проверки, извлечение значений параметров и т. Д. Но нужно учитывать следующее: перехватчики могут совместно использоваться несколькими Запросы. Так что же делает поток перехватчиков небезопасным?

Имея в виду этот вопрос, я попытался найти в интернете несколько хороших статей, касающихся этой проблемы. И я нашел очень хорошую статью, в которой они четко упомянули на примере, как перехватчики НЕ являются потокобезопасными.

Веб-страница: http://www.bullraider.com/java/struts2/tutorials/interceptors-and-thread-safety

Что я узнал из этой статьи, так это то, что основная причина, по которой перехватчики являются небезопасными, заключается в том, что перехватчики создаются только один раз. каждый перехватчик имеет только один объект. Таким образом, поля экземпляра небезопасны, когда один и тот же экземпляр Перехватчика совместно используется потоками.

В конце статьи упоминается, что есть случаи, когда даже перехватчики являются потокобезопасными. Но они не упоминали таких случаев. Я просмотрел сеть, чтобы найти ответ ... но зря: (

Может кто-нибудь сказать мне или предоставить мне ссылку, где я могу узнать, как сделать перехватчики потокобезопасными (или каковы сценарии, когда перехватчик потокобезопасен)?

Ответы [ 2 ]

14 голосов
/ 27 марта 2012

Любой перехватчик, который не использует полей экземпляра или другого общего состояния, является потокобезопасным:

Например, посмотрите на все встроенные перехватчики , которыеанализировать параметры HTTP-запроса и куки-файлы, выполнять регистрацию, проверку доступа, обработку исключений: они не используют поля экземпляра для изменяемого состояния (*), а просто работают с ActionInvocation экземпляром, который они получают в качестве параметров.

(*) некоторые имеют поля экземпляра для параметров конфигурации, которые устанавливаются при запуске Struts (в одном потоке), например ExceptionMappingInterceptor, или потоковые поля экземпляра, такие как Logger в LoggingInterceptor.

Если вы планируете написать свой собственный Interceptor, работайте только с параметром ActionInvocation, который вы передаете, и с локальными переменными в вашем методе intercept().Избегайте соблазна сделать метод перехвата synchronized или поместить вещи в блок synchronized{} - это создаст узкое место при подходе Struts к единственному экземпляру Interceptors.

Чтобы ответить на вопросы из комментариев:

(1) Почему создание экземпляра действия для каждого потока не влияет на производительность?

В современных JVM стоимостьсоздание объекта ничтожно мало.Не должно быть заметного влияния на производительность, если вы сохраняете свои действия легкими, избегая дорогостоящей инициализации, например, не создавая соединения с базой данных внутри действия, а используя пул соединений.

(2)рекомендовать НИКОГДА не использовать стек перехватчиков по умолчанию и всегда использовать собственный стек перехватчиков (где удаляются все неиспользуемые перехватчики, которые используют переменные экземпляра), чтобы он был потокобезопасным?

Не думаю, чтолюбые перехватчики по умолчанию, которые поставляются и конфигурируются с помощью Struts 2, не являются поточно-ориентированными;даже если они используют поля экземпляра (потому что они либо используются только для конфигурации, либо являются поточно-ориентированными, как Logger).

По моему личному опыту, вы должны когда-либо касаться / изменять стек перехватчиков, только если выесть веская причина (потокобезопасность встроенных перехватчиков не одна).Многие вещи ведут себя / ломаются неожиданным образом, если вы меняете стеки - запуск одного из встроенных стеков, таких как «default» или «paramPrepareParam», экономит много разочарований в долгосрочной перспективе.Добавление собственных пользовательских перехватчиков обычно менее разрушительно, чем удаление / перестановка перехватчиков из существующего стека.

0 голосов
/ 25 сентября 2013

Возможно связанный, класс ScopeInterceptor.java может иметь проблему с безопасностью потока: Проблема безопасности потока Java в классе Struts ScopeInterceptor?

...