逆向工程:如何在后端生成 SOAP 请求 XML?



我有以下类:

WS 接口:

package com.mypackage;
import javax.ejb.Remote;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
@Remote
@SOAPBinding(style = Style.DOCUMENT)
@WebService(name = "MathService", targetNamespace = "http://mypackage.com/")
public interface MathServiceWS {
@WebResult(name = "result", targetNamespace = "http://mypackage.com/")
@RequestWrapper(localName = "addRequest", className = "AddRequest", targetNamespace = "http://mypackage.com/")
@WebMethod(action = "http://mypackage.com/add", operationName = "add")
@ResponseWrapper(localName = "addResponse", className = "AddResponse", targetNamespace = "http://mypackage.com/")
Long add(@WebParam(name = "add", targetNamespace = "http://mypackage.com/") AddBean add);
}

WS 实现:

package com.mypackage;
import javax.ejb.Stateless;
import javax.jws.WebService;
@Stateless(mappedName = "MathService")
@WebService(serviceName = "MathService", endpointInterface = "com.mypackage.MathServiceWS", portName = "MathServicePort", targetNamespace = "http://mypackage.com/")
public class MathService implements MathServiceWS {
@Override
public Long add(AddBean add) {
Long first = new Long(add.getFirst().intValue());
Long second = new Long(add.getSecond().intValue());
return Long.valueOf(Math.addExact(first.longValue(), second.longValue()));
}
}

豆子:

package com.mypackage;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(
name = "Add",
namespace = "http://mypackage.com/",
propOrder = {
"first",
"second"
}
)
public class AddBean implements Serializable {
private static final long serialVersionUID = -7727938355039425419L;
@XmlElement(required = true)
private Integer first;
@XmlElement(required = true)
private Integer second;
public AddBean() {
}
public Integer getFirst() {
return first;
}
public void setFirst(Integer first) {
this.first = first;
}
public Integer getSecond() {
return second;
}
public void setSecond(Integer second) {
this.second = second;
}
}

部署此 WS 后,当我在 SoapUI 中添加 WSDL 时,在为用户提供输入后,添加方法请求如下所示:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:myp="http://mypackage.com/">
<soapenv:Header/>
<soapenv:Body>
<myp:addRequest>
<myp:add>
<first>1</first>
<second>2</second>
</myp:add>
</myp:addRequest>
</soapenv:Body>
</soapenv:Envelope>

现在,我想在我的com.mypackage.MathService.add(AddBean)方法中使用给定的用户输入来使用上述 SOAP 请求 XML。

  • 在 上使用 JAXBcom.mypackage.AddBean仅生成部分请求
  • Web 服务处理程序对于满足我的要求没有用

任何指针都会非常有帮助。

您可以创建自定义 SOAPHandler 对象,并可以通过自定义属性读取请求有效负载并将其设置为 SOAPMessageContext。请确保将范围设置为应用程序。

在服务类中,使用@javax.annotation.Resource注入javax.xml.ws.WebServiceContext,并通过自定义属性访问有效负载集。

例如:
1.创建处理程序并注册它。

public class PopulateSOAPMessagePayloadHandler implements SOAPHandler<SOAPMessageContext> {
public static final String SOAP_MESSAGE_PAYLOAD = "__soap_message_payload";
@Override
public boolean handleMessage(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (!outboundProperty.booleanValue()) {
// for incoming:
ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
try {
smc.getMessage().writeTo(bout);
String payload = bout.toString(StandardCharsets.UTF_8.name());
smc.put(SOAP_MESSAGE_PAYLOAD, payload);  //Set payload
smc.setScope(SOAP_MESSAGE_PAYLOAD, MessageContext.Scope.APPLICATION);  //make it application scope
} catch (SOAPException | IOException e) {
e.printStackTrace();
// handle exception if needed
throw new WebServiceException(e);
}
}
return true;
}
// Other method (no-op) omitted 
}


2. 获取有效负载

public class MathService implements MathServiceWS {
@Resource
private WebServiceContext context;
@Override
public Long add(AddBean add) {
String payload = (String) context.getMessageContext().get(SOAP_MESSAGE_PAYLOAD);
Long first = new Long(add.getFirst().intValue());
Long second = new Long(add.getSecond().intValue());
return Long.valueOf(Math.addExact(first.longValue(), second.longValue()));
}
}

希望对您有所帮助。

您可以轻松完全控制文档。首先让我们设置 bean:

@XmlRootElement(name="addRequest")
@XmlAccessorType(XmlAccessType.FIELD) //Probably you don't need this line. it is by default field accessible. 
public class AddBean implements Serializable {
private static final long serialVersionUID = -7727938355039425419L;
@XmlElement(name="first",required = true) //you don't need name attribute as field is already exactly the same as soap element
private Integer first;
@XmlElement(name="second",required = true) //you don't need name attribute as field is already exactly the same as soap element
private Integer second;
public AddBean() { }
//Getters and Setters
}

现在,我认为这是您正在寻找的部分。添加自定义命名空间声明并设置前缀等。如果使用org.springframework.ws.client.core.support.WebServiceGatewaySupport.getWebServiceTemplate发出 SOAP 请求,则可以执行以下操作:

public class WSCastorClient extends WebServiceGatewaySupport {
public CustomResponseObject callWebService(Addbean add) {
WebServiceTemplate wst = getWebServiceTemplate();
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.afterPropertiesSet();
wst.setMarshaller(marshaller);
wst.setUnmarshaller(marshaller);
wst.afterPropertiesSet();
CustomResponseObject response = (CustomResponseObject) 
wst.marshallSendAndReceive(add, new 
WebServiceMessageCallback() {
public void doWithMessage(WebServiceMessage message) { 
SaajSoapMessage saajSoapMessage = (SaajSoapMessage) message;
SOAPMesage soapMEssage = saajSoapMessage.getSaajMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
SOAPHeader head = soapMessage.getSOAPHeader();
SOAPBody soapBody = soapMessage.getSOAPBody();
//Now you have full control of the soap header, body, envelope. You can add any namespace declaration, prefix, add header element, etc. You can add remove whatever you want. 
soapEnvelope.removeNamespaceDeclaration(soapEnvelope.getPrefix()); //clear whatever namespace is there
soapEnvelope.addNamespaceDeclaration("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
soapEnvelope.addNamespaceDeclaration("myp", "http://mypackage.com/");
soapEnvelope.setPrefix("soapenv");
soapHeader.setPrefix("soapenv");
soapBody.setPrefix("soapenv");
Document doc = saajSoapMessage.getDocument();
StringWriter sw = new StringWriter();
Transformer transformer  = TransformerFactory.newInstance().newTransformer();
transformer.transform(new DOMSource(doc), new StreamResult(sw));
}       
});
return response;
}
//close off other brackets if I forgot any. 

最新更新