본문 바로가기
Spring

@RequestMapping 핸들러 매핑

by 자바초보자 2015. 10. 8.
728x90

@RequestMapping 핸들러 매핑

@RequestMapping 핸들러 매핑
@MVC의 핸들러 매핑을 위해서는 DefaultAnnotationHandlerMapping이 필요하다.
디폴트 핸들러 매핑이므로 다른 핸들러 매핑을 등록하지 않았다면 기본으로 사용 가능.
(다른 핸들러 매핑을 등록했다면 디폴트가 자동 적용되지 않으므로 빈 설정이 필요함)
@RequestMapping 어노테이션의 엘리먼트
· String[] value():URL 패턴
- 디폴트 엘리먼트
- 요청의 URL 패턴을 지정해서 매핑
@RequestMapping("/hello")
@RequestMapping({"/hello", "/hello/", "/hello.*"})
// path variable 사용 가능{}
@RequestMapping("main*")
@RequestMapping("/view.*")
@RequestMapping("/admin/**/user")
· RequestMethod[] method:HTTP 메소드
- HTTP 메소드를 정의한 enum
- GET, POST, HEAD, PUT, DELETE, OPTIONS, TRACE 7개의 HTTP 메소드가 정의되어 있다.
- 같은 URL이라도 요청 메소드에 따라 다른 메소드에 매핑 가능
@RequestMapping(value="/user/add", method=RequestMethod.GET)
@RequestMapping(value="/user/add", method=RequestMethod.POST)
요청 방식이 GET 방식일 때는 첫번째에, POST 방식일 때는 두번째에 매핑된다.
위의 두가지 매핑 설정만 있는 경우라면, GET이나 POST 방식 이외의 요청이 들어올 경우
HTTP 405 - Method Not Allowed 응답을 받게 됨.
- 타입 레벨에는 URL만 주고 메소드 레벨에는 HTTP 요청 메소드만 지정하는 방법
@RequestMapping(method="RequestMethod.GET)
- 단일 URL에 대해 다양한 HTTP 메소드(GET, POST, PUT, DELETE)를 적용하는 RESTful 스타일의 접근 방법
HTML 폼에서는 GET과 POST만 지원
자바스크립트나 스프링이 지원하는<form:form>를 이용해서 히든 필드를 통해
HTTP 메소드(PUT, DELETE 등)를 전달할 수 있다.
· String[] params():요청 파라미터
- 요청의 파라미터와 그 값을 비교해서 매핑
- 같은 URL을 사용하더라도 파라미터에 따라 별도의 작업
@RequestMapping(value="/user/edit", params="type=admin") // ①
@RequestMapping(value="/user/edit", params="type=admin") // ②
@RequestMapping("/user/edit") // ③
요청이 /user/edit?type="admin"으로 들어왔을 때,
①에 매핑된다.
왜? ③보다 더 상세한 조건을 만족한 ①이 선택된다.
- 꼭 URL에 포함된 파라미터만 비교하는건 아니다.
POST 방식으로 전송한 파라미터도 비교 대상이다.
단, method=RequestMethod.GET/POST를 지정하지 않았을 경우
- 특정 파라미터가 존재하지 않아야 한다는 조건도 지정 가능
@RequestMapping(value="/user/edit", params="!type")
· String[] headers():HTTP 헤더
- HTTP의 헤더 정보를 가져와 비교해서 매핑
- params와 비슷하게 '헤더이름 = 값'의 형식 사용
@RequestMapping(value="/view", headers="context-type=text/*")
context-type이 text/html이나 text/plan 등으로 되어 있는 경우에 매핑
타입 레벨 매핑과 메소드 레벨 (타입 레벨 = class 또는 interface, 메소드 레벨 = method)
· 타입 레벨 + 메소드 레벨 매핑
- 타입 레벨에 붙는 @RequestMapping은
타입 내의 모든 매핑용 메소드의 공통 조건을 지정할 때 사용
메소드 레벨에서 조건을 세분화
- 메소드 레벨의 매핑은 클래드 레벨의 매핑을 상속 받는다.
ex) user/add, user/edit, user/delete라는 URL에 매핑
@RequestMapping("/user")
public class UserController {
@RequestMapping("/add") public String add(){ ... }
@RequestMapping("/edit") public String edit(){ ... }
@RequestMapping("/delete") public String delete(){ ... }
}
- URL 패턴에 *이나 **을 사용가능
@RequestMapping("/user/*")
public class UserController {
@RequestMapping("/add") public String add(){ ... }
}
// =>/user/add로 결합
@RequestMapping("/user/**")
public class UserController {
@RequestMapping("/add") public String add(){ ... }
}
// =>/user/**/add로 결합
@RequestMapping("/user" 또는 "/user/" 또는 "/user/*")
public class UserController {
@RequestMapping("add") public String add(){ ... }
}
// =>/user/add로 결합 (직관적이지 않아서 비추)
- 메소드 레벨에서 다른 매핑 정보를 추가해서 사용 가능(methods라든지 params 등)
@RequestMapping("/user/add")
public class UserController {
@RequestMapping(methods=RequestMethod.GET) public String form(){ ...}
@RequestMapping(methods=RequestMethod.POST) public String submit(){... }
}
· 메소드 레벨 단독 매핑
- 타입 레벨에서 공통점이 없다면 굳이 타입, 메소드 레벨을 결합하지 않아도 된다.
- 타입 레벨에 조건 없는 @RequestMapping을 붙여두고,
메소드 레벨마다 다른 @ReqeustMapping 조건을 선언하면 된다.
주의!
타입 레벨에 @RequestMapping을 생각하면 클래드 자체가 매핑 되지 않으니 반드시 선언한다.
@RequestMapping
public class UserController {
@RequestMapping("/hello") public String hello(){ ... }
@RequestMapping("/main") public String main(){ ... }
}
- 컨트롤러 클래스에 @Controller 어노테이션을 붙여서 빈 자동스캔 방식으로 등록되게 했다면
클래스 레벨의 @RequestMapping을 생략할 수 있다.
@Controller
public class UserController {
@RequestMapping("/hello") public String hello(){ ... }
@RequestMapping("/main") public String main(){ ... }
}
· 타입 레벨 단독 매핑
- 핸들러 매핑은 원래 핸들러 오브젝트를 결정하는 전략.
다른 타입 컨트롤러와의 일관성을 위해 오브젝트까지만 매핑하고
최종 실행할 메소드는 핸들러 어댑터가 선정하게 하기 위해서 사용
@RequestMapping("/hello")
public class helloController implements Controller { ... }
- 원칙적으로 핸들러 매핑과 핸들러 어댑터는 독립적으로 조합될 수 있기 때문에 적용 가능한 방법
- 클래스 레벨의 URL 패턴이 /*로 끝나는 경우
메소드 이름이 메소드 레벨의 URL 패턴으로 사용되게 할 수 있다.
@RequestMapping("/user/*")
public class UserController {
@RequestMapping public string add(){ ... }
@RequestMapping public string edit(){ ... }
}
// 각각 /user/add와 /user/edit로 매핑된다.
타입 상속과 매핑
@RequestMapping이 적용된 클래스를 상속해서
컨트롤러로 사용하는 경우
수퍼클래스의 매핑 정보는 어떻게 됨?
타입 상속에 관한 대원칙 2가지.
1. @RequestMapping 정보는 상속된다.
2. 단, 서브 클래스에서 @RequestMapping을 재정의 하면 수퍼클래스의 정보는 무시된다.
인터페이스 구현의 의한 @ReqeustMapping 정보 상속은
클래스 상속과 거의 비슷하지만
몇가지 차이점이 있다.
· 상위 타입과 메소드의 @RequestMapping 상속
- 수퍼 클래스의 매핑 정보 상속
// Super
@RequestMapping("/user") public class Super {
@RequestMapping("/list") public string list(){ ... }
}
//Sub
public class Sub extends Super {}
결과
모두 상속
Sub 클래스를 컨트롤러로 등록하면, /user/list URL은 list() 메소드로 매핑
- 메소드 오버라이드
//Sub
public class Sub extends Super {
public String list(){ ... }
}
결과
메소드를 오버라이드했더라도
메소드에 @RequestMapping을 붙이지 않는다면
수퍼 클래스 메소드의 매핑 정보는 그대로 상속된다.
인터페이스의 경우도 마찬가지
· 상위 타입의 @RequestMapping과 하위 타입 메소드의 @RequestMapping 결합
- 상위 타입과 하위 메소드 정보의 결합
//Super
@RequestMapping("/user") public class Super {}
//Sub
public class Sub extends Super {
@RequestMapping("/list") public String list(){ ... }
}
결과
마찬가지로 /user/list URL은 list() 메소드로 매핑
매핑정보 결합은 URL 뿐 아니라, HTTP 메소드, 파라미터에도 적용된다.
인터페이스의 경우도 마찬가지
· 상위 타입 메소드의 @RequestMapping과 하위 타입의 @RequestMapping 결합
- 상위 메소드와 하위 타입의 결합
//Super
public class Super {
@RequestMapping("/list") public String list(){ ... }
}
//Sub
RequestMapping("/user") public class Sub extends Super {}
결과
마찬가지로 /user/list는 Sub가 상속받은 list() 메소드에 매핑된다.
주의
인터페이스의 경우도 동일한 방식으로 적용된다.
단, 인터페이스를 구현하는 메소드에
URL이 없는 빈 @RequestMapping을 붙이면
인터페이스 메소드의 매핑정보가 무시된다.
· 하위 타입과 메소드의 @RequestMapping 재정의
- 타입 레벨의 매핑정보 재정의
// Super
@RequestMaping("/user") public class Super {
@RequestMapping(value="/catalog", methods=RequestMethod.POST)
public String list() { ... }
}
// Sub
@RequestMapping("/user") public class Sub extends Super {
@RequestMapping("/list") public String list() { ... }
}
결과
@RequestMapping을 재정의하는 경우에는 상위 타입에서 정의한 정보와 결합되지 않는다.
Sub를 컨트롤러로 등록하면 /user/list 요청에 대한 메소드 매핑은 Sub의 list() 메소드에 매핑된다.
· 서브클래스 메소드의 URL 패턴 없은 @RequestMapping 재정의
- 하위 타입의 @RequestMapping은 항상 상위 타입의 @RequestMapping 정보를 대신한다.
- 하지만 클래스 상속에서 오버라이드한 하위 메소드에 한해서는
URL 조건이 없는 @RequestMapping을 붙였을 경우
상위 메소드의 @RequestMapping의 URL 조건이 그대로 상속된다.
[출처] [스프링 @MVC] @RequestMapping 핸들러 매핑|작성자 하얀늑대
출처 : http://blog.naver.com/comkwang17?Redirect=Log&logNo=140182037265
728x90