Как перехватить запрос во время жизненного цикла Джерси?
Я использовал Джерси в течение большей части года и только что наткнулся на проблему, на которую я не могу найти ответ: как вы перехватываете (или захватываете) жизненный цикл запроса на Джерси?
В идеале я мог бы выполнить некоторую настраиваемую фильтрацию/валидацию/отклонение между временем, в течение которого контейнер принимает запрос из сети, и временем, когда вызываются методы моего обработчика. Бонусные точки, если есть простой способ фильтровать перехватчики по подпутью (например, иметь один перехватчик для чего-либо под /, другой для чего-либо под/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);