当前位置: 首页 > 知识库问答 >
问题:

如何将两个具有相同名称空间和本地名称请求的独立web服务路由到不同的endpoint?

东门彬
2023-03-14

我试图创建两个独立的web服务,都在一个spring部署中,都从相同的xsd模式中生成wsdl,但是将它们路由到两个独立的endpoint,这样我就可以在不同的上下文中以不同的方式处理请求。

前任:

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都基于相同的xsd,因此请求的“命名空间”和“localPart”在线路上是相同的,无论我点击的是哪个Web服务(/SpmlReadOnly或 /SpmlCrud)。

因此,这就排除了不推荐的PayloadRootQNameEndpointMapping,因为localPart和namespace仍然是相同的,等等,...我当前的配置只是将请求路由到同一个endpoint方法处理程序,我无法区分调用了哪个web服务:

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "lookupRequest")
    @ResponsePayload
    public Source handleLookupRequest(SoapMessage message) throws Exception {
        ...
    }

我能做的事情是可能的吗?如果xsd是共享的,并且在模式的根部具有相同的命名空间,以及相同的localPart方法请求,是否有办法区分它们并映射到两个不同的endpoint?关于这一点的任何信息都将是有用的!我希望我不必设置两个单独的. war并在服务器上使用自己的代码库单独部署它们!

谢谢,达米安

共有1个答案

段宏毅
2023-03-14

您需要一些结合了URI有效负载根映射的东西。不幸的是,Spring-Ws没有这样的东西。但是因为它非常具有可扩展性,所以实现这一点非常容易。

TL;速度三角形定位法(dead reckoning)

参见GitHub上的这个分支以获得工作示例

详细信息

您需要创建组合的 URI QName 到 org.springframework.ws.server.endpoint.MethodEndpoint 实例的映射。此外,您还应该尽量减少会复制现有Spring-Ws函数的代码。

因此1)您需要在不使用的情况下显式配置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>

这就是您需要手动完成的所有操作,通常通过以下方式进行配置:

<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;
    }   
}

它扩展了< code > org . spring framework . ws . server . endpoint . mapping . payloadrootannotationmethodenpointmapping 。它所做的只是用从endpointURI提取的信息扩展消息的键(有效负载根元素的QNames)。为此,我使用了Spring的< code > @ org . Spring framework . web . bind . annotation . request mapping 注释,但有人认为这是一个黑客,可能会创建他/她自己的注释。

所以对于这样的endpoint:

@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

< code >受保护的QName getLookupKeyForMessage(message context message context)方法确保映射URI独立于应用程序部署的WAR上下文。

 类似资料:
  • 我发送一个POST请求,从一家运输公司生成AWB。为了做到这一点,我必须通过SOAP API POST请求发布多个数据条目。下面的XML是类似的,这是必需的(我已经简化了,否则它要求超过30个参数) 我是SOAP新手,请帮助我朝着正确的方向前进,我甚至非常感谢上面的XML代码,因为它有助于更好地理解。

  • 我用的是spring soap ws。 我有以下对应于复杂类型的JAXB域类 我有以下带有@XmlRegistry注释的类 以下是endpoint 当我发出 Soap 请求时,我正在使用 soap 请求中的终结点中给出NAMESPACE_URI。 在这里,在这种情况下,我得到以下回应 如果我使用"超文本传输协议://命名空间/url"作为NAMESPACE_URI在endpoint和肥皂请求我得到

  • 问题内容: 我有一个这样的架构层次结构: 一个文件夹中的所有文件都具有相同的命名空间。 现在,我想将名称空间映射到特定的Java包(我不能更改名称空间)。 我找到了将架构绑定到程序包的解决方案。但是然后我必须为每个xsd文件创建一个条目: 有没有一种方法可以直接定义名称空间和程序包名称之间的绑定? 另一种方法是在maven中定义包: 但是然后我必须为每个文件夹创建一个执行,这并不是我真正想要的。

  • 问题内容: 我正在尝试使用RSA 7.5和Websphere 7服务器开发IBM JAX_WS Web服务。因为我是一个初学者,所以我遵循Java类优先方法,即首先创建Java类,然后生成WSDL文件。 当我尝试创建wsdl文件时,出现异常: java.security.PrivilegedActionException:com.sun.xml.internal.bind.v2.runtime.I

  • 问题内容: 我正在用C#编写.NET Framework 3.5。 我正在尝试将某些Json解析为JObject。 Json如下: 当我尝试将此Json解析为JObject时,JObject仅了解LargeBox。SmallBox和MedBox的信息丢失。显然,这是因为它将“ TBox”解释为一个属性,并且该属性已被覆盖。 我从Delphi编码的服务中收到此Json。我正在尝试为该服务创建C#代理