예전에 정리했던 내용 참고 !
https://velog.io/@eeun95/작심구일러의-스프링-시작하기9
DispatcherServlet 구조
스프링 MVC의 프론트 컨트롤러가 바로 디스패쳐 서블릿이다. 이 디스패쳐 서블릿이 바로 스프링 MVC의 핵심!
dispatcherServlet도 부모클래스에서 HttpServlet을 상속받아서 사용하고 서블릿으로 동작
스프링 부트는 DispatcherServlet을 서블릿으로 자동으로 등록하면서 모든 경로(urlPatterns="/")에 대해 매핑
서블릿이 호출되면 HttpServlet이 제공하는 service() 호출
스프링 MVC는 DispatcherServlet의 부모인 FrameworkServlet을 오버라이드
FrameworkServlet.service()를 시작으로 여러 메서드가 호출되면서 DispatcherServlet.doDispatch 호출
핸들러매핑과 핸들러 어댑터
package hello.servlet.web.springmvc.old;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
// @Controller와 전혀 다름 임포트 주의!
@Component("/springmvc/old-controller")
public class OldController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("OldController.handleRequest");
return null;
}
}
이 컨트롤러가 호출되려면 2가지가 필요하다
스프링은 이미 필요한 핸들러 매핑과 핸들러 어댑터를 대부분 구현해둠 !
package hello.servlet.web.springmvc.old;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.HttpRequestHandler;
import java.io.IOException;
@Component("/springmvc/request-handler")
public class MyHttpRequestHandler implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("MyHttpRequestHandler.handleRequest");
}
}
스프링 빈 이름으로 핸들러를 찾아 httpRequestHandlerAdapter가 처리
🙋♀️ 우선순위가 가장 높은 핸들러 매핑과 핸들러 어댑터는 RequestMappingHandler~~이다. (99.9% 이 방식의 컨트롤러 사용)
뷰 리졸버
스프링 부트는 InternalResourceViewResolver라는 뷰 리졸버를 자동으로 등록하는데, 이때 application.properties에 설정 정보를 등록해주어야 한다.
#logging.level.org.apache.coyote.http11=debug
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
1순위 = BeanNameViewResolver
빈 이름으로 뷰를 찾아서 반환한다
2순위 = InternalResourceViewResolver
JSP를 처리할 수 있는 뷰를 반환한다
스프링 MVC 시작하기
스프링이 제공하는 컨트롤러는 어노테이션 기반으로 동작해서 매우 유연하고 실용적이다!
스프링은 어노테이션을 활용한 매우 유연하고 실용적인 컨트롤러를 만들었는데 이것이 바로 @RequestMapping 어노테이션을 사용하는 컨트롤러이다 ! ! !
package hello.servlet.web.springmvc.v1;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class SpringMemberFormControllerV1 {
@RequestMapping("/springmvc/v1/members/new-form")
public ModelAndView process() {
return new ModelAndView("new-form");
}
}
실용적인 방식
package hello.servlet.web.springmvc.v3;
import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@Controller
@RequestMapping("/springmvc/v3/members")
public class SpringMemberControllerV3 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@RequestMapping("/new-form")
public String newForm() {
return "new-form";
}
@RequestMapping("/save")
public String save(@RequestParam("username") String username,
@RequestParam("age") int age,
Model model) {
Member member = new Member(username, age);
memberRepository.save(member);
model.addAttribute("member", member);
return "save-result";
}
@RequestMapping
//@RequestMapping("/") 하면 왜 에러일까
public String members(Model model) {
List<Member> members = memberRepository.findAll();
model.addAttribute("members", members);
return "members";
}
}