Как перехватить запрос во время жизненного цикла Джерси?

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

В идеале я мог бы выполнить некоторую настраиваемую фильтрацию/валидацию/отклонение между временем, в течение которого контейнер принимает запрос из сети, и временем, когда вызываются методы моего обработчика. Бонусные точки, если есть простой способ фильтровать перехватчики по подпутью (например, иметь один перехватчик для чего-либо под /, другой для чего-либо под/user/и т.д.).

Спасибо!

Изменить. Чтобы быть немного яснее, общая идея здесь состоит в том, чтобы написать код, который будет запускаться для многих вызовов API без необходимости явного вызова этого кода из каждого метода обработчика. Это уменьшит дополнительный код и устранит необходимость передавать контексты запросов.

Ответ 1

Я нашел ответ.

Сначала создайте класс, реализующий ContainerRequestFilter. Интерфейс определяет следующий метод, в котором происходит фильтрация. Объект ContainerRequest содержит информацию о текущем запросе.

public ContainerRequest filter(ContainerRequest req);

После этого включите следующий XML в конфигурацию сервлета в web.xml

<init-param>
  <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
  <param-value>path.to.filtering.class</param-value>
</init-param>

Источники:

http://jersey.576304.n2.nabble.com/ContainerRequestFilter-and-Resources-td4419975.html http://markmail.org/message/p7yxygz4wpakqno5

Ответ 2

Этот поток немного устарел, но у меня было время перехватить запрос до и после. После долгого поиска в Интернете я, наконец, понял это:

<init-param>
    <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
    <param-value>blah.LoggingFilter</param-value>
</init-param>
<init-param>
    <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
    <param-value>blah.LoggingFilter</param-value>
</init-param>

а затем этот класс:

public class LoggingFilter extends LoggingFilter implements ContainerRequestFilter {

    private static final ThreadLocal<Long> startTime = new ThreadLocal<Long>();
    public static boolean verboseLogging = false;

    @Override
    public ContainerRequest filter(ContainerRequest arg0) {
        startTime.set(System.currentTimeMillis());
        return arg0;
    }

    @Override
    public ContainerResponse filter(ContainerRequest request, ContainerResponse response) {
        System.out.println(System.currentTimeMillis() - startTime.get().longValue());
        StringBuilder sb = new StringBuilder();
        sb.append("User:").append((request.getUserPrincipal() == null ? "unknown" : request.getUserPrincipal().getName()));
        sb.append(" - Path:").append(request.getRequestUri().getPath());
        //...
    }

Это перехватывает запрос в начале и в конце, чтобы вы могли установить таймер или что-то еще.

Это работает для Джерси 1.17. Не уверен насчет 2.x.

Ответ 3

Для серверной части мы используем класс Jersey Specific, чтобы сделать что-то вроде этого: ContainerResponseFilter

Подпись:

public ContainerResponse filter(ContainerRequest request, ContainerResponse response)

то вы можете делать такие вызовы, как:

Object entity  = response.getEntity();
    ... your logic here ...
return response;

Может ли это помочь?..

Ответ 4

Вы посмотрели на класс Джерси ClientFilter?

В настоящее время мы используем это для перехвата и выполнения API-интерфейсов и т.д. Там встроены фильтры регистрации, поэтому вы можете посмотреть на код, чтобы они могли понять, что писать.

Подпись:

public ClientResponse handle(final ClientRequest cr) throws ClientHandlerException...

Итак, вы можете начать с таких вещей, как:

....
cr.getHeaders()
....
return getNext().handle(cr);