我可能会有一个大型请求(SOAP)来到应用服务器通配符20,我想知道如何处理该请求,而不必将所有请求解析在内存中。
我的问题是,在CXF调用DocLiteralnInterceptor拦截器之后,请求本身成为内存中的一个完整对象。如何避免这种情况?对于我来说,在不破坏与SOAP请求相关的cxf预期功能的情况下,删除这个拦截器安全吗?
拦截器中的默认CXF
我的第一个想法是删除从10到15包含的所有拦截器,并编写一个拦截器来解析给定的请求(stax),但是我不知道如何处理解析的块,以及如何同时将处理过的块写入输出流,是否需要使用线程?我是否需要删除输出拦截器(这会破坏cxf)?
但是,拦截器只用于预处理或后处理--请求和业务逻辑应该在web服务方法中调用,但在这种情况下,我需要绕过web服务方法,从inInterceptor直接转到outInterceptor,对吗?
我的第二个想法是在DocLiteralnInterceptor解析一段请求(比如1000个subObject元素)之前添加拦截器,并将其封装到根(对象)元素中,并多次从启动DocLiteralnInterceptor,的拦截器链调用,这个解决方案是否可行?如果是的话,我怎么能这样做呢?在这种情况下,我不需要绕过webservice方法。但不确定这个解决方案在一般情况下是否可行
我的请求对象示例如下
<?xml version="1.0" encoding="UTF-8"?>
<object>
<subObject>
<id>12</id>
<item>
<id>15</id>
<name>block</name>
...<- other fields
</item>
</subObject>
...<- subObject element repeated 500k (500, 000) times
</object>发布于 2020-09-27 16:09:37
不确定是否可以在没有mtom的大请求中有效地使用cxf。
您可以尝试使用提供程序接口处理请求。
public class MyService implements Provider<StAXSource> {
}但是,如果您的响应也比我怀疑的提供者接口对您的帮助要大,因为您似乎需要返回StAXSource,如果您的请求很大,则需要消耗大量内存。
https://docs.oracle.com/middleware/1213/wls/WSGET/jax-ws-provider.htm#WSGET656
从上面的链接复制粘贴
package examples.webservices.jaxws;
import org.w3c.dom.Node;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Provider;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;
import javax.xml.ws.Service;
import java.io.ByteArrayInputStream;
/**
* A simple Provider-based web service implementation.
*
* @author Copyright (c) 2010, Oracle and/or its affiliates.
* All Rights Reserved.
*/
// The @ServiceMode annotation specifies whether the Provider instance
// receives entire messages or message payloads.
@ServiceMode(value = Service.Mode.PAYLOAD)
// Standard JWS annotation that configures the Provider-based web service.
@WebServiceProvider(portName = "SimpleClientPort",
serviceName = "SimpleClientService",
targetNamespace = "http://jaxws.webservices.examples/",
wsdlLocation = "SimpleClientService.wsdl")
public class SimpleClientProviderImpl implements Provider<Source> {
//Invokes an operation according to the contents of the request message.
public Source invoke(Source source) {
try {
DOMResult dom = new DOMResult();
Transformer trans = TransformerFactory.newInstance().newTransformer();
trans.transform(source, dom);
Node node = dom.getNode();
// Get the operation name node.
Node root = node.getFirstChild();
// Get the parameter node.
Node first = root.getFirstChild();
String input = first.getFirstChild().getNodeValue();
// Get the operation name.
String op = root.getLocalName();
if ("invokeNoTransaction".equals(op)) {
return sendSource(input);
} else {
return sendSource2(input);
}
}
catch (Exception e) {
throw new RuntimeException("Error in provider endpoint", e);
}
}
private Source sendSource(String input) {
String body =
"<ns:invokeNoTransactionResponse
xmlns:ns=\"http://jaxws.webservices.examples/\"><return>"
+ "constructed:" + input
+ "</return></ns:invokeNoTransactionResponse>";
Source source = new StreamSource(new ByteArrayInputStream(body.getBytes()));
return source;
}
private Source sendSource2(String input) {
String body =
"<ns:invokeTransactionResponse
xmlns:ns=\"http://jaxws.webservices.examples/\"><return>"
+ "constructed:" + input
+ "</return></ns:invokeTransactionResponse>";
Source source = new StreamSource(new ByteArrayInputStream(body.getBytes()));
return source;
}
} 如您所见,xml响应字符串保存在内存中。
您也可以尝试使用调度接口,即
(从同一链接复制)
package jaxws.dispatch.client;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.URL;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import javax.xml.ws.soap.SOAPBinding;
public class WebTest extends TestCase {
private static String in_str = "wiseking";
private static String request =
"<ns1:sayHello xmlns:ns1=\"http://example.org\"><arg0>"+in_str+"</arg0></ns1:sayHello>";
private static final QName portQName = new QName("http://example.org", "SimplePort");
private Service service = null;
protected void setUp() throws Exception {
String url_str = System.getProperty("wsdl");
URL url = new URL(url_str);
QName serviceName = new QName("http://example.org", "SimpleImplService");
service = Service.create(serviceName);
service.addPort(portQName, SOAPBinding.SOAP11HTTP_BINDING, url_str);
System.out.println("Setup complete.");
}
public void testSayHelloSource() throws Exception {
setUp();
Dispatch<Source> sourceDispatch =
service.createDispatch(portQName, Source.class, Service.Mode.PAYLOAD);
System.out.println("\nInvoking xml request: " + request);
Source result = sourceDispatch.invoke(new StreamSource(new StringReader(request)));
String xmlResult = sourceToXMLString(result);
System.out.println("Received xml response: " + xmlResult);
assertTrue(xmlResult.indexOf("HELLO:"+in_str)>=0);
}
private String sourceToXMLString(Source result) {
String xmlResult = null;
try {
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
OutputStream out = new ByteArrayOutputStream();
StreamResult streamResult = new StreamResult();
streamResult.setOutputStream(out);
transformer.transform(result, streamResult);
xmlResult = streamResult.getOutputStream().toString();
} catch (TransformerException e) {
e.printStackTrace();
}
return xmlResult;
}
}另一方面,您可以编写自己的servlet实现,它接受大型请求并逐段处理,并作为输出返回一些内容。
但总的来说,我怀疑没有mtom或类似的东西,用cxf处理大型请求是否可行。
https://stackoverflow.com/questions/64042452
复制相似问题