2020-7-4 스프링 MVC(1)
스프링 MVC
- 모델 : 평범한 자바객체(POJO), 도메인객체 또는 DTO로 화면에 전달할 데이터를 가진 객체
- 뷰 : HTML, JSP, 타임리프
- 컨트롤러 : 스프링MVC. 사용자 입력을 받아 모델 객체의 데이터를 변경하거나 모델 객체를 뷰에 전달하는 역할
- 입력값 검증
- 입력 받은 데이터로 모델 객체 변경
-
변경된 모델 객체를 뷰에 전달
@Controller
public class EventController {
@Autowired
private EventService eventService;
@GetMapping("/events")
public String events(Model model) {
model.addAttribute("events", eventService.getEvents());
return "events"; //view의 이름
}
}
- view의 이름인 events를 template디렉토리 밑에서 찾는다.
MVC패턴의 장점
- 동시다발적개발 : 백엔드, 프론트가 독립적으로 개발 가능
- 높은 결합도 : 논리적으로 관력있는 기능을 하나의 컨트롤러로 묶거나 특정 모델과 관련된 뷰를 그룹화할 수 있다.
- 낮은의존도 : 뷰,모델,컨트롤러는 각각 독립적이다
- 한모델에 대한 여러형태의 뷰를 가질 수 있다.
단점
- 코드 네비게이션이 복잡
- 코드 일관성 유지에 노력이 필요
- 높은 학습곡선
서블릿 애플리케이션
- 스프링MVC는 서블릿기반으로 웹 MVC를 손쉽게 해준다.
서블릿
-
서블릿 애플리케이션을 직접실행할 수 없다. 서블릿 컨테이너를 사용해야한다.
-
자바 엔터프라이즈 에디션은 웹애플리케이션 개발용 스펙과 API제공
-
요청 당 쓰레드사용
-
그중 가장 중요한게 HttpServlet
-
서블릿이전에는 CGI(Common Gatewat Interface)를 이용하여 요청당 프로세스로 만들었다.
-
장점
- 빠르다
- 플랫폼 독립적
- 보안
- 이식성
-
서블릿 엔진 또는 서블릿컨테이너(톰캣, 제티, 언더토…)
- 세션관리
- 네트워크서비스
- MIME기반 메세지 인코딩 디코딩
- 서블릿 생명주기 관리
-
서블릿 생명주기
- 서블릿 컨테이너가 서블릿 인스턴스의 init()을 호출하여 초기화. 한번 초기화하고 나면 그 뒤로는 생략
- 서블릿이 초기화된 다음. 클라이언트의 요청을 처리할 수 있다. 각 요청은 별도의 쓰레드로 처리하고 이때 서블릿 인스턴스의 service()를 호출.
- 이 안에서 HTTP요청을 받고 HTTP응답을 만든다.
- service()는 보통 HTTP메서드에 따라 doGet(), doPost() 등으로 처리를 위임. 따라서 보통 doGet(), doPost()를 구현한다.
- 컨테이너의 판단에 따라 해당 서블릿을 메모리에서 내려할 시점에 destroy()를 호출한다.
-
public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("doGet"); resp.getWriter().write("Hello Servlet"); } @Override public void destroy() { System.out.println("destory"); } @Override public void init() throws ServletException { System.out.println("init"); } }
- 가장원시적인 서블릿은 위의 클래스를 작성하고 그 작성한 서블릿을 web.xml에 직접 등록을 해줘서 사용을 해야됬다.
서블릿 리스너, 필터
서블릿리스너
- 웹 애플리케이션에서 발생하는 주요 이벤트를 감지하고 각 이벤트에 특별한 작성이 필요한 경우에 사용할 수 있다.
- 서블릿 컨텍스트 수준의 이벤트
- 컨텍스트 라이프사이클 이벤트
- 컨텍스트 애트리뷰트 변경 이벤트
- 세션수준의 이벤트
- 세션 라이프사이클 이벤트
- 세션 애트리뷰트 변경 이벤트
- 서블릿 컨텍스트 수준의 이벤트
서블릿필터
- 들어온 요청을 서블릿으로 보내고, 또 서블릿이 작성한 응답을 클라이언트로 보내기 전에 특별한 처리가 필요한 경우에 사용할 수 있다.
- 체인형태의 구조다. => 서블릿컨테이너와 서블릿 사이에 필터를 여러개 둘 수 있다. 체인은 순차적으로 동작한다.
- doGet()으로 들어오기전에 필터로 처리.
web.xml에 리스너와 필터를 등록할 수 있다. 필터는 url-pattern과 servlet-name으로 등록할 수 있다.
context 생성 - 서블릿 생성 - doGet - 서블릿 종료 - context종료순으로 실행
서블릿 애플리케이션에서 스프링 연동하기
- 서블릿에서 스프링이 제공하는 IoC컨테이너를 활용
- 스프링이 제공하는 서블릿 구현체 DispatcherServlet사용하기
DispatcherServlet
- 스프링 MVC의 핵심
- Front Contrller역할을 한다. => 모든 요청을 하나로 받아서 해당요청을 처리할 핸들러에게 분배한다(dispatch)
DispatcherServlet
- 초기화 : HandlerMapping(핸들러를 찾아주는 인터페이스), HandlerAdapter(핸들러를 실행하는 인터페이스), HadlerExceptionResolver, ViewResolver…등의 빈들을 탐색하고 초기화한다.
- 동작순서
- 요청을 분석(locale, theme, multipart…)
- 핸들러 매핑에 위임하여 요청을 처리할 핸들러를 찾는다.
- 등록되있는 핸들러 어댑터 중에 해당 핸들러를 실행할 수 있는 핸들러 어댑터를 찾는다.
- 찾아낸 핸들러어댑터로 응답을 처리
- 예외가 발생하면 예외처리핸들러에 위임
- 핸들러의 리턴값을 보고 어떻게 처리할지 판단 => 뷰이름에 해당하는 뷰를 찾아서 모델데이터를 렌더링, @ReponseEntity가 있다면 Converter를 이용하여 응답본문을 만든다.
- 최종응답을 보낸다.
스프링MVC 구성요소
- DispatcherServlet은 다양한 인터페이스들을 구현하고 있다.
- MultipartResolver : 파일업로드 요청처리, HttpServletRequest => MultipartHttpServletRequest로 변환해주어 File을 꺼낼 수 있는 API를 제공
- LocaleResolver : 클라이언트 위치(Locale)정보를 파악, 기본전략은 요청의 accept-language를 보고한다.
- ThemeResovler : 애플리케이션에 설정된 테마를 파악하고 변경. 특징에 따라 다른 CSS를 사용하는것.
- *HandlerMapping : 요청을 처리할 핸들러를 찾는 인터페이스
- *HandlerAdapter : 핸들러매핑이 찾아낸 핸들러를 처리, 스프링MVC확장력의핵심
- *HandlerExceptionResolvers : 요청 처리 중에 발생한 에러처리
- RequestToViewNameTranslator : 핸들러에서 뷰 이름을 명시적으로 리턴하지 않으면 요청을 기반으로 뷰 이름을 판단.
- *ViewResolver : 뷰이름에 해당하는 뷰를 찾아내는 인터페이스
- FlashMapManger : FlashMap인터페이스를 가져오고 저장, FlashMap은 주로 리다이렉션을 사용할때 매개변수를 사용하지 않고 데이터를 전달하고 정리할때 사용
- DipstacherServlet 기본 전략 : DispatcherServlet.properties
정리
-
DispatcherServlet은 굉장히 복잡한 서블릿이다.
-
DispatcherServlet 초기화 : 특정타입에 해당하는 빈을 찾는다 => 없으면 기본전략을 사용(DispatcherServlet.properties)
-
스프링부트를 사용하지 않는 스프링 MVC
-
서블릿컨테이너(ex, 톰캣)에 등록한 웹 애플리케이션(WAR)에 DispatcherServlet을 등록한다. web.xml에 서블릿 등록 or WebApplicationInitializer에 자바코드로 등록. 빈에 뭐가 등록되있는지가 중요.
-
public class WebApplication implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); context.register(WebConfig.class); context.refresh(); DispatcherServlet dispatcherServlet = new DispatcherServlet(context); ServletRegistration.Dynamic app = servletContext.addServlet("app", dispatcherServlet); app.addMapping("/app/*"); } } // 스프링3.1, 서블릿3.0이상부터 지원
-
-
스프링부트를 사용하는 스프링 MVC
- 자바애플리케이션에 내장톰켓을 만들고 그 안에 DispatcherServlet을 등록 => 부트 자동설정이 자동으로 해준다.
- 스프링부트의 주관에 따라 여러 인터페이스 구현체를 빈으로 등록한다.
Written on July 4, 2020