Использование ThreadLocal в корпоративном приложении
Если мое веб-приложение и приложение ejb находятся на одном компьютере (на одном JVM), и все вызовы ejb являются локальными вызовами, будет ли использование ThreadLocal
создавать какую-либо проблему при передаче информации из Интернета в ejb?
Любое обходное решение, если вызовы ejb удалены? Будет ли доступна информация о ThreadLocal
из веб-приложения в приложение ejb? Возможно ли использование ThreadLocal
в таком сценарии?
Ответы
Ответ 1
Для первого вопроса нет проблем, если вы удаляете переменные ThreadLocal в конце каждого вызова. Это важно, потому что контейнеры (сервлет или ejb) обычно используют потоки пользователей и, следовательно, повторно используют потоки, это имеет два эффекта: один "вызов" может видеть информацию о потоковом доступе, поступающую от предыдущего вызова, и если вы удалите приложение из контейнера, не останавливая JVM некоторые классы не могут быть собраны в мусор, потому что они по-прежнему ссылаются на поток контейнера. Поэтому поместите данные в threadlocal в блок try/finally и удалите в конечном итоге.
Вот сообщение, показывающее один из способов решения проблемы: ThreadLocal в веб-приложениях
Для второго вопроса, поскольку данные являются threadlocal, он не будет поставляться с удаленным вызовом, вы должны добавить параметр к своим интерфейсам, извлечь данные с одного потока и восстановить его с другой стороны...
Ответ 2
ThreadLocal не следует использовать в контекстах EJB. Нельзя гарантировать, что вызовы метода EJB находятся в одном и том же потоке (конечно, должно быть).
В EJB существует другой подход к вызову TransactionSyncrhonizationRegistry. Подробнее см. Объяснение/Использование.
Ответ 3
все вызовы ejb являются локальными вызовами, будет использоваться ThreadLocal create любой вопрос, пока
Нет, вы сами ответили на свой вопрос. Поскольку вызовы локальны, они выполняются в контексте одного потока.
Любое обходное решение, если вызовы ejb удалены?
В случае удаленных вызовов контейнер Java EE будет запущен в другой JVM, он будет генерировать собственные потоки для обработки входящего запроса RMI, нет возможности для удаленного контейнера Java EE узнать о локальных переменных потока, которые были объявлены с другой стороны. Передайте его как объект параметра.
Ответ 4
При использовании EJB 3.1 вы можете передавать контекстуальную информацию в EJBContext с помощью контекстные данные. Это всего лишь Map<String,Object>
.
Ответ 5
Это зависит от того, какую информацию вы передаете! Первый вопрос - слишком общий. Я предлагаю прочитать JavaDoc, связанный с ThreadLocal здесь.
ThreadLocal живет с серверной стороны приложения и используется, чтобы позволить Thread-safe вызовы объектов Thread.
Ответ 6
Для локальных вызовов ThreadLocal
должен работать нормально, если все сделано в одном потоке.
Для удаленных вызовов, которые могут запускаться на другом сервере, вам нужно будет придумать что-то еще. Либо передайте все значения в качестве параметров (которые будут работать, но вводят сложность в коде), либо используют что-то вроде распределенного кеша, например. Hazelcast, который будет функционировать как глобальный HashMap
, к которому имеют доступ все узлы кластера.
Ответ 7
ThreadLocal
не может использоваться со 100% уверенностью в веб-приложениях. У вас просто нет гарантии, что один поток будет использоваться для одного сеанса. На мой взгляд, это может стать очень трудным для поиска дыры в безопасности!
ctx.getContextData()
не работает для меня, он всегда возвращает null
!
Я также пробовал TransactionSynchronizationRegistry
, но я также получил null
.
Единственное, что сработало, - это использование JAAS в качестве обходного пути. Но это нехорошее решение.