使用JAX-RS在一个位置记录请求和响应 [英] Logging request and response in one place with JAX-RS

查看:98
本文介绍了使用JAX-RS在一个位置记录请求和响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个RESTEasy Web服务器,有很多方法。我希望实现logback来跟踪所有请求和响应,但我不想为每个方法添加 log.info()

I have a RESTEasy web server with lot of methods. I want implement logback to track all requests and responses, but I don't want add log.info() to every methods.

也许有办法在一个地方捕获请求和响应并记录它。也许类似于RESTEasy上HTTP请求流程链上的过滤器。

Maybe there's way to catch requests and responses in one place and log it. Maybe something like a filter on HTTP request process chain on 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());
        }
    }

    ...
}


推荐答案

您可以创建过滤器并轻松将它们绑定到您需要记录的端点,保持端点精简并专注于业务逻辑。

You can create filters and easily bind them to the endpoints you need to log, keeping your endpoints lean and focused on the business logic.

为了将过滤器绑定到REST端点,JAX-RS提供了meta-annot @NameBinding ,可以使用如下:

To bind filters to your REST endpoints, JAX-RS provides the meta-annotation @NameBinding and it can be used as following:

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



< h2>记录HTTP请求

@Logged 注释将用于修饰过滤器类,该类实现< a href =http://docs.oracle.com/javaee/7/api/javax/ws/rs/container/ContainerRequestFilter.html =noreferrer> ContainerRequestFilter ,允许您处理请求:

Logging the HTTP request

The @Logged annotation will be used to decorate a filter class, which implements ContainerRequestFilter, allowing you to handle the request:

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

@Provider 注释标记了在提供程序扫描阶段JAX-RS运行时应该可以发现的扩展接口的实现。

The @Provider annotation marks an implementation of an extension interface that should be discoverable by JAX-RS runtime during a provider scanning phase.

ContainerRequestContext 可帮助您从HTTP请求中提取信息。

The ContainerRequestContext helps you to extract information from the HTTP request.

以下是来自 ContainerRequestContext API 从HTTP请求中获取可能对您的日志有用的信息:

Here are methods from the ContainerRequestContext API to get information from the HTTP request that can be useful for your logs:

  • ContainerRequestContext#getMethod(): Get the HTTP method from the request.
  • ContainerRequestContext#getUriInfo(): Get URI information from the HTTP request.
  • ContainerRequestContext#getHeaders(): Get the headers from the HTTP request.
  • ContainerRequestContext#getMediaType(): Get the media type of the entity.
  • ContainerRequestContext#getEntityStream(): Get the entity input stream.

要记录响应,请考虑实现 ContainerResponseFilter

For logging the response, consider implementing a 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 可帮助您从HTTP响应中提取信息。

The ContainerResponseContext helps you to extract information from the HTTP response.

以下是 ContainerResponseContext API 从HTTP响应中获取可能对您的日志有用的信息:

Here are some methods from the ContainerResponseContext API to get information from the HTTP response that can be useful for your logs:

  • ContainerResponseContext#getStatus(): Get the status code from the HTTP response.
  • ContainerResponseContext#getHeaders(): Get the headers from the HTTP response.
  • ContainerResponseContext#getEntityStream(): Get the entity output stream.

将过滤器绑定到端点方法或类,使用上面定义的 @Logged 注释对它们进行注释。对于注释的方法和/或类,将执行过滤器:

To bind the filter to your endpoints methods or classes, annotate them with the @Logged annotation defined above. For the methods and/or classes which are annotated, the filters will be executed:

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

在上面的示例中,仅针对日志记录过滤器执行 myLoggedMethod(Long)因为它是用 @Logged 注释的。

In the example above, the logging filters will be executed only for myLoggedMethod(Long) because it's annotated with @Logged.

ContainerRequestContext ContainerResponseFilter 接口,你可以注入 ResourceInfo 在使用 的过滤器中@Context

@Context
ResourceInfo resourceInfo;

它可用于获取 方法 Class 与请求的网址匹配:

It can be used to get the Method and the Class which match with the requested URL:

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

HttpServletRequest HttpServletResponse 也可以注射:

HttpServletRequest and HttpServletResponse are also available for injection:

@Context
HttpServletRequest httpServletRequest;

@Context
HttpServletResponse httpServletResponse;

请参阅此回答可以注入的类型 @Context

Refer to this answer for the types that can be injected with @Context.

这篇关于使用JAX-RS在一个位置记录请求和响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆