使用 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 提供了元注释 @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 { }
记录 HTTP 请求
@Logged
注释将用于装饰过滤器类,它实现了 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()
:获取实体的媒体类型.ContainerRequestContext#getEntityStream()
:获取实体输入流.
要记录响应,请考虑实施 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()
:获取实体输出流.
要将过滤器绑定到您的端点方法或类,请使用上面定义的 @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;
可用于获取<代码>方法和与请求的 URL 匹配的 Class
:
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屋!