Обратите внимание, что есть случаи, когда вы определили свой собственный пользовательский класс и хотите сохранить атрибуты, тогда вы должны использовать copy.copy()
или copy.deepcopy()
, а не альтернативы, например, в Python 3:
import copy
class MyList(list):
pass
lst = MyList([1,2,3])
lst.name = 'custom list'
d = {
'original': lst,
'slicecopy' : lst[:],
'lstcopy' : lst.copy(),
'copycopy': copy.copy(lst),
'deepcopy': copy.deepcopy(lst)
}
for k,v in d.items():
print('lst: {}'.format(k), end=', ')
try:
name = v.name
except AttributeError:
name = 'NA'
print('name: {}'.format(name))
Выходы:
lst: original, name: custom list
lst: slicecopy, name: NA
lst: lstcopy, name: NA
lst: copycopy, name: custom list
lst: deepcopy, name: custom list
Если вы не хотите писать больше данных в ответ, вам не нужно иметь дело с OutputStream. Просто используйте объект ответа:
@Provider
public class SomeFilter implements ContainerResponseFilter {
private Logger LOG = LoggerFactory.getLogger(SomeFilter.class);
@Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException {
LOG.info("response entity: " + responseContext.getEntity());
}
}
OutputStream пуст во время вызова фильтра, потому что время выполнения JAX-RS не записано на него. После вашего фильтра среда выполнения выберет правильный MessageBodyWriter , который будет сериализовать объект в OutputStream.
Вы также можете перехватить все MessageBodyWriters с помощью WriterInterceptor . Следующий пример передает ByteArrayOutputStream в MessageBodyWriter и затем восстанавливает исходный OutputStream:
@Provider
public class ResponseInterceptor implements WriterInterceptor {
private Logger LOG = LoggerFactory.getLogger(ResponseInterceptor.class);
@Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
OutputStream originalStream = context.getOutputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
context.setOutputStream(baos);
try {
context.proceed();
} finally {
LOG.info("response body: " + baos.toString("UTF-8"));
baos.writeTo(originalStream);
baos.close();
context.setOutputStream(originalStream);
}
}
}
У меня была та же проблема и решалась по-другому, поэтому я оставляю здесь свой ответ, хотя вопрос уже отмечен как правильно ответил.
Я внедрил ContainerResponseFilter
и ввел Providers
, через который Я получил MessageBodyWriter
для конкретной сущности ответа и конкретного MediaType
; затем я использовал его для записи объекта в доступный OutputStream
, который я использовал для регистрации объекта.
Этот подход позволяет вам фиксировать точную полезную нагрузку ответа, а не только объект, прикрепленный к Response
, то есть, если объект будет сериализован как JSON, тогда вы запишете JSON, если он будет сериализован как XML, вы запишете XML. Если использовать метод toString()
прикрепленного объекта, этот подход является просто бесполезной вычислительной стоимостью.
Вот код (трюк выполняется в функции CustomResponseLogger.payloadMessage
):
@Provider
public class CustomResponseLogger implements ContainerResponseFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomResponseLogger.class);
@Context private Providers providers;
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
String message = new String("Outgoing message").concat(System.lineSeparator());
if (responseContext.getMediaType() != null)
message = message.concat("Content-Type: ").concat(responseContext.getMediaType().toString()).concat(System.lineSeparator());
message = message.concat("Payload: ").concat(payloadMessage(responseContext)).concat(System.lineSeparator());
LOGGER.info(message);
}
private String payloadMessage(ContainerResponseContext responseContext) throws IOException {
String message = new String();
if (responseContext.hasEntity()) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Class<?> entityClass = responseContext.getEntityClass();
Type entityType = responseContext.getEntityType();
Annotation[] entityAnnotations = responseContext.getEntityAnnotations();
MediaType mediaType = responseContext.getMediaType();
@SuppressWarnings("unchecked")
MessageBodyWriter<Object> bodyWriter = (MessageBodyWriter<Object>) providers.getMessageBodyWriter(entityClass,
entityType,
entityAnnotations,
mediaType); // I retrieve the bodywriter
bodyWriter.writeTo(responseContext.getEntity(),
entityClass,
entityType,
entityAnnotations,
mediaType,
responseContext.getHeaders(),
baos); // I use the bodywriter to write to an accessible outputStream
message = message.concat(new String(baos.toByteArray())); // I convert the stream to a String
}
return message;
}
}
Надеюсь, это поможет!