Java 获取我的请求的请求主体
如何获得我将要执行的实际请求主体Java 获取我的请求的请求主体,java,jax-rs,Java,Jax Rs,如何获得我将要执行的实际请求主体 Invocation i = webTarget.path("somepath") .request(MediaType.APPLICATION_JSON) .buildPut(Entity.entity(account, MediaType.APPLICATION_JSON)); log.debug(i.... ); // I want to log the request 您可以尝试包装实体的Outputstream。首先,
Invocation i = webTarget.path("somepath")
.request(MediaType.APPLICATION_JSON)
.buildPut(Entity.entity(account, MediaType.APPLICATION_JSON));
log.debug(i.... ); // I want to log the request
您可以尝试包装实体的Outputstream。首先,通过使用
javax.ws.rs.client.ClientRequestFilter
向ClientRequestContext添加自定义输出流
Client client = ClientBuilder.newClient().register(MyLoggingFilter.class);
public class MyLoggingOutputStreamWrapper extends OutputStream{
static final Logger logger = Logger.getLogger(...);
ByteArrayOutputStream myBuffer = new ...
private OutputStream target;
public MyLoggingOutputStreamWrapper(OutputStream target){ ...
// will be smarter to implement write(byte [], int, int) and call it from here
public void write(byte [] data){
myBuffer.write(data);
target.write(data);
}
... // other methods to delegate to target, especially the other write method
public void close(){
// not sure, if converting the buffer to a string is enough. may be in a different encoding than the platform default
logger.log(myBuffer.toString());
target.close();
}
}
@Provider
public class MyLoggingFilter implements ClientRequestFilter{
// implement the ClientRequestFilter.filter method
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
requestContext.setEntityOutputstream(new MyLoggingOutputStreamWrapper(requestContext.getEntityOutputstream()));
}
我不确定outputstream在哪一点用于序列化数据。可能是在您调用buildPut()的时候,但更有可能是在webclient访问时
另一种方法是获取底层的HttpClient并在那里注册一些侦听器以获取主体。我也遇到了类似的问题。我无法使用Jersey LoggingFilter(以及2.23中的新LoggingFeature),因为我需要自定义输出。有关使用其他选项的信息,请参见以下文章: 为了简洁起见,我简化了我的工作。这与最初的答案非常相似,但我修改了Jersey LoggingStream(这是一个您无法访问的内部类),并将登录的能力提高到最大大小 您有一个扩展OutputStream的类,以便可以捕获其中的实体。它将写入您的输出流以及原始输出流
public class MyLoggingStream extends FilterOutputStream
{
private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
public MyLoggingStream(final OutputStream inner)
{
super(inner);
}
public String getString(final Charset charset)
{
final byte[] entity = baos.toByteArray();
return new String(entity, charset);
}
@Override
public void write(final int i) throws IOException
{
baos.write(i);
out.write(i);
}
}
然后你有一个过滤器类。对于我的用例来说,能够获取实体并单独记录它是很重要的(为了简单起见,我将它放在下面的println中)。在Jersey的LoggingFilter和LoggingFeature中,实体由拦截器记录,因此您无法捕获它
@Provider
public class MyLoggingClientFilter implements ClientRequestFilter, ClientResponseFilter, WriterInterceptor
{
protected static String HTTPCLIENT_START_TIME = "my-http-starttime";
protected static String HTTPCLIENT_LOG_STREAM = "my-http-logging-stream";
@Context
private ResourceInfo resourceInfo;
public void filter(final ClientRequestContext requestContext) throws IOException
{
requestContext.setProperty(HTTPCLIENT_START_TIME, System.nanoTime());
final OutputStream stream = new MyLoggingStream(requestContext.getEntityStream());
requestContext.setEntityStream(stream);
requestContext.setProperty(HTTPCLIENT_LOG_STREAM, stream);
}
public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext)
{
StringBuilder builder = new StringBuilder("--------------------------").append(System.lineSeparator());
long startTime = (long)requestContext.getProperty(HTTPCLIENT_START_TIME);
final double duration = (System.nanoTime() - startTime) / 1_000_000.0;
builder.append("Response Time: ").append(duration);
if(requestContext.hasEntity())
{
final MyLoggingStream stream = (MyLoggingStream)requestContext.getProperty(HTTPCLIENT_LOG_STREAM);
String body = stream.getString(MessageUtils.getCharset(requestContext.getMediaType()));
builder.append(System.lineSeparator()).append("Entity: ").append(body);
}
builder.append(System.lineSeparator()).append("--------------------------");
System.out.println(builder.toString());
requestContext.removeProperty(HTTPCLIENT_START_TIME);
requestContext.removeProperty(HTTPCLIENT_LOG_STREAM);
}
@Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException
{
// This forces the data to be written to the output stream
context.proceed();
}
}这两个问题对您有帮助吗?-[如何使用Jersey获取完整的REST请求正文?][1]-[JAX-RS资源方法中获取原始请求正文][2][1]:[2]:您想在客户端还是服务器端记录它?是否要将日志记录在资源方法内部或之前?是否需要扩展WriterInterceptor并重写aroundWriteTo()?没有WriterInterceptor它似乎工作得很好这似乎根本不起作用。自定义的
OutputStream
从未写入,可能是因为主体已经写入。