9

2つの別々のWebサービスを作成しようとしています。どちらも1つのSpringデプロイメント内で、両方ともwsdlが同じxsdスキーマから生成されていますが、別々のコンテキストで異なる方法でリクエストを処理できるように、2つの別々のエンドポイントにルーティングされています。 。

元:

Webサービス1:アクセスのサブセット、低い特権、およびセキュリティの制約

Webサービス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」は同一のネットワークを通過します。

したがって、localPartと名前空間はまだ同一であるなどの理由で非推奨のPayloadRootQNameEndpointMappingを除外しています...そして私の現在の構成は単にリクエストを同じエンドポイントメソッドハンドラーにルーティングし、どのWebサービスが呼び出されたかを区別する方法がありません:

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

私にできることは可能ですか?xsdが共有され、スキーマのルートに同一の名前空間があり、同じlocalPartメソッドが要求する場合、それらを区別して2つの異なるエンドポイントにマップする方法はありますか?これに関する情報は役に立ちます!2つの別々の.warをセットアップして、サーバー上に独自のコードベースで別々にデプロイする必要がないことを願っています!

ありがとう、ダミアン

4

1 に答える 1

5

URI組み合わせてPayloadRootマッピングするものが必要です。残念ながら、Spring-Ws にはこのようなものはありません。しかし、非常に拡張可能であるため、これを実現するのは非常に簡単です。

TL;DR

実際の例については、GitHub のこのブランチを参照してください

詳細

org.springframework.ws.server.endpoint.MethodEndpoint結合された URI+QName のインスタンスへのマッピングを作成する必要があります。また、既存の 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 />(1 つの JAXB マーシャラーを備えた 1 つのアダプター)によって構成されます。

<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 から抽出された情報を使用して、メッセージのキー(ペイロード ルート要素の QName) を拡張するだけです。そのために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 コンテキストから独立していることを保証し、アプリケーションがデプロイされます。

于 2013-04-03T07:25:11.353 に答える