REST 로 가기: Spring 과 JAX - RS (Apache CXF) 에 Jetty 삽입

서버 핵심 자바 개발 자 들 에 게 세계 에 '보 여 주 는' 유일한 방법 은 API 를 사용 하 는 것 이다.오늘 게시 물 은 모두 JAX - RS 에 관 한 것 입 니 다. 자바 로 RESTful 서 비 스 를 작성 하고 공개 합 니 다.
그러나 저 희 는 응용 프로그램 서버, WAR 패키지 와 같은 전통 적 인 헤비급 방법 을 사용 하지 않 습 니 다.반면, 우 리 는 아주 좋 은 아파 치 CXF 프레임 워 크 를 사용 하고, 여전히 Spring 에 의존 하여 모든 구성 요 소 를 연결 할 것 이다.물론, 우 리 는 웹 서버 가 우리 의 서 비 스 를 실행 할 필요 가 있 기 때문에 멈 추 지 않 을 것 이다.뚱뚱 한 사람 이나 깡통 이라는 개념 을 사용 하여 우 리 는 Jetty 서버 를 우리 의 응용 프로그램 에 끼 워 넣 고 최종 JAR 을 다시 나 누 어 주 고 (모든 의존 항목 포함) 실행 할 수 있 도록 합 니 다.
이것 은 많은 일이 니까 우리 시작 합 시다.앞에서 말 한 바 와 같이 아파 치 CXF, Spring, Jetty 를 빌 드 블록 으로 사용 하기 때문에 POM 파일 에서 설명 합 니 다.특히 또 다른 의존 항 은 JSON 처리 에 뛰어난 잭 슨 라 이브 러 리 다.

    4.0.0

    com.example
    spring-one-jar
    0.0.1-SNAPSHOT
    jar

    
        UTF-8
        2.7.2
        3.2.0.RELEASE
        8.1.8.v20121106
    

       
        
            org.apache.cxf
            cxf-rt-frontend-jaxrs
            ${org.apache.cxf.version}
        

        
            javax.inject
            javax.inject
            1
        

        
            org.codehaus.jackson
            jackson-jaxrs
            1.9.11
        
     
        
            org.codehaus.jackson
            jackson-mapper-asl
            1.9.11
        
     
        
            cglib
            cglib-nodep
            2.2
        

        
            org.springframework
            spring-core
            ${org.springframework.version}
        

        
            org.springframework
            spring-context
            ${org.springframework.version}
        

        
            org.springframework
            spring-web
            ${org.springframework.version}
        
      
        
            org.eclipse.jetty
            jetty-server
            ${org.eclipse.jetty.version}
        
     
        
            org.eclipse.jetty
            jetty-webapp
            ${org.eclipse.jetty.version
          
    

    
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.0
                
                    1.6
                    1.6
                
              
            
                org.apache.maven.plugins
                maven-jar-plugin
                
                    
                        
                            com.example.Starter
                        
                    
                
            
            
                org.dstovall
                onejar-maven-plugin
                1.4.4
                
                    
                        
                            0.97
                            onejar
                        
                        
                            one-jar
                        
                    
                
            
        
    
    
    
        
            onejar-maven-plugin.googlecode.com
            http://onejar-maven-plugin.googlecode.com/svn/mavenrepo
        
    
 
    
        
            maven2-repository.dev.java.net
            http://download.java.net/maven/2/
        
    

그것 은 많은 것 이 있 지만 잘 알 것 이다.이제 간단 한 JAX - RS 앱 부터 첫 JAX - RS 서 비 스 를 개발 할 예정 이다.
package com.example.rs;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath( 'api' )
public class JaxRsApiApplication extends Application {
}

간단 해 보 입 니 다. 저희 프로그램 은 / api 를 JAX - RS 서비스의 입구 경로 로 정의 합 니 다.샘플 서 비 스 는 Person 류 가 대표 하 는 인원 을 관리 할 것 이다.
package com.example.model;

public class Person {
    private String email;
    private String firstName;
    private String lastName;

    public Person() {
    }

    public Person( final String email ) {
        this.email = email;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail( final String email ) {
        this.email = email;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setFirstName( final String firstName ) {
        this.firstName = firstName;
    }

    public void setLastName( final String lastName ) {
        this.lastName = lastName;
    } 
}

또한 기본 적 인 업무 서비스 (데이터베이스 나 다른 저장 소 는 포함 되 지 않 음) 를 따른다.
package com.example.services;

import java.util.ArrayList;
import java.util.Collection;

import org.springframework.stereotype.Service;

import com.example.model.Person;

@Service
public class PeopleService {
    public Collection< Person > getPeople( int page, int pageSize ) {
        Collection< Person > persons = new ArrayList< Person >( pageSize );

        for( int index = 0; index < pageSize; ++index ) {
            persons.add( new Person( String.format( 'person+%[email protected]', ( pageSize * ( page - 1 ) + index + 1 ) ) ) );
        }

        return persons;
    }

    public Person addPerson( String email ) {
        return new Person( email );
    }
}

보시 다시 피 요청 한 페이지 에 따라 인원 목록 을 동적 으로 생 성 합 니 다.표준 Spring 주석 @ Service 는 이러한 것 을 서비스 bean 으로 표시 합 니 다.우리 의 JAX - RS 서비스 인 People RestService 는 다음 코드 와 같이 검색 인원 을 사용 할 것 입 니 다.
package com.example.rs;

import java.util.Collection;

import javax.inject.Inject;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

import com.example.model.Person;
import com.example.services.PeopleService;

@Path( '/people' ) 
public class PeopleRestService {
    @Inject private PeopleService peopleService;

    @Produces( { 'application/json' } )
    @GET
    public Collection< Person > getPeople( @QueryParam( 'page') @DefaultValue( '1' ) final int page ) {
        return peopleService.getPeople( page, 5 );
    }

    @Produces( { 'application/json' } )
    @PUT
    public Person addPerson( @FormParam( 'email' ) final String email ) {
        return peopleService.addPerson( email );
    }
}

비록 매우 간단 하지만, 이 종 류 는 더 많은 설명 이 필요 하 다.우선, 우 리 는 / people 터미널 에 우리 의 RESTful 서 비 스 를 공개 해 야 합 니 다.이 를 / api (우리 의 JAX - RS 응용 프로그램 이 있 는 위치) 와 조합 하면 / api / people 을 한정 경로 로 제공 합 니 다.
이제 이 경로 에 HTTP GET 를 보 내 는 사람 이 있 으 면 getPeople 방법 을 사용 해 야 합 니 다.이 방법 은 선택 할 수 있 는 매개 변수 페이지 (기본 값 은 1) 를 받 아들 이 고 JSON 형식 으로 인원 목록 을 되 돌려 줍 니 다.반대로 같은 경로 로 HTTP PUT 를 보 내 는 사람 이 있 으 면 addPerson 방법 (필요 한 인자 email 사용) 을 호출 하고 JSON 형식 으로 new person 으로 돌아 가 야 합 니 다.
이제 애플 리 케 이 션 의 핵심 스프링 설정 을 살 펴 보 자.
package com.example.config;

import java.util.Arrays;

import javax.ws.rs.ext.RuntimeDelegate;

import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.example.rs.JaxRsApiApplication;
import com.example.rs.PeopleRestService;
import com.example.services.PeopleService;

@Configuration
public class AppConfig { 
    @Bean( destroyMethod = 'shutdown' )
    public SpringBus cxf() {
        return new SpringBus();
    }

    @Bean
    public Server jaxRsServer() {
        JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint( jaxRsApiApplication(), JAXRSServerFactoryBean.class );
        factory.setServiceBeans( Arrays.< Object >asList( peopleRestService() ) );
        factory.setAddress( '/' + factory.getAddress() );
        factory.setProviders( Arrays.< Object >asList( jsonProvider() ) );
        return factory.create();
    }

    @Bean 
    public JaxRsApiApplication jaxRsApiApplication() {
        return new JaxRsApiApplication();
    }

    @Bean 
    public PeopleRestService peopleRestService() {
        return new PeopleRestService();
    }

    @Bean 
    public PeopleService peopleService() {
        return new PeopleService();
    }

    @Bean
    public JacksonJsonProvider jsonProvider() {
        return new JacksonJsonProvider();
    }
}

복잡 해 보이 지 는 않 지만 백 스테이지 에 서 는 많은 일이 벌 어 졌 다.향료 로 분해 합 시다.이곳 의 두 가지 핵심 구성 요 소 는 공장 JAXRSServerFactory Bean 입 니 다. 이것 은 우리 의 JAX - RS 서버 인 스 턴 스 를 설정 하기 위해 모든 힘 든 작업 을 제 공 했 고, SpringBus 인 스 턴 스 는 Spring 과 Apache CXF 를 빈 틈 없 이 붙 였 습 니 다.모든 다른 구성 요 소 는 일반적인 Spring Bean 을 대표 합 니 다.
사진 에는 Jetty 웹 서버 인 스 턴 스 가 삽입 되 어 있 지 않 습 니 다.우리 의 주요 응용 프로그램 인 스타 터 는 바로 이렇게 한다.
package com.example;

import org.apache.cxf.transport.servlet.CXFServlet;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

import com.example.config.AppConfig;

public class Starter {
    public static void main( final String[] args ) throws Exception {
        Server server = new Server( 8080 );

        // Register and map the dispatcher servlet
        final ServletHolder servletHolder = new ServletHolder( new CXFServlet() );
        final ServletContextHandler context = new ServletContextHandler();   
        context.setContextPath( '/' );
        context.addServlet( servletHolder, '/rest/*' );  
        context.addEventListener( new ContextLoaderListener() );

        context.setInitParameter( 'contextClass', AnnotationConfigWebApplicationContext.class.getName() );
        context.setInitParameter( 'contextConfigLocation', AppConfig.class.getName() );

        server.setHandler( context );
        server.start();
        server.join(); 
    }
}

이 코드 를 보 니 포트 8080 에서 Jetty 서버 인 스 턴 스 를 실행 하고 있 습 니 다. 아파 치 CXF servlet 을 설정 하여 / rest / * 경로 의 모든 요청 (JAX - RS 응용 프로그램 과 서비스 와 함께 / rest / api / people 을 제공 합 니 다) 을 처리 하고 있 습 니 다. 위 에서 정의 한 설정 을 사용 하여 파라미터 화 된 Spring 컨 텍스트 디텍터 를 추가 하 였 습 니 다.마지막 으로 서버 를 시 작 했 습 니 다.이때 우리 가 가 진 것 은 우리 의 JAX - RS 서 비 스 를 위탁 관리 하 는 기능 이 완벽 한 웹 서버 다.그것 의 작용 을 좀 봅 시다.우선, 우 리 는 그것 을 하나의, 운행 가능 하고 재배 치 가능 한 지방 또는 항아리 로 포장 합 니 다.
mvn clean package

대상 폴 더 에서 위 치 를 주 워 서 실행 합 니 다.
java -jar target/spring-one-jar-0.0.1-SNAPSHOT.one-jar.jar

우 리 는 이러한 출력 을 보아 야 한다.
2013-01-19 11:43:08.636:INFO:oejs.Server:jetty-8.1.8.v20121106
2013-01-19 11:43:08.698:INFO:/:Initializing Spring root WebApplicationContext
Jan 19, 2013 11:43:08 AM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization started
Jan 19, 2013 11:43:08 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing Root WebApplicationContext: startup date [Sat Jan 19 11:43:08 EST 2013]; root of context hierarchy
Jan 19, 2013 11:43:08 AM org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
INFO: JSR-330 'javax.inject.Named' annotation found and supported for component scanning
Jan 19, 2013 11:43:08 AM org.springframework.web.context.support.AnnotationConfigWebApplicationContext loadBeanDefinitions
INFO: Successfully resolved class for [com.example.config.AppConfig]
Jan 19, 2013 11:43:09 AM org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor 
INFO: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
Jan 19, 2013 11:43:09 AM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1f8166e5: 
defining beans [org.springframework.context.annotation.internal
ConfigurationAnnotationProcessor,
org.springframework.context.annotation.internalAutowiredAnnotationProcessor,
org.springframework.context.annotation.internalRequiredAnnotationProces
sor,org.springframework.context.annotation.internalCommonAnnotationProcessor,appConfig,
org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,c
xf,jaxRsServer,jaxRsApiApplication,peopleRestService,peopleService,jsonProvider]; root of factory hierarchy
Jan 19, 2013 11:43:10 AM org.apache.cxf.endpoint.ServerImpl initDestination
INFO: Setting the server's publish address to be /api
Jan 19, 2013 11:43:10 AM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization completed in 2227 ms
2013-01-19 11:43:10.957:INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
2013-01-19 11:43:11.019:INFO:oejs.AbstractConnector:Started [email protected]:8080

모든 것 이 예상 한 대로 실 행 될 수 있 도록 서버 를 시작 하고 실행 합 니 다.
> curl http://localhost:8080/rest/api/people?page=2
[
  {'email':'[email protected]','firstName':null,'lastName':null},
  {'email':'[email protected]','firstName':null,'lastName':null},
  {'email':'[email protected]','firstName':null,'lastName':null}, 
  {'email':'[email protected]','firstName':null,'lastName':null}, 
  {'email':'[email protected]','firstName':null,'lastName':null}
]

> curl http://localhost:8080/rest/api/people -X PUT -d '[email protected]'
{'email':'[email protected]','firstName':null,'lastName':null}

너무 좋아요!그리고 우 리 는 XML 을 전혀 사용 하지 않 습 니 다!소스 코드: https: / / github. com / reta / spring - one - jar / tree / jetty - embedded
이 글 을 끝내기 전에 저 는 아주 좋 은 프로젝트 인 Dropwizard 를 언급 하고 싶 습 니 다. 비슷 한 개념 을 사 용 했 지만 Yammer 의 지원 으로 훌륭 하고 심혈 을 기울 여 디자인 한 프레임 워 크 로 밀 어 붙 였 습 니 다.
참고: REST 로 가기: Andriy Redko {devmind} 블 로그 에 JCG 파트너 Andrey Redko 에서 Spring 과 JAX - RS (Apache CXF) 의 Jetty 를 삽입 합 니 다.
번역https://www.javacodegeeks.com/2013/01/going-rest-embedding-jetty-with-spring-and-jax-rs-apache-cxf.html

좋은 웹페이지 즐겨찾기