jax-rs - 使用 @RepositoryRestResource 时记录请求/响应
问题描述
我正在使用来自. spring-data-rest-api
由于 JAX-RS 控制器是自动生成的,因此我无法手动添加记录器来记录传入请求。是否存在会自动记录请求的注释?
我的代码:
@RepositoryRestResource(collectionResourceRel = "organizations", path = "organizations")
public interface OrganizationRepository extends JpaRepository<Organization, UUID> {
}
解决方案
由于我的应用程序是用 Quarkus 编写的,并且我无法从 访问拦截器spring-web
,因此我创建了一个自定义注释并使用了过滤器。
@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Logged { }
@Logged
@Provider
public class RequestLoggingFilter implements ContainerRequestFilter {
/**
* @param requestContext used to extract information from the HTTP request such as the URI, headers and HTTP entity.
*/
@Override
public void filter(ContainerRequestContext requestContext) {
String message = getEntityBody(requestContext);
requestContext.setProperty("StartTime", System.currentTimeMillis());
String url = requestContext.getUriInfo().getAbsolutePath().toString();
StructuredDataUtils.logRequestAsJson(url, message);
}
/**
* @param requestContext HTTP request containing the request body.
* @return the request body of an HTTP request.
*/
private String getEntityBody(ContainerRequestContext requestContext) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = requestContext.getEntityStream();
String result = null;
try {
ReaderWriter.writeTo(in, out);
byte[] requestEntity = out.toByteArray();
if (requestEntity.length == 0) {
result = "";
} else {
result = new String(requestEntity, "UTF-8");
}
requestContext.setEntityStream(new ByteArrayInputStream(requestEntity));
} catch (IOException e) {
result = e.getMessage();
}
if (result.contains("password")) {
result = maskPassword(result);
}
return result;
}
/**
* @param jsonString JSON string containing password field.
* @return JSON string with password field hidden.
*/
private String maskPassword(String jsonString) {
return jsonString.replaceAll("(\\n?\\s*\"password\"\\s?:\\s?\")[^\\n\"]*(\",?\\n?)", "$1********$2");
}
}
@Logged
@Provider
public class ResponseLoggingFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) {
String responseMessage = convertObjectToJson(responseContext.getEntity());
String responseStatus = responseContext.getStatusInfo().toString();
String responseTime = String.valueOf(System.currentTimeMillis() - (Long) requestContext.getProperty("StartTime"));
String calledServiceName = "d2d-server"; // TODO: pass service name in @Logged() and set default
StructuredDataUtils.setStructuredDataFields(responseMessage, calledServiceName, responseStatus, responseTime);
}
}
然后我简单地标记一个方法@Logged
来记录 HTTP req/resp。
推荐阅读
- c# - 带有条件的 EF Core 迁移约束
- angular - 仅用一个材料表组件处理不同的数据源
- javascript - jQuery切换类打开和关闭问题
- python - 不允许迭代 `tf.Tensor`
- bash - sed 管道未返回预期的退出代码
- html - 在移动响应中,当我们停留在主类别列表上时,子类别应该在悬停时显示
- asp.net-core - 找不到页面 404 - 索引操作
- php - route() 在两条路线中返回不同的方式
- flutter - Flutter - 如果 ontap 是单击特定按钮,如何比较焦点节点
- ruby-on-rails-6 - Webpacker 无法从 node_modules npm 包中找到图像