问题描述
我正在实现与某些旧版SOAP服务进行交互的SOAP客户端。
所有SOAP正文请求都具有相同的格式,如下所示:
<soap:Body>
<execute>
<msg>
</msg>
</execute>
</soap:Body>
作为内容,msg元素支持任何 XML标记的列表,因此我可以在msg内部发送任何类型的元素:订单,客户,联系人等。
所有请求还具有相同的操作名称。
由于上述限制/方面,如果我使用spring的 ,由于soap主体中的根元素对于所有请求都是相同的,则每个请求都将属于Endpoint的相同方法。 如果我使用spring的 ,由于每个请求的操作都相同,因此所有请求将再次属于同一方法。
我在请求中唯一不同的是请求URI。 它根据我正在调用的操作的名称而改变。 像: 或
我的想法是为每种类型的请求提供一个端点。 例如:与产品相关的所有请求都将放入“ ProductsEndpoint”。 我想创建一个自定义的端点映射,以扩展Spring AbstractEndpointMapping。 在我的实现中,我将根据URI决定要调用的端点。
但是,如何在Spring的端点映射链中注册我的自定义端点映射?
最好的祝福
1楼
如果有人有像我上面解释的那样的请求,这里就是我决定要做的...
我创建了一个扩展spring org.springframework.ws.server.endpoint.adapter.method.MarshallingPayloadMethodProcessor
的类MultipleMarshallersPayloadMethodProcessor。
这是负责编组和解组参数的类。
在此类中,我定义了一个java.util.map,它将给定的URL与特定的Marshaller关联。
如果当前URL请求不是映射中的键,则它将使用MarshallingPayloadMethodProcessor类提供的默认Marshaller。
要将类注册为spring bean:
<bean id="marshallingPayloadMethodProcessor"
class="br.com.tim.fiber.middleware.services.server.helpers.MultipleMarshallersPayloadMethodProcessor">
<constructor-arg ref="defaultMarshaller" />
<property name="otherMarshallers">
<map>
<entry key="/Operation1?wsdl" value-ref="operation1Marshaller"></entry>
<entry key="/Operation2?wsdl" value-ref="operation2Marshaller"></entry>
</map>
</property>
</bean>
还有一个编组员的例子:
<bean id="operation1Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPaths">
<list>
<value>com.app.dtos.operation1</value>
<value>com.app.dtos.common</value>
</list>
</property>
</bean>
通过此设置,我可以根据URL封送和取消封送任何请求。 然后,我使用了Facade设计模式通过一个接收所有请求的单一方法来创建SOAP端点。 该方法仅检查URL并委托给特定的端点。
@Endpoint
public class FacadeEndpoint {
private static final String NAMESPACE_URI = "http://my.namespace.com/services";
@Autowired
private RequesEndpointURLExtractor requestUrlExtractor;
@Autowired
private OrdersEndpoint ordersEndpoint;
@SuppressWarnings("unchecked")
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "execute")
@ResponsePayload
public ExecuteResponse dispatch(@RequestPayload Execute request) {
String serviceURL = this.requestUrlExtractor.getCurrentURL();
ExecuteResponse response = null;
if (serviceURL.equals(ServiceRequestsEndpoint.CREATE_ENDPOINT_URI)) {
Operation1DTO serviceRequest = (Operation1DTO) request.getMsg().getAnies().get(0);
}
...
}
RequestEnpointURLExtractor只是一个从请求中提取完整URL的spring bean。
@Component
public class RequesEndpointURLExtractor {
public String getCurrentURL() {
TransportContext ctx = TransportContextHolder.getTransportContext();
HttpServletRequest httpServletRequest = ((HttpServletConnection) ctx.getConnection()).getHttpServletRequest();
String pathInfo = httpServletRequest.getPathInfo();
String queryString = httpServletRequest.getQueryString();
return pathInfo + "?" + queryString;
}
}
我可以创建一个与URL关联的自定义批注,然后将该批注用于在配置了URL的情况下处理请求的方法。 那将是一个更干净的解决方案,而不是我拥有的if / else if阶梯。
但是,由于这仅适用于简单的模型服务器,因此if / else if阶梯并不是什么大问题。