webentwicklung-frage-antwort-db.com.de

Protokollierungsanfrage und -antwort an einem Ort mit JAX-RS

Ich habe einen RESTEasy-Webserver mit vielen Methoden. Ich möchte Logback implementieren, um alle Anforderungen und Antworten zu verfolgen, aber ich möchte nicht, dass log.info() zu jeder Methode hinzugefügt wird. 

Vielleicht gibt es eine Möglichkeit, Anfragen und Antworten an einem Ort abzufangen und zu protokollieren. Vielleicht so etwas wie ein Filter für die HTTP-Request-Prozesskette für 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

Sie können Filter erstellen und diese einfach an die Endpunkte binden, die Sie für die Protokollierung benötigen. So bleiben Ihre Endpunkte schlank und konzentrieren sich auf die Geschäftslogik.

Definieren einer Namensbindungsanmerkung

Um Filter an Ihre REST -Endpunkte zu binden, stellt JAX-RS die Meta-Annotation @NameBinding bereit und kann wie folgt verwendet werden:

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

Protokollierung der HTTP-Anfrage

Die Annotation @Logged wird zum Dekorieren einer Filterklasse verwendet, die ContainerRequestFilter implementiert, sodass Sie die Anfrage bearbeiten können: 

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

Die Annotation @Provider / kennzeichnet eine Implementierung einer Erweiterungsschnittstelle, die während einer Provider-Scan-Phase von der JAX-RS-Laufzeit erkannt werden kann. 

Die ContainerRequestContext hilft Ihnen, Informationen aus der HTTP-Anfrage zu extrahieren. 

Hier sind Methoden aus der ContainerRequestContext-API , um Informationen aus der HTTP-Anforderung abzurufen, die für Ihre Protokolle nützlich sein können:

Protokollierung der HTTP-Antwort

Erwägen Sie zum Protokollieren der Antwort die Implementierung einer 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
    }
}

Die ContainerResponseContext hilft Ihnen, Informationen aus der HTTP-Antwort zu extrahieren.

Hier sind einige Methoden aus der ContainerResponseContext-API , um Informationen aus der HTTP-Antwort zu erhalten, die für Ihre Protokolle nützlich sein können:

Binden Sie die Filter an Ihre Endpunkte

Um den Filter an Ihre Endpunktmethoden oder -klassen zu binden, kommentieren Sie sie mit der oben definierten @Logged-Annotation. Für die Methoden und/oder Klassen, die mit Anmerkungen versehen sind, werden die Filter ausgeführt:

@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
        ...
    }
}

Im obigen Beispiel werden die Protokollierungsfilter nur für myLoggedMethod(Long) ausgeführt, da sie mit @Logged kommentiert sind.

Zusätzliche Information

Neben den in ContainerRequestContext und ContainerResponseFilter schnittstellen verfügbaren Methoden können Sie ResourceInfo in Ihre Filter einfügen, indem Sie @Context verwenden:

@Context
ResourceInfo resourceInfo;

Es kann verwendet werden, um die Method und die Class zu erhalten, die mit der angeforderten URL übereinstimmen:

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

HttpServletRequest und HttpServletResponse sind auch für die Injektion verfügbar:

@Context
HttpServletRequest httpServletRequest;

@Context
HttpServletResponse httpServletResponse;

In diesem answer finden Sie die Typen, die mit @Context injiziert werden können.

63
cassiomolin

Probieren Sie Interceptors aus (nicht nur Vanilla EJB-Interceptors, sondern auch CDI).

Sie sind für die Umsetzung von Cross Cutting Concerns (Aspekten) da.

0
Najeeb Arif