요청 URI 매칭
클라이언트가 요청한 URL과 @RequestMapping 어노테이션의 값을 이용해서 클라이언트의 요청을 어떤 컨트롤러의 어떤 메서드가 처리할 지가 결정된다.
매칭이 어떻게 이루어지는 지 알지 못할 경우 클라이언트의 요청 URL과 매칭되는 메서드를 설정할 수 없기 때문에, 어떻게 매칭이 이루어지는 지 아는 것은 작지만 매우 중요하다.
본 절에서는 매칭과 관련된 기본 내용인 경로와 @RequestMapping 어노테이션 간의 관계 그리고 @PathVariable을 이용한 URI 템플릿에 대해서 살펴보자.
1. 전체 경로와 서블릿 기반 경로 매칭 설정
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
<url-pattern>/game/*</url-pattern>
</servlet-mapping>
위 코드는 *.do로 오는 요청과 /game/으로 오는 요청을 dispatcher 서블릿이 처리하도록 설정하고 있다. 이 경우 다음의 두 @RequestMapping은 어떻게 할까?
@RequestMapping("/search/game.do")
public String search(...){
...
}
/search/game.do 요청은 <url-pattern>이 ".do"인 확장자 기반의 매칭이 되므로 서블릿 경로가 ""가 된다. 따라서, /search/game.do"이므로 요청은 값이 "search/game.do"인 @RequestMapping 어노테이션과 매칭된다.
@RequestMapping("/game/info")
public String info(...){
...
}
info() 메서드는 /game/info요청을 처리하지 않는다. 서블릿 매핑 설정에서 <url-pattern> 의 값을 "/game/*" 으로 설정했기 때문이다.
<url-pattern>의 값으로 디렉터리를 포함한 패턴을 지정하게 되면 서블릿 경로는 "/game"이 되며, 서블릿 경로를 제외한 나머지 경로를 이용해서 @RequestMapping 어노테이션의 값과 매칭 여부를 판단하게 되므로,
실제 비교할 때 사용되는 요청 URI는 "/info"가 된다. @RequestMapping 어노테이션의 값은 "/game/info" 이므로 비교할 요청 URI인 "info"와는 매칭되지 않는다.
- @RequestMapping: 어노테이션의 값으로(템플릿 변수)
- @PathVariable: 어노테이션을 이용해서{템플릿 변수}와 동일한 이름을 갖는 파라미터를 추가한다.
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class CharacterInfoController {
@RequestMapping("/game/users/{userId}/chracters/{chracterId}")
public String characterInfo(@PathVariable String userId/*madvirus*/, @PathVariable int characterId /*1*/, ModelMap model) {
model.addAttribute("userId", userId);
model.addAttribute("characterId", characterId);
return "game/character/info";
}
}
위 코드를 보면 @RequestMapping 어노테이션은 이름이 uesrId와 characterId인 변수를 포함하고 있다. 이들 변수는 @PathVariable 어노테이션이 적용된 동일한 이름을 갖는 파라미터에 매칭된다. 따라서 요청 URI가 "/game/users/madivirus/character/1"이면, characterInfo() 메서드의 userId 파라미터와 chracterId 파라미터의 값은 각각 "madvirus"와 1이 된다.
만약 파라미터 이름과 URI 템플릿의 변수 이름이 동일하지 않다면, 다음과 같이 @PathVariable에 매칭될 템플릿 변수 이름을 지정해주면 된다.
@RequestMapping("/game/users/{userId}")
public String userInfo(@PathVariable("userId") String id, ModelMap model){ //userId != id
...
}
3. @RequestMapping 어노테이션의 추가 설정 방법
@RequestMapping 어노테이션을 클래스와 메서드에 함께 적용할 경우, 메서드에 적용한 @RequestMapping 어노테이션의 값은 클래스에 적용한 @RequestMapping 어노테이션의 값은 클래스에 적용한 @RequestMapping 어노테이션의 값을 기본 경로로 사용하게 된다.
@Controller
@RequestMapping("/game/users/{userId}")
public class CharacterInfoController {
@RequestMapping("/characters/{characterId}")
public String characterInfo(@PathVariable String userId,
@PathVariable int characterId, ModelMap model) {
model.addAttribute("userId", user Id);
model.addAttribute("characterId", characterId);
return "game/character/info";
}
}
위 코드에서 characterInfo() 메서드에 적용된 @RequestMapping 어노테이션의 값은 "/chracters/{characterId}"인데, 실제로 매칭되는 값은 클래스에 적용된 @RequestMapping 어노테이션의 값을 포함한 "/game/users/{userId}/chracters/{chracterId}"가 된다.
cf.) @RequestMapping 어노테이션은 Ant 스타일의 패턴을 지원한다. 따라서, "*"나 "**"를 값으로 사용할 수 있다.
- ?: 1개의 문자와 매칭
- *: 0개 이상의 문자와 매칭
- **: 0개 이상의 디렉터리와 매칭
'Spring' 카테고리의 다른 글
[Spring] JDBC (0) | 2018.11.27 |
---|---|
[Spring] 기본2 (0) | 2018.11.27 |
[Spring] @RequestBody / @ResponseBody (0) | 2018.11.27 |
[Spring] ViewResolver (0) | 2018.11.27 |
[Spring] 기본 (0) | 2018.11.27 |