Получение контекста сервлетов, сеанса и запроса в внешнем контейнере 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.