반응형

@MVC의 핸들러 매핑을 위해서는 DefaultAnnotationHandlerMapping이 필요하다. 

디폴트 핸들러 매핑이므로 다른 핸들러 매핑을 등록하지 않았다면 기본으로 사용 가능.

(다른 핸들러 매핑을 등록했다면 디폴트가 자동 적용되지 않으므로 빈 설정이 필요함)

 

@RequestMapping 어노테이션의 엘리먼트

 · String[] value():URL 패턴

 - 디폴트 엘리먼트

 

 - 요청의 URL 패턴을 지정해서 매핑

  1. @RequestMapping("/hello")
  2. @RequestMapping({"/hello""/hello/""/hello.*"})
  3. // path variable 사용 가능{}
  4. @RequestMapping("main*")
  5. @RequestMapping("/view.*")
  6. @RequestMapping("/admin/**/user")

 

 · RequestMethod[] method:HTTP 메소드

 - HTTP 메소드를 정의한 enum

 

 - GET, POST, HEAD, PUT, DELETE, OPTIONS, TRACE 7개의 HTTP 메소드가 정의되어 있다.

 

 - 같은 URL이라도 요청 메소드에 따라 다른 메소드에 매핑 가능

  1. @RequestMapping(value="/user/add", method=RequestMethod.GET)
  2. @RequestMapping(value="/user/add", method=RequestMethod.POST)

  요청 방식이 GET 방식일 때는 첫번째에, POST 방식일 때는 두번째에 매핑된다.

  위의 두가지 매핑 설정만 있는 경우라면, GET이나 POST 방식 이외의 요청이 들어올 경우

  HTTP 405 - Method Not Allowed 응답을 받게 됨.

 

 - 타입 레벨에는 URL만 주고 메소드 레벨에는 HTTP 요청 메소드만 지정하는 방법

  1. @RequestMapping(method="RequestMethod.GET)

 

 - 단일 URL에 대해 다양한 HTTP 메소드(GET, POST, PUT, DELETE)를 적용하는 RESTful 스타일의 접근 방법

  HTML 폼에서는 GET과 POST만 지원

  자바스크립트나 스프링이 지원하는 <form:form>를 이용해서 히든 필드를 통해

  HTTP 메소드(PUT, DELETE 등)를 전달할 수 있다.

 

 · String[] params():요청 파라미터

 - 요청의 파라미터와 그 값을 비교해서 매핑

 

 - 같은 URL을 사용하더라도 파라미터에 따라 별도의 작업

  1. @RequestMapping(value="/user/edit", params="type=admin") // ①
  2. @RequestMapping(value="/user/edit", params="type=admin") // ②
  3. @RequestMapping("/user/edit")                            // ③

  요청이 /user/edit?type="admin"으로 들어왔을 때,

  ①에 매핑된다.

  왜? ③보다 더 상세한 조건을 만족한 ①이 선택된다.

 

 - 꼭 URL에 포함된 파라미터만 비교하는건 아니다.

  POST 방식으로 전송한 파라미터도 비교 대상이다.

  단, method=RequestMethod.GET/POST를 지정하지 않았을 경우

 

 - 특정 파라미터가 존재하지 않아야 한다는 조건도 지정 가능

  1. @RequestMapping(value="/user/edit", params="!type")

 

 · String[] headers():HTTP 헤더

 - HTTP의 헤더 정보를 가져와 비교해서 매핑

 

 - params와 비슷하게 '헤더이름 = 값'의 형식 사용

  1. @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에 매핑

  1. @RequestMapping("/user")
  2. public class UserController {
  3.     @RequestMapping("/add") public String add(){ ... }
  4.     @RequestMapping("/edit") public String edit(){ ... }
  5.     @RequestMapping("/delete") public String delete(){ ... }
  6. }

 

 - URL 패턴에 *이나 **을 사용가능

  1. @RequestMapping("/user/*")
  2. public class UserController {
  3.     @RequestMapping("/add") public String add(){ ... }
  4. }
  5. // => /user/add로 결합
  6.  
  7. @RequestMapping("/user/**")
  8. public class UserController {
  9.     @RequestMapping("/add") public String add(){ ... }
  10. }
  11. // => /user/**/add로 결합
  12.  
  13. @RequestMapping("/user" 또는 "/user/" 또는 "/user/*")
  14. public class UserController {
  15.     @RequestMapping("add") public String add(){ ... }
  16. }
  17. // => /user/add로 결합 (직관적이지 않아서 비추)

 

 - 메소드 레벨에서 다른 매핑 정보를 추가해서 사용 가능(methods라든지 params 등)

  1. @RequestMapping("/user/add")
  2. public class UserController {
  3.   @RequestMapping(methods=RequestMethod.GET) public String form(){ ...}
  4.   @RequestMapping(methods=RequestMethod.POST) public String submit(){... }
  5. }

 

 · 메소드 레벨 단독 매핑

 - 타입 레벨에서 공통점이 없다면 굳이 타입, 메소드 레벨을 결합하지 않아도 된다.

 

 - 타입 레벨에 조건 없는 @RequestMapping을 붙여두고,

    메소드 레벨마다 다른 @ReqeustMapping 조건을 선언하면 된다.

    주의!

    타입 레벨에 @RequestMapping을 생각하면 클래드 자체가 매핑 되지 않으니 반드시 선언한다.

  1. @RequestMapping
  2. public class UserController {
  3.     @RequestMapping("/hello") public String hello(){ ... }
  4.     @RequestMapping("/main") public String main(){ ... }
  5. }

 

 - 컨트롤러 클래스에 @Controller 어노테이션을 붙여서 빈 자동스캔 방식으로 등록되게 했다면

    클래스 레벨의 @RequestMapping을 생략할 수 있다.

  1. @Controller
  2. public class UserController {
  3.     @RequestMapping("/hello") public String hello(){ ... }
  4.     @RequestMapping("/main") public String main(){ ... }
  5. }

 

 · 타입 레벨 단독 매핑

 - 핸들러 매핑은 원래 핸들러 오브젝트를 결정하는 전략.

    다른 타입 컨트롤러와의 일관성을 위해 오브젝트까지만 매핑하고

    최종 실행할 메소드는 핸들러 어댑터가 선정하게 하기 위해서 사용

  1. @RequestMapping("/hello")
  2. public class helloController implements Controller { ... }

 

 - 원칙적으로 핸들러 매핑과 핸들러 어댑터는 독립적으로 조합될 수 있기 때문에 적용 가능한 방법

 

 - 클래스 레벨의 URL 패턴이 /*로 끝나는 경우

   메소드 이름이 메소드 레벨의 URL 패턴으로 사용되게 할 수 있다.

  1. @RequestMapping("/user/*")
  2. public class UserController {
  3.     @RequestMapping public string add(){ ... }  
  4.     @RequestMapping public string edit(){ ... }
  5. }
  6. // 각각 /user/add와 /user/edit로 매핑된다.

 

 

 

 

타입 상속과 매핑

@RequestMapping이 적용된 클래스를 상속해서

컨트롤러로 사용하는 경우

수퍼클래스의 매핑 정보는 어떻게 됨?

 

타입 상속에 관한 대원칙 2가지.

1. @RequestMapping 정보는 상속된다.

2. 단, 서브 클래스에서 @RequestMapping을 재정의 하면 수퍼클래스의 정보는 무시된다.

 

인터페이스 구현의 의한 @ReqeustMapping 정보 상속은

클래스 상속과 거의 비슷하지만

몇가지 차이점이 있다.

 

 · 상위 타입과 메소드의 @RequestMapping 상속

 - 수퍼 클래스의 매핑 정보 상속

  1. // Super
  2. @RequestMapping("/user") public class Super {
  3.     @RequestMapping("/list") public string list(){ ... }  
  4. }
  5. //Sub
  6. public class Sub extends Super {}

결과

  모두 상속

  Sub 클래스를 컨트롤러로 등록하면, /user/list URL은 list() 메소드로 매핑

 

 - 메소드 오버라이드

  1. //Sub
  2. public class Sub extends Super {
  3.     public String list(){ ... }
  4. }

결과

  메소드를 오버라이드했더라도

  메소드에 @RequestMapping을 붙이지 않는다면

  수퍼 클래스 메소드의 매핑 정보는 그대로 상속된다.

  인터페이스의 경우도 마찬가지

 

 · 상위 타입의 @RequestMapping과 하위 타입 메소드의 @RequestMapping 결합

 - 상위 타입과 하위 메소드 정보의 결합

  1. //Super
  2. @RequestMapping("/user") public class Super {}
  3. //Sub
  4. public class Sub extends Super {
  5.     @RequestMapping("/list") public String list(){ ... }
  6. }

결과

  마찬가지로 /user/list URL은 list() 메소드로 매핑

  매핑정보 결합은 URL 뿐 아니라, HTTP 메소드, 파라미터에도 적용된다.

  인터페이스의 경우도 마찬가지

 

 · 상위 타입 메소드의 @RequestMapping과 하위 타입의 @RequestMapping 결합

 - 상위 메소드와 하위 타입의 결합

  1. //Super
  2. public class Super {
  3.     @RequestMapping("/list") public String list(){ ... }
  4. }
  5. //Sub
  6. RequestMapping("/user") public class Sub extends Super {}

결과

  마찬가지로 /user/list는 Sub가 상속받은 list() 메소드에 매핑된다.

주의

  인터페이스의 경우도 동일한 방식으로 적용된다.

  단, 인터페이스를 구현하는 메소드에

  URL이 없는 빈 @RequestMapping을 붙이면

  인터페이스 메소드의 매핑정보가 무시된다.

 

 · 하위 타입과 메소드의 @RequestMapping 재정의

 - 타입 레벨의 매핑정보 재정의

  1. // Super
  2. @RequestMaping("/user") public class Super {
  3.     @RequestMapping(value="/catalog", methods=RequestMethod.POST)
  4.     public String list() { ... }
  5. }
  6. // Sub
  7. @RequestMapping("/user") public class Sub extends Super {
  8.     @RequestMapping("/list") public String list() { ... }
  9. }

결과

  @RequestMapping을 재정의하는 경우에는 상위 타입에서 정의한 정보와 결합되지 않는다.

  Sub를 컨트롤러로 등록하면 /user/list 요청에 대한 메소드 매핑은 Sub의 list() 메소드에 매핑된다.

 

 · 서브클래스 메소드의 URL 패턴 없은 @RequestMapping 재정의

 - 하위 타입의 @RequestMapping은 항상 상위 타입의 @RequestMapping 정보를 대신한다.

 

 - 하지만 클래스 상속에서 오버라이드한 하위 메소드에 한해서는

  URL 조건이 없는 @RequestMapping을 붙였을 경우

  상위 메소드의 @RequestMapping의 URL 조건이 그대로 상속된다.

 


출처: http://blog.naver.com/comkwang17?Redirect=Log&logNo=140182037265 


+ Recent posts