2016-11-01 9 views
0

Мы начали проверку запросов наших клиентов на сервере с помощью операции CRUD.Обработка предварительной/последующей обработки запросов CXF

Вместо вызова класса аудита для регистрации запроса мы хотим использовать фильтр CXF для предварительной обработки & послепроцесса каждого запроса. Что я имею в виду?

Мы хотим провести аудит каждого запроса на обновление (который содержит JSON) со своим старым значением (перед изменением, операцией GET в БД), но зарегистрировать его только в регистраторе после, запрос успешно завершен.

Мы уже используем этот метод для изменения тела ответа при вызове исключения (с использованием тега jaxsrs: providers и реализации ExceptionMapper), но я не могу понять, как его использовать для предварительной/пост-обработки Запросы.

Спасибо!


UPDATE:

Ну я вроде понял, что мне нужно сделать, чтобы сделать CXF Interceptor:

  • Создать класс, расширяющий AbstractPhaseInterceptor
  • в классе вызова конструктора super(Phase.[the-needed-pahse]) решить, когда будет выполняться ваш перехватчик (here - список всех фаз входящих/исходящих)
  • Override handleMessage как это унаследованный метод, здесь вы будете писать свою логику
  • Добавить перехватчик в web.xml файл вашего проекта

Например:

public void handleMessage(Message request) throws Fault {  
    try { 
     InputStream is = request.getContent(InputStream.class); 
     String reqBodyAsString = org.apache.commons.io.IOUtils.toString(is, "UTF-8"); 
     IOUtils.closeQuietly(is);  
     // Do the logic 
     is = org.apache.commons.io.IOUtils.toInputStream(reqBodyAsString, "UTF-8"); 
     request.setContent(InputStream.class, is); 
     org.apache.commons.io.IOUtils.closeQuietly(is); 
    } 
    catch (IOException ioe) { 
     ioe.printStackTrace(); 
    } 
} 

И web.xml файл:

<jaxrs:server id="[id]" address="[URL]"> 
    <jaxrs:inInterceptors><!-- because we want it to run BEFORE the request logic --> 
     <ref bean="[interceptor-id]" /> 
    </jaxrs:inInterceptors> 
</jaxrs:server> 

<bean id="[interceptor-id]" class="[package-path.interceptor-class-name]"/> 

Вы можете видеть, что после прочтения c Я снова запишу его в запрос. Это потому, что я получаю исключение, говоря, что мое тело null.

И вот где я застрял, у меня есть перехватчик, но после прочтения тела запроса кажется, что логика не может быть продолжена.

+0

Задумывались ли вы об этом прямо перед тем, как вы вставляете/обновляете базу данных (а не выполняете ее при перехвате HTTP) транзакционно? Используете ли вы какие-либо рамки ORM? Если вы используете спящий режим, есть способы задействовать события и использовать их для создания записей аудита. Пример: https://www.mkyong.com/hibernate/hibernate-interceptor-example-audit-log/ –

+0

@random_dude Мы не используем стандартную БД, и мы не хотим проверять каждую операцию только конкретную операции, отправленные с определенного URL-адреса.Перед операцией записи у нас нет всех данных, которые мы хотим зарегистрировать в транзакции, нам нужно сделать это немного выше в цепочке. –

+0

Почему вы закрываете входной поток сразу после его настройки? org.apache.commons.io.IOUtils.closeQuietly (is); ' – TMtech

ответ

0

Вы потребляете поток запросов. Перед записью необходимо кэшировать его и установить новый поток в сообщении CXF

public void handleMessage(Message message) { 
     //Get the message body into payload[] and set a new non-consumed inputStream into Message 
     InputStream in = message.getContent(InputStream.class); 
     byte payload[] = IOUtils.readBytesFromStream(in); //log this 
     ByteArrayInputStream bin = new ByteArrayInputStream(payload); 
    message.setContent(InputStream.class, bin); 
} 

Закрыть потоки не нужны. Обратите внимание, что вы можете использовать перехватчики регистрации CXF по умолчанию https://stackoverflow.com/a/37820362/6371459