1. 개요
LinkRest 는 데이터 기반 REST 웹 서비스를 구축하기 위한 오픈 소스 프레임워크입니다. JAX-RS 및 Apache Cayenne ORM 위에 구축되었으며HTTP/JSON 기반 메시지 프로토콜을 사용합니다.
기본적으로 이 프레임워크는 데이터 저장소를 웹에 쉽게 노출할 수 있는 방법을 제공하기 위한 것입니다.
다음 섹션에서는 LinkRest 를 사용하여 데이터 모델에 액세스하기 위해 REST 웹 서비스를 구축하는 방법을 살펴 보겠습니다 .
2. 메이븐 의존성
라이브러리 작업을 시작하려면 먼저 링크-레스트 의존성을 추가해야 합니다.
<dependency>
<groupId>com.nhl.link.rest</groupId>
<artifactId>link-rest</artifactId>
<version>2.9</version>
</dependency>
이것은 또한 cayenne-server 아티팩트를 가져옵니다.
또한 Jersey 를 JAX-RS 구현으로 사용하므로 JSON 응답을 직렬화하기 위해 jersey-container-servlet 의존성과 jersey-media-moxy 를 추가해야 합니다.
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.25.1</version>
</dependency>
이 예에서는 설정이 더 쉽기 때문에 메모리 내 H2 데이터베이스로 작업할 것입니다. 결과적으로 h2 도 추가합니다 .
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.196</version>
</dependency>
3. 카이엔 데이터 모델
작업할 데이터 모델에는 일대다 관계를 나타내는 부서 및 직원 엔터티가 포함됩니다.
언급한 바와 같이 LinkRest 는 Apache Cayenne ORM 을 사용하여 생성된 데이터 개체와 함께 작동합니다 . Cayenne 작업 은 이 기사의 주요 주제가 아니므로 자세한 내용은 Apache Cayenne 문서 를 확인하십시오 .
Cayenne 프로젝트를 cayenne-linkrest-project.xml 파일 에 저장 합니다.
cayenne-maven-plugin 을 실행한 후 두 개의 _Department 및 _Employee 추상 클래스 를 생성합니다. 이 클래스는 CayenneDataObject 클래스와 이들로부터 파생된 두 개의 구체적인 클래스인 Department 및 Employee 를 확장 합니다.
후자의 클래스는 LinkRest 와 함께 사용자 정의하고 사용할 수 있는 클래스 입니다.
4. LinkRest 애플리케이션 시작
다음 섹션에서는 REST Endpoints을 작성하고 테스트할 것이므로 실행하려면 런타임을 설정해야 합니다.
Jersey 를 JAX-RS 구현 으로 사용하고 있으므로 ResourceConfig 를 확장 하고 REST 엔드포인트를 정의하는 클래스를 보유할 패키지를 지정하는 클래스를 추가해 보겠습니다.
@ApplicationPath("/linkrest")
public class LinkRestApplication extends ResourceConfig {
public LinkRestApplication() {
packages("com.baeldung.linkrest.apis");
// load linkrest runtime
}
}
동일한 생성자에서 LinkRestRuntime 을 빌드하고 Jersey 컨테이너에 등록해야 합니다. 이 클래스는 CayenneRuntime 의 첫 번째 로드를 기반으로 합니다 .
ServerRuntime cayenneRuntime = ServerRuntime.builder()
.addConfig("cayenne-linkrest-project.xml")
.build();
LinkRestRuntime lrRuntime = LinkRestBuilder.build(cayenneRuntime);
super.register(lrRuntime);
마지막으로 web.xml 에 클래스를 추가해야 합니다 .
<servlet>
<servlet-name>linkrest</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.baeldung.LinkRestApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>linkrest</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
5. REST 리소스
이제 모델 클래스가 있으므로 REST 리소스 작성을 시작할 수 있습니다.
REST Endpoints은 표준 JAX-RS 어노테이션을 사용하여 생성되는 반면 응답은 LinkRest 클래스를 사용하여 빌드 됩니다 .
우리의 예는 다른 HTTP 방법을 사용하여 /department URL 에 액세스하는 일련의 CRUD Endpoints을 작성하는 것으로 구성됩니다 .
먼저 /department 에 매핑되는 DepartmentResource 클래스를 생성해 보겠습니다 .
@Path("department")
@Produces(MediaType.APPLICATION_JSON)
public class DepartmentResource {
@Context
private Configuration config;
// ...
}
LinkRest 클래스 에는 JAX-RS에서 제공하는 컨텍스트 어노테이션을 사용하여 삽입되는 JAX-RS 구성 클래스 의 인스턴스 가 필요합니다 .
다음으로 부서 개체 에 액세스하는 각 Endpoints을 계속 작성해 보겠습니다 .
5.1. POST를 사용하여 엔티티 생성
엔티티를 생성하기 위해 LinkRest 클래스는 UpdateBuilder 객체 를 반환하는 create() 메서드를 제공합니다.
@POST
public SimpleResponse create(String data) {
return LinkRest.create(Department.class, config).sync(data);
}
데이터 매개변수는 부서 를 나타내는 단일 JSON 개체 이거나 개체 배열일 수 있습니다. 이 매개변수는 sync() 메서드를 사용하여 UpdateBuilder 로 전송되어 하나 이상의 객체를 생성하고 레코드를 데이터베이스에 삽입한 후 메서드가 SimpleResponse 를 반환합니다 .
라이브러리는 응답에 대해 3가지 추가 형식을 정의합니다.
- DataResponse<T> – T 의 컬렉션을 나타내는 응답
- MetadataResponse<T> – 유형에 대한 메타데이터 정보를 포함합니다.
- SimpleResponse – 두 개의 성공 및 메시지 속성 을 포함하는 객체
다음으로 curl 을 사용하여 부서 레코드를 데이터베이스 에 추가해 보겠습니다.
curl -i -X POST -H "Content-Type:application/json"
-d "{"name":"IT"}" http://localhost:8080/linkrest/department
결과적으로 이 명령은 상태 201 Created 와 성공 속성을 반환합니다.
{"success":true}
JSON 배열을 전송하여 여러 개체를 만들 수도 있습니다.
curl -i -X POST -H "Content-Type:application/json"
-d "[{"name":"HR"},{"name":"Marketing"}]"
http://localhost:8080/linkrest/department
5.2. GET을 사용하여 엔티티 읽기
개체를 쿼리하는 기본 메서드 는 LinkRest 클래스 의 select() 메서드입니다 . 추가 쿼리 또는 필터링 메서드를 연결하는 데 사용할 수 있는 SelectBuilder 객체를 반환합니다 .
데이터베이스의 모든 부서 개체 를 반환 하는 DepartmentResource 클래스 에 엔드포인트를 생성해 보겠습니다 .
@GET
public DataResponse<Department> getAll(@Context UriInfo uriInfo) {
return LinkRest.select(Department.class, config).uri(uriInfo).get();
}
uri() 호출 은 SelectBuilder 에 대한 요청 정보를 설정하는 반면 get() 은 DataResponse<Department> 개체 로 래핑된 부서 컬렉션을 반환합니다.
이 Endpoints을 사용하기 전에 추가한 부서를 살펴보겠습니다.
curl -i -X GET http://localhost:8080/linkrest/department
응답은 데이터 배열과 총 속성 이 있는 JSON 개체의 형식을 취합니다 .
{"data":[
{"id":200,"name":"IT"},
{"id":201,"name":"Marketing"},
{"id":202,"name":"HR"}
],
"total":3}
또는 객체 컬렉션을 검색하기 위해 get () 대신 getOne() 을 사용하여 단일 객체를 반환할 수도 있습니다 .
주어진 ID를 가진 객체를 반환하는 /department/{departmentId} 에 매핑된 엔드포인트를 추가해 보겠습니다 . 이를 위해 byId() 메서드를 사용하여 레코드를 필터링합니다.
@GET
@Path("{id}")
public DataResponse<Department> getOne(@PathParam("id") int id,
@Context UriInfo uriInfo) {
return LinkRest.select(Department.class, config)
.byId(id).uri(uriInfo).getOne();
}
그런 다음 이 URL에 GET 요청을 보낼 수 있습니다.
curl -i -X GET http://localhost:8080/linkrest/department/200
결과는 하나의 요소가 있는 데이터 배열입니다.
{"data":[{"id":200,"name":"IT"}],"total":1}
5.3. PUT을 사용하여 엔티티 업데이트
레코드를 업데이트하려면 update() 또는 createOrUpdate() 메서드를 사용할 수 있습니다. 후자는 존재하는 경우 레코드를 업데이트하고 존재하지 않는 경우 생성합니다.
@PUT
public SimpleResponse createOrUpdate(String data) {
return LinkRest.createOrUpdate(Department.class, config).sync(data);
}
이전 섹션과 마찬가지로 데이터 인수는 단일 개체 또는 개체 배열일 수 있습니다.
이전에 추가한 부서 중 하나를 업데이트해 보겠습니다.
curl -i -X PUT -H "Content-Type:application/json"
-d "{"id":202,"name":"Human Resources"}"
http://localhost:8080/linkrest/department
이것은 성공 또는 오류 메시지와 함께 JSON 객체를 반환합니다. 그런 다음 ID가 202인 부서 이름이 변경되었는지 확인할 수 있습니다.
curl -i -X GET http://localhost:8080/linkrest/department/202
물론 이 명령은 새 이름을 가진 개체를 반환합니다.
{"data":[
{"id":202,"name":"Human Resources"}
],
"total":1}
5.4. DELETE 를 사용하여 엔티티 제거
그리고 개체를 제거하려면 DeleteBuilder 를 생성하는 delete() 메서드를 호출한 다음 id() 메서드 를 사용하여 삭제할 개체의 기본 키를 지정할 수 있습니다 .
@DELETE
@Path("{id}")
public SimpleResponse delete(@PathParam("id") int id) {
return LinkRest.delete(Department.class, config).id(id).delete();
}
그런 다음 curl 을 사용하여 이 Endpoints을 호출할 수 있습니다 .
curl -i -X DELETE http://localhost:8080/linkrest/department/202
5.5. 엔터티 간 관계 작업
LinkRest 에는 객체 간의 관계 작업을 보다 쉽게 해주는 메서드도 포함되어 있습니다.
Department 는 Employee 와 일대다 관계 이므로 EmployeeSubResource 클래스 에 액세스하는 /department/{departmentId}/employees 엔드포인트를 추가해 보겠습니다 .
@Path("{id}/employees")
public EmployeeSubResource getEmployees(
@PathParam("id") int id, @Context UriInfo uriInfo) {
return new EmployeeSubResource(id);
}
EmployeeSubResource 클래스 는 부서에 해당하므로 부서 ID를 설정하는 생성자와 구성 인스턴스를 갖습니다.
@Produces(MediaType.APPLICATION_JSON)
public class EmployeeSubResource {
private Configuration config;
private int departmentId;
public EmployeeSubResource(int departmentId, Configuration configuration) {
this.departmentId = departmentId;
this.config = config;
}
public EmployeeSubResource() {
}
}
개체를 JSON 개체로 직렬화하려면 기본 생성자가 필요합니다.
다음으로 부서에서 모든 직원을 검색하는 엔드포인트를 정의해 보겠습니다.
@GET
public DataResponse<Employee> getAll(@Context UriInfo uriInfo) {
return LinkRest.select(Employee.class, config)
.toManyParent(Department.class, departmentId, Department.EMPLOYEES)
.uri(uriInfo).get();
}
이 예제에서는 SelectBuilder 의 toManyParent() 메서드를 사용하여 지정된 부모가 있는 개체만 쿼리했습니다.
POST, PUT, DELETE 메서드의 Endpoints은 비슷한 방식으로 만들 수 있습니다.
직원을 부서에 추가하려면 POST 메서드를 사용 하여 departments/{departmentId}/employees 엔드포인트를 호출할 수 있습니다 .
curl -i -X POST -H "Content-Type:application/json"
-d "{"name":"John"}" http://localhost:8080/linkrest/department/200/employees
그런 다음 부서의 직원을 보기 위해 GET 요청을 보내겠습니다.
curl -i -X GET "http://localhost:8080/linkrest/department/200/employees
다음은 데이터 배열이 포함된 JSON 객체를 반환합니다.
{"data":[{"id":200,"name":"John"}],"total":1}
6. 요청 매개변수로 응답 사용자 지정
LinkRest 는 요청에 특정 매개 변수를 추가하여 응답을 사용자 지정하는 쉬운 방법을 제공합니다. 결과 집합의 속성 집합을 필터링, 정렬, 페이지 매기기 또는 제한하는 데 사용할 수 있습니다.
6.1. 필터링
cayenneExp 매개변수 를 사용하여 속성 값을 기반으로 결과를 필터링할 수 있습니다 . 이름에서 알 수 있듯이 Cayenne 식 의 형식을 따릅니다 .
이름이 "IT"인 부서만 반환하는 요청을 보내봅시다.
curl -i -X GET http://localhost:8080/linkrest/department?cayenneExp=name='IT'
6.2. 정렬
결과 세트를 정렬하기 위해 추가할 매개변수는 sort 및 dir 입니다. 이들 중 첫 번째는 정렬할 속성을 지정하고 두 번째는 정렬 방향을 지정합니다.
이름별로 정렬된 모든 부서를 살펴보겠습니다.
curl -i -X GET "http://localhost:8080/linkrest/department?sort=name&dir=ASC"
6.3. 쪽수 매기기
라이브러리는 시작 및 한계 매개변수를 추가하여 페이지 매김을 지원합니다.
curl -i -X GET "http://localhost:8080/linkrest/department?start=0&limit=2
6.4. 속성 선택
포함 및 제외 매개변수를 사용 하여 결과에 반환되는 속성 또는 관계를 제어할 수 있습니다.
예를 들어 부서 이름만 표시하는 요청을 전송해 보겠습니다.
curl -i -X GET "http://localhost:8080/linkrest/department?include=name
이름만 있는 부서의 직원과 이름을 표시하려면 include 속성을 두 번 사용할 수 있습니다.
curl -i -X GET "http://localhost:8080/linkrest/department?include=name&include=employees.name
7. 결론
이 기사에서는 LinkRest 프레임워크를 사용하여 REST Endpoints을 통해 데이터 모델을 신속하게 노출하는 방법을 보여주었습니다.
예제의 전체 소스 코드는 GitHub 에서 찾을 수 있습니다 .