web-dev-qa-db-fra.com

Comment intercepter une demande pendant le cycle de vie de Jersey?

J'ai utilisé Jersey pendant une bonne partie de l'année maintenant et je suis juste tombé sur un problème auquel je ne trouve pas la réponse: comment intercepter (ou accrocher) le cycle de vie de la demande de Jersey?

Idéalement, je serais en mesure d'effectuer un filtrage/validation/rejet personnalisé entre le moment où le conteneur accepte la demande du réseau et le moment où mes méthodes de gestionnaire sont appelées. Points bonus s'il existe un moyen facile de filtrer les intercepteurs par sous-chemin (par exemple, avoir un intercepteur pour tout ce qui est sous /, un autre pour tout ce qui est sous/utilisateur /, etc.).

Merci!

Edit: Pour être un peu plus clair, l'idée générale ici est de pouvoir écrire du code qui sera exécuté pour de nombreux appels d'API sans avoir à appeler explicitement ce code à partir de chaque méthode de gestionnaire. Cela réduirait le code supplémentaire et éliminerait la nécessité de transmettre les contextes de demande.

48
cww

J'ai trouvé la réponse.

Tout d'abord, créez une classe qui implémente ContainerRequestFilter. L'interface spécifie la méthode suivante, dans laquelle le filtrage a lieu. L'objet ContainerRequest contient des informations sur la demande en cours.

public ContainerRequest filter(ContainerRequest req);

Après cela, incluez le XML suivant dans la configuration du servlet dans web.xml

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

Sources:

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

50
cww

Ce fil est un peu ancien, mais je passais un moment interceptant à la fois avant et après la demande. Après une longue recherche sur le web, j'ai finalement compris ceci:

<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>

puis cette classe:

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());
        //...
    }

Cela intercepte la demande au début et à la fin afin que vous puissiez mettre un minuteur ou autre chose.

Cela fonctionne pour Jersey 1.17. Pas sûr de 2.x.

9
markthegrea

Pour la partie serveur, nous utilisons une classe spécifique à Jersey pour faire quelque chose comme ceci: ContainerResponseFilter

La signature est:

public ContainerResponse filter(ContainerRequest request, ContainerResponse response)

alors vous pouvez faire des appels comme:

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

Cela peut-il être utile? ..

0
a1o1