当前位置: 首页 > 面试题库 >

使用JAX-RS将请求和响应记录在一处

尹钱青
2023-03-14
问题内容

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

也许有一种方法可以将请求和响应收集到一个地方并记录下来。也许像RESTEasy上的HTTP请求过程链上的过滤器一样。

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

    ...
}

问题答案:

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

定义名称绑定注释

要将过滤器绑定到REST端点,JAX-
RS提供了元注释@NameBinding,它可以按以下方式使用:

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

记录HTTP请求

@Logged注释将被用来装饰一个过滤器类,它实现ContainerRequestFilter,让您在处理请求:

@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是可发现的实现过程中提供扫描相运行时。

ContainerRequestContext帮助你提取HTTP请求信息。

以下是ContainerRequestContextAPI中从HTTP请求获取信息的方法,这些信息可能对您的日志有用:

  • ContainerRequestContext#getMethod():从请求中获取HTTP方法。
  • ContainerRequestContext#getUriInfo():从HTTP请求获取URI信息。
  • ContainerRequestContext#getHeaders():从HTTP请求获取标头。
  • ContainerRequestContext#getMediaType():获取实体的媒体类型。
  • ContainerRequestContext#getEntityStream():获取实体输入流。

记录HTTP响应

要记录响应,请考虑实施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响应信息。

以下是ContainerResponseContextAPI的一些方法,这些方法可从HTTP响应中获取对您的日志有用的信息:

  • ContainerResponseContext#getStatus():从HTTP响应中获取状态代码。
  • ContainerResponseContext#getHeaders():从HTTP响应中获取标头。
  • ContainerResponseContext#getEntityStream():获取实体输出流。

将过滤器绑定到端点

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

@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

附加信息

除了ContainerRequestContextContainerResponseFilter接口中可用的方法外,您还可以ResourceInfo使用@Context以下方法插入过滤器:

@Context
ResourceInfo resourceInfo;

它可以用来获取MethodClass匹配请求的URL其中:

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

HttpServletRequest并且HttpServletResponse也可用于注射:

@Context
HttpServletRequest httpServletRequest;

@Context
HttpServletResponse httpServletResponse;


 类似资料:
  • 问题内容: 我想记录一个axis2客户端发出的所有请求/响应。我试图在http://code.google.com/support/bin/answer.py?hl=zh_CN&answer=15137中创建一个称为describer 的文件,但没有成功(我没有日志文件)。 请求是通过https发出的,我不确定是否重要。我试过了 和 没有成功。 问题答案: 对于SOAP消息的Axis2客户端日志记

  • 我正在尝试将API请求负载和响应数据记录到Azure Application Insight。使用跟踪我可以记录。但是我想知道什么是将请求和响应数据记录到application Insight的最佳方法。因为数据是巨大的,所以API调用的数量会更多。我不能仅仅使用跟踪来跟踪数十万个请求和响应数据。我尝试了一些博客,比如使用itelemetryinitializer/httpcontext.feat

  • 我在改型API中找不到记录完整请求/响应体的相关方法。我希望在探查器中得到一些帮助(但它只提供关于响应的元数据)。我尝试在构建器中设置日志级别,但这也没有帮助: 编辑:此代码正在工作。我不知道为什么它在早些时候不起作用。可能是因为我用的是旧版本的改装。

  • 我正在尝试将从远程服务获得的响应映射到对象中。对于客户端,我使用的是 JAX-RS 注释接口: 响应采用以下格式,作为对象的JSON列表: 我试图映射到的类是: 它总是返回一个带有空项目列表的项目实例。有什么想法吗? 更新 将其更改为: 返回

  • 我试图记录应用程序中的每个传入请求和传出响应。我正在使用jee 6,所以我没有ContainerRequestFilter和ContainerResponseFilter类。所以我决定用滤镜。 我用@WebFilter(“/*”)注释了一个类,并实现了Filter接口。我成功地读取了请求头和请求正文。我也很难阅读响应标题和响应正文。下面是代码片段 MyHttpServletResponse seW

  • 我有一些REST服务,我想记录请求和响应。它们接收一个JSON请求并生成另一个JSON响应。我创建了一个拦截器,但无法获取请求/响应正文。这是我的cxf配置: 这是我的拦截器代码: ContextMessageInInterceptor和ContextMessageOutInterceptor工作正常,它们分别转到ContextJSONInInterceptor和ContextJSONOutInt