使用JAX-RS在一个位置记录请求和响应 [英] Logging request and response in one place with 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()
:从请求中获取HTTP方法。 -
ContainerRequestContext#getUriInfo()
:从HTTP请求中获取URI信息。 -
ContainerRequestContext#getHeaders()
:从中获取标题HTTP请求。 -
ContainerRequestContext#getMediaType()
:获取实体的媒体类型。 - < a href =http://docs.oracle.com/javaee/7/api/javax/ws/rs/container/ContainerRequestContext.html#getEntityStream-- =noreferrer>
ContainerRequestContext# getEntityStream()
:获取实体输入流。
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()
:从HTTP响应中获取状态代码。 -
ContainerResponseContext#getHeaders()
:从HTTP响应中获取标题。 -
ContainerResponseContext#getEntityStream()
:获取实体输出流。
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;
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;
Refer to this answer for the types that can be injected with @Context
.
这篇关于使用JAX-RS在一个位置记录请求和响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!