web-dev-qa-db-fra.com

Enregistrement de la demande et de la réponse au même endroit avec JAX-RS

J'ai un serveur Web RESTEasy avec beaucoup de méthodes. Je veux implémenter logback pour suivre toutes les demandes et réponses, mais je ne veux pas ajouter log.info() à toutes les méthodes. 

Peut-être qu’il ya un moyen d’attraper les demandes et les réponses au même endroit et de le consigner. Peut-être que quelque chose comme un filtre sur la chaîne de processus de requête HTTP sur RESTEasy.

@Path("/rest")
@Produces("application/json")
public class CounterRestService {

    //Don't want use log in controler every method to track requests and responces
    static final Logger log = LoggerFactory.getLogger(CounterRestService.class); 

    @POST
    @Path("/create")
    public CounterResponce create(@QueryParam("name") String name) {
        log.info("create "+name)
        try {
            CounterService.getInstance().put(name);
            log.info("responce data"); // <- :((
            return new CounterResponce();
        } catch (Exception e){
            log.info("responce error data"); // <- :((
            return new CounterResponce("error", e.getMessage());
        }    
    }

    @POST
    @Path("/insert")
    public CounterResponce create(Counter counter) {
        try {
            CounterService.getInstance().put(counter);
            return new CounterResponce();
        } catch (Exception e){
            return new CounterResponce("error", e.getMessage());
        }
    }

    ...
}
24
Edgaras Karka

Vous pouvez créer des filtres et les lier facilement aux points de terminaison que vous devez consigner, tout en maintenant vos points de terminaison minces et concentrés sur la logique métier.

Définir une annotation de liaison de nom

Pour lier les filtres à vos points de terminaison REST, JAX-RS fournit la méta-annotation @NameBinding et peut être utilisé comme suit:

@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Logged { }

Consignation de la requête HTTP

L'annotation @Logged sera utilisée pour décorer une classe de filtre, qui implémente ContainerRequestFilter , vous permettant de gérer la demande: 

@Logged
@Provider
public class RequestLoggingFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        // Use the ContainerRequestContext to extract information from the HTTP request
        // Information such as the URI, headers and HTTP entity are available
    }
}

L'annotation @Provider marque l'implémentation d'une interface d'extension qui devrait être détectable par le moteur d'exécution JAX-RS au cours d'une phase d'analyse du fournisseur. 

La variable ContainerRequestContext vous aide à extraire des informations de la requête HTTP. 

Voici les méthodes de l'API ContainerRequestContext pour obtenir des informations de la requête HTTP qui peuvent être utiles pour vos journaux:

Consignation de la réponse HTTP

Pour consigner la réponse, envisagez de mettre en œuvre une ContainerResponseFilter :

@Logged
@Provider
public class ResponseLoggingFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext, 
                       ContainerResponseContext responseContext) throws IOException {
        // Use the ContainerRequestContext to extract information from the HTTP request
        // Use the ContainerResponseContext to extract information from the HTTP response
    }
}

ContainerResponseContext vous aide à extraire des informations de la réponse HTTP.

Voici quelques méthodes de l'API ContainerResponseContext pour obtenir des informations de la réponse HTTP qui peuvent être utiles pour vos journaux:

Liaison des filtres à vos points de terminaison

Pour lier le filtre à vos méthodes ou classes de points de terminaison, annotez-les avec l'annotation @Logged définie ci-dessus. Pour les méthodes et/ou les classes annotées, les filtres seront exécutés:

@Path("/")
public class MyEndpoint {

    @GET
    @Path("{id}")
    @Produces("application/json")
    public Response myMethod(@PathParam("id") Long id) {
        // This method is not annotated with @Logged
        // The logging filters won't be executed when invoking this method
        ...
    }

    @DELETE
    @Logged
    @Path("{id}")
    @Produces("application/json")
    public Response myLoggedMethod(@PathParam("id") Long id) {
        // This method is annotated with @Logged
        // The request logging filter will be executed before invoking this method
        // The response logging filter will be executed before invoking this method
        ...
    }
}

Dans l'exemple ci-dessus, les filtres de journalisation ne seront exécutés que pour myLoggedMethod(Long) car ils sont annotés avec @Logged.

Information additionnelle

Outre les méthodes disponibles dans les interfaces ContainerRequestContext et ContainerResponseFilter , vous pouvez injecter ResourceInfo dans vos filtres à l'aide de @Context :

@Context
ResourceInfo resourceInfo;

Il peut être utilisé pour obtenir le Method et le Class qui correspondent à l'URL demandée:

Class<?> resourceClass = resourceInfo.getResourceClass();
Method resourceMethod = resourceInfo.getResourceMethod();

HttpServletRequest et HttpServletResponse sont également disponibles pour injection:

@Context
HttpServletRequest httpServletRequest;

@Context
HttpServletResponse httpServletResponse;

Reportez-vous à cette answer pour connaître les types pouvant être injectés avec @Context .

63
cassiomolin

Essayez les intercepteurs (pas seulement les intercepteurs Vanilla EJB, vous pouvez utiliser CDI avec cela).

Ils sont là pour mettre en œuvre les préoccupations transversales (aspects).

0
Najeeb Arif