【发布时间】:2017-07-12 10:57:34
【问题描述】:
我是 SOA 开发环境中的 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) - 平台:windows 7 64bit/rhel 7 64bit - 阿帕奇雄猫 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 );
}
}
}
感谢您的帮助,这将非常有用。
【问题讨论】: