我正在尝试在一个弹簧部署中创建两个单独的Web服务,两者都使用相同的xsd架构生成wsdl,但是将它们路由到两个单独的端点,这样我就能以不同的方式处理请求单独的背景。
例如:
Webservice 1:访问权限,较低权限和安全性约束
Webservice 2:更高的权限
<sws:dynamic-wsdl id="spml-readonly"
portTypeName="SpmlReadOnlyService"
locationUri="SpmlReadOnly">
<sws:xsd location="/WEB-INF/xsd/spml/pstc_spmlv2_core.xsd"/>
</sws:dynamic-wsdl>
<sws:dynamic-wsdl id="spml-crud"
portTypeName="SpmlCrudService"
locationUri="SpmlCrud">
<sws:xsd location="/WEB-INF/xsd/spml/pstc_spmlv2_core.xsd"/>
<sws:xsd location="/WEB-INF/xsd/spml/pstc_spmlv2_search.xsd"/>
<sws:xsd location="/WEB-INF/xsd/spml/pstc_spmlv2_batch.xsd"/>
</sws:dynamic-wsdl>
现在因为两个wsdl都基于相同的xsds,所以请求的'namespace'和'localPart'都是相同的,无论我正在点击哪个Web服务(/ SpmlReadOnly或/ SpmlCrud)。 / p>
因此,排除了已弃用的PayloadRootQNameEndpointMapping,因为localPart和命名空间仍然相同,等等......我的当前配置只是将请求路由到同一个端点方法处理程序,我无法区分哪个Web服务被称为:
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "lookupRequest")
@ResponsePayload
public Source handleLookupRequest(SoapMessage message) throws Exception {
...
}
我能做什么甚至可能?如果xsd是共享的并且在模式的根目录中具有相同的名称空间,并且相同的localPart方法请求,那么是否有办法区分它们并映射到两个不同的端点?有关这方面的任何信息都很有用!我希望我不必设置两个单独的.wars,并在服务器上使用自己的代码库单独部署它们!
谢谢, 达米安
答案 0 :(得分:5)
您需要结合URI
和PayloadRoot
映射的内容。不幸的是,Spring-Ws没有这样的东西。但是因为它非常易于实现,所以很容易实现这一点。
<强> TL; DR 强>
请参阅This branch at GitHub了解工作示例
<强>详情
您需要创建组合URI + QName到org.springframework.ws.server.endpoint.MethodEndpoint
实例的映射。您还应该最小化复制现有Spring-Ws函数的代码。
所以1)你需要在不使用<sws:annotation-driven />
的情况下显式配置Spring-Ws注释:
这是你的要求(使用我的架构):
<ws:dynamic-wsdl id="spml-readonly" portTypeName="SpmlReadOnlyService" locationUri="SpmlReadOnly">
<ws:xsd location="classpath:springws/model/schema.xsd" />
</ws:dynamic-wsdl>
<ws:dynamic-wsdl id="spml-crud" portTypeName="SpmlCrudService" locationUri="SpmlCrud">
<ws:xsd location="classpath:springws/model/schema.xsd" />
<ws:xsd location="classpath:springws/model/schema2.xsd" />
</ws:dynamic-wsdl>
这就是您需要手动执行的操作,通常由<sws:annotation-driven />
配置(一个适配器和一个JAXB编组器):
<bean class="org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter">
<property name="methodArgumentResolvers">
<list>
<ref local="marshallingPayloadMethodProcessor"/>
</list>
</property>
<property name="methodReturnValueHandlers">
<list>
<ref local="marshallingPayloadMethodProcessor"/>
</list>
</property>
</bean>
<bean id="marshallingPayloadMethodProcessor" class="org.springframework.ws.server.endpoint.adapter.method.MarshallingPayloadMethodProcessor">
<property name="marshaller" ref="marshaller" />
<property name="unmarshaller" ref="marshaller" />
</bean>
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPaths">
<list>
<value>springws.model</value>
</list>
</property>
</bean>
这是自定义映射:
<bean class="springws.PathAndPayloadRootAnnotationEndpointMapping" />
2)你应该创建自己的映射
public class PathAndPayloadRootAnnotationEndpointMapping extends PayloadRootAnnotationMethodEndpointMapping
{
@Override
protected QName getLookupKeyForMessage(MessageContext messageContext) throws Exception
{
String urlPart = "";
QName payloadRootPart = super.getLookupKeyForMessage(messageContext);
TransportContext transportContext = TransportContextHolder.getTransportContext();
if (transportContext != null) {
WebServiceConnection connection = transportContext.getConnection();
if (connection != null && connection instanceof HttpServletConnection) {
String requestURI = ((HttpServletConnection)connection).getHttpServletRequest().getRequestURI();
String contextPath = ((HttpServletConnection)connection).getHttpServletRequest().getContextPath();
urlPart = requestURI.substring(contextPath.length());
}
}
return new QName(payloadRootPart.getNamespaceURI(), urlPart + "/" + payloadRootPart.getLocalPart());
}
@Override
protected List<QName> getLookupKeysForMethod(Method method)
{
List<QName> result = new ArrayList<QName>();
RequestMapping rm = AnnotationUtils.findAnnotation(method.getDeclaringClass(), RequestMapping.class);
String urlPart = rm == null || rm.value().length != 1 ? "" : rm.value()[0];
List<QName> methodPart = super.getLookupKeysForMethod(method);
for (QName qName : methodPart) {
result.add(new QName(qName.getNamespaceURI(), urlPart + "/" + qName.getLocalPart()));
}
return result;
}
}
扩展了org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping
。它所做的就是利用从端点URI提取的信息扩展消息的密钥(有效负载根元素的QNames)。我已经使用了Spring的@org.springframework.web.bind.annotation.RequestMapping
注释,但有人认为这是一个黑客可能会创建他/她自己的注释。
对于像这样的端点:
@org.springframework.ws.server.endpoint.annotation.Endpoint
@RequestMapping("/ws/SpmlReadOnly")
public class Endpoint1
{
@ResponsePayload
@PayloadRoot(namespace = "urn:test", localPart = "method1Request")
public Response2 method(@RequestPayload Request1 request) throws Exception
{
return new Response2("e1 m1");
}
}
关键不是:
namespace = urn:test
localName = method1Request
但是这个:
namespace = urn:test
localName = /ws/SpmlReadOnly/method1Request
protected QName getLookupKeyForMessage(MessageContext messageContext)
方法确保映射URI独立于WAR上下文,应用程序部署在。