Доступ к объекту HttpServletRequest / Response Java Web в файлах пользовательских классов - PullRequest
2 голосов
/ 19 февраля 2012

Я действительно устал от этой проблемы и не могу найти наилучшей практики для ее решения. Позвольте мне прояснить проблему с примером:

У меня есть статический метод, такой как:

public class AppError {
   public static void systemError(string errorMsg) { //Like "Can't connect to DB"
      HttpServletRequest request = ?????????? "HOW TO ACCESS?";
      request.setAttribute("Error", errorMsg);
      request.getRequestDispatcher("/error.jsp").forward(request, response(????????));
   }
}

Как видите, мне нужен доступ к объектам запросов и ответов, и я НЕ ХОЧУ передавать HttpServletRequest / Response по параметрам, потому что это означает передачу его туда, где вызван AppError.systemError, а это так много мест: чтение / запись файлов , cookie и пользовательские операции, операции с базой данных и т. д. *

Мне показалось, что я нашел решение, ThreadLocal, я использовал его в фильтре и сохранил объекты запросов и ответов, но затем метод Filter.Destroy (), где я освобождаю переменные ThreadLocal методом ThreadLocal.remove (), не вызывался при тестировании. это в режиме отладки. Это означает, что поток никогда не может быть освобожден.

ServletContextListerner также НЕ является РЕШЕНИЕМ, потому что я не смог найти способ доступа к объектам запросов и ответов в объекте ServletContext. Я ожидал такой метод, как ServletContext.getRequest (), но его нет.

Я также использую JSF, но проблема с JSF заключается в том, что FacesContext также недоступен в пользовательских классах. Кроме того, JSF загружается позже, чем слушатели, поэтому я не могу использовать свою систему ошибок в слушателях, если я использовал FacesContext для получения объектов запроса и ответа.

Так какая же здесь лучшая практика? Я имею в виду, что это явная проблема, и я не могу двигаться дальше без ее решения.

Кстати, метод ошибки является примером, есть и другие места, которые мне нужны для доступа к объектам запросов и ответов.

1 Ответ

4 голосов
/ 19 февраля 2012

В принципе нет причин, по которым правильно настроенный Фильтр не будет работать в сочетании с локальным хранилищем потоков (TLS).

Основная идея заключается не в очистке TLS в методе Filter#Destroy(), а в предложении finally после основной цепочки фильтрации:

@WebFilter(filterName="requestTLSFilter")
public class RequestTLSFilter extends Filter {

    private static final ThreadLocal<ServletRequest> THREAD_LOCAL = new ThreadLocal<ServletRequest>();

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        try {
            THREAD_LOCAL.put(request);
            chain.doFilter(request, response);
        } finally {
            THREAD_LOCAL.remove();
        }
    }

    // Other methods    
}

Что касается JSF, FacesContext.getCurrentInstance() доступен везде. JSF не знает, кто это вызывает, но он доступен для кодирования в цепочке вызовов только после вызова сервлета Facelets.

Есть еще одна альтернатива. Если у вашего контейнера есть поддержка Java-контракта авторизации для контейнеров (JACC), то следующий запрос также получит текущий запрос:

HttpServletRequest request = (HttpServletRequest) PolicyContext.getContext("javax.servlet.http.HttpServletRequest");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...