📖 어노테이션 정리
https://study5024.tistory.com/50
스프링(Spring) 어노테이션들 정리
📌스프링 기본 어노테이션1️⃣ @Target@Target 이 선언된 하위 어노테이션이 어떤 범위에 적용되는지 설정한다.@Target의 ElementType.ANNOTATION_TYPE는 아래 enum상수에 따라 범위를 결정한다 2️⃣@Component
study5024.tistory.com
어노테이션을 어느정도 알고 보면 도움된다
📌 어댑터
다양한 컨트롤러(Handler)를 유연하게 만들기위해 어댑터 패턴을 도입하게 되었다. 컨트롤러들은 동일한 인터페이스를 구현하도록 하고 해당 인터페이스와 공통 로직 사이에 어댑터를 두어 유연하게 만든다. 서로 다른 인터페이스를 갖는 두 클래스를 연결해주는 패턴이다.
> HandleAdapter를 상속 받고 있어서 HandleAdapter 의 supports() 사용해서 역할에 맞는 인터페이스 상속하는지 체크 후
로직 실행 예외로 RequestMappingHandlerAdapter는 supports() 사용x
이유 👉 RequestMappingHandlerAdapter는 모든 @RequestMapping 기반 핸들러를 처리
RequestMappingHandlerAdapter는 @RequestMapping, @GetMapping, @PostMapping 이 붙은 모든 컨트롤러를 처리
@Controller와 @RestController를 사용하는 컨트롤러 메서드는 핸들러 매핑(RequestMappingHandlerMapping)이 이미 확인했기 때문에, 별도로 supports() 검사가 필요 없다.
따라서 항상 true를 반환하여 모든 @RequestMapping 컨트롤러를 처리할 수 있도록 한다.
👉 핸들러 매핑(RequestMappingHandlerMapping)이 핸들러(컨트롤러) 찾는 과정
Spring 컨텍스트에서 @Controller, @RestController가 붙은 빈을 먼저 체크한 후, 그 안에서 @RequestMapping 관련 애너테이션을 분석하여 매핑 정보를 저장하는 구조
순서 👉
DispatcherServlet이 HandlerMapping 으로 컨트롤러(핸들러) 목록 찾음 > 그 후에 해당 컨트롤러를 처리할 수 있는 HandlerAdapter를 찾는다.
📌 DispatcherServlet 내부 동작 흐름 정리
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
//요청을 처리할 컨트롤러(핸들러)를 찾음
HandlerExecutionChain handler = getHandler(request);
//생략..
//적절한 HandlerAdapter 찾기
HandlerAdapter ha = getHandlerAdapter(handler.getHandler());
//생략..
//컨트롤러 실행
ModelAndView mv = ha.handle(request, response, handler.getHandler());
//생략..
}
📌HandlerMapping
종류
RequestMappingHandlerMapping | @RequestMapping 기반 매핑 | @Controller 또는 @RestController |
BeanNameUrlHandlerMapping | 빈 이름으로 매핑 | 스프링 빈 등록 컨트롤러 |
SimpleUrlHandlerMapping | 수동 URL 매핑 | properties 설정 파일에서 지정 |
HandlerAdapter (스프링 MVC)
스프링 MVC에서 컨트롤러(Controller)와 디스패처 서블릿(DispatcherServlet) 간의 연결을 담당하는 인터페이스
//기본 구조
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler);
}
- supports(Object handler): 주어진 컨트롤러를 지원하는지 확인
- handle(...): 요청을 처리하고 응답을 생성
HandlerAdapter 상속 받고 있고, 스프링에서 따로 설정하지 않아도 만들어주는 기본 어댑터
1. RequestMappingHandlerAdapter
👉 @RequestMapping 또는 @GetMapping, @PostMapping이 적용된 컨트롤러를 처리
👉 스프링 MVC의 기본 컨트롤러 (@Controller, @RestController)를 실행
2. SimpleControllerHandlerAdapter
👉 Controller 인터페이스를 구현한 핸들러를 실행
👉 스프링 2.x 이전 버전과의 호환성을 위해 제공
3. HttpRequestHandlerAdapter
클라이언트 -> 서버로 /view/item Get요청이 들어왔다고 가정하고 정리해보았다
👉 HttpRequestHandler 인터페이스를 구현한 핸들러를 실행
👉 서블릿 API (HttpServletRequest, HttpServletResponse)를 직접 다룰 때 사용
4.HandlerFunctionAdapter
👉 HandlerFunction을 처리하는 어댑터로, 함수형 스타일의 요청 처리를 지원합니다.
HandlerAdapter 상속받고있는 Adapter 목록
SimpleControllerHandlerAdapter는 유지보수 위해 존재해서 RequestMappingHandlerAdapter를 주로 사용
- 컨트롤러(Handler)는 비지니스 로직을 처리하고 알맞은 결과를 반환한다.
- 어댑터는 공통 로직과 컨트롤러(Handler)가 자연스럽게 연결되도록 한다.
- 프론트 컨트롤러는 공통으로 처리되는 로직을 수행한다.
📌 스프링 동작 예시
❌ 아래 예제는 @RestController이여서 위 사진의 8,9,10 생략
1️⃣ Handler (컨트롤러) 등록
@RestController
public class ParameterController {
@PostMapping(value = "/users", headers = "Content-Type=application/json")
public String handleHeaders(@RequestBody String data) {
return "Handled by headers: " + data;
}
}
- @RestController로 선언된 클래스는 Handler 역할
- @PostMapping("/users ")을 통해 요청을 처리
2️⃣ DispatcherServlet
✅ Servlet이 호출되면 HttpServlet이 제공하는 service()가 호출된다
Spring MVC는 DispatcherServlet의 부모인 FrameworkServlet에서 service()를 Override 해두었다.
✅ FrameworkServlet의 service() -> DispatcherServlet의 doService() -> doDispatch()로 이동
HandlerMapping이 요청 URL(/ users)이 들어오면 에 해당하는 컨트롤러를 찾아줍니다.
처리 할 컨트롤러 찾는 과정
✅ DispatcherServlet의 doDispatch()로 온다
✅ HandlerMapping 타입의 리스트 handlerMappings에서 각 Mappings가 관리하는 컨트롤러를 체크하며 처리 할 컨트롤러를 찾아준다
✅ 대상 컨트롤러 찾아줌
3️⃣ DispatcherServlet이 HandlerAdapter를 실행하는 과정
컨트롤러를 실행하기 위해 적절한 HandlerAdapter를 선택합니다.
RequestMappingHandlerAdapter가 선택되어 컨트롤러를 실행합니다.
✅ 처리 할 어댑터 찾는과정
✅ 처리 할 어댑터 찾음
스프링 MVC는 기본적으로 RequestMappingHandlerMapping 을 사용하여 요청을 적절한 컨트롤러 메서드로 매핑합니다.
4️⃣ 대상 컨트롤러에서 처리
✅ doDispatch()에서 선택한 컨트롤러로 보내줌
✅처리
5️⃣ 결과
이후 흐름
https://study5024.tistory.com/51
결론
- DispatcherServlet이 요청을 받고 HandlerMapping을 통해 적절한 컨트롤러(Handler)를 찾음
- HandlerAdapter가 컨트롤러를 실행할 수 있도록 연결해 줌
- 컨트롤러가 처리를 한 후 결과를 리턴
- 최종적으로 브라우저에 HTML 응답이 전달됨