1. 개요
라우팅은 Spring MVC 를 포함한 대부분의 웹 개발 프레임워크에서 나타나는 일반적인 개념입니다 .
경로는 처리기에 매핑되는 URL 패턴입니다. 핸들러는 웹 애플리케이션의 다운로드 가능한 자산과 같은 실제 파일이거나 MVC 애플리케이션의 컨트롤러와 같이 요청을 처리하는 클래스일 수 있습니다.
이 사용방법(예제)에서는 Play Framework 를 사용하여 웹 애플리케이션을 개발할 때 라우팅 측면을 살펴보겠습니다 .
2. 설정
먼저 Java Play 애플리케이션을 만들어야 합니다. 컴퓨터에서 Play 프레임워크를 설정하는 방법에 대한 자세한 내용은 소개 문서 에서 확인할 수 있습니다 .
설정이 끝나면 브라우저에서 액세스할 수 있는 작동하는 Play 애플리케이션이 있어야 합니다.
3. HTTP 라우팅
그렇다면 Play는 HTTP 요청을 보낼 때마다 참조할 컨트롤러를 어떻게 알 수 있을까요? 이 질문에 대한 답은 app/conf/routes 구성 파일에 있습니다.
Play의 라우터는 HTTP 요청을 작업 호출로 변환합니다. HTTP 요청은 MVC 아키텍처에서 이벤트로 간주되며 라우터는 어떤 컨트롤러에 대한 경로 파일과 실행할 해당 컨트롤러의 작업을 참조하여 이에 반응합니다.
이러한 각 이벤트는 쿼리 문자열이 포함된 요청 경로와 요청의 HTTP 메서드라는 두 가지 매개변수를 라우터에 제공합니다.
4. 플레이를 통한 기본 라우팅
라우터가 작업을 수행하려면 conf/routes 파일이 적절한 컨트롤러 작업에 대한 HTTP 메서드 및 URI 패턴의 매핑을 정의해야 합니다.
GET / controllers.HomeController.index
GET / assets/*file controllers.Assets.versioned(path="/public", file: Asset)
모든 경로 파일은 또한 /assets Endpoints 에서 클라이언트가 사용할 수 있는 play-routing/public 폴더 의 정적 리소스를 매핑해야 합니다 . HTTP 경로를 정의하는 구문과 HTTP 메서드 공간 URI 패턴 공간 컨트롤러 작업을 확인하십시오.
5. URI 패턴
이 섹션에서는 URI 패턴에 대해 조금 설명하겠습니다.
5.1. 정적 URI 패턴
위의 처음 세 URI 패턴은 정적입니다. 이는 컨트롤러 작업에서 추가 처리 없이 URL을 리소스에 매핑하는 것을 의미합니다.
컨트롤러 메서드가 호출되는 한 요청 전에 콘텐츠가 결정된 정적 리소스를 반환합니다.
5.2. 동적 URI 패턴
위의 마지막 URI 패턴은 동적입니다. 이는 이러한 URI에 대한 요청을 처리하는 컨트롤러 작업이 응답을 결정하기 위해 요청의 일부 정보가 필요함을 의미합니다. 위의 경우 파일 이름이 필요합니다.
정상적인 이벤트 순서는 라우터가 이벤트를 수신하고 URL에서 경로를 선택하고 해당 세그먼트를 디코딩하여 컨트롤러에 전달하는 것입니다.
그런 다음 경로 및 쿼리 매개변수가 컨트롤러 작업에 매개변수로 삽입됩니다. 다음 섹션에서 예제를 통해 이에 대해 설명하겠습니다.
6. 플레이를 통한 고급 라우팅
이 섹션에서는 동적 URI 패턴을 사용한 라우팅의 고급 옵션에 대해 자세히 설명합니다.
6.1. 단순 경로 매개변수
단순 경로 매개변수는 요청 URL에서 이름이 지정되지 않은 매개변수로, 호스트와 포트 뒤에 표시되며 나타나는 순서대로 구문 분석됩니다.
play-routing/app/HomeController.java 내부 에 새 작업을 생성해 보겠습니다.
public Result greet(String name) {
return ok("Hello " + name);
}
요청 URL에서 경로 매개변수를 선택하여 변수 이름에 매핑할 수 있기를 원합니다.
라우터는 경로 구성에서 해당 값을 가져옵니다.
이제 play-routing/conf/routes 를 열고 이 새 작업에 대한 매핑을 생성해 보겠습니다.
GET /greet/:name controllers.HomeController.greet(name: String)
이름이 콜론 구문을 사용하는 동적 경로 세그먼트임을 라우터에 알리고 이를 매개변수로 Greeting 액션 호출에 전달하는 방법에 주목하십시오.
이제 브라우저에 http://locahost:9000/greet/john 을 로드하면 이름이 표시됩니다.
Hello john
액션 매개변수가 문자열 유형인 경우 액션 호출 중에 매개변수 유형을 지정하지 않고 전달할 수 있지만 다른 유형의 경우에는 동일하지 않습니다.
나이 정보로 /greet Endpoints을 멋지게 꾸며 봅시다 .
HomeController 의 인사말 동작으로 돌아가서 다음과 같이 변경합니다.
public Result greet(String name, int age) {
return ok("Hello " + name + ", you are " + age + " years old");
}
그리고 경로:
GET /greet/:name/:age controllers.HomeController.greet(name: String, age: Integer)
변수 선언을 위한 Scala 구문 age: Integer 도 주목하십시오 . Java에서는 Integer age 구문을 사용합니다. Play 프레임워크는 Scala로 제작되었습니다. 결과적으로 많은 스칼라 구문이 있습니다.
http://localhost:9000/greet/john/26 을 로드하자 :
Hello john, you are 26 years old
6.2. 경로 매개변수의 와일드카드
경로 구성 파일에서 마지막 매핑은 다음과 같습니다.
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
경로의 동적 부분에 와일드카드를 사용합니다. 우리가 Play에게 말하는 것은 실제 요청에서 *file 을 대체하는 값이 무엇이든 경로 매개변수의 다른 경우처럼 디코딩되지 않고 전체적으로 구문 분석되어야 한다는 것입니다.
이 예에서 컨트롤러는 클라이언트가 play-routing/public 폴더 에서 파일을 다운로드할 수 있도록 하는 기본 제공 자산인 Assets 입니다. http://localhost:9000/assets/images/favicon.png 를 로드 하면 /public/images 폴더 에 Play 파비콘 이미지가 있으므로 브라우저에 Play 파비콘 이미지가 표시되어야 합니다.
HomeController.java 에서 우리만의 예제 액션을 만들어 봅시다 :
public Result introduceMe(String data) {
String[] clientData = data.split(",");
return ok("Your name is " + clientData[0] + ", you are " + clientData[1] + " years old");
}
이 작업에서 우리는 하나의 문자열 매개변수를 수신하고 이를 디코딩하기 위해 논리를 적용합니다. 이 경우 논리는 쉼표로 구분된 문자열 을 배열로 분할하는 것입니다. 이전에는 이 데이터를 해독하기 위해 라우터에 의존했습니다.
와일드 카드를 사용하면 우리는 우리 자신입니다. 우리는 클라이언트가 이 데이터를 전달하는 동안 구문이 정확하기를 바라고 있습니다. 이상적으로 는 수신 문자열을 사용하기 전에 유효성을 검사해야 합니다 .
이 작업에 대한 경로를 만들어 보겠습니다.
GET /*data controllers.HomeController.introduceMe(data)
이제 http://localhost:9000/john,26 URL을 로드합니다 . 다음과 같이 인쇄됩니다.
Your name is john, you are 26 years old
6.3. 경로 매개변수의 정규식
와일드카드와 마찬가지로 동적 부분에 정규식을 사용할 수 있습니다. 숫자를 받고 제곱을 반환하는 작업을 추가해 보겠습니다.
public Result squareMe(Long num) {
return ok(num + " Squared is " + (num * num));
}
이제 경로를 추가합니다.
GET /square/$num<[0-9]+> controllers.HomeController.squareMe(num:Long)
새로운 개념을 소개하기 위해 소개 경로 아래에 이 경로를 배치해 보겠습니다 . 이 라우팅 구성에서는 정규식 부분이 양의 정수인 경로만 처리할 수 있습니다.
이제 이전 단락에서 지시한 대로 경로를 배치하고 http://localhost:9000/square/2 를 로드 하면 ArrayIndexOutOfBoundsException 이 표시됩니다 .
서버 콘솔에서 오류 로그를 확인하면 action 호출이 실제로 squareMe 작업 이 아닌 IntroduceMe 작업에서 수행되었음을 알 수 있습니다. 앞서 와일드카드에 대해 말했듯이, 우리는 자체적으로 들어오는 데이터의 유효성을 검사하지 않았습니다.
쉼표로 구분된 문자열 대신 " square/2 "라는 문자열을 사용하여 소개 메서드가 호출되었습니다 . 결과적으로 분할한 후 크기가 1인 배열을 얻었습니다. 인덱스 1 에 도달하려고 하면 예외가 발생합니다.
당연히 우리는 호출이 squareMe 메서드로 라우팅될 것으로 예상할 것입니다. 왜 IntroductionMe 로 라우팅되었을까요 ? 그 이유는 라우팅 우선순위 라고 하는 다음에 다룰 재생 기능 때문입니다 .
7. 라우팅 우선순위
squareMe 와 insertMe 사이에 경로 사이에 충돌이 있는 경우 Play 는 선언 순서에서 첫 번째 경로를 선택합니다 .
왜 갈등이 있습니까? 와일드카드 컨텍스트 경로 /*data 때문에 기본 경로 / 이외의 모든 요청 URL과 일치합니다 . 따라서 URI 패턴이 와일드카드를 사용하는 모든 경로는 순서에서 마지막에 나타나야 합니다 .
이제 소개 경로가 squareMe 다음에 오도록 경로의 선언 순서를 변경 하고 다시 로드해 보겠습니다.
2 Squared is 4
경로에서 정규식의 성능을 테스트하려면 http://locahost:9000/square/-1 로드를 시도 하면 라우터가 squareMe 경로와 일치하지 않습니다. 대신, 소개 와 일치 하고 ArrayIndexOutOfBoundsException 을 다시 얻 습니다.
-1 은 제공된 정규식과 일치하지 않으며 어떤 알파벳도 일치하지 않기 때문 입니다.
8. 매개변수
지금까지 경로 파일에서 매개변수 유형을 선언하는 구문을 다루었습니다.
이 섹션에서는 경로의 매개변수를 처리할 때 사용할 수 있는 추가 옵션을 살펴보겠습니다.
8.1. 고정 값이 있는 매개변수
매개변수에 대해 고정된 값을 사용하고 싶을 때가 있습니다. 이것은 제공된 경로 매개변수를 사용하거나 요청 컨텍스트가 경로 / 인 경우 특정 고정 값을 사용하도록 Play에 지시하는 방법입니다.
그것을 보는 또 다른 방법은 동일한 컨트롤러 작업으로 이어지는 두 개의 Endpoints 또는 컨텍스트 경로를 갖는 것입니다. 하나의 Endpoints은 요청 URL의 매개 변수를 요구하고 해당 매개 변수가 없는 경우 다른 Endpoints으로 기본 설정됩니다.
이를 시연 하기 위해 HomeController 에 writer() 작업을 추가해 보겠습니다 .
public Result writer() {
return ok("Routing in Play by Baeldung");
}
API가 항상 String 을 반환하는 것을 원하지 않는다고 가정합니다 .
Routing in Play by Baeldung
요청에 저자 매개변수 가 없는 경우에만 고정 값 Baeldung 으로 기본 설정 하여 요청과 함께 기사 작성자의 이름을 전송하여 이를 제어하려고 합니다 .
이제 매개변수를 추가하여 작성기 작업을 추가 로 변경해 보겠습니다 .
public Result writer(String author) {
return ok("REST API with Play by " + author);
}
경로에 고정 값 매개변수를 추가하는 방법도 살펴보겠습니다.
GET /writer controllers.HomeController.writer(author = "Baeldung")
GET /writer/:author controllers.HomeController.writer(author: String)
이제 하나가 아닌 HomeController.index 작업 으로 이어지는 두 개의 개별 경로가 어떻게 생겼는지 확인하십시오.
이제 브라우저에서 http://localhost:9000/writer 를 로드하면 다음과 같은 결과가 나타납니다.
Routing in Play by Baeldung
그리고 http://localhost:9000/writer/john 을 로드하면 다음과 같은 결과 를 얻습니다.
Routing in Play by john
8.2. 기본값이 있는 매개변수
고정 값을 갖는 것 외에도 매개변수는 기본값을 가질 수도 있습니다. 둘 다 요청이 필수 값을 제공하지 않는 경우 컨트롤러 조치 매개변수에 폴백 값을 제공합니다.
둘 사이의 차이점은 고정 값이 경로 매개변수에 대한 폴백으로 사용되는 반면 기본값은 쿼리 매개변수에 대한 폴백으로 사용된다는 것 입니다.
경로 매개변수는 http://localhost:9000/param1/param2 형식이고 쿼리 매개변수는 http://localhost:9000/?param1=value1¶m2=value2 형식 입니다.
두 번째 차이점은 경로에서 둘을 선언하는 구문에 있습니다. 고정 값 매개변수는 다음과 같이 할당 연산자를 사용합니다.
author = "Baeldung"
기본값은 다른 유형의 할당을 사용하지만:
author ?= "Baeldung"
작성자 에 값이 없는 것으로 확인 된 경우 조건부로 Baeldung 을 작성자 에게 할당하는 ?= 연산자를 사용합니다 .
전체 데모를 보기 위해 HomeController.writer 작업을 만들어 보겠습니다. 예를 들어, 경로 매개변수인 작성자의 이름 외에도 요청에서 전달되지 않은 경우 기본적으로 1 이 되어야 하는 쿼리 매개변수로 작성자 ID 를 전달하려고 합니다 .
작성자 작업을 다음과 같이 변경 합니다.
public Result writer(String author, int id) {
return ok("Routing in Play by: " + author + " ID: " + id);
}
작가 는 다음으로 경로를 지정합니다.
GET /writer controllers.HomeController.writer(author="Baeldung", id: Int ?= 1)
GET /writer/:author controllers.HomeController.writer(author: String, id: Int ?= 1)
이제 http://localhost:9000/writer 를 로드하면 다음 을 볼 수 있습니다.
Routing in Play by: Baeldung ID: 1
http://localhost:9000/writer?id=10 을 누르면 다음이 제공됩니다.
Routing in Play by: Baeldung ID: 10
http://localhost:9000/writer/john 은 어떻 습니까?
Routing in Play by: john ID: 1
마지막으로 http://localhost:9000/writer/john?id=5 는 다음을 반환합니다.
Routing in Play by: john ID: 5
9. 결론
이 기사에서는 Play 애플리케이션의 라우팅 개념을 살펴보았습니다. 또한 이 사용방법(예제)의 라우팅 개념이 실제 예제에 적용되는 Play 프레임워크로 RESTful API 구축 에 대한 기사도 있습니다 .
늘 그렇듯이 이 예제의 소스 코드는 GitHub 에서 사용할 수 있습니다 .