복붙노트

[SPRING] Spring을 사용하는 CXF에서 다중 resouceBean 구성

SPRING

Spring을 사용하는 CXF에서 다중 resouceBean 구성

CXF RS 2.5.1을 Spring 3.0.6-RELEASE와 함께 사용하고 있습니다. "단일 종점"을위한 여러 구현 클래스를 갖고 싶습니다. 이 문제가보고되고 https://issues.apache.org/jira/browse/CXF-2439가 고정되어있는 것을 볼 수 있습니다. 그러나 CXF는 jaxrs : serviceBeans 태그에서 첫 번째 리소스 클래스를 선택합니다. 다른 요청의 경우, "요청 경로 / account / rest / transfer가 일치하는 작업이 없습니다"라는 메시지가 tomcat 콘솔에 표시됩니다. 아래는 구성입니다. 모든 입력을 감사하십시오.

을 포함한다.

    <listener>
        <listener-class> org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:account-servlet.xml</param-value>
    </context-param>

      <servlet>
    <servlet-name>CXF Servlet</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
       </servlet>

      <servlet-mapping>
    <servlet-name>CXF Servlet</servlet-name>
    <url-pattern>/*</url-pattern>
      </servlet-mapping>

account-servlet.xml

    <jaxrs:server id="accountService" address="/rest">
        <jaxrs:serviceBeans>
            <ref bean="transferService" />
                <ref bean="balanceService"/>
        </jaxrs:serviceBeans>
        <jaxrs:extensionMappings>
            <entry key="xml" value="application/xml" />
        </jaxrs:extensionMappings>
    </jaxrs:server>


    <bean id="transferService" class="com.mycompany.service.TransferService"/>
    <bean id="balanceService" class="com.mycompany.service.BalanceService"/>

BalanceService.java (가져 오기 생략)

        package com.mycompany.service;
        @Path("/")
         @Produces("application/xml")
        public class BalanceService{

    @GET
    @Path("/balance")
    public String getBalance() {
        StringBuilder response = new StringBuilder(128);
        response.append("<Balance>")
            .append("<amount>").append("250.00").append("</amount>")
            .append("</Balance>");
        return response.toString();
    }
       }

TransferService.java (가져 오기 생략)

package com.mycompany.service;

@Path("/")
@Produces("application/xml")
public class TransferService {

    @GET
    @Path("/transfer")
    public String getTransfer() {

        StringBuilder response = new StringBuilder(128);
        response.append("<Transfer>")
            .append("<amount>").append("350.00").append("</amount>")
            .append("</Transfer>");
        return response.toString();
    }
  }

POC에 대한 샘플 응용 프로그램이므로 프로그래밍 불규칙성 / 표준을 무시하십시오.

해결법

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

    1.@Path 매핑의 일부를 서비스 빈 클래스로 이동하여이 문제를 해결했습니다. 귀하의 경우 :

    @Path 매핑의 일부를 서비스 빈 클래스로 이동하여이 문제를 해결했습니다. 귀하의 경우 :

    BalanceService

    @Path("/balance")
    @Produces("application/xml")
    public class BalanceService {
        @GET
        @Path("/{id}")
        public String getBalance(@PathParam("id") long id) {
            ...
        }
    }
    

    전송 서비스

    @Path("/transfer")
    @Produces("application/xml")
    public class TransferService {
    
        @GET
        @Path("/{id}")
        public String getTransfer(@PathParam("id") long id) {
           ...      
        }
    }
    
  2. ==============================

    2.그래서 나는 인터넷 검색에 약간의 시간을 할애하지만이 문제에 대한 해결책을 찾지 못했습니다. 문서를 작성하여 솔루션을 추론 할 수있는 메모가 있습니다.

    그래서 나는 인터넷 검색에 약간의 시간을 할애하지만이 문제에 대한 해결책을 찾지 못했습니다. 문서를 작성하여 솔루션을 추론 할 수있는 메모가 있습니다.

    http://cxf.apache.org/docs/jax-rs-basics.html#JAX-RSBasics-Customselectionbetweenmultipleresources

    따라서 사용자 정의 리소스 비교기를 작성하고 적절한 jaxrs : server 구성 및 Eureka를 수행했습니다. 그것은 일했다!. 이제 javax : rs address의 단일 리소스 / 주소에 매핑 된 2 개의 구현 클래스가 있습니다.

    아래 표시된 사용자 지정 리소스 비교기의 논리는 URL 패턴에 따라 달라질 수 있습니다.

    모든 파일의 출처를 제공합니다. 이것이 미래에 누군가를 도울 수 있기를 바랍니다 :)

    <web-app>
      <display-name>Archetype Created Web Application</display-name>
    
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/account-servlet.xml</param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <servlet>
            <servlet-name>CXF Servlet</servlet-name>
            <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>CXF Servlet</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    
    </web-app>
    
    <beans>
        <jaxrs:server id="accountService" address="/rest">
            <jaxrs:serviceBeans>
                <ref bean="accountServiceImpl" />
                <ref bean="transferServiceImpl" />
            </jaxrs:serviceBeans>
            <jaxrs:resourceComparator>
                <bean id="accountServiceComparator" class="com.etrade.comparator.AccountServiceComparator"/>
            </jaxrs:resourceComparator>
            <jaxrs:extensionMappings>
                <entry key="xml" value="application/xml" />
            </jaxrs:extensionMappings>
        </jaxrs:server>
    
        <bean id="accountServiceImpl" class="com.etrade.service.AccountService" />
        <bean id="transferServiceImpl" class="com.etrade.service.TransferService" />
    </beans>
    
      <modelVersion>4.0.0</modelVersion>
      <groupId>cxf.rest</groupId>
      <artifactId>account</artifactId>
      <packaging>war</packaging>
      <version>0.0.1-SNAPSHOT</version>
      <name>account Maven Webapp</name>
      <url>http://maven.apache.org</url>
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
    
            <dependency>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-bundle-jaxrs</artifactId>
                <version>2.5.0</version>
            </dependency> 
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>3.0.5.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>3.0.5.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>3.0.5.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>3.0.5.RELEASE</version>
            </dependency>
    
      </dependencies>
      <build>
    
        <plugins>
          <plugin>
            <!-- This plugin is needed for the servlet example -->
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <version>7.2.0.v20101020</version>
          </plugin>
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.1</version>
            <executions>
              <execution><goals><goal>java</goal></goals></execution>
            </executions>
          </plugin>
        </plugins>
    
        <finalName>account</finalName>
      </build>
    </project>
    
    package com.etrade.comparator;
    
    import java.lang.reflect.Method;
    
    import javax.ws.rs.Path;
    
    import org.apache.cxf.jaxrs.ext.ResourceComparator;
    import org.apache.cxf.jaxrs.impl.UriInfoImpl;
    import org.apache.cxf.jaxrs.model.ClassResourceInfo;
    import org.apache.cxf.jaxrs.model.OperationResourceInfo;
    import org.apache.cxf.message.Message;
    
    public class AccountServiceComparator implements ResourceComparator{
    
        public int compare(ClassResourceInfo arg0, ClassResourceInfo arg1,
                Message message) {
    
            UriInfoImpl uriInfo = new UriInfoImpl(message);
    
            String path = uriInfo.getPath();
            String[] pathArray = path.split("/");
            String resourceUrlName = pathArray[1];
    
            System.out.println("Path : "+resourceUrlName);
    
            Method[] methods = arg0.getServiceClass().getMethods();
            int value = 1;
            String resource = null;
            for(Method method : methods) {
    
                Path annotationPath = method.getAnnotation(javax.ws.rs.Path.class);
                if(null != annotationPath){
                    String pathValue = annotationPath.value();
                    String[] parts = pathValue.split("/");
                    resource = parts[1];
                    System.out.println("resource : "+resource);
                }
    
                if(resourceUrlName.contains(resource)){
                    value = -1; 
                }
    
            }
            return value;
        }
    
        public int compare(OperationResourceInfo arg0, OperationResourceInfo arg1,
                Message arg2) {
            return 0;
        }
    
    }
    
    package com.etrade.service;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    
    @Path("/account")
    @Produces("application/xml")
    public class AccountService {
    
        @GET
        @Produces("application/xml")
        @Path("/balance/{id}")
        public String accountBalance(@PathParam("id") long id) {
            System.out.println("id : "+id);
            StringBuilder response = new StringBuilder(256);
            response.append("<Response>").append("<id>").append(id)
            .append("</id>").append("<balance>").append("250.00").append("</balance>")
            .append("</Response>");
    
            return response.toString();
        }
    
    }
    
    package com.etrade.service;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    
    @Path("/account")
    @Produces("application/xml")
    public class TransferService {
    
        @GET
        @Produces("application/xml")
        @Path("/transfer/{id}")
        public String accountTransfer(@PathParam("id") long id) {
            System.out.println("transfer id : "+id);
            StringBuilder response = new StringBuilder(256);
            response.append("<Response>").append("<id>").append(id)
            .append("</id>").append("<transfer>").append("250.00").append("</transfer>")
            .append("</Response>");
    
            return response.toString();
        }
    
    
    }
    
    http://localhost:8080/rest/account/balance/12
    http://localhost:8080/rest/transfer/balance/13
    
  3. ==============================

    3.당신은 아마도 루트 리소스를 비교하는 것과 같은 로직을 단순화 할 수 있습니다. 예를 들어, 요청 URI와 루트 리소스 클래스의 이름을 알면 결정을 내리기에 충분할 수 있습니다. 개별 메소드를 검사하는 것이 복잡해 보입니다. BTW에서 사용자 지정 리소스 비교자는 루트 리소스 및 / 또는 개별 리소스 메서드가 동등한 후보가 될 수있는 경우에만 필요합니다.

    당신은 아마도 루트 리소스를 비교하는 것과 같은 로직을 단순화 할 수 있습니다. 예를 들어, 요청 URI와 루트 리소스 클래스의 이름을 알면 결정을 내리기에 충분할 수 있습니다. 개별 메소드를 검사하는 것이 복잡해 보입니다. BTW에서 사용자 지정 리소스 비교자는 루트 리소스 및 / 또는 개별 리소스 메서드가 동등한 후보가 될 수있는 경우에만 필요합니다.

  4. ==============================

    4.나는이 방법으로 문제를 해결할 것이다.

    나는이 방법으로 문제를 해결할 것이다.

    그리고 그게 전부입니다. :)

  5. from https://stackoverflow.com/questions/9725770/multiple-resoucebean-configuration-in-cxf-using-spring by cc-by-sa and MIT license