Получение контекста сервлетов, сеанса и запроса в внешнем контейнере POJO
Есть ли способ получить сеанс из POJO? Или, в конечном счете, получить bean из POJO.
Чтобы уточнить:
В основном я создаю bean из сервлета, и мне нужно получить доступ к свойствам этого bean извне веб-контейнера (из POJO). Я не могу передать запрос в pojo; и запрос необходим для извлечения сеанса.
В частности, у меня есть веб-приложение, которое использует структуру Cactus для запуска тестов JUnit из веб-интерфейса. Однако сервлет, который вызывает тестовый бегун JUnit, компилируется в банке; Я добавил дополнительные раскрывающиеся меню для изменения параметров, из которых будет проверяться тест JUnit, для переключения между различными средами (кластеры WLI), поэтому, учитывая, что сервлет-бегун уже скомпилирован, я не могу его модифицировать, чтобы обрабатывать дополнительные параметры из нескольких сред. Я пробовал настойчивость подхода к записи в файл .dat, из которого тест JUnit будет считываться с помощью класса Reader; также я пробовал подход bean, который в конечном итоге не был доступен из теста JUnit.
Ответы
Ответ 1
Только если ваш POJO работает в потоке тот же, когда работает HttpServletRequest
, тогда вы сможете достичь этого с помощью ThreadLocal<T>
.
Создайте следующий класс:
public final class YourContext implements AutoCloseable {
private static ThreadLocal<YourContext> instance = new ThreadLocal<>();
private HttpServletRequest request;
private HttpServletResponse response;
private YourContext(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response;
}
public static YourContext create(HttpServletRequest request, HttpServletResponse response) {
YourContext context = new YourContext(request, response);
instance.set(context);
return context;
}
public static YourContext getCurrentInstance() {
return instance.get();
}
@Override
public void close() {
instance.remove();
}
public HttpServletRequest getRequest() {
return request;
}
public HttpSession getSession() {
return request.getSession();
}
public ServletContext getServletContext() {
return request.getServletContext();
}
// ... (add if necessary more methods here which return/delegate the request/response).
}
Внесите javax.servlet.Filter
, который делает следующее в doFilter()
методе и отображается на интересующем элементе url-pattern
, например. /*
или на servlet-name
сервлета вашего фронтального контроллера.
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try (YourContext context = YourContext.create(request, response)) {
chain.doFilter(request, response);
}
}
Обратите внимание на важность инструкции try-with-resources. Он гарантирует, что YourContext#close()
будет вызываться после того, как фильтр выполнит свое задание, а ресурс ThreadLocal
будет очищен. В противном случае поток будет по-прежнему содержать его при переработке для другого HTTP-запроса.
И вот как вы могли бы использовать его в POJO:
YourContext context = YourContext.getCurrentInstance();
HttpSession session = context.getSession();
Все это в основном также, как работают объекты Context
средней структуры MVC, такие как JSF FacesContext
, а другая в Калитка.
Сказал, что вы посмотрели на CDI? Возможно, проще сделать артефакты CDI-управляемыми, чтобы вы могли просто @Inject
их друг в друге.
Ответ 2
A Pojo - это простой старый Java-объект. POJOS не имеет ничего общего с сеансами.
Сеанс https доступен на объекте запроса.
Проверьте это
http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.6/api/index.html
в частности, интерфейс HttpServletRequest и метод getSession().
В разделе "bean" вашего вопроса. A bean - это класс java, который соответствует 3 стандартам.
- Нет конструктора arg
- сеттеры и получатели для доступа к закрытым полям
- Реализует сериализуемое.
POJO является bean, если он следует этим соглашениям.
Ответ 3
Предполагая, что вы имеете в виду программирование сервлета....
Нет прямого способа получить от POJO к сеансу. Вы должны получить сеанс из объекта HttpServletRequest.
Есть два популярных решения, которые я видел для этого.
Первый вариант - создать объект контекста некоторого типа, который содержит Session. Этот контекст затем передается вниз в ваш бизнес-уровень, чтобы ваши POJO могли получить эту информацию, если они в ней нуждаются.
Второй вариант - использовать хранилище ThreadLocal. Часто сеанс помещается в хранилище ThreadLocal фильтром или перехватчиком. Тогда любой объект в вашей системе может извлечь его из потока. Этот шаблон отображается во многих веб-фреймворках, таких как Spring и Struts.
Ответ 4
Да, есть.
Если вы используете веб-фреймворк, например, Wicket, часто существует способ получить текущую HttpSession. Оттуда вы можете получить W760 > ApplicationContext, и если у вас есть это, вы можете получить Spring Beans. Это работает в любом месте, поскольку мы используем только статические утилиты.
Пример кода:
import org.apache.wicket.protocol.http.WebApplication;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.context.WebApplicationContext;
ServletContext sc = WebApplication.getServletContext();
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(sc);
Object bean = wac.getBean("myBeanId");
Обратите внимание, что фильтр Spring Filter и Wicket Filter должен быть на месте и обрабатывать текущий запрос, в противном случае методы утилиты не будут работать.
Если вы не имели в виду Spring Beans, то вам пришлось бы хранить их в сеансе HTTP самостоятельно. Если у вас нет веб-фреймворка, вы можете захотеть сделать то, что предлагает rfeak и реализовать свой собственный ThreadLocal.