어제 쥐팩 서버를 시작하고 동기식 Couchbase 리포지토리를 사용하는 대략적인 코드를 남겨드렸습니다. RxJava 부분입니다. 오늘은 이 문제를 해결하고 Ratpack에 대해서도 자세히 설명해드리려고 합니다. 아직 완전한 REST API를 보여드리지는 못하지만 곧 그렇게 될 것입니다.)
내 이전 예제를 사용하여 필요할 때마다 새 리포지토리 개체를 인스턴스화했습니다. 이 방식 때문에 매번 새로운 Cluter 연결이 열리기도 했습니다. Ratpack을 사용하면 레지스트리와 같이 이 문제를 피할 수 있는 방법이 있습니다.
쥐팩 레지스트리
쥐팩 레지스트리 에서 사용할 수 있는 객체 저장소입니다. 컨텍스트 를 추가합니다. 기본적으로 빈 레지스트리가 생성됩니다. 여기에 객체 인스턴스를 추가할 수 있습니다. 이러한 객체는 유형별로 검색됩니다. 이름을 지정할 수 없습니다. 즉, 레지스트리에 유형당 하나의 객체만 가질 수 있습니다. 이상하게 보일 수 있지만 실제로는 Groovy에서 코딩할 때 매우 유용합니다. 다음을 살펴보세요. 이 예제 를 예로 들 수 있습니다. 매우 읽기 쉽습니다.
제 코드에서는 레지스트리에 넣을 리포지토리 객체만 Couchbase에 액세스하기 위해 사용하고 있습니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public 정적 void 메인(문자열... args) 던지기 예외 { RatpackServer.시작(서버 -> 서버 .레지스트리(레지스트리 ->레지스트리.추가(카우치베이스클러스터.create().오픈버킷().저장소())) .핸들러(체인 -> 체인.경로("create", ctx -> { 엔티티도큐먼트<사용자> 문서 = 엔티티도큐먼트.create(new 사용자("ldoguin", 31, "Laurent", "도긴")); 차단.get(() -> { 리포지토리 repo = ctx.get(리포지토리.클래스); 반환 repo.업서트(문서); }).다음(엔티티독 -> ctx.렌더링("OK")); }).경로("get", ctx -> { 차단.get(() -> { 리포지토리 repo = ctx.get(리포지토리.클래스); 엔티티도큐먼트<사용자> ldoguin = repo.get("ldoguin", 사용자.클래스); 반환 ldoguin; }).다음(사용자 -> ctx.렌더링(사용자.콘텐츠().toString())); }))); } |
보시다시피 레지스트리에서 개체를 검색하는 것은 쉽습니다. get 메서드를 호출하고 객체의 유형을 매개변수로 전달하기만 하면 됩니다.
이것은 정말 가벼운 애플리케이션에 아주 잘 작동합니다. 좀 더 심각한 경우에는 가이드 모듈.
Guice 모듈
Ratpack은 단순한 비동기식 비차단 웹 서버가 아닙니다. 또한 새로운 기능을 우아하게 추가할 수 있는 포괄적인 모듈 세트이기도 합니다. DI 프레임워크를 사용하여 레지스트리를 쉽게 확장할 수 있습니다. Ratpack에서 가장 일반적으로 사용되는 프레임워크는 Guice이지만 Spring 또는 기타 지원되는 프레임워크를 사용할 수 있습니다. Guice 모듈을 활성화하려면 다음 코드를 추가해야 합니다. build.gradle
파일을 종속성에 추가합니다:
1 2 3 4 5 |
종속성 { 컴파일 쥐팩.종속성("guice"), "com.couchbase.client:java-client:2.2.5" } |
Ratpack에는 훌륭한 Gradle 통합 기능이 있습니다. 모든 Ratpack 모듈은 그렇게 간단하게 추가할 수 있습니다. 이제 Guice 지원이 활성화되었으므로 적절한 레지스트리 구성을 추가하는 것으로 시작할 수 있습니다. 레지스트리에 버킷과 리포지토리 인스턴스를 추가하겠습니다. 첫 번째 단계는 Guice를 확장하는 클래스를 추가하여 Guice 모듈을 만드는 것입니다. AbstractModule.
1 2 3 4 5 6 7 8 9 10 |
public 클래스 구성 확장 AbstractModule { 보호됨 void 구성() { 카우치베이스클러스터 cc = 카우치베이스클러스터.create(); 버킷 버킷 = cc.오픈버킷(); 바인드(버킷.클래스).toInstance(버킷); 바인드(리포지토리.클래스).toInstance(버킷.저장소()); } } |
이 클래스가 생성되면 다음과 같이 Ratpack 레지스트리에 추가해야 합니다:
1 2 |
RatpackServer.시작(서버 -> 서버.레지스트리(Guice.레지스트리(b -> b.모듈(구성.클래스))) |
이제 향후 인스턴스 주입을 위해 더 깔끔하게 구성할 수 있습니다. 하지만 모든 것이 여전히 동기식입니다. 그래서 이 구성을 비동기 버전의 버킷과 리포지토리를 사용하도록 변경하겠습니다:
1 2 3 4 5 6 7 8 9 10 |
public 클래스 구성 확장 AbstractModule { 보호됨 void 구성() { 카우치베이스클러스터 cc = 카우치베이스클러스터.create(); 버킷 버킷 = cc.오픈버킷(); 바인드(비동기 버킷.클래스).toInstance(버킷.비동기()); 바인드(비동기 저장소.클래스).toInstance(버킷.저장소().비동기()); } } |
다음 단계는 Ratpack에서 RxJava Observables를 사용할 수 있는지 확인하는 것입니다. 그리고 인생은 아름답기 때문에(어떤 이들은 부티풀하다고 말하겠지만) 이를 위한 모듈이 있습니다.
RxJava 모듈
그리고 RxJava 모듈 는 Rx Observables와 Ratpack Promises 사이의 가교를 만드는 것을 목표로 합니다. Guice 모듈처럼 적절한 종속성을 추가하여 쉽게 활성화할 수 있습니다:
1 2 3 4 5 6 |
종속성 { 컴파일 쥐팩.종속성("guice"), 쥐팩.종속성("rx"), "com.couchbase.client:java-client:2.2.5" } |
또한 JVM당 한 번씩 모듈을 초기화해야 합니다. 따라서 초기화를 실행하기에 가장 좋은 위치는 Ratpack 서버가 초기화되기 전입니다. 이 작업은 호출을 통해 수행할 수 있습니다:
1 2 |
RxRatpack.초기화(); |
RxRatpack 객체에는 관찰 가능/약속 변환을 수행하는 정적 메서드가 있습니다. 가장 간단한 것은 다음과 같이 작동합니다:
1 2 |
RxRatpack.약속(repo.업서트(문서)).다음(엔티티독 -> ctx.렌더링("OK")); |
Observable은 0부터 모든 요소를 포함할 수 있기 때문에 Promise 결과로 주어지면 List로 변환된다는 점을 언급할 필요가 있습니다. 따라서 Observable에 객체가 하나만 있는 경우 명시적으로 목록의 첫 번째 요소를 가져와야 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public 정적 void 메인(문자열... args) 던지기 예외 { RxRatpack.초기화(); RatpackServer.시작(서버 -> 서버.레지스트리(Guice.레지스트리(b -> b.모듈(구성.클래스))) .핸들러(체인 -> 체인.경로("create", ctx -> { 엔티티도큐먼트<사용자> 문서 = 엔티티도큐먼트.create(new 사용자("ldoguin", 31, "Laurent", "도긴")); 비동기 저장소 repo = ctx.get(비동기 저장소.클래스); RxRatpack.약속(repo.업서트(문서)).다음(엔티티독 -> ctx.렌더링("OK")); }).경로("get", ctx -> { 비동기 저장소 repo = ctx.get(비동기 저장소.클래스); RxRatpack.약속(repo.get("ldoguin", 사용자.클래스)) .다음(사용자 -> ctx.렌더링(사용자.get(0).콘텐츠().toString())); }))); } |
이전 버전과 달라진 점은 DI에 Guice 기반 레지스트리를 사용한다는 점과 이제 Couchbase 호출이 모두 비동기식이라는 점입니다. 이제 사용자를 위한 적절한 REST API를 만들기 시작할 수 있는 좋은 위치에 있습니다. 이 주제는 다른 블로그 게시물에서 다룰 예정입니다.