Как зарегистрировать тело запроса объекта json в jersey 2.x с помощью WriterInterceptorContext? [Дубликат]

Обратите внимание, что есть случаи, когда вы определили свой собственный пользовательский класс и хотите сохранить атрибуты, тогда вы должны использовать 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
6
задан codehammer 15 August 2014 в 19:32
поделиться

2 ответа

Если вы не хотите писать больше данных в ответ, вам не нужно иметь дело с 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);
        }
    }

}
16
ответ дан lefloh 20 August 2018 в 16:21
поделиться
  • 1
    Мне понадобится OutputStream для регистрации полезной нагрузки ответа как String. Использование responseContext.getEntity () будет возвращать объект / объект ответа и если он не реализует метод toString, что это не будет полезно. – codehammer 16 August 2014 в 19:15
  • 2
    Понимаю, это имеет смысл ... спасибо за то, что вы обновили свой ответ. – codehammer 17 August 2014 в 20:22
  • 3
    Сделал еще одно обновление моего ответа. – lefloh 18 August 2014 в 20:39

У меня была та же проблема и решалась по-другому, поэтому я оставляю здесь свой ответ, хотя вопрос уже отмечен как правильно ответил.

Я внедрил 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;
    }
}

Надеюсь, это поможет!

1
ответ дан Gianluca 20 August 2018 в 16:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: