使用@RepositoryRestResource 时记录 Request/Response

Log Request/Response when Using @RepositoryRestResource

我正在使用 @RepositoryRestResource from spring-data-rest-api. Since the JAX-RS controller is automatically generated,我无法手动添加记录器来记录传入的请求。是否存在将自动记录请求的注释?

我的代码:

@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?)", "********");
    }
}
@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。