我是SOA開發上下文中CXF的用戶。CXF:如何重新發送來自CXF客戶端的原始請求?
我想知道如果我的問題有CXF解決方案。這是我的需要。 我們開發了一個服務於JAXWS端點的webapp,端點實現包括通過攔截器分析請求,將請求中的數據從Java服務層中的數據存儲到數據庫,並通過CXF客戶端將原始請求重新發送到另一臺服務器。 問題是我們的一些請求包含DSIG簽名(https://www.w3.org/TR/xmldsig-core/)或簽名的SAML聲明。 我們的需求是重新發送請求而不改變它們(例如代理)來自CXFClient。 CXF使用發送編組對象到服務器,但這樣原始流不發送
有沒有辦法重新從服務層從Java CXFClient傳入的請求而不改變它(簽名取決於請求格式:空格,命名空間前綴,回車...)?我們更喜歡CXFClient,因爲我們想重新使用我們自己的CXF攔截器來記錄傳出的請求。
我們已經測試了一個攔截器,以便在將原始請求發送到服務器之前替換outputStream,我們使用了這個答案:How To Modify The Raw XML message of an Outbound CXF Request?,但是我們仍然是KO,CXF仍然發送從編組對象產生的流。見下面的代碼。
上下文: - CXF 2.7.18(JDK 6)和3.1.10(JDK 8) - 平臺:視窗7的64位/ RHEL 7 64位 - 的Apache Tomcat 7 - TCPDUMP分析傳入流量
樣品我們的客戶代碼:
final Client cxfClient = org.apache.cxf.frontend.ClientProxy.getClient(portType);
cxfClient.getInInterceptors().clear();
cxfClient.getOutInterceptors().clear();
cxfClient.getOutFaultInterceptors().clear();
cxfClient.getRequestContext().put(CustomStreamerInterceptor.STREAM_TO_SEND,
PhaseInterceptorChain.getCurrentMessage().getContent(InputStream.class));
cxfClient.getOutInterceptors().add(new CustomStreamerInterceptor());
org.apache.cxf.transport.http.HTTPConduit http = (org.apache.cxf.transport.http.HTTPConduit) cxfClient.getConduit();
...
port.doSomething(someRequest);
CustomStreamerInterceptor:
package test;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.io.IOUtils;
import org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor.SoapOutEndingInterceptor;
import org.apache.cxf.helpers.LoadingByteArrayOutputStream;
import org.apache.cxf.interceptor.AbstractOutDatabindingInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.io.CacheAndWriteOutputStream;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.Phase;
public class CustomStreamerInterceptor extends AbstractOutDatabindingInterceptor {
public static final String STREAM_TO_SEND = "STREAM_TO_SEND";
public CustomStreamerInterceptor() {
super(Phase.WRITE_ENDING);
addAfter(SoapOutEndingInterceptor.class.getName());
}
@Override
public void handleMessage(Message message) throws Fault {
try {
InputStream toSend = (InputStream) message.get(STREAM_TO_SEND);
if (toSend != null) {
toSend.reset();
LoadingByteArrayOutputStream lBos = new LoadingByteArrayOutputStream();
IOUtils.copy(toSend, lBos);
CacheAndWriteOutputStream cawos = (CacheAndWriteOutputStream) message.getContent(OutputStream.class);
cawos.resetOut(lBos, false);//fail !
}
}
catch (Exception e) {
throw new Fault(e);
}
}
}
感謝您的任何幫助,這將是非常有用的。