복붙노트

[SPRING] 동일한 이름 공간과 로컬 이름 요청을 가진 두 개의 개별 웹 서비스를 어떻게 다른 끝점으로 라우팅 할 수 있습니까?

SPRING

동일한 이름 공간과 로컬 이름 요청을 가진 두 개의 개별 웹 서비스를 어떻게 다른 끝점으로 라우팅 할 수 있습니까?

나는 하나의 스프링 배포 내에서 wsdl이 동일한 xsd 스키마에서 생성되었지만 분리 된 컨텍스트에서 요청을 다르게 처리 할 수 ​​있도록 두 개의 개별 종점으로 라우팅되도록 두 개의 별도 웹 서비스를 만들려고합니다. .

전의:

웹 서비스 1 : 액세스, 하위 권한 및 보안 제약의 하위 집합

웹 서비스 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>

이제 두 wsdls는 동일한 xsds를 기반으로하기 때문에 요청의 '네임 스페이스'와 'localPart'는 어떤 웹 서비스 (/ SpmlReadOnly 또는 / SpmlCrud)와 관계없이 동일한 와이어를 사용합니다.

따라서 localPart와 네임 스페이스가 여전히 동일하기 때문에 더 이상 사용되지 않는 PayloadRootQNameEndpointMapping을 배제하고 있습니다 ... 그리고 현재의 구성은 요청을 동일한 끝점 메서드 처리기로 라우트하고 어떤 웹 서비스가 호출되었는지 구별 할 방법이 없습니다.

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

내가 할 수있는 일이 가능한가? xsd가 공유되고 스키마의 루트에 동일한 네임 스페이스를 갖고 동일한 localPart 메소드 요청이있는 경우이를 구별하고 두 개의 다른 끝점으로 매핑하는 방법이 있습니까? 이 정보는 유용 할 것입니다! 두 개의 분리 된 .wars를 설정하고 서버에 자체 코드 기반으로 별도로 배포 할 필요가 없기를 바라고 있습니다.

감사, 데미안

해결법

  1. ==============================

    1.URI와 PayloadRoot 매핑을 결합한 것이 필요합니다. 불행히도 Spring-W에는 이와 같은 것이 없습니다. 그러나 확장 성이 뛰어나므로이 작업을 쉽게 수행 할 수 있습니다.

    URI와 PayloadRoot 매핑을 결합한 것이 필요합니다. 불행히도 Spring-W에는 이와 같은 것이 없습니다. 그러나 확장 성이 뛰어나므로이 작업을 쉽게 수행 할 수 있습니다.

    TL, DR

    실제 예제는 GitHub의이 브랜치를 보라.

    세부

    결합 된 URI + QName과 org.springframework.ws.server.endpoint.MethodEndpoint 인스턴스의 매핑을 생성해야합니다. 또한 기존 Spring-W 기능을 복제하는 코드를 최소화해야한다.

    그래서 1) 를 사용하지 않고 Spring-W 주석을 명시 적으로 구성해야합니다.

    이것은 귀하의 요구 사항입니다 (내 스키마 포함) :

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

    이것은 일반적으로 (하나의 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
    

    보호 된 QName getLookupKeyForMessage (MessageContext messageContext) 메소드는 매핑 URI가 WAR 컨텍스트와 독립적이며, 애플리케이션이에 배포되었는지 확인합니다.

  2. from https://stackoverflow.com/questions/12369701/how-can-i-have-two-separate-web-services-with-identical-name-space-and-local-nam by cc-by-sa and MIT license