gpt4 book ai didi

web-services - 如何将两个具有相同 namespace 的单独Web服务和本地名称请求路由到不同的端点?

转载 作者:行者123 更新时间:2023-12-04 04:55:24 25 4
gpt4 key购买 nike

我正在尝试在一个 Spring 部署中创建2个单独的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,因此无论我要访问哪个Web服务(/SpmlReadOnly或/SpmlCrud),请求的“ namespace ”和“localPart”都会完全相同。

因此,这已排除了已弃用的PayloadRootQNameEndpointMapping,因为localPart和 namespace 仍然相同,等等,...而我当前的配置只是将请求路由到同一终结点方法处理程序,而我无法区分被称为哪个Web服务的方法:
    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "lookupRequest")
@ResponsePayload
public Source handleLookupRequest(SoapMessage message) throws Exception {
...
}

我什至可以做些什么?如果xsd是共享的,并且在模式的根部具有相同的 namespace ,并且具有相同的localPart方法请求,那么是否有办法区分它们并映射到两个不同的端点?关于此的任何信息将是有用的!我希望我不必设置两个单独的.wars并将它们与自己的代码库分别部署在服务器上!

谢谢,
达米安

最佳答案

您需要结合URIPayloadRoot映射的东西。不幸的是,Spring-Ws没有这样的东西。但是因为它非常可扩展,所以实现它确实很容易。

TL; DR

有关工作示例,请参见This branch at GitHub

详细信息

您需要创建URI + QName组合到org.springframework.ws.server.endpoint.MethodEndpoint实例的映射。另外,您应该最小化将复制现有Spring-Ws函数的代码。

所以1)您需要显式配置Spring-Ws批注,而无需使用<sws:annotation-driven />:

这是您的要求(使用我的模式):

<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注释,但是认为它是hack的人可以创建自己的注释。

所以对于这样的端点:
@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上下文无关。

关于web-services - 如何将两个具有相同 namespace 的单独Web服务和本地名称请求路由到不同的端点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12369701/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com